mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +01:00
[dxbc] Use SSBOs for dynamically indexed constant buffers if needed
SSBOs are tightly bound-checked on all Nvidia GPUs, so this allows for a more accurate workaround for games relying on OOB access behaviour.
This commit is contained in:
parent
68760f5b20
commit
3d213efe53
@ -34,7 +34,8 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pDesc->BindFlags & D3D11_BIND_CONSTANT_BUFFER) {
|
if (pDesc->BindFlags & D3D11_BIND_CONSTANT_BUFFER) {
|
||||||
info.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
info.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
|
||||||
|
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||||
info.stages |= m_device->GetEnabledShaderStages();
|
info.stages |= m_device->GetEnabledShaderStages();
|
||||||
info.access |= VK_ACCESS_UNIFORM_READ_BIT;
|
info.access |= VK_ACCESS_UNIFORM_READ_BIT;
|
||||||
}
|
}
|
||||||
|
@ -755,16 +755,20 @@ namespace dxvk {
|
|||||||
// (1) Number of constants in the buffer
|
// (1) Number of constants in the buffer
|
||||||
const uint32_t bufferId = ins.dst[0].idx[0].offset;
|
const uint32_t bufferId = ins.dst[0].idx[0].offset;
|
||||||
const uint32_t elementCount = ins.dst[0].idx[1].offset;
|
const uint32_t elementCount = ins.dst[0].idx[1].offset;
|
||||||
|
|
||||||
|
bool asSsbo = m_moduleInfo.options.dynamicIndexedConstantBufferAsSsbo
|
||||||
|
&& ins.controls.accessType() == DxbcConstantBufferAccessType::DynamicallyIndexed;
|
||||||
|
|
||||||
this->emitDclConstantBufferVar(bufferId, elementCount,
|
this->emitDclConstantBufferVar(bufferId, elementCount,
|
||||||
str::format("cb", bufferId).c_str());
|
str::format("cb", bufferId).c_str(), asSsbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitDclConstantBufferVar(
|
void DxbcCompiler::emitDclConstantBufferVar(
|
||||||
uint32_t regIdx,
|
uint32_t regIdx,
|
||||||
uint32_t numConstants,
|
uint32_t numConstants,
|
||||||
const char* name) {
|
const char* name,
|
||||||
|
bool asSsbo) {
|
||||||
// Uniform buffer data is stored as a fixed-size array
|
// Uniform buffer data is stored as a fixed-size array
|
||||||
// of 4x32-bit vectors. SPIR-V requires explicit strides.
|
// of 4x32-bit vectors. SPIR-V requires explicit strides.
|
||||||
const uint32_t arrayType = m_module.defArrayTypeUnique(
|
const uint32_t arrayType = m_module.defArrayTypeUnique(
|
||||||
@ -776,7 +780,9 @@ namespace dxvk {
|
|||||||
// struct and decorate that struct as a block.
|
// struct and decorate that struct as a block.
|
||||||
const uint32_t structType = m_module.defStructTypeUnique(1, &arrayType);
|
const uint32_t structType = m_module.defStructTypeUnique(1, &arrayType);
|
||||||
|
|
||||||
m_module.decorateBlock (structType);
|
m_module.decorate(structType, asSsbo
|
||||||
|
? spv::DecorationBufferBlock
|
||||||
|
: spv::DecorationBlock);
|
||||||
m_module.memberDecorateOffset(structType, 0, 0);
|
m_module.memberDecorateOffset(structType, 0, 0);
|
||||||
|
|
||||||
m_module.setDebugName (structType, str::format(name, "_t").c_str());
|
m_module.setDebugName (structType, str::format(name, "_t").c_str());
|
||||||
@ -796,7 +802,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_module.decorateDescriptorSet(varId, 0);
|
m_module.decorateDescriptorSet(varId, 0);
|
||||||
m_module.decorateBinding(varId, bindingId);
|
m_module.decorateBinding(varId, bindingId);
|
||||||
|
|
||||||
|
if (asSsbo)
|
||||||
|
m_module.decorate(varId, spv::DecorationNonWritable);
|
||||||
|
|
||||||
// Declare a specialization constant which will
|
// Declare a specialization constant which will
|
||||||
// store whether or not the resource is bound.
|
// store whether or not the resource is bound.
|
||||||
const uint32_t specConstId = m_module.specConstBool(true);
|
const uint32_t specConstId = m_module.specConstBool(true);
|
||||||
@ -813,7 +822,9 @@ namespace dxvk {
|
|||||||
// Store descriptor info for the shader interface
|
// Store descriptor info for the shader interface
|
||||||
DxvkResourceSlot resource;
|
DxvkResourceSlot resource;
|
||||||
resource.slot = bindingId;
|
resource.slot = bindingId;
|
||||||
resource.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
resource.type = asSsbo
|
||||||
|
? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
|
||||||
|
: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
|
resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
|
||||||
resource.access = VK_ACCESS_UNIFORM_READ_BIT;
|
resource.access = VK_ACCESS_UNIFORM_READ_BIT;
|
||||||
m_resourceSlots.push_back(resource);
|
m_resourceSlots.push_back(resource);
|
||||||
@ -1505,7 +1516,8 @@ namespace dxvk {
|
|||||||
void DxbcCompiler::emitDclImmediateConstantBufferUbo(
|
void DxbcCompiler::emitDclImmediateConstantBufferUbo(
|
||||||
uint32_t dwordCount,
|
uint32_t dwordCount,
|
||||||
const uint32_t* dwordArray) {
|
const uint32_t* dwordArray) {
|
||||||
this->emitDclConstantBufferVar(Icb_BindingSlotId, dwordCount / 4, "icb");
|
this->emitDclConstantBufferVar(Icb_BindingSlotId, dwordCount / 4, "icb",
|
||||||
|
m_moduleInfo.options.dynamicIndexedConstantBufferAsSsbo);
|
||||||
m_immConstData = DxvkShaderConstData(dwordCount, dwordArray);
|
m_immConstData = DxvkShaderConstData(dwordCount, dwordArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,7 +575,8 @@ namespace dxvk {
|
|||||||
void emitDclConstantBufferVar(
|
void emitDclConstantBufferVar(
|
||||||
uint32_t regIdx,
|
uint32_t regIdx,
|
||||||
uint32_t numConstants,
|
uint32_t numConstants,
|
||||||
const char* name);
|
const char* name,
|
||||||
|
bool asSsbo);
|
||||||
|
|
||||||
void emitDclSampler(
|
void emitDclSampler(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
@ -41,7 +41,7 @@ namespace dxvk {
|
|||||||
zeroInitWorkgroupMemory = options.zeroInitWorkgroupMemory;
|
zeroInitWorkgroupMemory = options.zeroInitWorkgroupMemory;
|
||||||
|
|
||||||
if (DxvkGpuVendor(devInfo.core.properties.vendorID) != DxvkGpuVendor::Amd)
|
if (DxvkGpuVendor(devInfo.core.properties.vendorID) != DxvkGpuVendor::Amd)
|
||||||
constantBufferRangeCheck = options.constantBufferRangeCheck;
|
dynamicIndexedConstantBufferAsSsbo = options.constantBufferRangeCheck;
|
||||||
|
|
||||||
// Disable early discard on RADV (with LLVM) due to GPU hangs
|
// Disable early discard on RADV (with LLVM) due to GPU hangs
|
||||||
// Disable early discard on Nvidia because it may hurt performance
|
// Disable early discard on Nvidia because it may hurt performance
|
||||||
|
@ -39,6 +39,10 @@ namespace dxvk {
|
|||||||
// Fixes issues in some games, breaks others.
|
// Fixes issues in some games, breaks others.
|
||||||
bool constantBufferRangeCheck = false;
|
bool constantBufferRangeCheck = false;
|
||||||
|
|
||||||
|
/// Implement dynamically indexed uniform buffers
|
||||||
|
/// with storage buffers for tight bounds checking
|
||||||
|
bool dynamicIndexedConstantBufferAsSsbo = false;
|
||||||
|
|
||||||
/// Clear thread-group shared memory to zero
|
/// Clear thread-group shared memory to zero
|
||||||
bool zeroInitWorkgroupMemory = false;
|
bool zeroInitWorkgroupMemory = false;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user