1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-19 05:52:11 +01:00

[d3d9] Don't bind textures if texture type doesnt match

This commit is contained in:
Robin Kertels 2024-12-08 22:56:07 +01:00 committed by Philip Rebohle
parent 67f4ec73aa
commit 65843aa016
9 changed files with 116 additions and 15 deletions

View File

@ -319,7 +319,7 @@ namespace dxvk {
return std::exchange(m_transitionedToHazardLayout, true);
}
D3DRESOURCETYPE GetType() {
D3DRESOURCETYPE GetType() const {
return m_type;
}
@ -441,6 +441,10 @@ namespace dxvk {
static VkImageType GetImageTypeFromResourceType(
D3DRESOURCETYPE Dimension);
static VkImageViewType GetImageViewTypeFromResourceType(
D3DRESOURCETYPE Dimension,
UINT Layer);
/**
* \brief Tracks sequence number for a given subresource
*
@ -553,10 +557,6 @@ namespace dxvk {
void ExportImageInfo();
static VkImageViewType GetImageViewTypeFromResourceType(
D3DRESOURCETYPE Dimension,
UINT Layer);
};
}

View File

@ -3372,10 +3372,17 @@ namespace dxvk {
BindShader<DxsoProgramTypes::VertexShader>(GetCommonShader(shader));
m_vsShaderMasks = newShader->GetShaderMask();
UpdateTextureTypeMismatchesForShader(newShader, m_vsShaderMasks.samplerMask, caps::MaxTexturesPS + 1);
}
else
else {
m_vsShaderMasks = D3D9ShaderMasks();
// Fixed function vertex shaders don't support sampling textures.
m_dirtyTextures = m_vsShaderMasks.samplerMask & m_mismatchingTextureTypes;
m_mismatchingTextureTypes &= ~m_vsShaderMasks.samplerMask;
}
m_flags.set(D3D9DeviceFlag::DirtyInputLayout);
return D3D_OK;
@ -3730,6 +3737,8 @@ namespace dxvk {
BindShader<DxsoProgramTypes::PixelShader>(newShader);
newShaderMasks = newShader->GetShaderMask();
UpdateTextureTypeMismatchesForShader(newShader, newShaderMasks.samplerMask, 0);
}
else {
// TODO: What fixed function textures are in use?
@ -3737,6 +3746,10 @@ namespace dxvk {
// The RT output is always 0 for fixed function.
newShaderMasks = FixedFunctionMask;
// Fixed function always uses spec constants to decide the texture type.
m_dirtyTextures = newShaderMasks.samplerMask & m_mismatchingTextureTypes;
m_mismatchingTextureTypes &= ~newShaderMasks.samplerMask;
}
// If we have any RTs we would have bound to the the FB
@ -4341,12 +4354,12 @@ namespace dxvk {
const uint32_t textureType = newTexture != nullptr
? uint32_t(newTexture->GetType() - D3DRTYPE_TEXTURE)
: 0;
// There are 4 texture types, so we need 2 bits.
// There are 3 texture types, so we need 2 bits.
const uint32_t offset = StateSampler * 2;
const uint32_t textureBitMask = 0b11u << offset;
const uint32_t textureBits = textureType << offset;
// In fixed function shaders and SM < 3 we put the type mask
// In fixed function shaders and SM < 2 we put the type mask
// into a spec constant to select the used sampler type.
m_textureTypes &= ~textureBitMask;
m_textureTypes |= textureBits;
@ -6123,11 +6136,12 @@ namespace dxvk {
inline void D3D9DeviceEx::UpdateTextureBitmasks(uint32_t index, DWORD combinedUsage) {
const uint32_t bit = 1 << index;
m_activeTextureRTs &= ~bit;
m_activeTextureDSs &= ~bit;
m_activeTextures &= ~bit;
m_activeTexturesToUpload &= ~bit;
m_activeTexturesToGen &= ~bit;
m_activeTextureRTs &= ~bit;
m_activeTextureDSs &= ~bit;
m_activeTextures &= ~bit;
m_activeTexturesToUpload &= ~bit;
m_activeTexturesToGen &= ~bit;
m_mismatchingTextureTypes &= ~bit;
auto tex = GetCommonTexture(m_state.textures[index]);
if (tex != nullptr) {
@ -6168,6 +6182,8 @@ namespace dxvk {
if (unlikely(m_fetch4Enabled & bit))
UpdateActiveFetch4(index);
UpdateTextureTypeMismatchesForTexture(index);
} else {
if (unlikely(m_fetch4 & bit))
UpdateActiveFetch4(index);
@ -6322,6 +6338,66 @@ namespace dxvk {
}
void D3D9DeviceEx::UpdateTextureTypeMismatchesForShader(const D3D9CommonShader* shader, uint32_t shaderSamplerMask, uint32_t shaderSamplerOffset) {
if (unlikely(shader->GetInfo().majorVersion() < 2)) {
// SM 1 shaders don't define the texture type in the shader.
// We always use spec constants for those.
m_dirtyTextures = shaderSamplerMask & m_mismatchingTextureTypes;
m_mismatchingTextureTypes &= ~shaderSamplerMask;
return;
}
for (uint32_t i : bit::BitMask(shaderSamplerMask)) {
const D3D9CommonTexture* texture = GetCommonTexture(m_state.textures[i]);
if (unlikely(texture == nullptr)) {
// Unbound textures are not mismatching texture types
m_dirtyTextures |= m_mismatchingTextureTypes & (1 << i);
m_mismatchingTextureTypes &= ~(1 << i);
continue;
}
VkImageViewType boundViewType = D3D9CommonTexture::GetImageViewTypeFromResourceType(texture->GetType(), D3D9CommonTexture::AllLayers);
VkImageViewType shaderViewType = shader->GetImageViewType(i - shaderSamplerOffset);
if (unlikely(boundViewType != shaderViewType)) {
m_dirtyTextures |= 1 << i;
m_mismatchingTextureTypes |= 1 << i;
} else {
// The texture type is no longer mismatching, make sure we bind the texture now.
m_dirtyTextures |= m_mismatchingTextureTypes & (1 << i);
m_mismatchingTextureTypes &= ~(1 << i);
}
}
}
void D3D9DeviceEx::UpdateTextureTypeMismatchesForTexture(uint32_t stateSampler) {
uint32_t shaderTextureIndex;
const D3D9CommonShader* shader;
if (unlikely(stateSampler > caps::MaxTexturesPS + 1)) {
shader = GetCommonShader(m_state.vertexShader);
shaderTextureIndex = stateSampler - caps::MaxTexturesPS - 1;
} else {
shader = GetCommonShader(m_state.pixelShader);
shaderTextureIndex = stateSampler;
}
if (unlikely(shader == nullptr || shader->GetInfo().majorVersion() < 2)) {
return;
}
const D3D9CommonTexture* tex = GetCommonTexture(m_state.textures[stateSampler]);
VkImageViewType boundViewType = D3D9CommonTexture::GetImageViewTypeFromResourceType(tex->GetType(), D3D9CommonTexture::AllLayers);
VkImageViewType shaderViewType = shader->GetImageViewType(shaderTextureIndex);
// D3D9 does not have 1D textures. The value of VIEW_TYPE_1D is 0
// which is the default when there is no declaration for the type.
bool shaderUsesTexture = shaderViewType != VkImageViewType(0);
if (unlikely(boundViewType != shaderViewType && shaderUsesTexture)) {
const uint32_t samplerBit = 1u << stateSampler;
m_mismatchingTextureTypes |= 1 << samplerBit;
}
}
void D3D9DeviceEx::GenerateTextureMips(uint32_t mask) {
for (uint32_t texIdx : bit::BitMask(mask)) {
// Guaranteed to not be nullptr...
@ -7056,8 +7132,8 @@ namespace dxvk {
void D3D9DeviceEx::UndirtyTextures(uint32_t usedMask) {
const uint32_t activeMask = usedMask & m_activeTextures;
const uint32_t inactiveMask = usedMask & ~m_activeTextures;
const uint32_t activeMask = usedMask & (m_activeTextures & ~m_mismatchingTextureTypes);
const uint32_t inactiveMask = usedMask & (~m_activeTextures | m_mismatchingTextureTypes);
for (uint32_t i : bit::BitMask(activeMask))
BindTexture(i);

View File

@ -817,6 +817,10 @@ namespace dxvk {
void UpdateActiveFetch4(uint32_t stateSampler);
void UpdateTextureTypeMismatchesForShader(const D3D9CommonShader* shader, uint32_t shaderSamplerMask, uint32_t shaderSamplerOffset);
void UpdateTextureTypeMismatchesForTexture(uint32_t stateSampler);
void UploadManagedTexture(D3D9CommonTexture* pResource);
void UploadManagedTextures(uint32_t mask);
@ -1461,6 +1465,7 @@ namespace dxvk {
uint32_t m_drefClamp = 0;
uint32_t m_cubeTextures = 0;
uint32_t m_textureTypes = 0;
uint32_t m_mismatchingTextureTypes = 0;
uint32_t m_projectionBitfield = 0;
uint32_t m_dirtySamplerStates = 0;

View File

@ -57,6 +57,7 @@ namespace dxvk {
m_shader = pModule->compile(*pDxsoModuleInfo, name, AnalysisInfo, constantLayout);
m_isgn = pModule->isgn();
m_usedSamplers = pModule->usedSamplers();
m_textureTypes = pModule->textureTypes();
// Shift up these sampler bits so we can just
// do an or per-draw in the device.

View File

@ -54,11 +54,18 @@ namespace dxvk {
uint32_t GetMaxDefinedConstant() const { return m_maxDefinedConst; }
VkImageViewType GetImageViewType(uint32_t samplerSlot) const {
const uint32_t offset = samplerSlot * 2;
const uint32_t mask = 0b11;
return static_cast<VkImageViewType>((m_textureTypes >> offset) & mask);
}
private:
DxsoIsgn m_isgn;
uint32_t m_usedSamplers;
uint32_t m_usedRTs;
uint32_t m_textureTypes;
DxsoProgramInfo m_info;
DxsoShaderMetaInfo m_meta;

View File

@ -41,6 +41,7 @@ namespace dxvk {
m_usedSamplers = 0;
m_usedRTs = 0;
m_textureTypes = 0;
m_rRegs.reserve(DxsoMaxTempRegs);
for (uint32_t i = 0; i < m_rRegs.size(); i++)
@ -762,6 +763,10 @@ namespace dxvk {
// We could also be depth compared!
DclSampler(idx, binding, samplerType, true, implicit);
}
const uint32_t offset = idx * 2;
uint32_t textureBits = uint32_t(viewType);
m_textureTypes |= textureBits << offset;
}
else {
// Could be any of these!

View File

@ -248,6 +248,7 @@ namespace dxvk {
uint32_t usedSamplers() const { return m_usedSamplers; }
uint32_t usedRTs() const { return m_usedRTs; }
uint32_t maxDefinedConstant() const { return m_maxDefinedConstant; }
uint32_t textureTypes() const { return m_textureTypes; }
private:
@ -358,6 +359,8 @@ namespace dxvk {
uint32_t m_usedSamplers;
uint32_t m_usedRTs;
uint32_t m_textureTypes;
uint32_t m_specUbo = 0;
uint32_t m_rsBlock = 0;

View File

@ -38,6 +38,7 @@ namespace dxvk {
m_constants = compiler->constants();
m_maxDefinedConst = compiler->maxDefinedConstant();
m_usedSamplers = compiler->usedSamplers();
m_textureTypes = compiler->textureTypes();
compiler->finalize();

View File

@ -61,6 +61,8 @@ namespace dxvk {
uint32_t maxDefinedConstant() { return m_maxDefinedConst; }
uint32_t textureTypes() { return m_textureTypes; }
private:
void runCompiler(
@ -77,6 +79,7 @@ namespace dxvk {
DxsoIsgn m_isgn;
uint32_t m_usedSamplers;
uint32_t m_usedRTs;
uint32_t m_textureTypes;
DxsoShaderMetaInfo m_meta;
uint32_t m_maxDefinedConst;