graphics device refactors
This commit is contained in:
@@ -8,22 +8,36 @@
|
||||
|
||||
namespace wiGraphics
|
||||
{
|
||||
// CommandList can be used to record graphics commands from a CPU thread
|
||||
// Use GraphicsDevice::BeginCommandList() to start a command list
|
||||
// Use GraphicsDevice::SubmitCommandLists() to give all started command lists to the GPU for execution
|
||||
// CommandList recording is not thread safe
|
||||
typedef uint8_t CommandList;
|
||||
static const CommandList COMMANDLIST_COUNT = 32;
|
||||
static const CommandList COMMANDLIST_COUNT = 32; // If you increase command list count, more memory will be statically allocated for per-command list resources
|
||||
static const CommandList INVALID_COMMANDLIST = COMMANDLIST_COUNT;
|
||||
|
||||
// Descriptor binding counts:
|
||||
// It's OK increase these limits if not enough
|
||||
// But it's better to refactor shaders to use bindless descriptors if they require more resources
|
||||
static const uint32_t DESCRIPTORBINDER_CBV_COUNT = 15;
|
||||
static const uint32_t DESCRIPTORBINDER_SRV_COUNT = 64;
|
||||
static const uint32_t DESCRIPTORBINDER_UAV_COUNT = 16;
|
||||
static const uint32_t DESCRIPTORBINDER_SAMPLER_COUNT = 16;
|
||||
struct DescriptorBindingTable
|
||||
{
|
||||
GPUBuffer CBV[DESCRIPTORBINDER_CBV_COUNT];
|
||||
uint64_t CBV_offset[DESCRIPTORBINDER_CBV_COUNT] = {};
|
||||
GPUResource SRV[DESCRIPTORBINDER_SRV_COUNT];
|
||||
int SRV_index[DESCRIPTORBINDER_SRV_COUNT] = {};
|
||||
GPUResource UAV[DESCRIPTORBINDER_UAV_COUNT];
|
||||
int UAV_index[DESCRIPTORBINDER_UAV_COUNT] = {};
|
||||
Sampler SAM[DESCRIPTORBINDER_SAMPLER_COUNT];
|
||||
};
|
||||
|
||||
constexpr uint32_t AlignTo(uint32_t value, uint32_t alignment)
|
||||
{
|
||||
return ((value + alignment - 1) / alignment) * alignment;
|
||||
}
|
||||
|
||||
constexpr uint64_t AlignTo(uint64_t value, uint64_t alignment)
|
||||
{
|
||||
return ((value + alignment - 1) / alignment) * alignment;
|
||||
@@ -67,8 +81,8 @@ namespace wiGraphics
|
||||
virtual int CreateSubresource(Texture* texture, SUBRESOURCE_TYPE type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount) const = 0;
|
||||
virtual int CreateSubresource(GPUBuffer* buffer, SUBRESOURCE_TYPE type, uint64_t offset, uint64_t size = ~0) const = 0;
|
||||
|
||||
virtual int GetDescriptorIndex(const GPUResource* resource, SUBRESOURCE_TYPE type, int subresource = -1) const { return -1; };
|
||||
virtual int GetDescriptorIndex(const Sampler* sampler) const { return -1; };
|
||||
virtual int GetDescriptorIndex(const GPUResource* resource, SUBRESOURCE_TYPE type, int subresource = -1) const = 0;
|
||||
virtual int GetDescriptorIndex(const Sampler* sampler) const = 0;
|
||||
|
||||
virtual void WriteShadingRateValue(SHADING_RATE rate, void* dest) const {};
|
||||
virtual void WriteTopLevelAccelerationStructureInstance(const RaytracingAccelerationStructureDesc::TopLevel::Instance* instance, void* dest) const {}
|
||||
@@ -86,7 +100,7 @@ namespace wiGraphics
|
||||
virtual void SubmitCommandLists() = 0;
|
||||
|
||||
virtual void WaitForGPU() const = 0;
|
||||
virtual void ClearPipelineStateCache() {};
|
||||
virtual void ClearPipelineStateCache() = 0;
|
||||
|
||||
constexpr uint64_t GetFrameCount() const { return FRAMECOUNT; }
|
||||
|
||||
@@ -107,13 +121,13 @@ namespace wiGraphics
|
||||
constexpr uint32_t GetVariableRateShadingTileSize() const { return VARIABLE_RATE_SHADING_TILE_SIZE; }
|
||||
constexpr uint64_t GetTimestampFrequency() const { return TIMESTAMP_FREQUENCY; }
|
||||
|
||||
virtual SHADERFORMAT GetShaderFormat() const { return SHADERFORMAT_NONE; }
|
||||
virtual SHADERFORMAT GetShaderFormat() const = 0;
|
||||
|
||||
virtual Texture GetBackBuffer(const SwapChain* swapchain) const = 0;
|
||||
|
||||
///////////////Thread-sensitive////////////////////////
|
||||
|
||||
virtual void WaitCommandList(CommandList cmd, CommandList wait_for) {}
|
||||
virtual void WaitCommandList(CommandList cmd, CommandList wait_for) = 0;
|
||||
virtual void RenderPassBegin(const SwapChain* swapchain, CommandList cmd) = 0;
|
||||
virtual void RenderPassBegin(const RenderPass* renderpass, CommandList cmd) = 0;
|
||||
virtual void RenderPassEnd(CommandList cmd) = 0;
|
||||
@@ -146,13 +160,13 @@ namespace wiGraphics
|
||||
virtual void CopyBuffer(const GPUBuffer* pDst, uint64_t dst_offset, const GPUBuffer* pSrc, uint64_t src_offset, uint64_t size, CommandList cmd) = 0;
|
||||
virtual void QueryBegin(const GPUQueryHeap *heap, uint32_t index, CommandList cmd) = 0;
|
||||
virtual void QueryEnd(const GPUQueryHeap *heap, uint32_t index, CommandList cmd) = 0;
|
||||
virtual void QueryResolve(const GPUQueryHeap* heap, uint32_t index, uint32_t count, const GPUBuffer* dest, uint64_t dest_offset, CommandList cmd) {}
|
||||
virtual void QueryResolve(const GPUQueryHeap* heap, uint32_t index, uint32_t count, const GPUBuffer* dest, uint64_t dest_offset, CommandList cmd) = 0;
|
||||
virtual void QueryReset(const GPUQueryHeap* heap, uint32_t index, uint32_t count, CommandList cmd) {}
|
||||
virtual void Barrier(const GPUBarrier* barriers, uint32_t numBarriers, CommandList cmd) = 0;
|
||||
virtual void BuildRaytracingAccelerationStructure(const RaytracingAccelerationStructure* dst, CommandList cmd, const RaytracingAccelerationStructure* src = nullptr) {}
|
||||
virtual void BindRaytracingPipelineState(const RaytracingPipelineState* rtpso, CommandList cmd) {}
|
||||
virtual void DispatchRays(const DispatchRaysDesc* desc, CommandList cmd) {}
|
||||
virtual void PushConstants(const void* data, uint32_t size, CommandList cmd) {}
|
||||
virtual void PushConstants(const void* data, uint32_t size, CommandList cmd) = 0;
|
||||
|
||||
virtual void EventBegin(const char* name, CommandList cmd) = 0;
|
||||
virtual void EventEnd(CommandList cmd) = 0;
|
||||
@@ -160,7 +174,6 @@ namespace wiGraphics
|
||||
|
||||
|
||||
|
||||
|
||||
// Some useful helpers:
|
||||
|
||||
struct GPULinearAllocator
|
||||
@@ -179,6 +192,7 @@ namespace wiGraphics
|
||||
// Returns true if the allocation was successful
|
||||
inline bool IsValid() const { return data != nullptr && buffer.IsValid(); }
|
||||
};
|
||||
|
||||
// Allocates temporary memory that the CPU can write and GPU can read.
|
||||
// It is only alive for one frame and automatically invalidated after that.
|
||||
GPUAllocation AllocateGPU(uint64_t dataSize, CommandList cmd)
|
||||
|
||||
@@ -1622,39 +1622,11 @@ using namespace DX12_Internal;
|
||||
}
|
||||
void GraphicsDevice_DX12::DescriptorBinder::reset()
|
||||
{
|
||||
table = {};
|
||||
dirty_res = true;
|
||||
dirty_sam = true;
|
||||
ringOffset_res = 0;
|
||||
ringOffset_sam = 0;
|
||||
|
||||
for (int i = 0; i < arraysize(CBV); ++i)
|
||||
{
|
||||
CBV[i] = {};
|
||||
}
|
||||
for (int i = 0; i < arraysize(CBV_offset); ++i)
|
||||
{
|
||||
CBV_offset[i] = {};
|
||||
}
|
||||
for (int i = 0; i < arraysize(SRV); ++i)
|
||||
{
|
||||
SRV[i] = {};
|
||||
}
|
||||
for (int i = 0; i < arraysize(SRV_index); ++i)
|
||||
{
|
||||
SRV_index[i] = {};
|
||||
}
|
||||
for (int i = 0; i < arraysize(UAV); ++i)
|
||||
{
|
||||
UAV[i] = {};
|
||||
}
|
||||
for (int i = 0; i < arraysize(UAV_index); ++i)
|
||||
{
|
||||
UAV_index[i] = {};
|
||||
}
|
||||
for (int i = 0; i < arraysize(SAM); ++i)
|
||||
{
|
||||
SAM[i] = {};
|
||||
}
|
||||
}
|
||||
void GraphicsDevice_DX12::DescriptorBinder::flush(bool graphics, CommandList cmd)
|
||||
{
|
||||
@@ -1673,8 +1645,8 @@ using namespace DX12_Internal;
|
||||
continue;
|
||||
}
|
||||
|
||||
const GPUBuffer& buffer = CBV[x.ShaderRegister];
|
||||
uint64_t offset = CBV_offset[x.ShaderRegister];
|
||||
const GPUBuffer& buffer = table.CBV[x.ShaderRegister];
|
||||
uint64_t offset = table.CBV_offset[x.ShaderRegister];
|
||||
|
||||
D3D12_GPU_VIRTUAL_ADDRESS address;
|
||||
|
||||
@@ -1774,8 +1746,8 @@ using namespace DX12_Internal;
|
||||
default:
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
|
||||
{
|
||||
const GPUResource& resource = SRV[ShaderRegister];
|
||||
const int subresource = SRV_index[ShaderRegister];
|
||||
const GPUResource& resource = table.SRV[ShaderRegister];
|
||||
const int subresource = table.SRV_index[ShaderRegister];
|
||||
if (!resource.IsValid())
|
||||
{
|
||||
switch (binding)
|
||||
@@ -1839,8 +1811,8 @@ using namespace DX12_Internal;
|
||||
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
|
||||
{
|
||||
const GPUResource& resource = UAV[ShaderRegister];
|
||||
const int subresource = UAV_index[ShaderRegister];
|
||||
const GPUResource& resource = table.UAV[ShaderRegister];
|
||||
const int subresource = table.UAV_index[ShaderRegister];
|
||||
if (!resource.IsValid())
|
||||
{
|
||||
switch (binding)
|
||||
@@ -1888,8 +1860,8 @@ using namespace DX12_Internal;
|
||||
|
||||
case D3D12_DESCRIPTOR_RANGE_TYPE_CBV:
|
||||
{
|
||||
const GPUBuffer& buffer = CBV[ShaderRegister];
|
||||
uint64_t offset = CBV_offset[ShaderRegister];
|
||||
const GPUBuffer& buffer = table.CBV[ShaderRegister];
|
||||
uint64_t offset = table.CBV_offset[ShaderRegister];
|
||||
|
||||
if (!buffer.IsValid())
|
||||
{
|
||||
@@ -1964,7 +1936,7 @@ using namespace DX12_Internal;
|
||||
|
||||
UINT ShaderRegister = x.BaseShaderRegister + descriptor_index;
|
||||
|
||||
const Sampler& sampler = SAM[ShaderRegister];
|
||||
const Sampler& sampler = table.SAM[ShaderRegister];
|
||||
if (!sampler.IsValid())
|
||||
{
|
||||
device->device->CopyDescriptorsSimple(1, dst, device->nullSAM, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
@@ -2122,7 +2094,7 @@ using namespace DX12_Internal;
|
||||
{
|
||||
pso_validate(cmd);
|
||||
|
||||
descriptors[cmd].flush(true, cmd);
|
||||
binders[cmd].flush(true, cmd);
|
||||
|
||||
auto pso_internal = to_internal(active_pso[cmd]);
|
||||
if (pso_internal->rootconstants.Constants.Num32BitValues > 0)
|
||||
@@ -2137,7 +2109,7 @@ using namespace DX12_Internal;
|
||||
}
|
||||
void GraphicsDevice_DX12::predispatch(CommandList cmd)
|
||||
{
|
||||
descriptors[cmd].flush(false, cmd);
|
||||
binders[cmd].flush(false, cmd);
|
||||
|
||||
auto cs_internal = to_internal(active_cs[cmd]);
|
||||
if (cs_internal->rootconstants.Constants.Num32BitValues > 0)
|
||||
@@ -5354,7 +5326,7 @@ using namespace DX12_Internal;
|
||||
wss << "cmd" << cmd;
|
||||
commandLists[cmd][queue]->SetName(wss.str().c_str());
|
||||
|
||||
descriptors[cmd].init(this);
|
||||
binders[cmd].init(this);
|
||||
}
|
||||
|
||||
// Start the command list in a default state:
|
||||
@@ -5369,7 +5341,7 @@ using namespace DX12_Internal;
|
||||
};
|
||||
GetCommandList(cmd)->SetDescriptorHeaps(arraysize(heaps), heaps);
|
||||
|
||||
descriptors[cmd].reset();
|
||||
binders[cmd].reset();
|
||||
|
||||
if (queue == QUEUE_GRAPHICS)
|
||||
{
|
||||
@@ -5716,11 +5688,12 @@ using namespace DX12_Internal;
|
||||
void GraphicsDevice_DX12::BindResource(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource)
|
||||
{
|
||||
assert(slot < DESCRIPTORBINDER_SRV_COUNT);
|
||||
if (descriptors[cmd].SRV[slot].internal_state != resource->internal_state || descriptors[cmd].SRV_index[slot] != subresource)
|
||||
auto& binder = binders[cmd];
|
||||
if (binder.table.SRV[slot].internal_state != resource->internal_state || binder.table.SRV_index[slot] != subresource)
|
||||
{
|
||||
descriptors[cmd].SRV[slot] = *resource;
|
||||
descriptors[cmd].SRV_index[slot] = subresource;
|
||||
descriptors[cmd].dirty_res = true;
|
||||
binder.table.SRV[slot] = *resource;
|
||||
binder.table.SRV_index[slot] = subresource;
|
||||
binder.dirty_res = true;
|
||||
}
|
||||
}
|
||||
void GraphicsDevice_DX12::BindResources(const GPUResource* const* resources, uint32_t slot, uint32_t count, CommandList cmd)
|
||||
@@ -5736,11 +5709,12 @@ using namespace DX12_Internal;
|
||||
void GraphicsDevice_DX12::BindUAV(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource)
|
||||
{
|
||||
assert(slot < DESCRIPTORBINDER_UAV_COUNT);
|
||||
if (descriptors[cmd].UAV[slot].internal_state != resource->internal_state || descriptors[cmd].UAV_index[slot] != subresource)
|
||||
auto& binder = binders[cmd];
|
||||
if (binder.table.UAV[slot].internal_state != resource->internal_state || binder.table.UAV_index[slot] != subresource)
|
||||
{
|
||||
descriptors[cmd].UAV[slot] = *resource;
|
||||
descriptors[cmd].UAV_index[slot] = subresource;
|
||||
descriptors[cmd].dirty_res = true;
|
||||
binder.table.UAV[slot] = *resource;
|
||||
binder.table.UAV_index[slot] = subresource;
|
||||
binder.dirty_res = true;
|
||||
}
|
||||
}
|
||||
void GraphicsDevice_DX12::BindUAVs(const GPUResource* const* resources, uint32_t slot, uint32_t count, CommandList cmd)
|
||||
@@ -5756,20 +5730,22 @@ using namespace DX12_Internal;
|
||||
void GraphicsDevice_DX12::BindSampler(const Sampler* sampler, uint32_t slot, CommandList cmd)
|
||||
{
|
||||
assert(slot < DESCRIPTORBINDER_SAMPLER_COUNT);
|
||||
if (descriptors[cmd].SAM[slot].internal_state != sampler->internal_state)
|
||||
auto& binder = binders[cmd];
|
||||
if (binder.table.SAM[slot].internal_state != sampler->internal_state)
|
||||
{
|
||||
descriptors[cmd].SAM[slot] = *sampler;
|
||||
descriptors[cmd].dirty_sam = true;
|
||||
binder.table.SAM[slot] = *sampler;
|
||||
binder.dirty_sam = true;
|
||||
}
|
||||
}
|
||||
void GraphicsDevice_DX12::BindConstantBuffer(const GPUBuffer* buffer, uint32_t slot, CommandList cmd, uint64_t offset)
|
||||
{
|
||||
assert(slot < DESCRIPTORBINDER_CBV_COUNT);
|
||||
if (descriptors[cmd].CBV[slot].internal_state != buffer->internal_state || descriptors[cmd].CBV_offset[slot] != offset)
|
||||
auto& binder = binders[cmd];
|
||||
if (binder.table.CBV[slot].internal_state != buffer->internal_state || binder.table.CBV_offset[slot] != offset)
|
||||
{
|
||||
descriptors[cmd].CBV[slot] = *buffer;
|
||||
descriptors[cmd].CBV_offset[slot] = offset;
|
||||
descriptors[cmd].dirty_res = true;
|
||||
binder.table.CBV[slot] = *buffer;
|
||||
binder.table.CBV_offset[slot] = offset;
|
||||
binder.dirty_res = true;
|
||||
|
||||
// Root constant buffer root signature state tracking:
|
||||
auto internal_state = to_internal(buffer);
|
||||
@@ -5784,7 +5760,7 @@ using namespace DX12_Internal;
|
||||
// CBV flag marked as bound for this slot:
|
||||
// Also, the corresponding slot is marked dirty
|
||||
internal_state->cbv_mask[cmd] |= 1 << slot;
|
||||
descriptors[cmd].dirty_root_cbvs |= 1 << slot;
|
||||
binder.dirty_root_cbvs |= 1 << slot;
|
||||
}
|
||||
}
|
||||
void GraphicsDevice_DX12::BindVertexBuffers(const GPUBuffer* const* vertexBuffers, uint32_t slot, uint32_t count, const uint32_t* strides, const uint64_t* offsets, CommandList cmd)
|
||||
@@ -5871,9 +5847,9 @@ using namespace DX12_Internal;
|
||||
GetCommandList(cmd)->SetGraphicsRootSignature(internal_state->rootSignature.Get());
|
||||
|
||||
// Invalidate graphics root bindings:
|
||||
descriptors[cmd].dirty_res = true;
|
||||
descriptors[cmd].dirty_sam = true;
|
||||
descriptors[cmd].dirty_root_cbvs = ~0;
|
||||
binders[cmd].dirty_res = true;
|
||||
binders[cmd].dirty_sam = true;
|
||||
binders[cmd].dirty_root_cbvs = ~0;
|
||||
|
||||
// Set the bindless tables:
|
||||
uint32_t bindpoint = internal_state->bindpoint_bindless;
|
||||
@@ -5915,9 +5891,9 @@ using namespace DX12_Internal;
|
||||
GetCommandList(cmd)->SetComputeRootSignature(internal_state->rootSignature.Get());
|
||||
|
||||
// Invalidate compute root bindings:
|
||||
descriptors[cmd].dirty_res = true;
|
||||
descriptors[cmd].dirty_sam = true;
|
||||
descriptors[cmd].dirty_root_cbvs = ~0;
|
||||
binders[cmd].dirty_res = true;
|
||||
binders[cmd].dirty_sam = true;
|
||||
binders[cmd].dirty_root_cbvs = ~0;
|
||||
|
||||
// Set the bindless tables:
|
||||
uint32_t bindpoint = internal_state->bindpoint_bindless;
|
||||
|
||||
@@ -119,20 +119,12 @@ namespace wiGraphics
|
||||
|
||||
struct DescriptorBinder
|
||||
{
|
||||
DescriptorBindingTable table;
|
||||
GraphicsDevice_DX12* device = nullptr;
|
||||
uint32_t ringOffset_res = 0;
|
||||
uint32_t ringOffset_sam = 0;
|
||||
bool dirty_res = false;
|
||||
bool dirty_sam = false;
|
||||
|
||||
GPUBuffer CBV[DESCRIPTORBINDER_CBV_COUNT];
|
||||
uint64_t CBV_offset[DESCRIPTORBINDER_CBV_COUNT];
|
||||
GPUResource SRV[DESCRIPTORBINDER_SRV_COUNT];
|
||||
int SRV_index[DESCRIPTORBINDER_SRV_COUNT];
|
||||
GPUResource UAV[DESCRIPTORBINDER_UAV_COUNT];
|
||||
int UAV_index[DESCRIPTORBINDER_UAV_COUNT];
|
||||
Sampler SAM[DESCRIPTORBINDER_SAMPLER_COUNT];
|
||||
|
||||
uint32_t dirty_root_cbvs = 0; // bitmask
|
||||
|
||||
struct DescriptorHandles
|
||||
@@ -145,7 +137,7 @@ namespace wiGraphics
|
||||
void reset();
|
||||
void flush(bool graphics, CommandList cmd);
|
||||
};
|
||||
DescriptorBinder descriptors[COMMANDLIST_COUNT];
|
||||
DescriptorBinder binders[COMMANDLIST_COUNT];
|
||||
|
||||
std::vector<D3D12_RESOURCE_BARRIER> frame_barriers[COMMANDLIST_COUNT];
|
||||
|
||||
|
||||
@@ -1134,17 +1134,10 @@ using namespace Vulkan_Internal;
|
||||
return value;
|
||||
}
|
||||
|
||||
void GraphicsDevice_Vulkan::FrameResources::DescriptorBinder::init(GraphicsDevice_Vulkan* device)
|
||||
void GraphicsDevice_Vulkan::FrameResources::DescriptorBinderPool::init(GraphicsDevice_Vulkan* device)
|
||||
{
|
||||
this->device = device;
|
||||
|
||||
// Important that these don't reallocate themselves during writing descriptors!
|
||||
descriptorWrites.reserve(128);
|
||||
bufferInfos.reserve(128);
|
||||
imageInfos.reserve(128);
|
||||
texelBufferViews.reserve(128);
|
||||
accelerationStructureViews.reserve(128);
|
||||
|
||||
VkResult res;
|
||||
|
||||
// Create descriptor pool:
|
||||
@@ -1204,7 +1197,7 @@ using namespace Vulkan_Internal;
|
||||
// This is because init can be called mid-frame when there is allocation error, but the bindings must be retained!
|
||||
|
||||
}
|
||||
void GraphicsDevice_Vulkan::FrameResources::DescriptorBinder::destroy()
|
||||
void GraphicsDevice_Vulkan::FrameResources::DescriptorBinderPool::destroy()
|
||||
{
|
||||
if (descriptorPool != VK_NULL_HANDLE)
|
||||
{
|
||||
@@ -1214,51 +1207,38 @@ using namespace Vulkan_Internal;
|
||||
device->allocationhandler->destroylocker.unlock();
|
||||
}
|
||||
}
|
||||
void GraphicsDevice_Vulkan::FrameResources::DescriptorBinder::reset()
|
||||
void GraphicsDevice_Vulkan::FrameResources::DescriptorBinderPool::reset()
|
||||
{
|
||||
dirty = true;
|
||||
|
||||
if (descriptorPool != VK_NULL_HANDLE)
|
||||
{
|
||||
VkResult res = vkResetDescriptorPool(device->device, descriptorPool, 0);
|
||||
assert(res == VK_SUCCESS);
|
||||
}
|
||||
|
||||
for (int i = 0; i < arraysize(CBV); ++i)
|
||||
{
|
||||
CBV[i] = {};
|
||||
}
|
||||
for (int i = 0; i < arraysize(CBV_offset); ++i)
|
||||
{
|
||||
CBV_offset[i] = {};
|
||||
}
|
||||
for (int i = 0; i < arraysize(SRV); ++i)
|
||||
{
|
||||
SRV[i] = {};
|
||||
}
|
||||
for (int i = 0; i < arraysize(SRV_index); ++i)
|
||||
{
|
||||
SRV_index[i] = {};
|
||||
}
|
||||
for (int i = 0; i < arraysize(UAV); ++i)
|
||||
{
|
||||
UAV[i] = {};
|
||||
}
|
||||
for (int i = 0; i < arraysize(UAV_index); ++i)
|
||||
{
|
||||
UAV_index[i] = {};
|
||||
}
|
||||
for (int i = 0; i < arraysize(SAM); ++i)
|
||||
{
|
||||
SAM[i] = {};
|
||||
}
|
||||
}
|
||||
void GraphicsDevice_Vulkan::FrameResources::DescriptorBinder::flush(bool graphics, CommandList cmd)
|
||||
|
||||
void GraphicsDevice_Vulkan::DescriptorBinder::init(GraphicsDevice_Vulkan* device)
|
||||
{
|
||||
this->device = device;
|
||||
|
||||
// Important that these don't reallocate themselves during writing descriptors!
|
||||
descriptorWrites.reserve(128);
|
||||
bufferInfos.reserve(128);
|
||||
imageInfos.reserve(128);
|
||||
texelBufferViews.reserve(128);
|
||||
accelerationStructureViews.reserve(128);
|
||||
}
|
||||
void GraphicsDevice_Vulkan::DescriptorBinder::reset()
|
||||
{
|
||||
table = {};
|
||||
dirty = true;
|
||||
}
|
||||
void GraphicsDevice_Vulkan::DescriptorBinder::flush(bool graphics, CommandList cmd)
|
||||
{
|
||||
if (!dirty)
|
||||
return;
|
||||
dirty = false;
|
||||
|
||||
auto& binder_pool = device->GetFrameResources().binder_pools[cmd];
|
||||
auto pso_internal = graphics ? to_internal(device->active_pso[cmd]) : nullptr;
|
||||
auto cs_internal = graphics ? nullptr : to_internal(device->active_cs[cmd]);
|
||||
|
||||
@@ -1277,7 +1257,7 @@ using namespace Vulkan_Internal;
|
||||
|
||||
VkDescriptorSetAllocateInfo allocInfo = {};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
allocInfo.descriptorPool = descriptorPool;
|
||||
allocInfo.descriptorPool = binder_pool.descriptorPool;
|
||||
allocInfo.descriptorSetCount = 1;
|
||||
allocInfo.pSetLayouts = &descriptorSetLayout;
|
||||
|
||||
@@ -1285,10 +1265,10 @@ using namespace Vulkan_Internal;
|
||||
VkResult res = vkAllocateDescriptorSets(device->device, &allocInfo, &descriptorSet);
|
||||
while (res == VK_ERROR_OUT_OF_POOL_MEMORY)
|
||||
{
|
||||
poolSize *= 2;
|
||||
destroy();
|
||||
init(device);
|
||||
allocInfo.descriptorPool = descriptorPool;
|
||||
binder_pool.poolSize *= 2;
|
||||
binder_pool.destroy();
|
||||
binder_pool.init(device);
|
||||
allocInfo.descriptorPool = binder_pool.descriptorPool;
|
||||
res = vkAllocateDescriptorSets(device->device, &allocInfo, &descriptorSet);
|
||||
}
|
||||
assert(res == VK_SUCCESS);
|
||||
@@ -1337,7 +1317,7 @@ using namespace Vulkan_Internal;
|
||||
imageInfos.back() = {};
|
||||
|
||||
const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_S;
|
||||
const Sampler& sampler = SAM[original_binding];
|
||||
const Sampler& sampler = table.SAM[original_binding];
|
||||
if (!sampler.IsValid())
|
||||
{
|
||||
imageInfos.back().sampler = device->nullSampler;
|
||||
@@ -1356,7 +1336,7 @@ using namespace Vulkan_Internal;
|
||||
imageInfos.back() = {};
|
||||
|
||||
const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_T;
|
||||
const GPUResource& resource = SRV[original_binding];
|
||||
const GPUResource& resource = table.SRV[original_binding];
|
||||
if (!resource.IsValid() || !resource.IsTexture())
|
||||
{
|
||||
switch (viewtype)
|
||||
@@ -1391,7 +1371,7 @@ using namespace Vulkan_Internal;
|
||||
}
|
||||
else
|
||||
{
|
||||
int subresource = SRV_index[original_binding];
|
||||
int subresource = table.SRV_index[original_binding];
|
||||
auto texture_internal = to_internal((const Texture*)&resource);
|
||||
if (subresource >= 0)
|
||||
{
|
||||
@@ -1415,7 +1395,7 @@ using namespace Vulkan_Internal;
|
||||
imageInfos.back().imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_U;
|
||||
const GPUResource& resource = UAV[original_binding];
|
||||
const GPUResource& resource = table.UAV[original_binding];
|
||||
if (!resource.IsValid() || !resource.IsTexture())
|
||||
{
|
||||
switch (viewtype)
|
||||
@@ -1449,7 +1429,7 @@ using namespace Vulkan_Internal;
|
||||
}
|
||||
else
|
||||
{
|
||||
int subresource = UAV_index[original_binding];
|
||||
int subresource = table.UAV_index[original_binding];
|
||||
auto texture_internal = to_internal((const Texture*)&resource);
|
||||
if (subresource >= 0)
|
||||
{
|
||||
@@ -1470,8 +1450,8 @@ using namespace Vulkan_Internal;
|
||||
bufferInfos.back() = {};
|
||||
|
||||
const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_B;
|
||||
const GPUBuffer& buffer = CBV[original_binding];
|
||||
uint64_t offset = CBV_offset[original_binding];
|
||||
const GPUBuffer& buffer = table.CBV[original_binding];
|
||||
uint64_t offset = table.CBV_offset[original_binding];
|
||||
|
||||
if (!buffer.IsValid())
|
||||
{
|
||||
@@ -1495,14 +1475,14 @@ using namespace Vulkan_Internal;
|
||||
texelBufferViews.back() = {};
|
||||
|
||||
const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_T;
|
||||
const GPUResource& resource = SRV[original_binding];
|
||||
const GPUResource& resource = table.SRV[original_binding];
|
||||
if (!resource.IsValid() || !resource.IsBuffer())
|
||||
{
|
||||
texelBufferViews.back() = device->nullBufferView;
|
||||
}
|
||||
else
|
||||
{
|
||||
int subresource = SRV_index[original_binding];
|
||||
int subresource = table.SRV_index[original_binding];
|
||||
auto buffer_internal = to_internal((const GPUBuffer*)&resource);
|
||||
if (subresource >= 0)
|
||||
{
|
||||
@@ -1523,14 +1503,14 @@ using namespace Vulkan_Internal;
|
||||
texelBufferViews.back() = {};
|
||||
|
||||
const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_U;
|
||||
const GPUResource& resource = UAV[original_binding];
|
||||
const GPUResource& resource = table.UAV[original_binding];
|
||||
if (!resource.IsValid() || !resource.IsBuffer())
|
||||
{
|
||||
texelBufferViews.back() = device->nullBufferView;
|
||||
}
|
||||
else
|
||||
{
|
||||
int subresource = UAV_index[original_binding];
|
||||
int subresource = table.UAV_index[original_binding];
|
||||
auto buffer_internal = to_internal((const GPUBuffer*)&resource);
|
||||
if (subresource >= 0)
|
||||
{
|
||||
@@ -1554,7 +1534,7 @@ using namespace Vulkan_Internal;
|
||||
{
|
||||
// SRV
|
||||
const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_T;
|
||||
const GPUResource& resource = SRV[original_binding];
|
||||
const GPUResource& resource = table.SRV[original_binding];
|
||||
if (!resource.IsValid() || !resource.IsBuffer())
|
||||
{
|
||||
bufferInfos.back().buffer = device->nullBuffer;
|
||||
@@ -1562,7 +1542,7 @@ using namespace Vulkan_Internal;
|
||||
}
|
||||
else
|
||||
{
|
||||
int subresource = SRV_index[original_binding];
|
||||
int subresource = table.SRV_index[original_binding];
|
||||
auto buffer_internal = to_internal((const GPUBuffer*)&resource);
|
||||
bufferInfos.back().buffer = buffer_internal->resource;
|
||||
bufferInfos.back().range = VK_WHOLE_SIZE;
|
||||
@@ -1572,7 +1552,7 @@ using namespace Vulkan_Internal;
|
||||
{
|
||||
// UAV
|
||||
const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_U;
|
||||
const GPUResource& resource = UAV[original_binding];
|
||||
const GPUResource& resource = table.UAV[original_binding];
|
||||
if (!resource.IsValid() || !resource.IsBuffer())
|
||||
{
|
||||
bufferInfos.back().buffer = device->nullBuffer;
|
||||
@@ -1580,7 +1560,7 @@ using namespace Vulkan_Internal;
|
||||
}
|
||||
else
|
||||
{
|
||||
int subresource = UAV_index[original_binding];
|
||||
int subresource = table.UAV_index[original_binding];
|
||||
auto buffer_internal = to_internal((const GPUBuffer*)&resource);
|
||||
bufferInfos.back().buffer = buffer_internal->resource;
|
||||
bufferInfos.back().range = VK_WHOLE_SIZE;
|
||||
@@ -1598,7 +1578,7 @@ using namespace Vulkan_Internal;
|
||||
accelerationStructureViews.back().accelerationStructureCount = 1;
|
||||
|
||||
const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_T;
|
||||
const GPUResource& resource = SRV[original_binding];
|
||||
const GPUResource& resource = table.SRV[original_binding];
|
||||
if (!resource.IsValid() || !resource.IsAccelerationStructure())
|
||||
{
|
||||
assert(0); // invalid acceleration structure!
|
||||
@@ -1834,7 +1814,7 @@ using namespace Vulkan_Internal;
|
||||
{
|
||||
pso_validate(cmd);
|
||||
|
||||
GetFrameResources().descriptors[cmd].flush(true, cmd);
|
||||
binders[cmd].flush(true, cmd);
|
||||
|
||||
auto pso_internal = to_internal(active_pso[cmd]);
|
||||
if (pso_internal->pushconstants.size > 0)
|
||||
@@ -1851,7 +1831,7 @@ using namespace Vulkan_Internal;
|
||||
}
|
||||
void GraphicsDevice_Vulkan::predispatch(CommandList cmd)
|
||||
{
|
||||
GetFrameResources().descriptors[cmd].flush(false, cmd);
|
||||
binders[cmd].flush(false, cmd);
|
||||
|
||||
auto cs_internal = to_internal(active_cs[cmd]);
|
||||
if (cs_internal->pushconstants.size > 0)
|
||||
@@ -2591,7 +2571,7 @@ using namespace Vulkan_Internal;
|
||||
}
|
||||
vkDestroyCommandPool(device, frame.initCommandPool, nullptr);
|
||||
|
||||
for (auto& descriptormanager : frame.descriptors)
|
||||
for (auto& descriptormanager : frame.binder_pools)
|
||||
{
|
||||
descriptormanager.destroy();
|
||||
}
|
||||
@@ -5657,8 +5637,10 @@ using namespace Vulkan_Internal;
|
||||
res = vkAllocateCommandBuffers(device, &commandBufferInfo, &frame.commandBuffers[cmd][queue]);
|
||||
assert(res == VK_SUCCESS);
|
||||
|
||||
frame.descriptors[cmd].init(this);
|
||||
frame.binder_pools[cmd].init(this);
|
||||
}
|
||||
|
||||
binders[cmd].init(this);
|
||||
}
|
||||
|
||||
res = vkResetCommandPool(device, GetFrameResources().commandPools[cmd][queue], 0);
|
||||
@@ -5673,7 +5655,8 @@ using namespace Vulkan_Internal;
|
||||
assert(res == VK_SUCCESS);
|
||||
|
||||
// reset descriptor allocators:
|
||||
GetFrameResources().descriptors[cmd].reset();
|
||||
GetFrameResources().binder_pools[cmd].reset();
|
||||
binders[cmd].reset();
|
||||
|
||||
if (queue == QUEUE_GRAPHICS)
|
||||
{
|
||||
@@ -5999,12 +5982,12 @@ using namespace Vulkan_Internal;
|
||||
void GraphicsDevice_Vulkan::BindResource(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource)
|
||||
{
|
||||
assert(slot < DESCRIPTORBINDER_SRV_COUNT);
|
||||
auto& descriptors = GetFrameResources().descriptors[cmd];
|
||||
if (descriptors.SRV[slot].internal_state != resource->internal_state || descriptors.SRV_index[slot] != subresource)
|
||||
auto& binder = binders[cmd];
|
||||
if (binder.table.SRV[slot].internal_state != resource->internal_state || binder.table.SRV_index[slot] != subresource)
|
||||
{
|
||||
descriptors.SRV[slot] = *resource;
|
||||
descriptors.SRV_index[slot] = subresource;
|
||||
descriptors.dirty = true;
|
||||
binder.table.SRV[slot] = *resource;
|
||||
binder.table.SRV_index[slot] = subresource;
|
||||
binder.dirty = true;
|
||||
}
|
||||
}
|
||||
void GraphicsDevice_Vulkan::BindResources(const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd)
|
||||
@@ -6020,12 +6003,12 @@ using namespace Vulkan_Internal;
|
||||
void GraphicsDevice_Vulkan::BindUAV(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource)
|
||||
{
|
||||
assert(slot < DESCRIPTORBINDER_UAV_COUNT);
|
||||
auto& descriptors = GetFrameResources().descriptors[cmd];
|
||||
if (descriptors.UAV[slot].internal_state != resource->internal_state || descriptors.UAV_index[slot] != subresource)
|
||||
auto& binder = binders[cmd];
|
||||
if (binder.table.UAV[slot].internal_state != resource->internal_state || binder.table.UAV_index[slot] != subresource)
|
||||
{
|
||||
descriptors.UAV[slot] = *resource;
|
||||
descriptors.UAV_index[slot] = subresource;
|
||||
descriptors.dirty = true;
|
||||
binder.table.UAV[slot] = *resource;
|
||||
binder.table.UAV_index[slot] = subresource;
|
||||
binder.dirty = true;
|
||||
}
|
||||
}
|
||||
void GraphicsDevice_Vulkan::BindUAVs(const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd)
|
||||
@@ -6041,22 +6024,22 @@ using namespace Vulkan_Internal;
|
||||
void GraphicsDevice_Vulkan::BindSampler(const Sampler* sampler, uint32_t slot, CommandList cmd)
|
||||
{
|
||||
assert(slot < DESCRIPTORBINDER_SAMPLER_COUNT);
|
||||
auto& descriptors = GetFrameResources().descriptors[cmd];
|
||||
if (descriptors.SAM[slot].internal_state != sampler->internal_state)
|
||||
auto& binder = binders[cmd];
|
||||
if (binder.table.SAM[slot].internal_state != sampler->internal_state)
|
||||
{
|
||||
descriptors.SAM[slot] = *sampler;
|
||||
descriptors.dirty = true;
|
||||
binder.table.SAM[slot] = *sampler;
|
||||
binder.dirty = true;
|
||||
}
|
||||
}
|
||||
void GraphicsDevice_Vulkan::BindConstantBuffer(const GPUBuffer* buffer, uint32_t slot, CommandList cmd, uint64_t offset)
|
||||
{
|
||||
assert(slot < DESCRIPTORBINDER_CBV_COUNT);
|
||||
auto& descriptors = GetFrameResources().descriptors[cmd];
|
||||
if (descriptors.CBV[slot].internal_state != buffer->internal_state || descriptors.CBV_offset[slot] != offset)
|
||||
auto& binder = binders[cmd];
|
||||
if (binder.table.CBV[slot].internal_state != buffer->internal_state || binder.table.CBV_offset[slot] != offset)
|
||||
{
|
||||
descriptors.CBV[slot] = *buffer;
|
||||
descriptors.CBV_offset[slot] = offset;
|
||||
descriptors.dirty = true;
|
||||
binder.table.CBV[slot] = *buffer;
|
||||
binder.table.CBV_offset[slot] = offset;
|
||||
binder.dirty = true;
|
||||
}
|
||||
}
|
||||
void GraphicsDevice_Vulkan::BindVertexBuffers(const GPUBuffer *const* vertexBuffers, uint32_t slot, uint32_t count, const uint32_t* strides, const uint64_t* offsets, CommandList cmd)
|
||||
@@ -6209,14 +6192,14 @@ using namespace Vulkan_Internal;
|
||||
|
||||
if (active_pso[cmd] == nullptr)
|
||||
{
|
||||
GetFrameResources().descriptors[cmd].dirty = true;
|
||||
binders[cmd].dirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto active_internal = to_internal(active_pso[cmd]);
|
||||
if (internal_state->binding_hash != active_internal->binding_hash)
|
||||
{
|
||||
GetFrameResources().descriptors[cmd].dirty = true;
|
||||
binders[cmd].dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6244,7 +6227,7 @@ using namespace Vulkan_Internal;
|
||||
{
|
||||
if (active_cs[cmd] == nullptr)
|
||||
{
|
||||
GetFrameResources().descriptors[cmd].dirty = true;
|
||||
binders[cmd].dirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -6252,7 +6235,7 @@ using namespace Vulkan_Internal;
|
||||
auto active_internal = to_internal(active_cs[cmd]);
|
||||
if (internal_state->binding_hash != active_internal->binding_hash)
|
||||
{
|
||||
GetFrameResources().descriptors[cmd].dirty = true;
|
||||
binders[cmd].dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -187,33 +187,16 @@ namespace wiGraphics
|
||||
VkCommandPool initCommandPool = VK_NULL_HANDLE;
|
||||
VkCommandBuffer initCommandBuffer = VK_NULL_HANDLE;
|
||||
|
||||
struct DescriptorBinder
|
||||
struct DescriptorBinderPool
|
||||
{
|
||||
GraphicsDevice_Vulkan* device;
|
||||
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
|
||||
uint32_t poolSize = 256;
|
||||
|
||||
std::vector<VkWriteDescriptorSet> descriptorWrites;
|
||||
std::vector<VkDescriptorBufferInfo> bufferInfos;
|
||||
std::vector<VkDescriptorImageInfo> imageInfos;
|
||||
std::vector<VkBufferView> texelBufferViews;
|
||||
std::vector<VkWriteDescriptorSetAccelerationStructureKHR> accelerationStructureViews;
|
||||
bool dirty = false;
|
||||
|
||||
GPUBuffer CBV[DESCRIPTORBINDER_CBV_COUNT];
|
||||
uint64_t CBV_offset[DESCRIPTORBINDER_CBV_COUNT];
|
||||
GPUResource SRV[DESCRIPTORBINDER_SRV_COUNT];
|
||||
int SRV_index[DESCRIPTORBINDER_SRV_COUNT];
|
||||
GPUResource UAV[DESCRIPTORBINDER_UAV_COUNT];
|
||||
int UAV_index[DESCRIPTORBINDER_UAV_COUNT];
|
||||
Sampler SAM[DESCRIPTORBINDER_SAMPLER_COUNT];
|
||||
|
||||
void init(GraphicsDevice_Vulkan* device);
|
||||
void destroy();
|
||||
void reset();
|
||||
void flush(bool graphics, CommandList cmd);
|
||||
};
|
||||
DescriptorBinder descriptors[COMMANDLIST_COUNT];
|
||||
} binder_pools[COMMANDLIST_COUNT];
|
||||
};
|
||||
FrameResources frames[BUFFERCOUNT];
|
||||
const FrameResources& GetFrameResources() const { return frames[GetBufferIndex()]; }
|
||||
@@ -230,6 +213,24 @@ namespace wiGraphics
|
||||
return GetFrameResources().commandBuffers[cmd][cmd_meta[cmd].queue];
|
||||
}
|
||||
|
||||
struct DescriptorBinder
|
||||
{
|
||||
DescriptorBindingTable table;
|
||||
GraphicsDevice_Vulkan* device;
|
||||
|
||||
std::vector<VkWriteDescriptorSet> descriptorWrites;
|
||||
std::vector<VkDescriptorBufferInfo> bufferInfos;
|
||||
std::vector<VkDescriptorImageInfo> imageInfos;
|
||||
std::vector<VkBufferView> texelBufferViews;
|
||||
std::vector<VkWriteDescriptorSetAccelerationStructureKHR> accelerationStructureViews;
|
||||
bool dirty = false;
|
||||
|
||||
void init(GraphicsDevice_Vulkan* device);
|
||||
void reset();
|
||||
void flush(bool graphics, CommandList cmd);
|
||||
};
|
||||
DescriptorBinder binders[COMMANDLIST_COUNT];
|
||||
|
||||
std::vector<VkMemoryBarrier> frame_memoryBarriers[COMMANDLIST_COUNT];
|
||||
std::vector<VkImageMemoryBarrier> frame_imageBarriers[COMMANDLIST_COUNT];
|
||||
std::vector<VkBufferMemoryBarrier> frame_bufferBarriers[COMMANDLIST_COUNT];
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace wiVersion
|
||||
// minor features, major updates, breaking compatibility changes
|
||||
const int minor = 57;
|
||||
// minor bug fixes, alterations, refactors, updates
|
||||
const int revision = 13;
|
||||
const int revision = 14;
|
||||
|
||||
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user