From 8fdf9e67d39b332999e08318c87befa315f17679 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Mon, 25 May 2020 06:09:45 +0100 Subject: [PATCH] [d3d9, dxso] Implement FETCH4 --- src/d3d9/d3d9_device.cpp | 32 ++++++++++++++++++++--- src/d3d9/d3d9_device.h | 5 ++++ src/d3d9/d3d9_spec_constants.h | 1 + src/dxso/dxso_compiler.cpp | 47 ++++++++++++++++++++++++++++------ src/dxso/dxso_compiler.h | 2 ++ 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index 1fd7bf488..4e2ac349a 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -3507,6 +3507,16 @@ namespace dxvk { m_dirtySamplerStates |= 1u << StateSampler; else if (Type == D3DSAMP_SRGBTEXTURE) BindTexture(StateSampler); + + constexpr DWORD Fetch4Enabled = MAKEFOURCC('G', 'E', 'T', '4'); + constexpr DWORD Fetch4Disabled = MAKEFOURCC('G', 'E', 'T', '1'); + + if (Type == D3DSAMP_MIPMAPLODBIAS) { + if (Value == Fetch4Enabled) + m_fetch4Enabled |= 1u << StateSampler; + else if (Value == Fetch4Disabled) + m_fetch4Enabled &= ~(1u << StateSampler); + } } return D3D_OK; @@ -5603,21 +5613,26 @@ namespace dxvk { if (m_flags.test(D3D9DeviceFlag::DirtyInputLayout)) BindInputLayout(); - auto UpdateSamplerTypes = [&](uint32_t types, uint32_t projections) { + auto UpdateSamplerTypes = [&](uint32_t types, uint32_t projections, uint32_t fetch4) { if (m_lastSamplerTypeBitfield != types) UpdateSamplerSpecConsant(types); if (m_lastProjectionBitfield != projections) UpdateProjectionSpecConstant(projections); + + if (m_lastFetch4 != fetch4) + UpdateFetch4SpecConstant(fetch4); }; if (likely(UseProgrammablePS())) { UploadConstants(); + uint32_t fetch4 = m_fetch4Enabled & (m_activeTextures & m_psShaderMasks.samplerMask); + if (GetCommonShader(m_state.pixelShader)->GetInfo().majorVersion() >= 2) - UpdateSamplerTypes(m_d3d9Options.forceSamplerTypeSpecConstants ? m_samplerTypeBitfield : 0u, 0u); + UpdateSamplerTypes(m_d3d9Options.forceSamplerTypeSpecConstants ? m_samplerTypeBitfield : 0u, 0u, fetch4); else - UpdateSamplerTypes(m_samplerTypeBitfield, m_projectionBitfield); // For implicit samplers... + UpdateSamplerTypes(m_samplerTypeBitfield, m_projectionBitfield, fetch4); // For implicit samplers... UpdateBoolSpecConstantPixel( m_state.psConsts.bConsts[0] & @@ -5625,7 +5640,7 @@ namespace dxvk { } else { UpdateBoolSpecConstantPixel(0); - UpdateSamplerTypes(0u, 0u); + UpdateSamplerTypes(0u, 0u, 0u); UpdateFixedFunctionPS(); } @@ -6316,6 +6331,15 @@ namespace dxvk { } + void D3D9DeviceEx::UpdateFetch4SpecConstant(uint32_t value) { + EmitCs([cBitfield = value](DxvkContext* ctx) { + ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::Fetch4, cBitfield); + }); + + m_lastFetch4 = value; + } + + void D3D9DeviceEx::ApplyPrimitiveType( DxvkContext* pContext, D3DPRIMITIVETYPE PrimType) { diff --git a/src/d3d9/d3d9_device.h b/src/d3d9/d3d9_device.h index aa7d48cd2..9fccb1a03 100644 --- a/src/d3d9/d3d9_device.h +++ b/src/d3d9/d3d9_device.h @@ -1036,6 +1036,9 @@ namespace dxvk { uint32_t m_activeTextures = 0; uint32_t m_activeTexturesToUpload = 0; + uint32_t m_fetch4Enabled = 0; + uint32_t m_lastFetch4 = 0; + uint32_t m_activeHazardsDS = 0; uint32_t m_lastHazardsDS = 0; @@ -1189,6 +1192,8 @@ namespace dxvk { void UpdateProjectionSpecConstant(uint32_t value); + void UpdateFetch4SpecConstant(uint32_t value); + }; } diff --git a/src/d3d9/d3d9_spec_constants.h b/src/d3d9/d3d9_spec_constants.h index 5d1bd3c0c..6b2b8cb55 100644 --- a/src/d3d9/d3d9_spec_constants.h +++ b/src/d3d9/d3d9_spec_constants.h @@ -17,6 +17,7 @@ namespace dxvk { VertexShaderBools = 8, PixelShaderBools = 9, + Fetch4 = 10 }; } \ No newline at end of file diff --git a/src/dxso/dxso_compiler.cpp b/src/dxso/dxso_compiler.cpp index 0e5fa38cf..c452420df 100644 --- a/src/dxso/dxso_compiler.cpp +++ b/src/dxso/dxso_compiler.cpp @@ -468,6 +468,10 @@ namespace dxvk { } } + m_ps.fetch4Spec = m_module.specConst32(m_module.defIntType(32, 0), 0); + m_module.decorateSpecId(m_ps.fetch4Spec, getSpecId(D3D9SpecConstantId::Fetch4)); + m_module.setDebugName(m_ps.fetch4Spec, "s_fetch4"); + this->setupRenderStateInfo(); this->emitPsSharedConstants(); @@ -2766,12 +2770,22 @@ void DxsoCompiler::emitControlFlowGenericLoop( } } + uint32_t fetch4 = 0; + if (m_programInfo.type() == DxsoProgramType::PixelShader) { + fetch4 = m_module.opBitFieldUExtract( + m_module.defIntType(32, 0), m_ps.fetch4Spec, + m_module.consti32(samplerIdx), m_module.consti32(1)); + + fetch4 = m_module.opIEqual(m_module.defBoolType(), fetch4, m_module.constu32(1)); + } + result.id = this->emitSample( projDivider != 0, typeId, imageVarId, texcoordVar.id, reference, + fetch4, imageOperands); if (switchProjResult) { @@ -2783,6 +2797,7 @@ void DxsoCompiler::emitControlFlowGenericLoop( imageVarId, texcoordVar.id, reference, + fetch4, imageOperands); uint32_t shouldProj = m_module.opBitFieldUExtract( @@ -3028,40 +3043,56 @@ void DxsoCompiler::emitControlFlowGenericLoop( uint32_t sampledImage, uint32_t coordinates, uint32_t reference, + uint32_t fetch4, const SpirvImageOperands& operands) { const bool depthCompare = reference != 0; const bool explicitLod = (operands.flags & spv::ImageOperandsLodMask) || (operands.flags & spv::ImageOperandsGradMask); + uint32_t val; + + // No Fetch 4 if (projected) { if (depthCompare) { if (explicitLod) - return m_module.opImageSampleProjDrefExplicitLod(resultType, sampledImage, coordinates, reference, operands); + val = m_module.opImageSampleProjDrefExplicitLod(resultType, sampledImage, coordinates, reference, operands); else - return m_module.opImageSampleProjDrefImplicitLod(resultType, sampledImage, coordinates, reference, operands); + val = m_module.opImageSampleProjDrefImplicitLod(resultType, sampledImage, coordinates, reference, operands); } else { if (explicitLod) - return m_module.opImageSampleProjExplicitLod(resultType, sampledImage, coordinates, operands); + val = m_module.opImageSampleProjExplicitLod(resultType, sampledImage, coordinates, operands); else - return m_module.opImageSampleProjImplicitLod(resultType, sampledImage, coordinates, operands); + val = m_module.opImageSampleProjImplicitLod(resultType, sampledImage, coordinates, operands); } } else { if (depthCompare) { if (explicitLod) - return m_module.opImageSampleDrefExplicitLod(resultType, sampledImage, coordinates, reference, operands); + val = m_module.opImageSampleDrefExplicitLod(resultType, sampledImage, coordinates, reference, operands); else - return m_module.opImageSampleDrefImplicitLod(resultType, sampledImage, coordinates, reference, operands); + val = m_module.opImageSampleDrefImplicitLod(resultType, sampledImage, coordinates, reference, operands); } else { if (explicitLod) - return m_module.opImageSampleExplicitLod(resultType, sampledImage, coordinates, operands); + val = m_module.opImageSampleExplicitLod(resultType, sampledImage, coordinates, operands); else - return m_module.opImageSampleImplicitLod(resultType, sampledImage, coordinates, operands); + val = m_module.opImageSampleImplicitLod(resultType, sampledImage, coordinates, operands); } } + + + if (fetch4 && !depthCompare) { + uint32_t fetch4Val = m_module.opImageGather(resultType, sampledImage, coordinates, m_module.consti32(0), operands); + // B R G A swizzle... Funny D3D9 order. + const std::array indices = { 2, 0, 1, 3 }; + fetch4Val = m_module.opVectorShuffle(resultType, fetch4Val, fetch4Val, indices.size(), indices.data()); + + val = m_module.opSelect(resultType, fetch4, fetch4Val, val); + } + + return val; } diff --git a/src/dxso/dxso_compiler.h b/src/dxso/dxso_compiler.h index b46ff6822..1bf18be4e 100644 --- a/src/dxso/dxso_compiler.h +++ b/src/dxso/dxso_compiler.h @@ -157,6 +157,7 @@ namespace dxvk { uint32_t functionId = 0; uint32_t samplerTypeSpec = 0; uint32_t projectionSpec = 0; + uint32_t fetch4Spec = 0; ////////////// // Misc Types @@ -642,6 +643,7 @@ namespace dxvk { uint32_t sampledImage, uint32_t coordinates, uint32_t reference, + uint32_t fetch4, const SpirvImageOperands& operands); ///////////////////////////////