diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index a984cee00ed..f704723db7a 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -3387,7 +3387,7 @@ namespace dxvk { BindShader(GetCommonShader(shader)); m_vsShaderMasks = newShader->GetShaderMask(); - UpdateTextureTypeMismatchesForShader(newShader, m_vsShaderMasks.samplerMask, caps::MaxTexturesPS + 1); + UpdateTextureTypeMismatchesForShader(newShader, m_vsShaderMasks.samplerMask, FirstVSSamplerSlot); } else { m_vsShaderMasks = D3D9ShaderMasks(); @@ -6415,10 +6415,10 @@ namespace dxvk { void D3D9DeviceEx::UpdateTextureTypeMismatchesForTexture(uint32_t stateSampler) { uint32_t shaderTextureIndex; const D3D9CommonShader* shader; - if (likely(stateSampler <= caps::MaxTexturesPS)) { + if (likely(IsPSSampler(stateSampler))) { shader = GetCommonShader(m_state.pixelShader); shaderTextureIndex = stateSampler; - } else if (unlikely(stateSampler >= caps::MaxTexturesPS + 1)) { + } else if (unlikely(IsVSSampler(stateSampler))) { shader = GetCommonShader(m_state.vertexShader); shaderTextureIndex = stateSampler - caps::MaxTexturesPS - 1; } else { diff --git a/src/d3d9/d3d9_device.h b/src/d3d9/d3d9_device.h index cec35f3d49f..3a2a4184dcd 100644 --- a/src/d3d9/d3d9_device.h +++ b/src/d3d9/d3d9_device.h @@ -653,15 +653,41 @@ namespace dxvk { const D3DDISPLAYMODEEX* pFullscreenDisplayMode, IDirect3DSwapChain9** ppSwapChain); + /** + * @brief Sets the given sampler state + * + * @param StateSampler Sampler index (according to our internal way of storing samplers) + * @param Type Sampler state type to change + * @param Value State value + */ HRESULT SetStateSamplerState( DWORD StateSampler, D3DSAMPLERSTATETYPE Type, DWORD Value); + /** + * @brief Sets the given sampler texture + * + * @param StateSampler Sampler index (according to our internal way of storing samplers) + * @param pTexture Texture to use + */ HRESULT SetStateTexture(DWORD StateSampler, IDirect3DBaseTexture9* pTexture); + /** + * @brief Sets the transform for the given sampler + * + * @param idx Sampler index (according to our internal way of storing samplers) + * @param pMatrix Transform matrix + */ HRESULT SetStateTransform(uint32_t idx, const D3DMATRIX* pMatrix); + /** + * @brief Sets the fixed function texture processing state + * + * @param Stage Sampler index (according to our internal way of storing samplers) + * @param Type Fixed function texture stage type + * @param Value Value for the state + */ HRESULT SetStateTextureStageState( DWORD Stage, D3D9TextureStageStateTypes Type, @@ -818,8 +844,40 @@ namespace dxvk { void UpdateActiveFetch4(uint32_t stateSampler); + /** + * @brief Sets the mismatching texture type bits for all samplers if necessary. + * + * This function will check all samplers the shader uses and set the set the mismatching texture type bit for the given sampler if it does not + * match the texture type expected by the respective shader. + * + * It will *not* unset the bit if the texture type does match. + * + * @param stateSampler Sampler index (according to our internal way of storing samplers) + */ + + /** + * @brief Sets the mismatching texture type bits for all samplers if necessary. + * + * This function will check all samplers the shader uses and set the set the mismatching texture type bit for the given sampler if it does not + * match the texture type expected by the shader. + * + * @param shader The shader + * @param shaderSamplerMask Mask of all samplers that the shader uses (according to our internal way of storing samplers) + * @param shaderSamplerOffset First index of the shader's samplers according to our internal way of storing samplers. + * Used to transform the sampler indices that are relative to the entire pipeline to ones relative to the shader. + */ void UpdateTextureTypeMismatchesForShader(const D3D9CommonShader* shader, uint32_t shaderSamplerMask, uint32_t shaderSamplerOffset); + /** + * @brief Sets the mismatching texture type bit for the given sampler. + * + * This function will set the mismatching texture type bit for the given sampler if it does not + * match the texture type expected by the respective shader. + * + * It will *not* unset the bit if the texture type does match. + * + * @param stateSampler Sampler index (according to our internal way of storing samplers) + */ void UpdateTextureTypeMismatchesForTexture(uint32_t stateSampler); void UploadManagedTexture(D3D9CommonTexture* pResource); diff --git a/src/d3d9/d3d9_shader.cpp b/src/d3d9/d3d9_shader.cpp index 6ab5df3d719..f8807e0cb01 100644 --- a/src/d3d9/d3d9_shader.cpp +++ b/src/d3d9/d3d9_shader.cpp @@ -63,7 +63,7 @@ namespace dxvk { // do an or per-draw in the device. // We shift by 17 because 16 ps samplers + 1 dmap (tess) if (ShaderStage == VK_SHADER_STAGE_VERTEX_BIT) - m_usedSamplers <<= caps::MaxTexturesPS + 1; + m_usedSamplers <<= FirstVSSamplerSlot; m_usedRTs = pModule->usedRTs(); diff --git a/src/d3d9/d3d9_stateblock.cpp b/src/d3d9/d3d9_stateblock.cpp index 8b62c1d58ab..ef8f76bb67c 100644 --- a/src/d3d9/d3d9_stateblock.cpp +++ b/src/d3d9/d3d9_stateblock.cpp @@ -436,7 +436,7 @@ namespace dxvk { void D3D9StateBlock::CapturePixelSamplerStates() { m_captures.flags.set(D3D9CapturedStateFlag::SamplerStates); - for (uint32_t i = 0; i < caps::MaxTexturesPS + 1; i++) { + for (uint32_t i = 0; i < FirstVSSamplerSlot; i++) { m_captures.samplers.set(i, true); m_captures.samplerStates[i].set(D3DSAMP_ADDRESSU, true); @@ -519,7 +519,7 @@ namespace dxvk { void D3D9StateBlock::CaptureVertexSamplerStates() { m_captures.flags.set(D3D9CapturedStateFlag::SamplerStates); - for (uint32_t i = caps::MaxTexturesPS + 1; i < SamplerCount; i++) { + for (uint32_t i = FirstVSSamplerSlot; i < SamplerCount; i++) { m_captures.samplers.set(i, true); m_captures.samplerStates[i].set(D3DSAMP_DMAPOFFSET, true); } diff --git a/src/d3d9/d3d9_util.h b/src/d3d9/d3d9_util.h index 76cd31a7cc6..4e920228254 100644 --- a/src/d3d9/d3d9_util.h +++ b/src/d3d9/d3d9_util.h @@ -44,6 +44,11 @@ namespace dxvk { } } + /** + * @brief Returns whether or not the sampler index is valid + * + * @param Sampler Sampler index (according to the API) + */ inline bool InvalidSampler(DWORD Sampler) { if (Sampler >= caps::MaxTexturesPS && Sampler < D3DDMAPSAMPLER) return true; @@ -54,6 +59,19 @@ namespace dxvk { return false; } + /** + * @brief The first sampler that belongs to the vertex shader according to our internal way of storing samplers + */ + constexpr uint32_t FirstVSSamplerSlot = caps::MaxTexturesPS + 1; + + /** + * @brief Remaps a sampler index by the API to an internal one + * + * Remaps the sampler index according to the way the API counts them to how we count and store them internally. + * + * @param Sampler Sampler index (according to API) + * @return DWORD Sampler index (according to our internal way of storing samplers) + */ inline DWORD RemapSamplerState(DWORD Sampler) { if (Sampler >= D3DDMAPSAMPLER) Sampler = caps::MaxTexturesPS + (Sampler - D3DDMAPSAMPLER); @@ -61,13 +79,62 @@ namespace dxvk { return Sampler; } + /** + * @brief Remaps the sampler from an index applying to the entire pipeline to one relative to the shader stage and returns the shader type + * + * The displacement map sampler will be treated as a 17th pixel shader sampler. + * + * @param Sampler Sampler index (according to our internal way of storing samplers) + * @return std::pair Shader stage that it belongs to and the relative sampler index + */ inline std::pair RemapStateSamplerShader(DWORD Sampler) { - if (Sampler >= caps::MaxTexturesPS + 1) - return std::make_pair(DxsoProgramTypes::VertexShader, Sampler - caps::MaxTexturesPS - 1); + if (Sampler >= FirstVSSamplerSlot) + return std::make_pair(DxsoProgramTypes::VertexShader, Sampler - FirstVSSamplerSlot); return std::make_pair(DxsoProgramTypes::PixelShader, Sampler); } + /** + * @brief Returns whether the sampler belongs to the vertex shader. + * + * The displacement map sampler is part of a fixed function feature, + * so it does not belong to the vertex shader. + * Use IsDMAPSampler to check for that. + * + * @param Sampler Sampler index (according to our internal way of storing samplers) + */ + inline bool IsVSSampler(uint32_t Sampler) { + return Sampler >= FirstVSSamplerSlot; + } + + /** + * @brief Returns whether the sampler belongs to the pixel shader. + * + * The displacement map sampler is part of a fixed function feature, + * so (unlike in RemapStateSamplerShader) it does not belong to the pixel shader. + * Use IsDMAPSampler to check for that. + * + * @param Sampler Sampler index (according to our internal way of storing samplers) + */ + inline bool IsPSSampler(uint32_t Sampler) { + return Sampler <= caps::MaxTexturesPS; + } + + /** + * @brief Returns whether the sampler is the displacement map sampler + * + * @param Sampler Sampler index (according to our internal way of storing samplers) + */ + inline bool IsDMAPSampler(uint32_t Sampler) { + return Sampler > caps::MaxTexturesPS; + } + + /** + * @brief Remaps the sampler from an index (counted according to the API) to one relative to the shader stage and returns the shader type + * + * @param Sampler Sampler index (according to the API) + * @return std::pair Shader stage that it belongs to and the relative sampler index + */ inline std::pair RemapSamplerShader(DWORD Sampler) { Sampler = RemapSamplerState(Sampler); @@ -243,6 +310,9 @@ namespace dxvk { uint32_t(offsets[1].y) > extent.height; } + /** + * @brief Mirrors D3DTEXTURESTAGESTATETYPE but starts at 0 + */ enum D3D9TextureStageStateTypes : uint32_t { DXVK_TSS_COLOROP = 0, @@ -272,6 +342,12 @@ namespace dxvk { constexpr uint32_t DXVK_TSS_TCI_CAMERASPACEREFLECTIONVECTOR = 0x00030000; constexpr uint32_t DXVK_TSS_TCI_SPHEREMAP = 0x00040000; + /** + * @brief Remaps a texture stage type by the API to an internal one + * + * @param Type Texture stage type according to the API + * @return D3D9TextureStageStateTypes Texture stage type according to our internal way of storing them + */ inline D3D9TextureStageStateTypes RemapTextureStageStateType(D3DTEXTURESTAGESTATETYPE Type) { return D3D9TextureStageStateTypes(Type - 1); } diff --git a/src/dxso/dxso_compiler.cpp b/src/dxso/dxso_compiler.cpp index 54c0f0543b3..1d7e1bf1db4 100644 --- a/src/dxso/dxso_compiler.cpp +++ b/src/dxso/dxso_compiler.cpp @@ -2965,7 +2965,7 @@ void DxsoCompiler::emitControlFlowGenericLoop( uint32_t lOffset = m_module.opAccessChain(m_module.defPointerType(float_t, spv::StorageClassUniform), m_ps.sharedState, 1, &index); lOffset = m_module.opLoad(float_t, lOffset); - + uint32_t zIndex = 2; uint32_t scale = m_module.opCompositeExtract(float_t, result.id, 1, &zIndex); scale = m_module.opFMul(float_t, scale, lScale); @@ -2980,7 +2980,7 @@ void DxsoCompiler::emitControlFlowGenericLoop( auto SampleType = [&](DxsoSamplerType samplerType) { uint32_t bitOffset = m_programInfo.type() == DxsoProgramTypes::VertexShader - ? samplerIdx + caps::MaxTexturesPS + 1 + ? samplerIdx + FirstVSSamplerSlot : samplerIdx; uint32_t isNull = m_spec.get(m_module, m_specUbo, SpecSamplerNull, bitOffset, 1);