Skip to content

Commit

Permalink
D3D: Add texture and buffer enhanced barriers
Browse files Browse the repository at this point in the history
  • Loading branch information
godlikepanos committed Jun 8, 2024
1 parent 1d48d9b commit 2f1a26a
Show file tree
Hide file tree
Showing 6 changed files with 364 additions and 69 deletions.
1 change: 1 addition & 0 deletions AnKi/Gr/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,7 @@ enum class BufferUsageBit : U64
| kIndirectTraceRays | kTransferSource | kAccelerationStructureBuild | kShaderBindingTable,
kAllWrite = kStorageGeometryWrite | kStorageFragmentWrite | kStorageComputeWrite | kStorageTraceRaysWrite | kTexelGeometryWrite
| kTexelFragmentWrite | kTexelComputeWrite | kTexelTraceRaysWrite | kTransferDestination | kAccelerationStructureBuildScratch,

kAll = kAllRead | kAllWrite,
};
ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(BufferUsageBit)
Expand Down
133 changes: 133 additions & 0 deletions AnKi/Gr/D3D/D3DBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,137 @@ Error BufferImpl::init(const BufferInitInfo& inf)
return Error::kNone;
}

D3D12_BUFFER_BARRIER BufferImpl::computeBarrier(BufferUsageBit before, BufferUsageBit after) const
{
ANKI_ASSERT((m_usage & before) == before);
ANKI_ASSERT((m_usage & after) == after);

const D3D12_BUFFER_BARRIER out = {.SyncBefore = computeSync(before),
.SyncAfter = computeSync(after),
.AccessBefore = computeAccess(before),
.AccessAfter = computeAccess(after),
.pResource = m_resource,
.Offset = 0,
.Size = kMaxU64};

return out;
}

D3D12_BARRIER_SYNC BufferImpl::computeSync(BufferUsageBit usage) const
{
if(usage == BufferUsageBit::kNone)
{
return D3D12_BARRIER_SYNC_NONE;
}

const Bool rt = getGrManagerImpl().getDeviceCapabilities().m_rayTracingEnabled;
D3D12_BARRIER_SYNC sync = {};

if(!!(usage & BufferUsageBit::kAllIndirect))
{
sync |= D3D12_BARRIER_SYNC_EXECUTE_INDIRECT;
}

if(!!(usage & (BufferUsageBit::kIndex | BufferUsageBit::kVertex)))
{
sync |= D3D12_BARRIER_SYNC_INDEX_INPUT | D3D12_BARRIER_SYNC_VERTEX_SHADING;
}

if(!!(usage & BufferUsageBit::kAllGeometry))
{
sync |= D3D12_BARRIER_SYNC_VERTEX_SHADING;
}

if(!!(usage & BufferUsageBit::kAllFragment))
{
sync |= D3D12_BARRIER_SYNC_PIXEL_SHADING;
}

if(!!(usage & (BufferUsageBit::kAllCompute & ~BufferUsageBit::kIndirectCompute)))
{
sync |= D3D12_BARRIER_SYNC_COMPUTE_SHADING;
}

if(!!(usage & (BufferUsageBit::kAccelerationStructureBuild | BufferUsageBit::kAccelerationStructureBuildScratch)) && rt)
{
sync |= D3D12_BARRIER_SYNC_BUILD_RAYTRACING_ACCELERATION_STRUCTURE;
}

if(!!(usage & (BufferUsageBit::kAllTraceRays & ~BufferUsageBit::kIndirectTraceRays)) && rt)
{
sync |= D3D12_BARRIER_SYNC_RAYTRACING;
}

if(!!(usage & BufferUsageBit::kAllTransfer))
{
sync |= D3D12_BARRIER_SYNC_COPY;
}

ANKI_ASSERT(sync);
return sync;
}

D3D12_BARRIER_ACCESS BufferImpl::computeAccess(BufferUsageBit usage) const
{
if(usage == BufferUsageBit::kNone)
{
return D3D12_BARRIER_ACCESS_NO_ACCESS;
}

D3D12_BARRIER_ACCESS out = {};

if(!!(usage & BufferUsageBit::kVertex))
{
out |= D3D12_BARRIER_ACCESS_VERTEX_BUFFER;
}

if(!!(usage & BufferUsageBit::kAllUniform))
{
out |= D3D12_BARRIER_ACCESS_CONSTANT_BUFFER;
}

if(!!(usage & BufferUsageBit::kIndex))
{
out |= D3D12_BARRIER_ACCESS_INDEX_BUFFER;
}

if(!!(usage & ((BufferUsageBit::kAllStorage | BufferUsageBit::kAllTexel) & BufferUsageBit::kAllWrite)))
{
out |= D3D12_BARRIER_ACCESS_UNORDERED_ACCESS;
}

if(!!(usage & ((BufferUsageBit::kAllStorage | BufferUsageBit::kAllTexel) & BufferUsageBit::kAllRead)))
{
out |= D3D12_BARRIER_ACCESS_SHADER_RESOURCE;
}

if(!!(usage & BufferUsageBit::kAllIndirect))
{
out |= D3D12_BARRIER_ACCESS_INDIRECT_ARGUMENT;
}

if(!!(usage & BufferUsageBit::kTransferDestination))
{
out |= D3D12_BARRIER_ACCESS_COPY_DEST;
}

if(!!(usage & BufferUsageBit::kTransferSource))
{
out |= D3D12_BARRIER_ACCESS_COPY_SOURCE;
}

if(!!(usage & (BufferUsageBit::kAccelerationStructureBuild | BufferUsageBit::kAccelerationStructureBuildScratch)))
{
out |= D3D12_BARRIER_ACCESS_COMMON;
}

if(!!(usage & BufferUsageBit::kShaderBindingTable))
{
out |= D3D12_BARRIER_ACCESS_RAYTRACING_ACCELERATION_STRUCTURE_READ;
}

ANKI_ASSERT(out);
return out;
}

} // end namespace anki
6 changes: 6 additions & 0 deletions AnKi/Gr/D3D/D3DBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,18 @@ class BufferImpl final : public Buffer
return *m_resource;
}

D3D12_BUFFER_BARRIER computeBarrier(BufferUsageBit before, BufferUsageBit after) const;

private:
ID3D12Resource* m_resource = nullptr;

#if ANKI_ASSERTIONS_ENABLED
Bool m_mapped = false;
#endif

D3D12_BARRIER_SYNC computeSync(BufferUsageBit usage) const;

D3D12_BARRIER_ACCESS computeAccess(BufferUsageBit usage) const;
};
/// @}

Expand Down
55 changes: 29 additions & 26 deletions AnKi/Gr/D3D/D3DCommandBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -680,41 +680,44 @@ void CommandBuffer::setPipelineBarrier(ConstWeakArray<TextureBarrierInfo> textur
ANKI_D3D_SELF(CommandBufferImpl);
self.commandCommon();

DynamicArray<D3D12_RESOURCE_BARRIER, MemoryPoolPtrWrapper<StackMemoryPool>> resourceBarriers(self.m_fastPool);
DynamicArray<D3D12_TEXTURE_BARRIER, MemoryPoolPtrWrapper<StackMemoryPool>> texBarriers(self.m_fastPool);
DynamicArray<D3D12_BUFFER_BARRIER, MemoryPoolPtrWrapper<StackMemoryPool>> bufferBarriers(self.m_fastPool);

for(const TextureBarrierInfo& barrier : textures)
{
const TextureImpl& impl = static_cast<const TextureImpl&>(barrier.m_textureView.getTexture());
D3D12_TEXTURE_BARRIER& d3dBarrier = *texBarriers.emplaceBack();
d3dBarrier = impl.computeBarrierInfo(barrier.m_previousUsage, barrier.m_nextUsage, barrier.m_textureView.getSubresource());
}

D3D12_RESOURCE_BARRIER& d3dBarrier = *resourceBarriers.emplaceBack();
d3dBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
d3dBarrier.Transition.pResource = &impl.getD3DResource();

if(barrier.m_textureView.isAllSurfacesOrVolumes() && barrier.m_textureView.getDepthStencilAspect() == impl.getDepthStencilAspect())
{
d3dBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
}
else
{
d3dBarrier.Transition.Subresource = impl.calcD3DSubresourceIndex(barrier.m_textureView.getSubresource());
}

impl.computeBarrierInfo(barrier.m_previousUsage, barrier.m_nextUsage, d3dBarrier.Transition.StateBefore, d3dBarrier.Transition.StateAfter);

if(d3dBarrier.Transition.StateBefore & D3D12_RESOURCE_STATE_UNORDERED_ACCESS
&& d3dBarrier.Transition.StateAfter & D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
{
D3D12_RESOURCE_BARRIER& d3dBarrier = *resourceBarriers.emplaceBack();
d3dBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
d3dBarrier.UAV.pResource = &impl.getD3DResource();
}
for(const BufferBarrierInfo& barrier : buffers)
{
const BufferImpl& impl = static_cast<const BufferImpl&>(barrier.m_bufferView.getBuffer());
D3D12_BUFFER_BARRIER& d3dBarrier = *bufferBarriers.emplaceBack();
d3dBarrier = impl.computeBarrier(barrier.m_previousUsage, barrier.m_nextUsage);
}

ANKI_ASSERT(buffers.getSize() == 0 && "TODO");
ANKI_ASSERT(accelerationStructures.getSize() == 0 && "TODO");

ANKI_ASSERT(resourceBarriers.getSize() > 0);
self.m_cmdList->ResourceBarrier(resourceBarriers.getSize(), resourceBarriers.getBegin());
Array<D3D12_BARRIER_GROUP, 3> barrierGroups;
U32 barrierGroupCount = 0;

if(texBarriers.getSize())
{
barrierGroups[barrierGroupCount++] = {.Type = D3D12_BARRIER_TYPE_TEXTURE,
.NumBarriers = texBarriers.getSize(),
.pTextureBarriers = texBarriers.getBegin()};
}

if(bufferBarriers.getSize())
{
barrierGroups[barrierGroupCount++] = {.Type = D3D12_BARRIER_TYPE_BUFFER,
.NumBarriers = bufferBarriers.getSize(),
.pBufferBarriers = bufferBarriers.getBegin()};
}

ANKI_ASSERT(barrierGroupCount > 0);
self.m_cmdList->Barrier(barrierGroupCount, barrierGroups.getBegin());
}

void CommandBuffer::beginOcclusionQuery([[maybe_unused]] OcclusionQuery* query)
Expand Down
Loading

0 comments on commit 2f1a26a

Please sign in to comment.