I had tried to generate mipmaps for both DX9 and DX11 in same way, i needed them to sample specific levels from pixel shader. After that i noticed that sampling is different on different DX versions, and seems to be worse with DX11 and good with DX9.
Next i tried to visualize it by rendering a backbuffer copy image and 4x downscaled size with ImGui and the results were:
DX9 with mipmaps generation: dx9 w mips
DX9 without mipmaps generation: dx9 wo mips
DX11 with mipmaps generation: dx11 w mips
DX11 without mipmaps generation: dx11 wo mips
The texture creation is absolutely same:
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
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. It's clear that DX11 image are excessively sharp and looking same w/ and w/o mipmaps. 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)?