Skip to content

Commit

Permalink
[d3d9] Slightly clean up sampler slot handling
Browse files Browse the repository at this point in the history
  • Loading branch information
K0bin authored and doitsujin committed Feb 21, 2025
1 parent f7d5688 commit 94b48c1
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 10 deletions.
6 changes: 3 additions & 3 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,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 {
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

0 comments on commit 94b48c1

Please sign in to comment.