Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stalker texture type fix #4704

Merged
merged 2 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/d3d9/d3d9_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3387,7 +3387,7 @@ namespace dxvk {
BindShader<DxsoProgramTypes::VertexShader>(GetCommonShader(shader));
m_vsShaderMasks = newShader->GetShaderMask();

UpdateTextureTypeMismatchesForShader(newShader, m_vsShaderMasks.samplerMask, caps::MaxTexturesPS + 1);
UpdateTextureTypeMismatchesForShader(newShader, m_vsShaderMasks.samplerMask, FirstVSSamplerSlot);
}
else {
m_vsShaderMasks = D3D9ShaderMasks();
Expand Down Expand Up @@ -6415,12 +6415,15 @@ namespace dxvk {
void D3D9DeviceEx::UpdateTextureTypeMismatchesForTexture(uint32_t stateSampler) {
uint32_t shaderTextureIndex;
const D3D9CommonShader* shader;
if (unlikely(stateSampler > caps::MaxTexturesPS + 1)) {
if (likely(IsPSSampler(stateSampler))) {
shader = GetCommonShader(m_state.pixelShader);
shaderTextureIndex = stateSampler;
} else if (unlikely(IsVSSampler(stateSampler))) {
shader = GetCommonShader(m_state.vertexShader);
shaderTextureIndex = stateSampler - caps::MaxTexturesPS - 1;
} else {
shader = GetCommonShader(m_state.pixelShader);
shaderTextureIndex = stateSampler;
// Do not type check the fixed function displacement map texture.
return;
}

if (unlikely(shader == nullptr || shader->GetInfo().majorVersion() < 2 || m_d3d9Options.forceSamplerTypeSpecConstants)) {
Expand Down
58 changes: 58 additions & 0 deletions src/d3d9/d3d9_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/d3d9/d3d9_shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
4 changes: 2 additions & 2 deletions src/d3d9/d3d9_stateblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
80 changes: 78 additions & 2 deletions src/d3d9/d3d9_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -54,20 +59,82 @@ 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);

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<DxsoProgramType, DWORD> Shader stage that it belongs to and the relative sampler index
*/
inline std::pair<DxsoProgramType, DWORD> 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<DxsoProgramType, DWORD> Shader stage that it belongs to and the relative sampler index
*/
inline std::pair<DxsoProgramType, DWORD> RemapSamplerShader(DWORD Sampler) {
Sampler = RemapSamplerState(Sampler);

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions src/dxso/dxso_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down