1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-20 19:54:19 +01:00

[d3d9+dxso] Rely on robustness for unset HW VS & PS constants

This commit is contained in:
Robin Kertels 2021-09-10 00:47:01 +02:00 committed by Joshie
parent 869f75895c
commit 530f87f158
2 changed files with 63 additions and 19 deletions

View File

@ -78,22 +78,28 @@ namespace dxvk {
m_dxsoOptions = DxsoOptions(this, m_d3d9Options);
const bool supportsRobustness2 = m_dxvkDevice->features().extRobustness2.robustBufferAccess2;
bool useRobustConstantAccess = canSWVP && supportsRobustness2;
bool useRobustConstantAccess = supportsRobustness2;
if (useRobustConstantAccess) {
m_robustSSBOAlignment = m_dxvkDevice->properties().extRobustness2.robustStorageBufferAccessSizeAlignment;
m_robustUBOAlignment = m_dxvkDevice->properties().extRobustness2.robustUniformBufferAccessSizeAlignment;
const uint32_t floatBufferAlignment = m_dxsoOptions.vertexFloatConstantBufferAsSSBO ? m_robustSSBOAlignment : m_robustUBOAlignment;
useRobustConstantAccess &= m_vsLayout.floatSize() % floatBufferAlignment == 0;
useRobustConstantAccess &= m_vsLayout.intSize() % m_robustUBOAlignment == 0;
useRobustConstantAccess &= m_vsLayout.bitmaskSize() % m_robustUBOAlignment == 0;
if (canSWVP) {
const uint32_t floatBufferAlignment = m_dxsoOptions.vertexFloatConstantBufferAsSSBO ? m_robustSSBOAlignment : m_robustUBOAlignment;
useRobustConstantAccess &= m_vsLayout.floatSize() % floatBufferAlignment == 0;
useRobustConstantAccess &= m_vsLayout.intSize() % m_robustUBOAlignment == 0;
useRobustConstantAccess &= m_vsLayout.bitmaskSize() % m_robustUBOAlignment == 0;
} else {
useRobustConstantAccess &= m_vsLayout.totalSize() % m_robustUBOAlignment == 0;
}
useRobustConstantAccess &= m_psLayout.totalSize() % m_robustUBOAlignment == 0;
}
if (!useRobustConstantAccess) {
m_vsFloatConstsCount = m_vsLayout.floatCount;
m_vsIntConstsCount = m_vsLayout.intCount;
m_vsBoolConstsCount = m_vsLayout.boolCount;
m_psFloatConstsCount = m_psLayout.floatCount;
if (supportsRobustness2 && canSWVP) {
if (supportsRobustness2) {
Logger::warn("Disabling robust constant buffer access because of alignment.");
}
}
@ -4836,6 +4842,11 @@ namespace dxvk {
DxvkBufferSlice(cBuffer, 0, cBuffer->info().size));
});
if (ShaderStage == DxsoProgramType::PixelShader)
m_boundPSConstantsBufferSize = buffer->info().size;
else
m_boundVSConstantsBufferSize = buffer->info().size;
return buffer;
}
@ -4954,7 +4965,11 @@ namespace dxvk {
template <DxsoProgramType ShaderStage, typename HardwareLayoutType, typename SoftwareLayoutType, typename ShaderType>
inline void D3D9DeviceEx::UploadConstantSet(const SoftwareLayoutType& Src, const ShaderType& Shader) {
inline void D3D9DeviceEx::UploadConstantSet(const SoftwareLayoutType& Src, const D3D9ConstantLayout& Layout, const ShaderType& Shader) {
/*
* We just copy the float constants that have been set by the application and rely on robustness
* to return 0 on OOB reads.
*/
D3D9ConstantSets& constSet = m_consts[ShaderStage];
if (!constSet.dirty)
@ -4962,6 +4977,29 @@ namespace dxvk {
constSet.dirty = false;
const uint32_t floatCount = ShaderStage == DxsoProgramType::VertexShader ? m_vsFloatConstsCount : m_psFloatConstsCount;
const uint32_t intRange = caps::MaxOtherConstants * sizeof(Vector4i);
const uint32_t intDataSize = constSet.meta.maxConstIndexI * sizeof(Vector4i);
uint32_t floatDataSize = std::min(constSet.meta.maxConstIndexF, floatCount) * sizeof(Vector4);
const uint32_t minSize = std::max(m_robustUBOAlignment, 64u); // Make sure we do not recreate the buffer because the new one has to be a tiny bit larger
const uint32_t bufferSize = std::max(floatDataSize + intRange, minSize);
floatDataSize = bufferSize - intRange; // Read additional floats for padding so we don't end up with garbage data
VkDeviceSize& boundConstantBufferSize = ShaderStage == DxsoProgramType::VertexShader ? m_boundVSConstantsBufferSize : m_boundPSConstantsBufferSize;
if (boundConstantBufferSize != bufferSize) {
constexpr uint32_t slotId = computeResourceSlotId(ShaderStage, DxsoBindingType::ConstantBuffer, 0);
EmitCs([
cBuffer = constSet.buffer,
cSlotId = slotId,
cSize = bufferSize
] (DxvkContext* ctx) {
ctx->bindResourceBuffer(cSlotId,
DxvkBufferSlice(cBuffer, 0, cSize));
});
boundConstantBufferSize = bufferSize;
}
DxvkBufferSliceHandle slice = constSet.buffer->allocSlice();
EmitCs([
@ -4973,18 +5011,20 @@ namespace dxvk {
auto* dst = reinterpret_cast<HardwareLayoutType*>(slice.mapPtr);
if (constSet.meta.maxConstIndexF)
std::memcpy(dst->fConsts, Src.fConsts, constSet.meta.maxConstIndexF * sizeof(Vector4));
if (constSet.meta.maxConstIndexI)
std::memcpy(dst->iConsts, Src.iConsts, constSet.meta.maxConstIndexI * sizeof(Vector4i));
if (constSet.meta.maxConstIndexI != 0)
std::memcpy(dst->iConsts, Src.iConsts, intDataSize);
if (constSet.meta.maxConstIndexF != 0)
std::memcpy(dst->fConsts, Src.fConsts, floatDataSize);
if (constSet.meta.needsConstantCopies) {
Vector4* data = reinterpret_cast<Vector4*>(dst->fConsts);
auto& shaderConsts = GetCommonShader(Shader)->GetConstants();
for (const auto& constant : shaderConsts)
data[constant.uboIdx] = *reinterpret_cast<const Vector4*>(constant.float32);
for (const auto& constant : shaderConsts) {
if (constant.uboIdx < constSet.meta.maxConstIndexF)
data[constant.uboIdx] = *reinterpret_cast<const Vector4*>(constant.float32);
}
}
}
@ -4995,9 +5035,9 @@ namespace dxvk {
if (CanSWVP())
return UploadSoftwareConstantSet(m_state.vsConsts, m_vsLayout);
else
return UploadConstantSet<ShaderStage, D3D9ShaderConstantsVSHardware>(m_state.vsConsts, m_state.vertexShader);
return UploadConstantSet<ShaderStage, D3D9ShaderConstantsVSHardware>(m_state.vsConsts, m_vsLayout, m_state.vertexShader);
} else {
return UploadConstantSet<ShaderStage, D3D9ShaderConstantsPS> (m_state.psConsts, m_state.pixelShader);
return UploadConstantSet<ShaderStage, D3D9ShaderConstantsPS> (m_state.psConsts, m_psLayout, m_state.pixelShader);
}
}
@ -6392,6 +6432,10 @@ namespace dxvk {
} else /* if constexpr (ConstantType == D3D9ConstantType::Bool) */ {
m_vsBoolConstsCount = std::max(m_vsBoolConstsCount, StartRegister + Count);
}
} else {
if constexpr (ConstantType == D3D9ConstantType::Float) {
m_psFloatConstsCount = std::max(m_psFloatConstsCount, StartRegister + Count);
}
}
if constexpr (ConstantType != D3D9ConstantType::Bool) {

View File

@ -811,16 +811,13 @@ namespace dxvk {
void BindAlphaTestState();
template <DxsoProgramType ShaderStage, typename HardwareLayoutType, typename SoftwareLayoutType, typename ShaderType>
inline void UploadHardwareConstantSet(void* pData, const SoftwareLayoutType& Src, const ShaderType& Shader);
template <typename SoftwareLayoutType>
inline void UploadSoftwareConstantSet(const SoftwareLayoutType& Src, const D3D9ConstantLayout& Layout);
inline void CopySoftwareConstants(DxsoConstantBuffers cBufferTarget, Rc<DxvkBuffer>& dstBuffer, const void* src, uint32_t copySize, bool useSSBO);
template <DxsoProgramType ShaderStage, typename HardwareLayoutType, typename SoftwareLayoutType, typename ShaderType>
inline void UploadConstantSet(const SoftwareLayoutType& Src, const ShaderType& Shader);
inline void UploadConstantSet(const SoftwareLayoutType& Src, const D3D9ConstantLayout& Layout, const ShaderType& Shader);
template <DxsoProgramType ShaderStage>
void UploadConstants();
@ -1231,6 +1228,9 @@ namespace dxvk {
uint32_t m_vsFloatConstsCount = 0;
uint32_t m_vsIntConstsCount = 0;
uint32_t m_vsBoolConstsCount = 0;
uint32_t m_psFloatConstsCount = 0;
VkDeviceSize m_boundVSConstantsBufferSize = 0;
VkDeviceSize m_boundPSConstantsBufferSize = 0;
D3D9ConstantLayout m_vsLayout;
D3D9ConstantLayout m_psLayout;