From 3718cee9eb950b298395cb5875f686ac3aa8819f Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Mon, 16 Aug 2021 17:26:21 +0100 Subject: [PATCH] [d3d9] Clean up texture type tracking Additionally stops leaky pipelines on PS 1.x shaders from partial mask updates. --- src/d3d9/d3d9_device.cpp | 64 ++++++++++++++++------------------------ src/d3d9/d3d9_device.h | 6 ++-- 2 files changed, 29 insertions(+), 41 deletions(-) diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index 457a414d2..869e37dec 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -3700,14 +3700,26 @@ namespace dxvk { if (m_state.textures[StateSampler] == pTexture) return D3D_OK; + auto oldTexture = GetCommonTexture(m_state.textures[StateSampler]); + auto newTexture = GetCommonTexture(pTexture); + // We need to check our ops and disable respective stages. // Given we have transition from a null resource to // a valid resource or vice versa. - if (StateSampler < 16 && (pTexture == nullptr || m_state.textures[StateSampler] == nullptr)) - m_flags.set(D3D9DeviceFlag::DirtyFFPixelShader); + if (StateSampler < 16) { + const uint32_t offset = StateSampler * 2; + const uint32_t textureType = newTexture != nullptr + ? uint32_t(newTexture->GetType() - D3DRTYPE_TEXTURE) + : 0; + const uint32_t textureBitMask = 0b11u << offset; + const uint32_t textureBits = textureType << offset; - auto oldTexture = GetCommonTexture(m_state.textures[StateSampler]); - auto newTexture = GetCommonTexture(pTexture); + m_textureTypes &= ~textureBitMask; + m_textureTypes |= textureBits; + + if (newTexture == nullptr || oldTexture == nullptr) + m_flags.set(D3D9DeviceFlag::DirtyFFPixelShader); + } DWORD oldUsage = oldTexture != nullptr ? oldTexture->Desc()->Usage : 0; DWORD newUsage = newTexture != nullptr ? newTexture->Desc()->Usage : 0; @@ -5808,17 +5820,6 @@ namespace dxvk { D3D9CommonTexture* commonTex = GetCommonTexture(m_state.textures[StateSampler]); - // For all our pixel shader textures - if (likely(StateSampler < 16)) { - const uint32_t offset = StateSampler * 2; - const uint32_t textureType = uint32_t(commonTex->GetType() - D3DRTYPE_TEXTURE); - const uint32_t textureBitMask = 0b11u << offset; - const uint32_t textureBits = textureType << offset; - - m_samplerTypeBitfield &= ~textureBitMask; - m_samplerTypeBitfield |= textureBits; - } - EmitCs([ cSlot = slot, cImageView = commonTex->GetSampleView(srgb) @@ -5829,18 +5830,6 @@ namespace dxvk { void D3D9DeviceEx::UnbindTextures(uint32_t mask) { - // For all our pixel shader textures - const uint32_t pixelShaderMask = (1u << 16u) - 1; - - // Update the sampler type bitfield to 0 for the - // unbound textures. - uint32_t typeMask = 0; - for (uint32_t i : bit::BitMask(mask & pixelShaderMask)) - typeMask |= 0b11u << (i * 2u); - - m_samplerTypeBitfield &= ~typeMask; - } - EmitCs([ cMask = mask ](DxvkContext* ctx) { @@ -6009,7 +5998,7 @@ namespace dxvk { BindInputLayout(); auto UpdateSamplerTypes = [&](uint32_t types, uint32_t projections, uint32_t fetch4) { - if (m_lastSamplerTypeBitfield != types) + if (m_lastSamplerTypes != types) UpdateSamplerSpecConsant(types); if (m_lastProjectionBitfield != projections) @@ -6022,15 +6011,14 @@ namespace dxvk { if (likely(UseProgrammablePS())) { UploadConstants(); - const uint32_t psTextureMask = m_activeTextures & m_psShaderMasks.samplerMask; - - uint32_t fetch4 = m_fetch4 & psTextureMask; - uint32_t projected = m_projectionBitfield & psTextureMask; + const uint32_t psTextureMask = usedTextureMask & ((1u << 16u) - 1u); + const uint32_t fetch4 = m_fetch4 & psTextureMask; + const uint32_t projected = m_projectionBitfield & psTextureMask; if (GetCommonShader(m_state.pixelShader)->GetInfo().majorVersion() >= 2) - UpdateSamplerTypes(m_d3d9Options.forceSamplerTypeSpecConstants ? m_samplerTypeBitfield : 0u, 0u, fetch4); + UpdateSamplerTypes(m_d3d9Options.forceSamplerTypeSpecConstants ? m_textureTypes : 0u, 0u, fetch4); else - UpdateSamplerTypes(m_samplerTypeBitfield, projected, fetch4); // For implicit samplers... + UpdateSamplerTypes(m_textureTypes, projected, fetch4); // For implicit samplers... UpdateBoolSpecConstantPixel( m_state.psConsts.bConsts[0] & @@ -6563,9 +6551,9 @@ namespace dxvk { void D3D9DeviceEx::UpdateFixedFunctionPS() { // Shader... - if (m_flags.test(D3D9DeviceFlag::DirtyFFPixelShader) || m_lastSamplerTypeBitfieldFF != m_samplerTypeBitfield) { + if (m_flags.test(D3D9DeviceFlag::DirtyFFPixelShader) || m_lastSamplerTypesFF != m_textureTypes) { m_flags.clr(D3D9DeviceFlag::DirtyFFPixelShader); - m_lastSamplerTypeBitfieldFF = m_samplerTypeBitfield; + m_lastSamplerTypesFF = m_textureTypes; // Used args for a given operation. auto ArgsMask = [](DWORD Op) { @@ -6617,7 +6605,7 @@ namespace dxvk { stage.AlphaArg2 = data[DXVK_TSS_ALPHAARG2]; const uint32_t samplerOffset = idx * 2; - stage.Type = (m_samplerTypeBitfield >> samplerOffset) & 0xffu; + stage.Type = (m_textureTypes >> samplerOffset) & 0xffu; stage.ResultIsTemp = data[DXVK_TSS_RESULTARG] == D3DTA_TEMP; uint32_t ttff = data[DXVK_TSS_TEXTURETRANSFORMFLAGS]; @@ -6716,7 +6704,7 @@ namespace dxvk { ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::SamplerType, cBitfield); }); - m_lastSamplerTypeBitfield = value; + m_lastSamplerTypes = value; } diff --git a/src/d3d9/d3d9_device.h b/src/d3d9/d3d9_device.h index 1d49f4af9..4f37ab857 100644 --- a/src/d3d9/d3d9_device.h +++ b/src/d3d9/d3d9_device.h @@ -1182,7 +1182,7 @@ namespace dxvk { uint32_t m_instancedData = 0; uint32_t m_depthTextures = 0; - uint32_t m_samplerTypeBitfield = 0; + uint32_t m_textureTypes = 0; uint32_t m_projectionBitfield = 0; uint32_t m_dirtySamplerStates = 0; @@ -1207,11 +1207,11 @@ namespace dxvk { uint32_t m_lastBoolSpecConstantPixel = 0; uint32_t m_lastSamplerDepthMode = 0; uint32_t m_lastProjectionBitfield = 0; - uint32_t m_lastSamplerTypeBitfield = 0; + uint32_t m_lastSamplerTypes = 0; uint32_t m_lastPointMode = 0; uint32_t m_lastFetch4 = 0; uint32_t m_lastHazardsDS = 0; - uint32_t m_lastSamplerTypeBitfieldFF = 0; + uint32_t m_lastSamplerTypesFF = 0; D3D9ShaderMasks m_vsShaderMasks = D3D9ShaderMasks(); D3D9ShaderMasks m_psShaderMasks = FixedFunctionMask;