首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >dx9和dx11映射的差异

dx9和dx11映射的差异
EN

Stack Overflow用户
提问于 2022-07-09 14:13:08
回答 1查看 164关注 0票数 1

我试图以同样的方式为DX9和DX11生成mipmap,我需要它们从像素着色器中采样特定的级别。在那之后,我注意到在不同的DX版本上,抽样是不同的,而且在DX11中更糟,对DX9更好。

接下来,我尝试通过使用ImGui呈现一个备份副本图像并缩小4倍的大小来可视化它,结果如下:

带有mipmap生成的DX9:dx9 w mips

没有mipmap生成的DX9:dx9

带有mipmap生成的DX11:dx11 w mips

没有mipmap生成的DX11:dx11

纹理的创建是完全相同的:

DX9

代码语言:javascript
复制
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

代码语言:javascript
复制
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));

MIN/MAG/MIP滤波器的采样状态为线性,MaxLOD为D3D11_FLOAT32_MAX。很明显,DX11图像过于锐利,看上去与w/o映射相同。所以我的问题是为什么它发生在DX11,而不是发生在DX9,当我确信它确实正确地生成mipmap,并且我可以从它们在着色器内采样(着色取样也看起来更清晰)?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-09 19:30:40

一般的答案是自动生成的mipmips完全由驱动程序决定。因此,自动生成的mips的质量因驱动程序的不同而有很大差异,在某些情况下,对于某些格式,它可以像点采样一样低质量。

这实际上是DirectX 12没有“自动生成的mips”功能的原因之一。相反,如果您需要此功能,建议使用计算机着色器。有关示例,请参见用于DirectX的DX12工具包

尽管如此,您需要验证所有返回HRESULT值的函数,因为您可能会在忽略的某个地方得到一个错误代码。例如,我怀疑在交换链缓冲区上调用SetAutoGenFilterType是否真的像您认为的那样。即使您只是将它们视为快速失败,也不要忽略HRESULT返回。

对于DirectX 11,应该启用调试设备并查找输出。由于DirectX 9是遗留的,因此自Windows7以来就不支持用于它的“调试设备”。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72922067

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档