[英]difference between dx9 and dx11 mipmaps
I had tried to generate mipmaps for both DX9 and DX11 in same way, i needed them to sample specific levels from pixel shader.我曾尝试以相同的方式为 DX9 和 DX11 生成 mipmap,我需要它们从像素着色器中采样特定级别。 After that i noticed that sampling is different on different DX versions, and seems to be worse with DX11 and good with DX9.
之后我注意到不同 DX 版本的采样不同,DX11 似乎更差,DX9 更好。
Next i tried to visualize it by rendering a backbuffer copy image and 4x downscaled size with ImGui and the results were:接下来,我尝试通过使用 ImGui 渲染后缓冲复制图像和 4 倍缩小尺寸来将其可视化,结果是:
DX9 with mipmaps generation: dx9 w mips DX9 与 mipmaps 生成: dx9 w mips
DX9 without mipmaps generation: dx9 wo mips没有生成 mipmap 的 DX9: dx9 wo mips
DX11 with mipmaps generation: dx11 w mips DX11 与 mipmaps 生成: dx11 w mips
DX11 without mipmaps generation: dx11 wo mips没有生成 mipmap 的 DX11: dx11 wo mips
The texture creation is absolutely same:纹理创建是完全一样的:
DX9 DX9
static IDirect3DTexture9* pBackBufferResource = nullptr;
IDirect3DSurface9* pBackBuffer = nullptr;
g_pd3dDevice->GetBackBuffer(0U, 0U, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
D3DSURFACE_DESC descBack = { };
pBackBuffer->GetDesc(&descBack);
if (pBackBufferResource == nullptr)
{
g_pd3dDevice->CreateTexture(descBack.Width, descBack.Height, 1U, D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP, descBack.Format, D3DPOOL_DEFAULT, &pBackBufferResource, nullptr);
/*
* explicitly set linear filter for mipmap generation
* for some reason 'D3DSAMP_MIPFILTER' sampler state doesn't actually change this
*/
pBackBufferResource->SetAutoGenFilterType(D3DTEXF_LINEAR);
}
// get the most detailed mip-level surface
IDirect3DSurface9* pResourceTopSurface = nullptr;
pBackBufferResource->GetSurfaceLevel(0U, &pResourceTopSurface);
// because backbuffer haven't mipmap, we couldn't just copy its texture, we're update only most detailed mip-level
g_pd3dDevice->StretchRect(pBackBuffer, nullptr, pResourceTopSurface, nullptr, D3DTEXF_LINEAR);
// the 'D3DUSAGE_AUTOGENMIPMAP' flag of texture creation will regenerate mipmap automatically, but here do it manually just for sure
pBackBufferResource->GenerateMipSubLevels();
ImVec2 vecMin = { 10.f, 10.f };
ImVec2 vecMax = { vecMin.x + floorf((float)descBack.Width / 4.0f), vecMin.y + floorf((float)descBack.Height / 4.0f) };
ImGui::GetForegroundDrawList()->AddImage(pBackBufferResource, vecMin, vecMax);
ImGui::GetForegroundDrawList()->AddRect(vecMin, vecMax, IM_COL32(0, 0, 0, 255));
DX11 DX11
static ID3D11Texture2D* pBackBufferCopy = nullptr;
static ID3D11ShaderResourceView* pBackBufferResource = nullptr;
ID3D11Texture2D* pBackBuffer = nullptr;
g_mainRenderTargetView->GetResource(reinterpret_cast<ID3D11Resource**>(&pBackBuffer));
D3D11_TEXTURE2D_DESC descBack = { };
pBackBuffer->GetDesc(&descBack);
if (pBackBufferCopy == nullptr)
{
D3D11_TEXTURE2D_DESC descBackCopy = descBack;
descBackCopy.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
descBackCopy.MipLevels = 0U;
descBackCopy.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
g_pd3dDevice->CreateTexture2D(&descBackCopy, nullptr, &pBackBufferCopy);
}
// because backbuffer haven't mipmap, we couldn't copy its texture just with 'CopyResource()', so we're update only most detailed mip-level
g_pd3dDeviceContext->CopySubresourceRegion(pBackBufferCopy, 0U, 0U, 0U, 0U, pBackBuffer, 0U, nullptr);
pBackBuffer->Release();
if (pBackBufferResource == nullptr)
{
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDescBuffer = { };
resourceViewDescBuffer.Format = descBack.Format;
resourceViewDescBuffer.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
resourceViewDescBuffer.Texture2D.MostDetailedMip = 0U;
resourceViewDescBuffer.Texture2D.MipLevels = ~0U;
g_pd3dDevice->CreateShaderResourceView(pBackBufferCopy, &resourceViewDescBuffer, &pBackBufferResource);
}
// regenerate mipmap based on updated most detailed mip-level
g_pd3dDeviceContext->GenerateMips(pBackBufferResource);
ImVec2 vecMin = { 10.f, 10.f };
ImVec2 vecMax = { vecMin.x + floorf((float)descBack.Width / 4.0f), vecMin.y + floorf((float)descBack.Height / 4.0f) };
ImGui::GetForegroundDrawList()->AddImage(pBackBufferResource, vecMin, vecMax);
ImGui::GetForegroundDrawList()->AddRect(vecMin, vecMax, IM_COL32(0, 0, 0, 255));
Sampler states of MIN/MAG/MIP filters are LINEAR and MaxLOD is D3D11_FLOAT32_MAX for both renderers.两个渲染器的 MIN/MAG/MIP 过滤器的采样器状态为 LINEAR,MaxLOD 为 D3D11_FLOAT32_MAX。 It's clear that DX11 image are excessively sharp and looking same w/ and w/o mipmaps.
很明显,DX11 图像过于清晰,并且在使用和不使用 mipmap 时看起来都一样。 So my question is why it happens with DX11 and doesn't happens with DX9, when i'm sure that it does generate mipmaps properly and i can sample from them inside shader (shader sampling is also looking sharper)?
所以我的问题是为什么它会发生在 DX11 上而不会发生在 DX9 上,当我确定它确实会正确生成 mipmap 并且我可以在着色器中从它们中采样(着色器采样也看起来更清晰)?
The general answer is that auto-generated mipmips is left entirely up to the driver.一般的答案是自动生成的 mipmips 完全由驱动程序决定。 As such, the quality of auto-generated mips is going vary widely from driver to driver, and in some cases for some formats it can be as low-quality as point-sampling.
因此,自动生成的 mip 的质量因驱动程序而异,在某些情况下,对于某些格式,它的质量可能与点采样一样低。
This is in fact one of the reasons that DirectX 12 doesn't have 'auto-generated mips' as a feature.这实际上是 DirectX 12 没有“自动生成的 mips”功能的原因之一。 Instead if you need this feature, the recommendation is to use a compute shader.
相反,如果您需要此功能,建议使用计算着色器。 For an example, see DirectX Tool Kit for DX12 .
有关示例,请参阅适用于 DX12 的 DirectX 工具包。
All that said, you need to validate all functions that return HRESULT
values as you are likely getting an error code back somewhere you are ignoring.话虽如此,您需要验证所有返回
HRESULT
值的函数,因为您可能会在您忽略的某个地方返回错误代码。 For example, I doubt that calling SetAutoGenFilterType
on a swapchain buffer actually does what you think it does.例如,我怀疑在交换链缓冲区上调用
SetAutoGenFilterType
是否真的如你所想。 Even if you just treat them as fail fast , don't ignore HRESULT
returns.即使您只是将它们视为快速失败,也不要忽略
HRESULT
返回。
For DirectX 11, you should enable the debug device and look for output.对于 DirectX 11,您应该启用调试设备并查找输出。 Since DirectX 9 is legacy, the 'debug device' for it has not been supported since Windows 7.
由于 DirectX 9 是旧版,因此自 Windows 7 起不再支持它的“调试设备”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.