1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-13 16:08:50 +01:00

[dxvk] Rework compute barrier handling to use common functions

Cleans up code a bit and should technically even make things a bit
more efficient.
This commit is contained in:
Philip Rebohle 2022-08-10 18:45:53 +02:00
parent 01014c1a2b
commit 11fbcd3131
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 31 additions and 93 deletions

View File

@ -1239,7 +1239,8 @@ namespace dxvk {
uint32_t y, uint32_t y,
uint32_t z) { uint32_t z) {
if (this->commitComputeState()) { if (this->commitComputeState()) {
this->commitComputeInitBarriers(); this->commitComputeBarriers<false>();
this->commitComputeBarriers<true>();
m_queryManager.beginQueries(m_cmd, m_queryManager.beginQueries(m_cmd,
VK_QUERY_TYPE_PIPELINE_STATISTICS); VK_QUERY_TYPE_PIPELINE_STATISTICS);
@ -1248,8 +1249,6 @@ namespace dxvk {
m_queryManager.endQueries(m_cmd, m_queryManager.endQueries(m_cmd,
VK_QUERY_TYPE_PIPELINE_STATISTICS); VK_QUERY_TYPE_PIPELINE_STATISTICS);
this->commitComputePostBarriers();
} }
m_cmd->addStatCtr(DxvkStatCounter::CmdDispatchCalls, 1); m_cmd->addStatCtr(DxvkStatCounter::CmdDispatchCalls, 1);
@ -1265,7 +1264,8 @@ namespace dxvk {
m_execBarriers.recordCommands(m_cmd); m_execBarriers.recordCommands(m_cmd);
if (this->commitComputeState()) { if (this->commitComputeState()) {
this->commitComputeInitBarriers(); this->commitComputeBarriers<false>();
this->commitComputeBarriers<true>();
m_queryManager.beginQueries(m_cmd, m_queryManager.beginQueries(m_cmd,
VK_QUERY_TYPE_PIPELINE_STATISTICS); VK_QUERY_TYPE_PIPELINE_STATISTICS);
@ -1277,8 +1277,6 @@ namespace dxvk {
m_queryManager.endQueries(m_cmd, m_queryManager.endQueries(m_cmd,
VK_QUERY_TYPE_PIPELINE_STATISTICS); VK_QUERY_TYPE_PIPELINE_STATISTICS);
this->commitComputePostBarriers();
m_execBarriers.accessBuffer(bufferSlice, m_execBarriers.accessBuffer(bufferSlice,
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
VK_ACCESS_INDIRECT_COMMAND_READ_BIT, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
@ -5429,37 +5427,38 @@ namespace dxvk {
} }
void DxvkContext::commitComputeInitBarriers() { template<bool DoEmit>
void DxvkContext::commitComputeBarriers() {
const auto& layout = m_state.cp.pipeline->getBindings()->layout(); const auto& layout = m_state.cp.pipeline->getBindings()->layout();
bool requiresBarrier = false; // Exit early if we're only checking for hazards and
// if the barrier set is empty, to avoid some overhead.
if (!DoEmit && !m_execBarriers.hasResourceBarriers())
return;
uint32_t index = 0; for (uint32_t i = 0; i < DxvkDescriptorSets::CsSetCount; i++) {
for (uint32_t i = 0; i < DxvkDescriptorSets::SetCount && !requiresBarrier; i++) {
uint32_t bindingCount = layout.getBindingCount(i); uint32_t bindingCount = layout.getBindingCount(i);
for (uint32_t j = 0; j < bindingCount && !requiresBarrier; j++) { for (uint32_t j = 0; j < bindingCount; j++) {
const DxvkBindingInfo& binding = layout.getBinding(i, j); const DxvkBindingInfo& binding = layout.getBinding(i, j);
const DxvkShaderResourceSlot& slot = m_rc[binding.resourceBinding]; const DxvkShaderResourceSlot& slot = m_rc[binding.resourceBinding];
DxvkAccessFlags dstAccess = DxvkBarrierSet::getAccessTypes(binding.access);
DxvkAccessFlags srcAccess = 0; DxvkAccessFlags srcAccess = 0;
switch (binding.descriptorType) { switch (binding.descriptorType) {
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
if (likely(slot.bufferSlice.length())) { if (likely(slot.bufferSlice.length())) {
srcAccess = m_execBarriers.getBufferAccess( srcAccess = this->checkBufferBarrier<DoEmit>(slot.bufferSlice,
slot.bufferSlice.getSliceHandle()); VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, binding.access);
} }
break; break;
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
if (likely(slot.bufferView != nullptr)) { if (likely(slot.bufferView != nullptr)) {
srcAccess = m_execBarriers.getBufferAccess( srcAccess = this->checkBufferViewBarrier<DoEmit>(slot.bufferView,
slot.bufferView->getSliceHandle()); VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, binding.access);
} }
break; break;
@ -5467,9 +5466,8 @@ namespace dxvk {
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
if (likely(slot.imageView != nullptr)) { if (likely(slot.imageView != nullptr)) {
srcAccess = m_execBarriers.getImageAccess( srcAccess = this->checkImageViewBarrier<DoEmit>(slot.imageView,
slot.imageView->image(), VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, binding.access);
slot.imageView->imageSubresources());
} }
break; break;
@ -5477,10 +5475,12 @@ namespace dxvk {
/* nothing to do */; /* nothing to do */;
} }
if (srcAccess == 0) if (DoEmit || srcAccess == 0)
continue; continue;
// Skip write-after-write barriers if explicitly requested // Skip write-after-write barriers if explicitly requested
DxvkAccessFlags dstAccess = DxvkBarrierSet::getAccessTypes(binding.access);
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
| VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
@ -5489,75 +5489,11 @@ namespace dxvk {
&& ((srcAccess | dstAccess) == DxvkAccess::Write)) && ((srcAccess | dstAccess) == DxvkAccess::Write))
continue; continue;
requiresBarrier = (srcAccess | dstAccess).test(DxvkAccess::Write); if ((srcAccess | dstAccess).test(DxvkAccess::Write)) {
}
index += bindingCount;
}
if (requiresBarrier)
m_execBarriers.recordCommands(m_cmd); m_execBarriers.recordCommands(m_cmd);
} return;
void DxvkContext::commitComputePostBarriers() {
const auto& layout = m_state.cp.pipeline->getBindings()->layout();
uint32_t index = 0;
for (uint32_t i = 0; i < DxvkDescriptorSets::SetCount; i++) {
uint32_t bindingCount = layout.getBindingCount(i);
for (uint32_t j = 0; j < bindingCount; j++) {
const DxvkBindingInfo& binding = layout.getBinding(i, j);
const DxvkShaderResourceSlot& slot = m_rc[binding.resourceBinding];
VkPipelineStageFlags stages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
VkAccessFlags access = binding.access;
switch (binding.descriptorType) {
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
if (likely(slot.bufferSlice.length())) {
m_execBarriers.accessBuffer(
slot.bufferSlice.getSliceHandle(),
stages, access,
slot.bufferSlice.bufferInfo().stages,
slot.bufferSlice.bufferInfo().access);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
if (likely(slot.bufferView != nullptr)) {
m_execBarriers.accessBuffer(
slot.bufferView->getSliceHandle(),
stages, access,
slot.bufferView->bufferInfo().stages,
slot.bufferView->bufferInfo().access);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
if (likely(slot.imageView != nullptr)) {
m_execBarriers.accessImage(
slot.imageView->image(),
slot.imageView->imageSubresources(),
slot.imageView->imageInfo().layout,
stages, access,
slot.imageView->imageInfo().layout,
slot.imageView->imageInfo().stages,
slot.imageView->imageInfo().access);
}
break;
default:
/* nothing to do */;
} }
} }
index += bindingCount;
} }
} }

View File

@ -1535,7 +1535,9 @@ namespace dxvk {
template<bool Indexed, bool Indirect> template<bool Indexed, bool Indirect>
bool commitGraphicsState(); bool commitGraphicsState();
void commitComputeInitBarriers(); template<bool DoEmit>
void commitComputeBarriers();
void commitComputePostBarriers(); void commitComputePostBarriers();
template<bool Indexed, bool Indirect, bool DoEmit> template<bool Indexed, bool Indirect, bool DoEmit>