From 0262fbc70a04ee88d8514b0599207de0e9716ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 30 Jul 2022 19:55:56 +0200 Subject: [PATCH] Implement 3D textures for D3D11 --- GPU/Common/FragmentShaderGenerator.cpp | 20 ++++++-- GPU/Common/TextureCacheCommon.cpp | 4 -- GPU/D3D11/TextureCacheD3D11.cpp | 67 ++++++++++++++++++++------ GPU/D3D11/TextureCacheD3D11.h | 4 +- GPU/Vulkan/TextureCacheVulkan.cpp | 5 ++ 5 files changed, 74 insertions(+), 26 deletions(-) diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index 5b03db8cf0df..0dca9af611c3 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -210,7 +210,11 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu } } else { WRITE(p, "SamplerState samp : register(s0);\n"); - WRITE(p, "Texture2D tex : register(t0);\n"); + if (texture3D) { + WRITE(p, "Texture3D tex : register(t0);\n"); + } else { + WRITE(p, "Texture2D tex : register(t0);\n"); + } if (readFramebufferTex) { // No sampler required, we Load WRITE(p, "Texture2D fboTex : register(t1);\n"); @@ -547,10 +551,18 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu if (!shaderDepal) { if (compat.shaderLanguage == HLSL_D3D11) { - if (doTextureProjection) { - WRITE(p, " vec4 t = tex.Sample(samp, v_texcoord.xy / v_texcoord.z)%s;\n", bgraTexture ? ".bgra" : ""); + if (texture3D) { + if (doTextureProjection) { + WRITE(p, " vec4 t = tex.Sample(samp, vec3(v_texcoord.xy / v_texcoord.z, u_mipBias))%s;\n", bgraTexture ? ".bgra" : ""); + } else { + WRITE(p, " vec4 t = tex.Sample(samp, vec3(%s.xy, u_mipBias))%s;\n", texcoord, bgraTexture ? ".bgra" : ""); + } } else { - WRITE(p, " vec4 t = tex.Sample(samp, %s.xy)%s;\n", texcoord, bgraTexture ? ".bgra" : ""); + if (doTextureProjection) { + WRITE(p, " vec4 t = tex.Sample(samp, v_texcoord.xy / v_texcoord.z)%s;\n", bgraTexture ? ".bgra" : ""); + } else { + WRITE(p, " vec4 t = tex.Sample(samp, %s.xy)%s;\n", texcoord, bgraTexture ? ".bgra" : ""); + } } } else if (compat.shaderLanguage == HLSL_D3D9) { if (doTextureProjection) { diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index aa43ff87f06e..1c09fd6065c0 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2177,10 +2177,6 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt entry->status &= ~TexCacheEntry::STATUS_NO_MIPS; } - if (plan.depth > 1) { - entry->status |= TexCacheEntry::STATUS_3D; - } - // Will be filled in again during decode. entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK; return true; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index e2bb7ece02e5..9fef0f602e0b 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -467,24 +467,46 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { } // We don't yet have mip generation, so clamp the number of levels to the ones we can load directly. - int levels = std::min(plan.levelsToCreate, plan.levelsToLoad); - - D3D11_TEXTURE2D_DESC desc{}; - desc.CPUAccessFlags = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.ArraySize = 1; - desc.SampleDesc.Count = 1; - desc.Width = tw; - desc.Height = th; - desc.Format = dstFmt; - desc.MipLevels = levels; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + int levels;; ID3D11ShaderResourceView *view; - ID3D11Texture2D *texture = DxTex(entry); + ID3D11Resource *texture = DxTex(entry); _assert_(texture == nullptr); - ASSERT_SUCCESS(device_->CreateTexture2D(&desc, nullptr, &texture)); + if (plan.depth == 1) { + ID3D11Texture2D *tex; + D3D11_TEXTURE2D_DESC desc{}; + desc.CPUAccessFlags = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.ArraySize = 1; + desc.SampleDesc.Count = 1; + desc.Width = tw; + desc.Height = th; + desc.Format = dstFmt; + desc.MipLevels = plan.levelsToCreate; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + ASSERT_SUCCESS(device_->CreateTexture2D(&desc, nullptr, &tex)); + texture = tex; + + levels = std::min(plan.levelsToCreate, plan.levelsToLoad); + } else { + ID3D11Texture3D *tex; + D3D11_TEXTURE3D_DESC desc{}; + desc.CPUAccessFlags = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.Width = tw; + desc.Height = th; + desc.Depth = plan.depth; + desc.Format = dstFmt; + desc.MipLevels = 1; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + ASSERT_SUCCESS(device_->CreateTexture3D(&desc, nullptr, &tex)); + texture = tex; + + levels = plan.depth; + } + ASSERT_SUCCESS(device_->CreateShaderResourceView(texture, nullptr, &view)); entry->texturePtr = texture; entry->textureView = view; @@ -525,11 +547,24 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { LoadTextureLevel(*entry, data, stride, *plan.replaced, srcLevel, plan.scaleFactor, texFmt, false); - ID3D11Texture2D *texture = DxTex(entry); - context_->UpdateSubresource(texture, i, nullptr, data, stride, 0); + if (plan.depth == 1) { + context_->UpdateSubresource(texture, i, nullptr, data, stride, 0); + } else { + D3D11_BOX box{}; + box.front = i; + box.back = i + 1; + box.right = w * plan.scaleFactor; + box.bottom = h * plan.scaleFactor; + context_->UpdateSubresource(texture, 0, &box, data, stride, 0); + } FreeAlignedMemory(data); } + // Signal that we support depth textures so use it as one. + if (plan.depth > 1) { + entry->status |= TexCacheEntry::STATUS_3D; + } + if (levels == 1) { entry->status |= TexCacheEntry::STATUS_NO_MIPS; } else { diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 131398e2dcc4..6ababb2b30b5 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -77,8 +77,8 @@ class TextureCacheD3D11 : public TextureCacheCommon { ID3D11Device *device_; ID3D11DeviceContext *context_; - ID3D11Texture2D *&DxTex(TexCacheEntry *entry) { - return (ID3D11Texture2D *&)entry->texturePtr; + ID3D11Resource *&DxTex(TexCacheEntry *entry) { + return (ID3D11Resource *&)entry->texturePtr; } ID3D11ShaderResourceView *DxView(TexCacheEntry *entry) { return (ID3D11ShaderResourceView *)entry->textureView; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 876ea81f568e..6b31a5a9e0c6 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -808,6 +808,11 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { entry->vkTex->EndCreate(cmdInit, false, prevStage, layout); VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); + // Signal that we support depth textures so use it as one. + if (plan.depth > 1) { + entry->status |= TexCacheEntry::STATUS_3D; + } + if (plan.replaced->Valid()) { entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus())); }