From 7a82d57517ec87de71f2ab00d6833cebe38253cf Mon Sep 17 00:00:00 2001 From: turanszkij Date: Thu, 18 Jul 2019 00:25:22 +0100 Subject: [PATCH] vulkan, dx12: new descriptor update method; vulkan, dx12: new dynamic buffer update method; other updates; --- Editor/Translator.cpp | 4 + WickedEngine/wiGraphicsDevice_DX12.cpp | 481 ++++----- WickedEngine/wiGraphicsDevice_DX12.h | 57 +- WickedEngine/wiGraphicsDevice_Vulkan.cpp | 1172 +++++++++------------- WickedEngine/wiGraphicsDevice_Vulkan.h | 48 +- WickedEngine/wiImage.cpp | 11 +- WickedEngine/wiImage.h | 10 +- WickedEngine/wiRenderer.cpp | 2 + WickedEngine/wiVersion.cpp | 2 +- WickedEngine/wiWidget.cpp | 46 +- 10 files changed, 862 insertions(+), 971 deletions(-) diff --git a/Editor/Translator.cpp b/Editor/Translator.cpp index d06e3072d..cb285020b 100644 --- a/Editor/Translator.cpp +++ b/Editor/Translator.cpp @@ -32,6 +32,8 @@ void Translator::LoadShaders() desc.rs = wiRenderer::GetRasterizerState(RSTYPE_DOUBLESIDED); desc.bs = wiRenderer::GetBlendState(BSTYPE_ADDITIVE); desc.pt = TRIANGLELIST; + desc.numRTs = 1; + desc.RTFormats[0] = wiRenderer::GetDevice()->GetBackBufferFormat(); device->CreatePipelineState(&desc, &pso_solidpart); } @@ -46,6 +48,8 @@ void Translator::LoadShaders() desc.rs = wiRenderer::GetRasterizerState(RSTYPE_WIRE_DOUBLESIDED_SMOOTH); desc.bs = wiRenderer::GetBlendState(BSTYPE_TRANSPARENT); desc.pt = LINELIST; + desc.numRTs = 1; + desc.RTFormats[0] = wiRenderer::GetDevice()->GetBackBufferFormat(); device->CreatePipelineState(&desc, &pso_wirepart); } diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index a08c9732a..cc7942d25 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -1259,165 +1259,213 @@ namespace wiGraphics - GraphicsDevice_DX12::FrameResources::DescriptorTableFrameAllocator::DescriptorTableFrameAllocator(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT maxRenameCount) + GraphicsDevice_DX12::FrameResources::DescriptorTableFrameAllocator::DescriptorTableFrameAllocator(GraphicsDevice_DX12* device, UINT maxRenameCount_resources, UINT maxRenameCount_samplers) : device(device) { - if (type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) - { - itemCount = GPU_SAMPLER_HEAP_COUNT; - } - else if (type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) - { - itemCount = (GPU_RESOURCE_HEAP_CBV_COUNT + GPU_RESOURCE_HEAP_SRV_COUNT + GPU_RESOURCE_HEAP_UAV_COUNT); - } - else - { - assert(0); - } + HRESULT hr; D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {}; heapDesc.NodeMask = 0; - heapDesc.Type = type; - - heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - heapDesc.NumDescriptors = itemCount * SHADERSTAGE_COUNT; - HRESULT hr = device->CreateDescriptorHeap(&heapDesc, __uuidof(ID3D12DescriptorHeap), (void**)&heap_CPU); + heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - heapDesc.NumDescriptors = itemCount * SHADERSTAGE_COUNT * maxRenameCount; - hr = device->CreateDescriptorHeap(&heapDesc, __uuidof(ID3D12DescriptorHeap), (void**)&heap_GPU); + heapDesc.NumDescriptors = (GPU_RESOURCE_HEAP_CBV_COUNT + GPU_RESOURCE_HEAP_SRV_COUNT + GPU_RESOURCE_HEAP_UAV_COUNT) * SHADERSTAGE_COUNT * maxRenameCount_resources; + hr = device->device->CreateDescriptorHeap(&heapDesc, __uuidof(ID3D12DescriptorHeap), (void**)&resource_heap_GPU); assert(SUCCEEDED(hr)); - descriptorType = type; - itemSize = device->GetDescriptorHandleIncrementSize(type); + heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; + heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + heapDesc.NumDescriptors = GPU_SAMPLER_HEAP_COUNT * SHADERSTAGE_COUNT * maxRenameCount_samplers; + hr = device->device->CreateDescriptorHeap(&heapDesc, __uuidof(ID3D12DescriptorHeap), (void**)&sampler_heap_GPU); + assert(SUCCEEDED(hr)); - boundDescriptors = new wiCPUHandle[SHADERSTAGE_COUNT * itemCount]; + reset(); } GraphicsDevice_DX12::FrameResources::DescriptorTableFrameAllocator::~DescriptorTableFrameAllocator() { - SAFE_RELEASE(heap_CPU); - SAFE_RELEASE(heap_GPU); - SAFE_DELETE_ARRAY(boundDescriptors); + SAFE_RELEASE(resource_heap_GPU); + SAFE_RELEASE(sampler_heap_GPU); } - void GraphicsDevice_DX12::FrameResources::DescriptorTableFrameAllocator::reset(ID3D12Device* device, D3D12_CPU_DESCRIPTOR_HANDLE* nullDescriptorsSamplerCBVSRVUAV) + void GraphicsDevice_DX12::FrameResources::DescriptorTableFrameAllocator::reset() { - memset(boundDescriptors, 0, sizeof(wiCPUHandle)*SHADERSTAGE_COUNT*itemCount); - - ringOffset = 0; - + ringOffset_resources = 0; + ringOffset_samplers = 0; for (int stage = 0; stage < SHADERSTAGE_COUNT; ++stage) { - dirty[stage] = true; - - // Fill staging tables with null descriptors (TODO make nicer and reduce copy ops): - if (descriptorType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) - { - for (int slot = 0; slot < GPU_RESOURCE_HEAP_CBV_COUNT; ++slot) - { - D3D12_CPU_DESCRIPTOR_HANDLE dst_staging = heap_CPU->GetCPUDescriptorHandleForHeapStart(); - dst_staging.ptr += (stage * itemCount + slot) * itemSize; - - device->CopyDescriptorsSimple(1, dst_staging, nullDescriptorsSamplerCBVSRVUAV[1], (D3D12_DESCRIPTOR_HEAP_TYPE)descriptorType); - } - for (int slot = 0; slot < GPU_RESOURCE_HEAP_SRV_COUNT; ++slot) - { - D3D12_CPU_DESCRIPTOR_HANDLE dst_staging = heap_CPU->GetCPUDescriptorHandleForHeapStart(); - dst_staging.ptr += (stage * itemCount + GPU_RESOURCE_HEAP_CBV_COUNT + slot) * itemSize; - - device->CopyDescriptorsSimple(1, dst_staging, nullDescriptorsSamplerCBVSRVUAV[2], (D3D12_DESCRIPTOR_HEAP_TYPE)descriptorType); - } - for (int slot = 0; slot < GPU_RESOURCE_HEAP_UAV_COUNT; ++slot) - { - D3D12_CPU_DESCRIPTOR_HANDLE dst_staging = heap_CPU->GetCPUDescriptorHandleForHeapStart(); - dst_staging.ptr += (stage * itemCount + GPU_RESOURCE_HEAP_CBV_COUNT + GPU_RESOURCE_HEAP_SRV_COUNT + slot) * itemSize; - - device->CopyDescriptorsSimple(1, dst_staging, nullDescriptorsSamplerCBVSRVUAV[3], (D3D12_DESCRIPTOR_HEAP_TYPE)descriptorType); - } - } - else - { - for (int slot = 0; slot < GPU_SAMPLER_HEAP_COUNT; ++slot) - { - D3D12_CPU_DESCRIPTOR_HANDLE dst_staging = heap_CPU->GetCPUDescriptorHandleForHeapStart(); - dst_staging.ptr += (stage * itemCount + slot) * itemSize; - - device->CopyDescriptorsSimple(1, dst_staging, nullDescriptorsSamplerCBVSRVUAV[0], (D3D12_DESCRIPTOR_HEAP_TYPE)descriptorType); - } - } - + tables[stage].reset(); } } - void GraphicsDevice_DX12::FrameResources::DescriptorTableFrameAllocator::update(SHADERSTAGE stage, UINT offset, wiCPUHandle descriptor, ID3D12Device* device) + void GraphicsDevice_DX12::FrameResources::DescriptorTableFrameAllocator::validate(CommandList cmd) { - if (descriptor == WI_NULL_HANDLE) + for (int stage = 0; stage < SHADERSTAGE_COUNT; ++stage) { - return; - } - UINT idx = stage * itemCount + offset; + Table& table = tables[stage]; - if (boundDescriptors[idx] == descriptor) - { - return; - } - - boundDescriptors[idx] = descriptor; - - dirty[stage] = true; - - D3D12_CPU_DESCRIPTOR_HANDLE dst_staging = heap_CPU->GetCPUDescriptorHandleForHeapStart(); - dst_staging.ptr += idx * itemSize; - - device->CopyDescriptorsSimple(1, dst_staging, ToNativeHandle(descriptor), (D3D12_DESCRIPTOR_HEAP_TYPE)descriptorType); - } - void GraphicsDevice_DX12::FrameResources::DescriptorTableFrameAllocator::validate(ID3D12Device* device, ID3D12GraphicsCommandList* commandList) - { - for (int stage = VS; stage < SHADERSTAGE_COUNT; ++stage) - { - if (dirty[stage]) + if (table.dirty_resources) { - // copy prev table contents to new dest - D3D12_CPU_DESCRIPTOR_HANDLE dst = heap_GPU->GetCPUDescriptorHandleForHeapStart(); - dst.ptr += ringOffset; - D3D12_CPU_DESCRIPTOR_HANDLE src = heap_CPU->GetCPUDescriptorHandleForHeapStart(); - src.ptr += (stage * itemCount) * itemSize; - device->CopyDescriptorsSimple(itemCount, dst, src, (D3D12_DESCRIPTOR_HEAP_TYPE)descriptorType); + table.dirty_resources = false; + + const UINT descriptor_size = device->device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + for (UINT slot = 0; slot < GPU_RESOURCE_HEAP_CBV_COUNT; ++slot) + { + const GPUBuffer* buffer = table.CBV[slot]; + + D3D12_CPU_DESCRIPTOR_HANDLE dst = resource_heap_GPU->GetCPUDescriptorHandleForHeapStart(); + dst.ptr += ringOffset_resources + slot * descriptor_size; + + D3D12_CPU_DESCRIPTOR_HANDLE descriptor = {}; + if (buffer != nullptr) + { + if (buffer->desc.Usage == USAGE_DYNAMIC) + { + auto it = device->dynamic_constantbuffers[cmd].find(buffer); + if (it != device->dynamic_constantbuffers[cmd].end()) + { + DynamicResourceState& state = it->second; + state.binding[stage] = true; + D3D12_CONSTANT_BUFFER_VIEW_DESC cbv; + cbv.BufferLocation = ((ID3D12Resource*)state.allocation.buffer->resource)->GetGPUVirtualAddress(); + cbv.BufferLocation += (D3D12_GPU_VIRTUAL_ADDRESS)state.allocation.offset; + cbv.SizeInBytes = (UINT)Align((size_t)buffer->desc.ByteWidth, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT); + + // Instead of copying like usually, here we create a CBV in place into the GPU-visible table: + device->device->CreateConstantBufferView(&cbv, dst); + continue; + } + } + else + { + descriptor = ToNativeHandle(buffer->CBV); + } + } + + if (descriptor.ptr == 0) + { + descriptor = device->nullCBV; + } + + device->device->CopyDescriptorsSimple(1, dst, descriptor, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + for (UINT slot = 0; slot < GPU_RESOURCE_HEAP_SRV_COUNT; ++slot) + { + const GPUResource* resource = table.SRV[slot]; + const int arrayIndex = table.SRV_index[slot]; + + D3D12_CPU_DESCRIPTOR_HANDLE descriptor = {}; + if (resource != nullptr) + { + if (arrayIndex < 0) + { + descriptor = ToNativeHandle(resource->SRV); + } + else + { + descriptor = ToNativeHandle(resource->additionalSRVs[arrayIndex]); + } + } + + if (descriptor.ptr == 0) + { + descriptor = device->nullSRV; + } + + D3D12_CPU_DESCRIPTOR_HANDLE dst = resource_heap_GPU->GetCPUDescriptorHandleForHeapStart(); + dst.ptr += ringOffset_resources + (GPU_RESOURCE_HEAP_CBV_COUNT + slot) * descriptor_size; + + device->device->CopyDescriptorsSimple(1, dst, descriptor, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + for (UINT slot = 0; slot < GPU_RESOURCE_HEAP_UAV_COUNT; ++slot) + { + const GPUResource* resource = table.UAV[slot]; + const int arrayIndex = table.UAV_index[slot]; + + D3D12_CPU_DESCRIPTOR_HANDLE descriptor = {}; + if (resource != nullptr) + { + if (arrayIndex < 0) + { + descriptor = ToNativeHandle(resource->UAV); + } + else + { + descriptor = ToNativeHandle(resource->additionalUAVs[arrayIndex]); + } + } + + if (descriptor.ptr == 0) + { + descriptor = device->nullUAV; + } + + D3D12_CPU_DESCRIPTOR_HANDLE dst = resource_heap_GPU->GetCPUDescriptorHandleForHeapStart(); + dst.ptr += ringOffset_resources + (GPU_RESOURCE_HEAP_CBV_COUNT + GPU_RESOURCE_HEAP_SRV_COUNT + slot) * descriptor_size; + + device->device->CopyDescriptorsSimple(1, dst, descriptor, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } // bind table to root sig - D3D12_GPU_DESCRIPTOR_HANDLE table = heap_GPU->GetGPUDescriptorHandleForHeapStart(); - table.ptr += ringOffset; + D3D12_GPU_DESCRIPTOR_HANDLE binding_table = resource_heap_GPU->GetGPUDescriptorHandleForHeapStart(); + binding_table.ptr += ringOffset_resources; + + if (stage == CS) + { + device->GetDirectCommandList(cmd)->SetComputeRootDescriptorTable(0, binding_table); + } + else + { + device->GetDirectCommandList(cmd)->SetGraphicsRootDescriptorTable(stage * 2 + 0, binding_table); + } + + // allocate next chunk + ringOffset_resources += (GPU_RESOURCE_HEAP_CBV_COUNT + GPU_RESOURCE_HEAP_SRV_COUNT + GPU_RESOURCE_HEAP_UAV_COUNT) * descriptor_size; + } + + if (table.dirty_samplers) + { + table.dirty_samplers = false; + + const UINT descriptor_size = device->device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + + for (UINT slot = 0; slot < GPU_SAMPLER_HEAP_COUNT; ++slot) + { + const Sampler* sampler = table.SAM[slot]; + + D3D12_CPU_DESCRIPTOR_HANDLE descriptor = {}; + if (sampler == nullptr || sampler->resource == WI_NULL_HANDLE) + { + descriptor = device->nullSampler; + } + else + { + descriptor = ToNativeHandle(sampler->resource); + } + + D3D12_CPU_DESCRIPTOR_HANDLE dst = sampler_heap_GPU->GetCPUDescriptorHandleForHeapStart(); + dst.ptr += ringOffset_samplers + slot * descriptor_size; + + device->device->CopyDescriptorsSimple(1, dst, descriptor, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + } + + // bind table to root sig + D3D12_GPU_DESCRIPTOR_HANDLE binding_table = sampler_heap_GPU->GetGPUDescriptorHandleForHeapStart(); + binding_table.ptr += ringOffset_samplers; if (stage == CS) { // compute descriptor heap: - - if (descriptorType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) - { - commandList->SetComputeRootDescriptorTable(0, table); - } - else - { - commandList->SetComputeRootDescriptorTable(1, table); - } + device->GetDirectCommandList(cmd)->SetComputeRootDescriptorTable(1, binding_table); } else { // graphics descriptor heap: - - if (descriptorType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) - { - commandList->SetGraphicsRootDescriptorTable(stage * 2 + 0, table); - } - else - { - commandList->SetGraphicsRootDescriptorTable(stage * 2 + 1, table); - } + device->GetDirectCommandList(cmd)->SetGraphicsRootDescriptorTable(stage * 2 + 1, binding_table); } - // mark this as up to date - dirty[stage] = false; - // allocate next chunk - ringOffset += itemCount*itemSize; + ringOffset_samplers += GPU_SAMPLER_HEAP_COUNT * descriptor_size; } + + } } @@ -1511,9 +1559,8 @@ namespace wiGraphics { lock.lock(); - //dataCur = reinterpret_cast(Align(reinterpret_cast(dataCur), alignment)); + dataCur = reinterpret_cast(Align(reinterpret_cast(dataCur), alignment)); - dataSize = Align(dataSize, alignment); assert(dataCur + dataSize <= dataEnd); uint8_t* retVal = dataCur; @@ -1953,8 +2000,7 @@ namespace wiGraphics { SAFE_RELEASE(frames[fr].commandLists[i]); SAFE_RELEASE(frames[fr].commandAllocators[i]); - SAFE_DELETE(frames[fr].ResourceDescriptorsGPU[i]); - SAFE_DELETE(frames[fr].SamplerDescriptorsGPU[i]); + SAFE_DELETE(frames[fr].descriptors[i]); SAFE_DELETE(frames[fr].resourceBuffer[i]); } } @@ -2083,7 +2129,7 @@ namespace wiGraphics { copyQueueLock.lock(); { - uint8_t* dest = bufferUploader->allocate(pDesc->ByteWidth, alignment); + uint8_t* dest = bufferUploader->allocate(pDesc->ByteWidth, 1); memcpy(dest, pInitialData->pSysMem, pDesc->ByteWidth); static_cast(copyCommandList)->CopyBufferRegion( (ID3D12Resource*)pBuffer->resource, 0, bufferUploader->resource, bufferUploader->calculateOffset(dest), pDesc->ByteWidth); @@ -3454,8 +3500,7 @@ namespace wiGraphics hr = device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, frames[fr].commandAllocators[cmd], nullptr, __uuidof(ID3D12GraphicsCommandList), (void**)&frames[fr].commandLists[cmd]); hr = static_cast(frames[fr].commandLists[cmd])->Close(); - frames[fr].ResourceDescriptorsGPU[cmd] = new FrameResources::DescriptorTableFrameAllocator(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1024); - frames[fr].SamplerDescriptorsGPU[cmd] = new FrameResources::DescriptorTableFrameAllocator(device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 16); + frames[fr].descriptors[cmd] = new FrameResources::DescriptorTableFrameAllocator(this, 1024, 16); frames[fr].resourceBuffer[cmd] = new FrameResources::ResourceFrameAllocator(device, 1024 * 1024 * 4); } } @@ -3470,7 +3515,7 @@ namespace wiGraphics ID3D12DescriptorHeap* heaps[] = { - GetFrameResources().ResourceDescriptorsGPU[cmd]->heap_GPU, GetFrameResources().SamplerDescriptorsGPU[cmd]->heap_GPU + GetFrameResources().descriptors[cmd]->resource_heap_GPU, GetFrameResources().descriptors[cmd]->sampler_heap_GPU }; GetDirectCommandList((CommandList)cmd)->SetDescriptorHeaps(ARRAYSIZE(heaps), heaps); @@ -3480,8 +3525,7 @@ namespace wiGraphics D3D12_CPU_DESCRIPTOR_HANDLE nullDescriptors[] = { nullSampler,nullCBV,nullSRV,nullUAV }; - GetFrameResources().ResourceDescriptorsGPU[cmd]->reset(device, nullDescriptors); - GetFrameResources().SamplerDescriptorsGPU[cmd]->reset(device, nullDescriptors); + GetFrameResources().descriptors[cmd]->reset(); GetFrameResources().resourceBuffer[cmd]->clear(); D3D12_RECT pRects[8]; @@ -3608,23 +3652,12 @@ namespace wiGraphics void GraphicsDevice_DX12::BindResource(SHADERSTAGE stage, const GPUResource* resource, UINT slot, CommandList cmd, int arrayIndex) { assert(slot < GPU_RESOURCE_HEAP_SRV_COUNT); - - if (resource != nullptr && resource->resource != WI_NULL_HANDLE) + auto& table = GetFrameResources().descriptors[cmd]->tables[stage]; + if (table.SRV[slot] != resource || table.SRV_index[slot] != arrayIndex) { - if (arrayIndex < 0) - { - if (resource->SRV != WI_NULL_HANDLE) - { - GetFrameResources().ResourceDescriptorsGPU[cmd]->update(stage, GPU_RESOURCE_HEAP_CBV_COUNT + slot, - resource->SRV, device); - } - } - else - { - assert(resource->additionalSRVs.size() > static_cast(arrayIndex) && "Invalid arrayIndex!"); - GetFrameResources().ResourceDescriptorsGPU[cmd]->update(stage, GPU_RESOURCE_HEAP_CBV_COUNT + slot, - resource->additionalSRVs[arrayIndex], device); - } + table.SRV[slot] = resource; + table.SRV_index[slot] = arrayIndex; + table.dirty_resources = true; } } void GraphicsDevice_DX12::BindResources(SHADERSTAGE stage, const GPUResource *const* resources, UINT slot, UINT count, CommandList cmd) @@ -3640,23 +3673,12 @@ namespace wiGraphics void GraphicsDevice_DX12::BindUAV(SHADERSTAGE stage, const GPUResource* resource, UINT slot, CommandList cmd, int arrayIndex) { assert(slot < GPU_RESOURCE_HEAP_UAV_COUNT); - - if (resource != nullptr && resource->resource != WI_NULL_HANDLE) + auto& table = GetFrameResources().descriptors[cmd]->tables[stage]; + if (table.UAV[slot] != resource || table.UAV_index[slot] != arrayIndex) { - if (arrayIndex < 0) - { - if (resource->UAV != WI_NULL_HANDLE) - { - GetFrameResources().ResourceDescriptorsGPU[cmd]->update(stage, GPU_RESOURCE_HEAP_CBV_COUNT + GPU_RESOURCE_HEAP_SRV_COUNT + slot, - resource->UAV, device); - } - } - else - { - assert(resource->additionalUAVs.size() > static_cast(arrayIndex) && "Invalid arrayIndex!"); - GetFrameResources().ResourceDescriptorsGPU[cmd]->update(stage, GPU_RESOURCE_HEAP_CBV_COUNT + GPU_RESOURCE_HEAP_SRV_COUNT + slot, - resource->additionalUAVs[arrayIndex], device); - } + table.UAV[slot] = resource; + table.UAV_index[slot] = arrayIndex; + table.dirty_resources = true; } } void GraphicsDevice_DX12::BindUAVs(SHADERSTAGE stage, const GPUResource *const* resources, UINT slot, UINT count, CommandList cmd) @@ -3671,44 +3693,28 @@ namespace wiGraphics } void GraphicsDevice_DX12::UnbindResources(UINT slot, UINT num, CommandList cmd) { - for (int stage = 0; stage < SHADERSTAGE_COUNT; ++stage) - { - for (UINT i = 0; i < num; ++i) - { - GetFrameResources().ResourceDescriptorsGPU[cmd]->update((SHADERSTAGE)stage, GPU_RESOURCE_HEAP_CBV_COUNT + slot + i, - nullSRV.ptr, device); - } - } } void GraphicsDevice_DX12::UnbindUAVs(UINT slot, UINT num, CommandList cmd) { - for (int stage = 0; stage < SHADERSTAGE_COUNT; ++stage) - { - for (UINT i = 0; i < num; ++i) - { - GetFrameResources().ResourceDescriptorsGPU[cmd]->update(CS, GPU_RESOURCE_HEAP_CBV_COUNT + GPU_RESOURCE_HEAP_SRV_COUNT + slot + i, - nullUAV.ptr, device); - } - } } void GraphicsDevice_DX12::BindSampler(SHADERSTAGE stage, const Sampler* sampler, UINT slot, CommandList cmd) { assert(slot < GPU_SAMPLER_HEAP_COUNT); - - if (sampler != nullptr && sampler->resource != WI_NULL_HANDLE) + auto& table = GetFrameResources().descriptors[cmd]->tables[stage]; + if (table.SAM[slot] != sampler) { - GetFrameResources().SamplerDescriptorsGPU[cmd]->update(stage, slot, - sampler->resource, device); + table.SAM[slot] = sampler; + table.dirty_samplers = true; } } void GraphicsDevice_DX12::BindConstantBuffer(SHADERSTAGE stage, const GPUBuffer* buffer, UINT slot, CommandList cmd) { assert(slot < GPU_RESOURCE_HEAP_CBV_COUNT); - - if (buffer != nullptr && buffer->CBV != WI_NULL_HANDLE) + auto& table = GetFrameResources().descriptors[cmd]->tables[stage]; + if (buffer->desc.Usage == USAGE_DYNAMIC || table.CBV[slot] != buffer) { - GetFrameResources().ResourceDescriptorsGPU[cmd]->update(stage, slot, - buffer->CBV, device); + table.CBV[slot] = buffer; + table.dirty_resources = true; } } void GraphicsDevice_DX12::BindVertexBuffers(const GPUBuffer *const* vertexBuffers, UINT slot, UINT count, const UINT* strides, const UINT* offsets, CommandList cmd) @@ -3789,50 +3795,42 @@ namespace wiGraphics } void GraphicsDevice_DX12::Draw(UINT vertexCount, UINT startVertexLocation, CommandList cmd) { - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); - GetFrameResources().SamplerDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); GetDirectCommandList(cmd)->DrawInstanced(vertexCount, 1, startVertexLocation, 0); } void GraphicsDevice_DX12::DrawIndexed(UINT indexCount, UINT startIndexLocation, UINT baseVertexLocation, CommandList cmd) { - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); - GetFrameResources().SamplerDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); GetDirectCommandList(cmd)->DrawIndexedInstanced(indexCount, 1, startIndexLocation, baseVertexLocation, 0); } void GraphicsDevice_DX12::DrawInstanced(UINT vertexCount, UINT instanceCount, UINT startVertexLocation, UINT startInstanceLocation, CommandList cmd) { - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); - GetFrameResources().SamplerDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); GetDirectCommandList(cmd)->DrawInstanced(vertexCount, instanceCount, startVertexLocation, startInstanceLocation); } void GraphicsDevice_DX12::DrawIndexedInstanced(UINT indexCount, UINT instanceCount, UINT startIndexLocation, UINT baseVertexLocation, UINT startInstanceLocation, CommandList cmd) { - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); - GetFrameResources().SamplerDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); GetDirectCommandList(cmd)->DrawIndexedInstanced(indexCount, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); } void GraphicsDevice_DX12::DrawInstancedIndirect(const GPUBuffer* args, UINT args_offset, CommandList cmd) { - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); - GetFrameResources().SamplerDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); GetDirectCommandList(cmd)->ExecuteIndirect(drawInstancedIndirectCommandSignature, 1, (ID3D12Resource*)args->resource, args_offset, nullptr, 0); } void GraphicsDevice_DX12::DrawIndexedInstancedIndirect(const GPUBuffer* args, UINT args_offset, CommandList cmd) { - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); - GetFrameResources().SamplerDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); GetDirectCommandList(cmd)->ExecuteIndirect(drawIndexedInstancedIndirectCommandSignature, 1, (ID3D12Resource*)args->resource, args_offset, nullptr, 0); } void GraphicsDevice_DX12::Dispatch(UINT threadGroupCountX, UINT threadGroupCountY, UINT threadGroupCountZ, CommandList cmd) { - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); - GetFrameResources().SamplerDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); GetDirectCommandList(cmd)->Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ); } void GraphicsDevice_DX12::DispatchIndirect(const GPUBuffer* args, UINT args_offset, CommandList cmd) { - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); - GetFrameResources().SamplerDescriptorsGPU[cmd]->validate(device, GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); GetDirectCommandList(cmd)->ExecuteIndirect(dispatchIndirectCommandSignature, 1, (ID3D12Resource*)args->resource, args_offset, nullptr, 0); } void GraphicsDevice_DX12::CopyTexture2D(const Texture2D* pDst, const Texture2D* pSrc, CommandList cmd) @@ -3897,36 +3895,55 @@ namespace wiGraphics dataSize = std::min((int)buffer->desc.ByteWidth, dataSize); dataSize = (dataSize >= 0 ? dataSize : buffer->desc.ByteWidth); - size_t alignment = buffer->desc.BindFlags & BIND_CONSTANT_BUFFER ? D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; - - D3D12_RESOURCE_BARRIER barrier = {}; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.Transition.pResource = (ID3D12Resource*)buffer->resource; - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COMMON; - if (buffer->desc.BindFlags & BIND_CONSTANT_BUFFER || buffer->desc.BindFlags & BIND_VERTEX_BUFFER) + if (buffer->desc.Usage == USAGE_DYNAMIC && buffer->desc.BindFlags & BIND_CONSTANT_BUFFER) { - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; + // Dynamic buffer will be used from host memory directly: + DynamicResourceState& state = dynamic_constantbuffers[cmd][buffer]; + state.allocation = AllocateGPU(dataSize, cmd); + memcpy(state.allocation.data, data, dataSize); + + for (int stage = 0; stage < SHADERSTAGE_COUNT; ++stage) + { + if (state.binding[stage]) + { + GetFrameResources().descriptors[cmd]->tables[stage].dirty_resources = true; + } + } } - else if (buffer->desc.BindFlags & BIND_INDEX_BUFFER) + else { - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_INDEX_BUFFER; + // Contents will be transferred to device memory: + + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier.Transition.pResource = (ID3D12Resource*)buffer->resource; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COMMON; + if (buffer->desc.BindFlags & BIND_CONSTANT_BUFFER || buffer->desc.BindFlags & BIND_VERTEX_BUFFER) + { + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; + } + else if (buffer->desc.BindFlags & BIND_INDEX_BUFFER) + { + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_INDEX_BUFFER; + } + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST; + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + GetDirectCommandList(cmd)->ResourceBarrier(1, &barrier); + + uint8_t* dest = GetFrameResources().resourceBuffer[cmd]->allocate(dataSize, 1); + memcpy(dest, data, dataSize); + GetDirectCommandList(cmd)->CopyBufferRegion( + (ID3D12Resource*)buffer->resource, 0, + (ID3D12Resource*)GetFrameResources().resourceBuffer[cmd]->buffer.resource, GetFrameResources().resourceBuffer[cmd]->calculateOffset(dest), + dataSize + ); + + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; + GetDirectCommandList(cmd)->ResourceBarrier(1, &barrier); + } - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST; - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - GetDirectCommandList(cmd)->ResourceBarrier(1, &barrier); - - uint8_t* dest = GetFrameResources().resourceBuffer[cmd]->allocate(dataSize, alignment); - memcpy(dest, data, dataSize); - GetDirectCommandList(cmd)->CopyBufferRegion( - (ID3D12Resource*)buffer->resource, 0, - (ID3D12Resource*)GetFrameResources().resourceBuffer[cmd]->buffer.resource, GetFrameResources().resourceBuffer[cmd]->calculateOffset(dest), - dataSize - ); - - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; - GetDirectCommandList(cmd)->ResourceBarrier(1, &barrier); } @@ -3983,7 +4000,7 @@ namespace wiGraphics return result; } - uint8_t* dest = allocator.allocate(dataSize, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT); + uint8_t* dest = allocator.allocate(dataSize, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT); assert(dest != nullptr); // todo: this needs to be handled as well diff --git a/WickedEngine/wiGraphicsDevice_DX12.h b/WickedEngine/wiGraphicsDevice_DX12.h index db9a4a831..1909ec418 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.h +++ b/WickedEngine/wiGraphicsDevice_DX12.h @@ -6,10 +6,12 @@ #include "wiWindowRegistration.h" #include "wiSpinLock.h" #include "wiContainers.h" +#include "wiGraphicsDevice_SharedInternals.h" #include #include +#include #include #include #include @@ -73,24 +75,45 @@ namespace wiGraphics struct DescriptorTableFrameAllocator { - ID3D12DescriptorHeap* heap_CPU = nullptr; - ID3D12DescriptorHeap* heap_GPU = nullptr; - UINT descriptorType; - UINT itemSize; - UINT itemCount; - UINT ringOffset; - bool dirty[SHADERSTAGE_COUNT]; - wiCPUHandle* boundDescriptors = nullptr; + GraphicsDevice_DX12* device = nullptr; + ID3D12DescriptorHeap* resource_heap_GPU = nullptr; + ID3D12DescriptorHeap* sampler_heap_GPU = nullptr; + UINT ringOffset_resources = 0; + UINT ringOffset_samplers = 0; - DescriptorTableFrameAllocator(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT maxRenameCount); + struct Table + { + const GPUBuffer* CBV[GPU_RESOURCE_HEAP_CBV_COUNT]; + const GPUResource* SRV[GPU_RESOURCE_HEAP_SRV_COUNT]; + int SRV_index[GPU_RESOURCE_HEAP_SRV_COUNT]; + const GPUResource* UAV[GPU_RESOURCE_HEAP_UAV_COUNT]; + int UAV_index[GPU_RESOURCE_HEAP_UAV_COUNT]; + const Sampler* SAM[GPU_SAMPLER_HEAP_COUNT]; + + bool dirty_resources; + bool dirty_samplers; + + void reset() + { + memset(CBV, 0, sizeof(CBV)); + memset(SRV, 0, sizeof(SRV)); + memset(SRV_index, -1, sizeof(SRV_index)); + memset(UAV, 0, sizeof(UAV)); + memset(UAV_index, -1, sizeof(UAV_index)); + memset(SAM, 0, sizeof(SAM)); + dirty_resources = true; + dirty_samplers = true; + } + + } tables[SHADERSTAGE_COUNT]; + + DescriptorTableFrameAllocator(GraphicsDevice_DX12* device, UINT maxRenameCount_resources, UINT maxRenameCount_samplers); ~DescriptorTableFrameAllocator(); - void reset(ID3D12Device* device, D3D12_CPU_DESCRIPTOR_HANDLE* nullDescriptorsSamplerCBVSRVUAV); - void update(SHADERSTAGE stage, UINT slot, wiCPUHandle descriptor, ID3D12Device* device); - void validate(ID3D12Device* device, ID3D12GraphicsCommandList* commandList); + void reset(); + void validate(CommandList cmd); }; - DescriptorTableFrameAllocator* ResourceDescriptorsGPU[COMMANDLIST_COUNT] = {}; - DescriptorTableFrameAllocator* SamplerDescriptorsGPU[COMMANDLIST_COUNT] = {}; + DescriptorTableFrameAllocator* descriptors[COMMANDLIST_COUNT] = {}; struct ResourceFrameAllocator { @@ -112,6 +135,12 @@ namespace wiGraphics FrameResources& GetFrameResources() { return frames[GetFrameCount() % BACKBUFFER_COUNT]; } inline ID3D12GraphicsCommandList* GetDirectCommandList(CommandList cmd) { return static_cast(GetFrameResources().commandLists[cmd]); } + struct DynamicResourceState + { + GPUAllocation allocation; + bool binding[SHADERSTAGE_COUNT] = {}; + }; + std::unordered_map dynamic_constantbuffers[COMMANDLIST_COUNT]; D3D12_CPU_DESCRIPTOR_HANDLE nullSampler = {}; D3D12_CPU_DESCRIPTOR_HANDLE nullCBV = {}; diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index b9a41a564..bcb5b0509 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -792,16 +792,7 @@ namespace wiGraphics bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufferInfo.flags = 0; - - // Allow access from copy queue: - bufferInfo.sharingMode = VK_SHARING_MODE_CONCURRENT; - - uint32_t queueFamilyIndices[] = { - static_cast(queueIndices.graphicsFamily), - static_cast(queueIndices.copyFamily) - }; - bufferInfo.pQueueFamilyIndices = queueFamilyIndices; - bufferInfo.queueFamilyIndexCount = ARRAYSIZE(queueFamilyIndices); + bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; VkResult res = vkCreateBuffer(device, &bufferInfo, nullptr, &resource); @@ -844,9 +835,8 @@ namespace wiGraphics { lock.lock(); - //dataCur = reinterpret_cast(Align(reinterpret_cast(dataCur), alignment)); + dataCur = reinterpret_cast(Align(reinterpret_cast(dataCur), alignment)); - dataSize = Align(dataSize, alignment); assert(dataCur + dataSize <= dataEnd); uint8_t* retVal = dataCur; @@ -929,20 +919,6 @@ namespace wiGraphics } - - // Create staging descriptor table: - { - VkDescriptorSetAllocateInfo allocInfo = {}; - allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - allocInfo.descriptorPool = descriptorPool; - allocInfo.descriptorSetCount = SHADERSTAGE_COUNT; - allocInfo.pSetLayouts = device->defaultDescriptorSetlayouts; - - if (vkAllocateDescriptorSets(device->device, &allocInfo, descriptorSet_CPU) != VK_SUCCESS) { - throw std::runtime_error("failed to allocate descriptor set!"); - } - } - // Create GPU-visible descriptor tables: { VkDescriptorSetAllocateInfo allocInfo = {}; @@ -953,12 +929,14 @@ namespace wiGraphics for (int stage = 0; stage < SHADERSTAGE_COUNT; ++stage) { + Table& table = tables[stage]; + allocInfo.pSetLayouts = &device->defaultDescriptorSetlayouts[stage]; - descriptorSet_GPU[stage].resize(SHADERSTAGE_COUNT * maxRenameCount); + table.descriptorSet_GPU.resize(maxRenameCount); for (uint32_t i = 0; i < maxRenameCount; ++i) { - if (vkAllocateDescriptorSets(device->device, &allocInfo, &descriptorSet_GPU[stage][i]) != VK_SUCCESS) { + if (vkAllocateDescriptorSets(device->device, &allocInfo, &table.descriptorSet_GPU[i]) != VK_SUCCESS) { throw std::runtime_error("failed to allocate descriptor set!"); } } @@ -966,199 +944,6 @@ namespace wiGraphics } - - // Preload default descriptor tables: - - for (int i = 0; i < ARRAYSIZE(bufferInfo); ++i) - { - bufferInfo[i].buffer = device->nullBuffer; - bufferInfo[i].offset = 0; - bufferInfo[i].range = VK_WHOLE_SIZE; - } - - for (int i = 0; i < ARRAYSIZE(imageInfo); ++i) - { - imageInfo[i].imageView = device->nullImageView; - imageInfo[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - } - - for (int i = 0; i < ARRAYSIZE(bufferViews); ++i) - { - bufferViews[i] = device->nullBufferView; - } - - for (int i = 0; i < ARRAYSIZE(samplerInfo); ++i) - { - samplerInfo[i].imageView = VK_NULL_HANDLE; - samplerInfo[i].sampler = device->nullSampler; - } - - - for (int stage = 0; stage < SHADERSTAGE_COUNT; ++stage) - { - int offset = 0; - - // CBV: - { - assert(offset == VULKAN_DESCRIPTOR_SET_OFFSET_CBV); - - VkWriteDescriptorSet writeDescriptors = {}; - writeDescriptors.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptors.dstSet = descriptorSet_CPU[stage]; - writeDescriptors.dstArrayElement = 0; - writeDescriptors.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - writeDescriptors.dstBinding = offset; - writeDescriptors.descriptorCount = GPU_RESOURCE_HEAP_CBV_COUNT; - writeDescriptors.pBufferInfo = bufferInfo; - writeDescriptors.pImageInfo = nullptr; - writeDescriptors.pTexelBufferView = nullptr; - initWrites[stage].push_back(writeDescriptors); - - offset += writeDescriptors.descriptorCount; - - } - - // SRV - Texture: - { - assert(offset == VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TEXTURE); - - VkWriteDescriptorSet writeDescriptors = {}; - writeDescriptors.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptors.dstSet = descriptorSet_CPU[stage]; - writeDescriptors.dstArrayElement = 0; - writeDescriptors.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - writeDescriptors.dstBinding = offset; - writeDescriptors.descriptorCount = GPU_RESOURCE_HEAP_SRV_COUNT; - writeDescriptors.pBufferInfo = nullptr; - writeDescriptors.pImageInfo = imageInfo; - writeDescriptors.pTexelBufferView = nullptr; - initWrites[stage].push_back(writeDescriptors); - - offset += writeDescriptors.descriptorCount; - - } - // SRV - Typed Buffer: - { - assert(offset == VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TYPEDBUFFER); - - VkWriteDescriptorSet writeDescriptors = {}; - writeDescriptors.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptors.dstSet = descriptorSet_CPU[stage]; - writeDescriptors.dstArrayElement = 0; - writeDescriptors.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - writeDescriptors.dstBinding = offset; - writeDescriptors.descriptorCount = GPU_RESOURCE_HEAP_SRV_COUNT; - writeDescriptors.pBufferInfo = nullptr; - writeDescriptors.pImageInfo = nullptr; - writeDescriptors.pTexelBufferView = bufferViews; - initWrites[stage].push_back(writeDescriptors); - - offset += writeDescriptors.descriptorCount; - - } - // SRV - Untyped Buffer: - { - assert(offset == VULKAN_DESCRIPTOR_SET_OFFSET_SRV_UNTYPEDBUFFER); - - VkWriteDescriptorSet writeDescriptors = {}; - writeDescriptors.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptors.dstSet = descriptorSet_CPU[stage]; - writeDescriptors.dstArrayElement = 0; - writeDescriptors.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - writeDescriptors.dstBinding = offset; - writeDescriptors.descriptorCount = GPU_RESOURCE_HEAP_SRV_COUNT; - writeDescriptors.pBufferInfo = bufferInfo; - writeDescriptors.pImageInfo = nullptr; - writeDescriptors.pTexelBufferView = nullptr; - initWrites[stage].push_back(writeDescriptors); - - offset += writeDescriptors.descriptorCount; - - } - - // UAV - Texture: - { - assert(offset == VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TEXTURE); - - VkWriteDescriptorSet writeDescriptors = {}; - writeDescriptors.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptors.dstSet = descriptorSet_CPU[stage]; - writeDescriptors.dstArrayElement = 0; - writeDescriptors.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - writeDescriptors.dstBinding = offset; - writeDescriptors.descriptorCount = GPU_RESOURCE_HEAP_UAV_COUNT; - writeDescriptors.pBufferInfo = nullptr; - writeDescriptors.pImageInfo = imageInfo; - writeDescriptors.pTexelBufferView = nullptr; - initWrites[stage].push_back(writeDescriptors); - - offset += writeDescriptors.descriptorCount; - - } - // UAV - Typed Buffer: - { - assert(offset == VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TYPEDBUFFER); - - VkWriteDescriptorSet writeDescriptors = {}; - writeDescriptors.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptors.dstSet = descriptorSet_CPU[stage]; - writeDescriptors.dstArrayElement = 0; - writeDescriptors.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - writeDescriptors.dstBinding = offset; - writeDescriptors.descriptorCount = GPU_RESOURCE_HEAP_UAV_COUNT; - writeDescriptors.pBufferInfo = nullptr; - writeDescriptors.pImageInfo = nullptr; - writeDescriptors.pTexelBufferView = bufferViews; - initWrites[stage].push_back(writeDescriptors); - - offset += writeDescriptors.descriptorCount; - - } - // UAV - Untyped Buffer: - { - assert(offset == VULKAN_DESCRIPTOR_SET_OFFSET_UAV_UNTYPEDBUFFER); - - VkWriteDescriptorSet writeDescriptors = {}; - writeDescriptors.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptors.dstSet = descriptorSet_CPU[stage]; - writeDescriptors.dstArrayElement = 0; - writeDescriptors.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - writeDescriptors.dstBinding = offset; - writeDescriptors.descriptorCount = GPU_RESOURCE_HEAP_UAV_COUNT; - writeDescriptors.pBufferInfo = bufferInfo; - writeDescriptors.pImageInfo = nullptr; - writeDescriptors.pTexelBufferView = nullptr; - initWrites[stage].push_back(writeDescriptors); - - offset += writeDescriptors.descriptorCount; - - } - - - // Sampler: - { - assert(offset == VULKAN_DESCRIPTOR_SET_OFFSET_SAMPLER); - - VkWriteDescriptorSet writeDescriptors = {}; - writeDescriptors.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptors.dstSet = descriptorSet_CPU[stage]; - writeDescriptors.dstArrayElement = 0; - writeDescriptors.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - writeDescriptors.dstBinding = offset; - writeDescriptors.descriptorCount = GPU_SAMPLER_HEAP_COUNT; - writeDescriptors.pBufferInfo = nullptr; - writeDescriptors.pImageInfo = samplerInfo; - writeDescriptors.pTexelBufferView = nullptr; - initWrites[stage].push_back(writeDescriptors); - - offset += writeDescriptors.descriptorCount; - - } - - boundDescriptors[stage].resize(offset); - } - - reset(); } @@ -1170,145 +955,400 @@ namespace wiGraphics { for (int stage = 0; stage < SHADERSTAGE_COUNT; ++stage) { - ringOffset[stage] = 0; - dirty[stage] = true; - - - // STAGING CPU descriptor table needs to be initialized: - vkUpdateDescriptorSets(device->device, static_cast(initWrites[stage].size()), initWrites[stage].data(), 0, nullptr); - - std::fill(boundDescriptors[stage].begin(), boundDescriptors[stage].end(), WI_NULL_HANDLE); - + tables[stage].reset(); } } - void GraphicsDevice_Vulkan::FrameResources::DescriptorTableFrameAllocator::validate(VkCommandBuffer commandList) + void GraphicsDevice_Vulkan::FrameResources::DescriptorTableFrameAllocator::validate(CommandList cmd) { for (int stage = 0; stage < SHADERSTAGE_COUNT; ++stage) { - if (dirty[stage]) + Table& table = tables[stage]; + if (table.dirty) { + table.dirty = false; - // 1.) Copy descriptors from STAGING -> to GPU visible table: + // allocate all the descriptor writes for the whole table layout on the stack to reduce calling of vkUpdateDescriptorSets(): + const int writeCount = + GPU_RESOURCE_HEAP_CBV_COUNT + + GPU_RESOURCE_HEAP_SRV_COUNT * 3 + + GPU_RESOURCE_HEAP_UAV_COUNT * 3 + + GPU_SAMPLER_HEAP_COUNT; + VkWriteDescriptorSet descriptorWrites[writeCount]; + VkDescriptorBufferInfo bufferInfos[writeCount]; + VkDescriptorImageInfo imageInfos[writeCount]; + VkBufferView texelBufferViews[writeCount]; - VkCopyDescriptorSet copyDescriptors[8] = {}; - - // CBV: + for (int slot = 0; slot < GPU_RESOURCE_HEAP_CBV_COUNT; ++slot) { - copyDescriptors[0].sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copyDescriptors[0].descriptorCount = GPU_RESOURCE_HEAP_CBV_COUNT; - copyDescriptors[0].srcSet = descriptorSet_CPU[stage]; - copyDescriptors[0].srcBinding = VULKAN_DESCRIPTOR_SET_OFFSET_CBV; - copyDescriptors[0].srcArrayElement = 0; - copyDescriptors[0].dstSet = descriptorSet_GPU[stage][ringOffset[stage]]; - copyDescriptors[0].dstBinding = VULKAN_DESCRIPTOR_SET_OFFSET_CBV; - copyDescriptors[0].dstArrayElement = 0; + const GPUBuffer* buffer = table.CBV[slot]; + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_CBV + slot; + + bufferInfos[binding] = {}; + if (buffer != nullptr) + { + bufferInfos[binding].range = buffer->desc.ByteWidth; + if (buffer->desc.Usage == USAGE_DYNAMIC) + { + auto it = device->dynamic_constantbuffers[cmd].find(buffer); + if (it != device->dynamic_constantbuffers[cmd].end()) + { + DynamicResourceState& state = it->second; + bufferInfos[binding].buffer = (VkBuffer)state.allocation.buffer->resource; + bufferInfos[binding].offset = state.allocation.offset; + state.binding[stage] = true; + } + } + else + { + bufferInfos[binding].buffer = (VkBuffer)buffer->resource; + bufferInfos[binding].offset = 0; + } + } + + if(bufferInfos[binding].buffer == VK_NULL_HANDLE) + { + bufferInfos[binding].buffer = device->nullBuffer; + bufferInfos[binding].offset = 0; + bufferInfos[binding].range = VK_WHOLE_SIZE; + } + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = &bufferInfos[binding]; + descriptorWrites[binding].pImageInfo = nullptr; + descriptorWrites[binding].pTexelBufferView = nullptr; } - // SRV - Texture: + for (int slot = 0; slot < GPU_RESOURCE_HEAP_SRV_COUNT; ++slot) { - copyDescriptors[1].sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copyDescriptors[1].descriptorCount = GPU_RESOURCE_HEAP_SRV_COUNT; - copyDescriptors[1].srcSet = descriptorSet_CPU[stage]; - copyDescriptors[1].srcBinding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TEXTURE; - copyDescriptors[1].srcArrayElement = 0; - copyDescriptors[1].dstSet = descriptorSet_GPU[stage][ringOffset[stage]]; - copyDescriptors[1].dstBinding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TEXTURE; - copyDescriptors[1].dstArrayElement = 0; - } - // SRV - Typed Buffer: - { - copyDescriptors[2].sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copyDescriptors[2].descriptorCount = GPU_RESOURCE_HEAP_SRV_COUNT; - copyDescriptors[2].srcSet = descriptorSet_CPU[stage]; - copyDescriptors[2].srcBinding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TYPEDBUFFER; - copyDescriptors[2].srcArrayElement = 0; - copyDescriptors[2].dstSet = descriptorSet_GPU[stage][ringOffset[stage]]; - copyDescriptors[2].dstBinding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TYPEDBUFFER; - copyDescriptors[2].dstArrayElement = 0; - } - // SRV - Untyped Buffer: - { - copyDescriptors[3].sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copyDescriptors[3].descriptorCount = GPU_RESOURCE_HEAP_SRV_COUNT; - copyDescriptors[3].srcSet = descriptorSet_CPU[stage]; - copyDescriptors[3].srcBinding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_UNTYPEDBUFFER; - copyDescriptors[3].srcArrayElement = 0; - copyDescriptors[3].dstSet = descriptorSet_GPU[stage][ringOffset[stage]]; - copyDescriptors[3].dstBinding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_UNTYPEDBUFFER; - copyDescriptors[3].dstArrayElement = 0; + // first fill all with null: + { + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TEXTURE + slot; + + imageInfos[binding] = {}; + imageInfos[binding].imageView = device->nullImageView; + imageInfos[binding].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = nullptr; + descriptorWrites[binding].pImageInfo = &imageInfos[binding]; + descriptorWrites[binding].pTexelBufferView = nullptr; + } + { + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_UNTYPEDBUFFER + slot; + + bufferInfos[binding] = {}; + bufferInfos[binding].buffer = device->nullBuffer; + bufferInfos[binding].offset = 0; + bufferInfos[binding].range = VK_WHOLE_SIZE; + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = &bufferInfos[binding]; + descriptorWrites[binding].pImageInfo = nullptr; + descriptorWrites[binding].pTexelBufferView = nullptr; + } + { + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TYPEDBUFFER + slot; + + texelBufferViews[binding] = device->nullBufferView; + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = nullptr; + descriptorWrites[binding].pImageInfo = nullptr; + descriptorWrites[binding].pTexelBufferView = &texelBufferViews[binding]; + } + + const GPUResource* resource = table.SRV[slot]; + const int arrayIndex = table.SRV_index[slot]; + if (resource == nullptr) + { + continue; + } + + wiCPUHandle SRV = arrayIndex < 0 ? resource->SRV : resource->additionalSRVs[arrayIndex]; + + if (resource->IsTexture() && resource->SRV != VK_NULL_HANDLE) + { + // Texture: + + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TEXTURE + slot; + + imageInfos[binding] = {}; + imageInfos[binding].imageView = (VkImageView)resource->SRV; + imageInfos[binding].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = nullptr; + descriptorWrites[binding].pImageInfo = &imageInfos[binding]; + descriptorWrites[binding].pTexelBufferView = nullptr; + } + else if(resource->IsBuffer()) + { + // Buffer: + const GPUBuffer* buffer = (const GPUBuffer*)resource; + + if (buffer->desc.Format == FORMAT_UNKNOWN && buffer->resource != WI_NULL_HANDLE) + { + // structured buffer, raw buffer: + + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_UNTYPEDBUFFER + slot; + + bufferInfos[binding] = {}; + bufferInfos[binding].buffer = (VkBuffer)buffer->resource; + bufferInfos[binding].offset = 0; + bufferInfos[binding].range = buffer->desc.ByteWidth; + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = &bufferInfos[binding]; + descriptorWrites[binding].pImageInfo = nullptr; + descriptorWrites[binding].pTexelBufferView = nullptr; + + } + else if (resource->SRV != VK_NULL_HANDLE) + { + // typed buffer: + + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TYPEDBUFFER + slot; + + texelBufferViews[binding] = (VkBufferView)SRV; + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = nullptr; + descriptorWrites[binding].pImageInfo = nullptr; + descriptorWrites[binding].pTexelBufferView = &texelBufferViews[binding]; + } + + } } - // UAV - Texture: + for (int slot = 0; slot < GPU_RESOURCE_HEAP_UAV_COUNT; ++slot) { - copyDescriptors[4].sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copyDescriptors[4].descriptorCount = GPU_RESOURCE_HEAP_UAV_COUNT; - copyDescriptors[4].srcSet = descriptorSet_CPU[stage]; - copyDescriptors[4].srcBinding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TEXTURE; - copyDescriptors[4].srcArrayElement = 0; - copyDescriptors[4].dstSet = descriptorSet_GPU[stage][ringOffset[stage]]; - copyDescriptors[4].dstBinding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TEXTURE; - copyDescriptors[4].dstArrayElement = 0; - } - // UAV - Typed Buffer: - { - copyDescriptors[5].sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copyDescriptors[5].descriptorCount = GPU_RESOURCE_HEAP_UAV_COUNT; - copyDescriptors[5].srcSet = descriptorSet_CPU[stage]; - copyDescriptors[5].srcBinding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TYPEDBUFFER; - copyDescriptors[5].srcArrayElement = 0; - copyDescriptors[5].dstSet = descriptorSet_GPU[stage][ringOffset[stage]]; - copyDescriptors[5].dstBinding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TYPEDBUFFER; - copyDescriptors[5].dstArrayElement = 0; - } - // UAV - Untyped Buffer: - { - copyDescriptors[6].sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copyDescriptors[6].descriptorCount = GPU_RESOURCE_HEAP_UAV_COUNT; - copyDescriptors[6].srcSet = descriptorSet_CPU[stage]; - copyDescriptors[6].srcBinding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_UNTYPEDBUFFER; - copyDescriptors[6].srcArrayElement = 0; - copyDescriptors[6].dstSet = descriptorSet_GPU[stage][ringOffset[stage]]; - copyDescriptors[6].dstBinding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_UNTYPEDBUFFER; - copyDescriptors[6].dstArrayElement = 0; + // first fill all with null: + { + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TEXTURE + slot; + + imageInfos[binding] = {}; + imageInfos[binding].imageView = device->nullImageView; + imageInfos[binding].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = nullptr; + descriptorWrites[binding].pImageInfo = &imageInfos[binding]; + descriptorWrites[binding].pTexelBufferView = nullptr; + } + { + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_UNTYPEDBUFFER + slot; + + bufferInfos[binding] = {}; + bufferInfos[binding].buffer = device->nullBuffer; + bufferInfos[binding].offset = 0; + bufferInfos[binding].range = VK_WHOLE_SIZE; + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = &bufferInfos[binding]; + descriptorWrites[binding].pImageInfo = nullptr; + descriptorWrites[binding].pTexelBufferView = nullptr; + } + { + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TYPEDBUFFER + slot; + + texelBufferViews[binding] = device->nullBufferView; + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = nullptr; + descriptorWrites[binding].pImageInfo = nullptr; + descriptorWrites[binding].pTexelBufferView = &texelBufferViews[binding]; + } + + const GPUResource* resource = table.UAV[slot]; + const int arrayIndex = table.UAV_index[slot]; + if (resource == nullptr) + { + continue; + } + + wiCPUHandle UAV = arrayIndex < 0 ? resource->UAV : resource->additionalUAVs[arrayIndex]; + + if (resource->IsTexture() && resource->UAV != VK_NULL_HANDLE) + { + // Texture: + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TEXTURE + slot; + + imageInfos[binding] = {}; + imageInfos[binding].imageView = (VkImageView)UAV; + imageInfos[binding].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = nullptr; + descriptorWrites[binding].pImageInfo = &imageInfos[binding]; + descriptorWrites[binding].pTexelBufferView = nullptr; + } + else if (resource->IsBuffer()) + { + // Buffer: + const GPUBuffer* buffer = (const GPUBuffer*)resource; + + if (buffer->desc.Format == FORMAT_UNKNOWN && buffer->resource != WI_NULL_HANDLE) + { + // structured buffer, raw buffer: + + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_UNTYPEDBUFFER + slot; + + bufferInfos[binding] = {}; + bufferInfos[binding].buffer = (VkBuffer)buffer->resource; + bufferInfos[binding].offset = 0; + bufferInfos[binding].range = buffer->desc.ByteWidth; + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = &bufferInfos[binding]; + descriptorWrites[binding].pImageInfo = nullptr; + descriptorWrites[binding].pTexelBufferView = nullptr; + + } + else if (resource->UAV != VK_NULL_HANDLE) + { + // typed buffer: + + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TYPEDBUFFER + slot; + + texelBufferViews[binding] = (VkBufferView)UAV; + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = nullptr; + descriptorWrites[binding].pImageInfo = nullptr; + descriptorWrites[binding].pTexelBufferView = &texelBufferViews[binding]; + + } + + } } - // Sampler: + for (int slot = 0; slot < GPU_SAMPLER_HEAP_COUNT; ++slot) { - copyDescriptors[7].sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copyDescriptors[7].descriptorCount = GPU_SAMPLER_HEAP_COUNT; - copyDescriptors[7].srcSet = descriptorSet_CPU[stage]; - copyDescriptors[7].srcBinding = VULKAN_DESCRIPTOR_SET_OFFSET_SAMPLER; - copyDescriptors[7].srcArrayElement = 0; - copyDescriptors[7].dstSet = descriptorSet_GPU[stage][ringOffset[stage]]; - copyDescriptors[7].dstBinding = VULKAN_DESCRIPTOR_SET_OFFSET_SAMPLER; - copyDescriptors[7].dstArrayElement = 0; + const Sampler* sampler = table.SAM[slot]; + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SAMPLER + slot; + + imageInfos[binding] = {}; + imageInfos[binding].imageView = VK_NULL_HANDLE; + + if (sampler == nullptr || sampler->resource == WI_NULL_HANDLE) + { + imageInfos[binding].sampler = device->nullSampler; + } + else + { + imageInfos[binding].sampler = (VkSampler)sampler->resource; + } + + descriptorWrites[binding] = {}; + descriptorWrites[binding].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[binding].dstSet = table.descriptorSet_GPU[table.ringOffset]; + descriptorWrites[binding].dstBinding = binding; + descriptorWrites[binding].dstArrayElement = 0; + descriptorWrites[binding].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; + descriptorWrites[binding].descriptorCount = 1; + descriptorWrites[binding].pBufferInfo = nullptr; + descriptorWrites[binding].pImageInfo = &imageInfos[binding]; + descriptorWrites[binding].pTexelBufferView = nullptr; } - vkUpdateDescriptorSets(device->device, 0, nullptr, ARRAYSIZE(copyDescriptors), copyDescriptors); - + vkUpdateDescriptorSets(device->device, writeCount, descriptorWrites, 0, nullptr); // 2.) Bind GPU visible descriptor table which we just updated: if (stage == CS) { - vkCmdBindDescriptorSets(commandList, VK_PIPELINE_BIND_POINT_COMPUTE, device->defaultPipelineLayout_Compute, 0, 1, &descriptorSet_GPU[stage][ringOffset[stage]], 0, nullptr); + vkCmdBindDescriptorSets(device->GetDirectCommandList(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, device->defaultPipelineLayout_Compute, 0, 1, &table.descriptorSet_GPU[table.ringOffset], 0, nullptr); } else { - vkCmdBindDescriptorSets(commandList, VK_PIPELINE_BIND_POINT_GRAPHICS, device->defaultPipelineLayout_Graphics, stage, 1, &descriptorSet_GPU[stage][ringOffset[stage]], 0, nullptr); + vkCmdBindDescriptorSets(device->GetDirectCommandList(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, device->defaultPipelineLayout_Graphics, stage, 1, &table.descriptorSet_GPU[table.ringOffset], 0, nullptr); } - - // mark the descriptors of this stage as up to date - dirty[stage] = false; - // allocate next chunk for GPU visible descriptor table: - ringOffset[stage]++; + table.ringOffset++; - if (ringOffset[stage] >= descriptorSet_GPU[stage].size()) + if (table.ringOffset >= table.descriptorSet_GPU.size()) { // ran out of descriptor allocation space, stall CPU and wrap the ring buffer: assert(0 && "TODO Stall"); - ringOffset[stage] = 0; + table.ringOffset = 0; } } @@ -2326,7 +2366,7 @@ namespace wiGraphics for (int cmd = 0; cmd < COMMANDLIST_COUNT; ++cmd) { - SAFE_DELETE(frame.ResourceDescriptorsGPU[cmd]); + SAFE_DELETE(frame.descriptors[cmd]); SAFE_DELETE(frame.resourceBuffer[cmd]); } } @@ -2421,13 +2461,7 @@ namespace wiGraphics bufferInfo.flags = 0; - uint32_t queueFamilyIndices[] = { - static_cast(queueIndices.graphicsFamily), - static_cast(queueIndices.copyFamily) - }; - bufferInfo.pQueueFamilyIndices = queueFamilyIndices; - bufferInfo.queueFamilyIndexCount = ARRAYSIZE(queueFamilyIndices); - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; // either owned by copy queue OR graphics queue, but not both at the same time + bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -2463,10 +2497,10 @@ namespace wiGraphics copyQueueLock.lock(); { uint8_t* dest = bufferUploader->allocate(static_cast(memRequirements.size), static_cast(memRequirements.alignment)); - memcpy(dest, pInitialData->pSysMem, static_cast(memRequirements.size)); + memcpy(dest, pInitialData->pSysMem, pBuffer->desc.ByteWidth); VkBufferCopy copyRegion = {}; - copyRegion.size = memRequirements.size; + copyRegion.size = pBuffer->desc.ByteWidth; copyRegion.srcOffset = bufferUploader->calculateOffset(dest); copyRegion.dstOffset = 0; @@ -2635,14 +2669,7 @@ namespace wiGraphics imageInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; } - - uint32_t queueFamilyIndices[] = { - static_cast(queueIndices.graphicsFamily), - static_cast(queueIndices.copyFamily) - }; - imageInfo.pQueueFamilyIndices = queueFamilyIndices; - imageInfo.queueFamilyIndexCount = ARRAYSIZE(queueFamilyIndices); - imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; // either owned by copy queue OR graphics queue, but not both at the same time + imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; VkResult res; res = vkCreateImage(device, &imageInfo, nullptr, reinterpret_cast(&pTexture2D->resource)); @@ -4597,7 +4624,7 @@ namespace wiGraphics } frame.resourceBuffer[cmd] = new FrameResources::ResourceFrameAllocator(physicalDevice, device, 4 * 1024 * 1024); - frame.ResourceDescriptorsGPU[cmd] = new FrameResources::DescriptorTableFrameAllocator(this, 1024); + frame.descriptors[cmd] = new FrameResources::DescriptorTableFrameAllocator(this, 1024); } } @@ -4639,7 +4666,7 @@ namespace wiGraphics vkCmdSetBlendConstants(GetDirectCommandList(static_cast(cmd)), blendConstants); // reset descriptor allocators: - GetFrameResources().ResourceDescriptorsGPU[cmd]->reset(); + GetFrameResources().descriptors[cmd]->reset(); // reset immediate resource allocators: GetFrameResources().resourceBuffer[cmd]->clear(); @@ -4765,108 +4792,13 @@ namespace wiGraphics void GraphicsDevice_Vulkan::BindResource(SHADERSTAGE stage, const GPUResource* resource, UINT slot, CommandList cmd, int arrayIndex) { assert(slot < GPU_RESOURCE_HEAP_SRV_COUNT); - - if (resource != nullptr && resource->resource != VK_NULL_HANDLE) + auto& table = GetFrameResources().descriptors[cmd]->tables[stage]; + if (table.SRV[slot] != resource || table.SRV_index[slot] != arrayIndex) { - wiCPUHandle SRV = arrayIndex < 0 ? resource->SRV : resource->additionalSRVs[arrayIndex]; - - if (resource->IsTexture() && resource->SRV != VK_NULL_HANDLE) - { - // Texture: - - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TEXTURE + slot; - - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == SRV) - { - return; - } - - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageView = (VkImageView)resource->SRV; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = nullptr; - descriptorWrite.pImageInfo = &imageInfo; - descriptorWrite.pTexelBufferView = nullptr; - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); - GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = SRV; - } - else - { - // Buffer: - const GPUBuffer* buffer = (const GPUBuffer*)resource; - - if (buffer->desc.Format == FORMAT_UNKNOWN) - { - // structured buffer, raw buffer: - - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_UNTYPEDBUFFER + slot; - - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == buffer->resource) - { - return; - } - - VkDescriptorBufferInfo bufferInfo = {}; - bufferInfo.buffer = (VkBuffer)buffer->resource; - bufferInfo.offset = 0; - bufferInfo.range = buffer->desc.ByteWidth; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = &bufferInfo; - descriptorWrite.pImageInfo = nullptr; - descriptorWrite.pTexelBufferView = nullptr; - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); - GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = buffer->resource; - - } - else if (resource->SRV != VK_NULL_HANDLE) - { - // typed buffer: - - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TYPEDBUFFER + slot; - - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == SRV) - { - return; - } - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = nullptr; - descriptorWrite.pImageInfo = nullptr; - descriptorWrite.pTexelBufferView = reinterpret_cast(&SRV); - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); - GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = SRV; - } - - } + table.SRV[slot] = resource; + table.SRV_index[slot] = arrayIndex; + table.dirty = true; } - } void GraphicsDevice_Vulkan::BindResources(SHADERSTAGE stage, const GPUResource *const* resources, UINT slot, UINT count, CommandList cmd) { @@ -4881,108 +4813,13 @@ namespace wiGraphics void GraphicsDevice_Vulkan::BindUAV(SHADERSTAGE stage, const GPUResource* resource, UINT slot, CommandList cmd, int arrayIndex) { assert(slot < GPU_RESOURCE_HEAP_UAV_COUNT); - - if (resource != nullptr && resource->resource != VK_NULL_HANDLE) + auto& table = GetFrameResources().descriptors[cmd]->tables[stage]; + if (table.UAV[slot] != resource || table.UAV_index[slot] != arrayIndex) { - wiCPUHandle UAV = arrayIndex < 0 ? resource->UAV : resource->additionalUAVs[arrayIndex]; - - if (resource->IsTexture() && resource->UAV != VK_NULL_HANDLE) - { - // Texture: - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TEXTURE + slot; - - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == UAV) - { - return; - } - - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageView = (VkImageView)UAV; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = nullptr; - descriptorWrite.pImageInfo = &imageInfo; - descriptorWrite.pTexelBufferView = nullptr; - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); - GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = UAV; - } - else - { - // Buffer: - const GPUBuffer* buffer = (const GPUBuffer*)resource; - - if (buffer->desc.Format == FORMAT_UNKNOWN) - { - // structured buffer, raw buffer: - - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_UNTYPEDBUFFER + slot; - - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == buffer->resource) - { - return; - } - - VkDescriptorBufferInfo bufferInfo = {}; - bufferInfo.buffer = (VkBuffer)buffer->resource; - bufferInfo.offset = 0; - bufferInfo.range = buffer->desc.ByteWidth; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = &bufferInfo; - descriptorWrite.pImageInfo = nullptr; - descriptorWrite.pTexelBufferView = nullptr; - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); - GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = buffer->resource; - - } - else if (resource->UAV != VK_NULL_HANDLE) - { - // typed buffer: - - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TYPEDBUFFER + slot; - - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == UAV) - { - return; - } - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = nullptr; - descriptorWrite.pImageInfo = nullptr; - descriptorWrite.pTexelBufferView = reinterpret_cast(&UAV); - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); - GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = UAV; - - } - - } + table.UAV[slot] = resource; + table.UAV_index[slot] = arrayIndex; + table.dirty = true; } - } void GraphicsDevice_Vulkan::BindUAVs(SHADERSTAGE stage, const GPUResource *const* resources, UINT slot, UINT count, CommandList cmd) { @@ -5003,68 +4840,21 @@ namespace wiGraphics void GraphicsDevice_Vulkan::BindSampler(SHADERSTAGE stage, const Sampler* sampler, UINT slot, CommandList cmd) { assert(slot < GPU_SAMPLER_HEAP_COUNT); - - if (sampler != nullptr && sampler->resource != VK_NULL_HANDLE) + auto& table = GetFrameResources().descriptors[cmd]->tables[stage]; + if (table.SAM[slot] != sampler) { - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SAMPLER + slot; - - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == sampler->resource) - { - return; - } - - VkDescriptorImageInfo imageInfo = {}; - imageInfo.sampler = (VkSampler)sampler->resource; - imageInfo.imageView = VK_NULL_HANDLE; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = nullptr; - descriptorWrite.pImageInfo = &imageInfo; - descriptorWrite.pTexelBufferView = nullptr; - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); - GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = sampler->resource; + table.SAM[slot] = sampler; + table.dirty = true; } } void GraphicsDevice_Vulkan::BindConstantBuffer(SHADERSTAGE stage, const GPUBuffer* buffer, UINT slot, CommandList cmd) { assert(slot < GPU_RESOURCE_HEAP_CBV_COUNT); - - if (buffer != nullptr && buffer->resource != VK_NULL_HANDLE) + auto& table = GetFrameResources().descriptors[cmd]->tables[stage]; + if (buffer->desc.Usage == USAGE_DYNAMIC || table.CBV[slot] != buffer) { - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_CBV + slot; - - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == buffer->resource) - { - return; - } - - VkDescriptorBufferInfo bufferInfo = {}; - bufferInfo.buffer = (VkBuffer)buffer->resource; - bufferInfo.offset = 0; - bufferInfo.range = buffer->desc.ByteWidth; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = &bufferInfo; - descriptorWrite.pImageInfo = nullptr; - descriptorWrite.pTexelBufferView = nullptr; - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); - GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = buffer->resource; + table.CBV[slot] = buffer; + table.dirty = true; } } void GraphicsDevice_Vulkan::BindVertexBuffers(const GPUBuffer *const* vertexBuffers, UINT slot, UINT count, const UINT* strides, const UINT* offsets, CommandList cmd) @@ -5111,25 +4901,25 @@ namespace wiGraphics void GraphicsDevice_Vulkan::Draw(UINT vertexCount, UINT startVertexLocation, CommandList cmd) { renderPass[cmd].validate(device, GetDirectCommandList(cmd)); - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); vkCmdDraw(GetDirectCommandList(cmd), static_cast(vertexCount), 1, startVertexLocation, 0); } void GraphicsDevice_Vulkan::DrawIndexed(UINT indexCount, UINT startIndexLocation, UINT baseVertexLocation, CommandList cmd) { renderPass[cmd].validate(device, GetDirectCommandList(cmd)); - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); vkCmdDrawIndexed(GetDirectCommandList(cmd), static_cast(indexCount), 1, startIndexLocation, baseVertexLocation, 0); } void GraphicsDevice_Vulkan::DrawInstanced(UINT vertexCount, UINT instanceCount, UINT startVertexLocation, UINT startInstanceLocation, CommandList cmd) { renderPass[cmd].validate(device, GetDirectCommandList(cmd)); - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); vkCmdDraw(GetDirectCommandList(cmd), static_cast(vertexCount), static_cast(instanceCount), startVertexLocation, startInstanceLocation); } void GraphicsDevice_Vulkan::DrawIndexedInstanced(UINT indexCount, UINT instanceCount, UINT startIndexLocation, UINT baseVertexLocation, UINT startInstanceLocation, CommandList cmd) { renderPass[cmd].validate(device, GetDirectCommandList(cmd)); - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); vkCmdDrawIndexed(GetDirectCommandList(cmd), static_cast(indexCount), static_cast(instanceCount), startIndexLocation, baseVertexLocation, startInstanceLocation); } void GraphicsDevice_Vulkan::DrawInstancedIndirect(const GPUBuffer* args, UINT args_offset, CommandList cmd) @@ -5142,7 +4932,7 @@ namespace wiGraphics { renderPass[cmd].disable(GetDirectCommandList(cmd)); - GetFrameResources().ResourceDescriptorsGPU[cmd]->validate(GetDirectCommandList(cmd)); + GetFrameResources().descriptors[cmd]->validate(cmd); vkCmdDispatch(GetDirectCommandList(cmd), threadGroupCountX, threadGroupCountY, threadGroupCountZ); } void GraphicsDevice_Vulkan::DispatchIndirect(const GPUBuffer* args, UINT args_offset, CommandList cmd) @@ -5204,86 +4994,104 @@ namespace wiGraphics dataSize = (dataSize >= 0 ? dataSize : buffer->desc.ByteWidth); - - renderPass[cmd].disable(GetDirectCommandList(cmd)); - - - - // barrier to transfer: - - VkPipelineStageFlags stages = 0; - - VkBufferMemoryBarrier barrier = {}; - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - barrier.buffer = (VkBuffer)buffer->resource; - barrier.srcAccessMask = 0; - if (buffer->desc.BindFlags & BIND_CONSTANT_BUFFER) + if (buffer->desc.Usage == USAGE_DYNAMIC && buffer->desc.BindFlags & BIND_CONSTANT_BUFFER) { - barrier.srcAccessMask |= VK_ACCESS_UNIFORM_READ_BIT; - stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + // Dynamic buffer will be used from host memory directly: + DynamicResourceState& state = dynamic_constantbuffers[cmd][buffer]; + state.allocation = AllocateGPU(dataSize, cmd); + memcpy(state.allocation.data, data, dataSize); + + for (int stage = 0; stage < SHADERSTAGE_COUNT; ++stage) + { + if (state.binding[stage]) + { + GetFrameResources().descriptors[cmd]->tables[stage].dirty = true; + } + } } - if (buffer->desc.BindFlags & BIND_VERTEX_BUFFER) + else { - barrier.srcAccessMask |= VK_ACCESS_INDEX_READ_BIT; - stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + // Contents will be transferred to device memory: + + renderPass[cmd].disable(GetDirectCommandList(cmd)); + + + // barrier to transfer: + + VkPipelineStageFlags stages = 0; + + VkBufferMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.buffer = (VkBuffer)buffer->resource; + barrier.srcAccessMask = 0; + if (buffer->desc.BindFlags & BIND_CONSTANT_BUFFER) + { + barrier.srcAccessMask |= VK_ACCESS_UNIFORM_READ_BIT; + stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + } + if (buffer->desc.BindFlags & BIND_VERTEX_BUFFER) + { + barrier.srcAccessMask |= VK_ACCESS_INDEX_READ_BIT; + stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + } + if (buffer->desc.BindFlags & BIND_INDEX_BUFFER) + { + barrier.srcAccessMask |= VK_ACCESS_INDEX_READ_BIT; + stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + } + if (buffer->desc.BindFlags & BIND_SHADER_RESOURCE) + { + barrier.srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; + stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + } + if (buffer->desc.BindFlags & BIND_UNORDERED_ACCESS) + { + barrier.srcAccessMask |= VK_ACCESS_SHADER_WRITE_BIT; + stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + } + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + + vkCmdPipelineBarrier( + GetDirectCommandList(cmd), + stages, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_DEPENDENCY_BY_REGION_BIT, + 0, nullptr, + 1, &barrier, + 0, nullptr + ); + + + // issue data copy: + uint8_t* dest = GetFrameResources().resourceBuffer[cmd]->allocate(dataSize, 1); + memcpy(dest, data, dataSize); + + VkBufferCopy copyRegion = {}; + copyRegion.size = dataSize; + copyRegion.srcOffset = GetFrameResources().resourceBuffer[cmd]->calculateOffset(dest); + copyRegion.dstOffset = 0; + + vkCmdCopyBuffer(GetDirectCommandList(cmd), (VkBuffer)GetFrameResources().resourceBuffer[cmd]->buffer.resource, + (VkBuffer)buffer->resource, 1, ©Region); + + + + // reverse barrier: + std::swap(barrier.srcAccessMask, barrier.dstAccessMask); + + vkCmdPipelineBarrier( + GetDirectCommandList(cmd), + VK_PIPELINE_STAGE_TRANSFER_BIT, + stages, + VK_DEPENDENCY_BY_REGION_BIT, + 0, nullptr, + 1, &barrier, + 0, nullptr + ); + } - if (buffer->desc.BindFlags & BIND_INDEX_BUFFER) - { - barrier.srcAccessMask |= VK_ACCESS_INDEX_READ_BIT; - stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; - } - if (buffer->desc.BindFlags & BIND_SHADER_RESOURCE) - { - barrier.srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; - stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - } - if (buffer->desc.BindFlags & BIND_UNORDERED_ACCESS) - { - barrier.srcAccessMask |= VK_ACCESS_SHADER_WRITE_BIT; - stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - } - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - - vkCmdPipelineBarrier( - GetDirectCommandList(cmd), - stages, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_DEPENDENCY_BY_REGION_BIT, - 0, nullptr, - 1, &barrier, - 0, nullptr - ); - - - // issue data copy: - uint8_t* dest = GetFrameResources().resourceBuffer[cmd]->allocate(dataSize, 256); - memcpy(dest, data, dataSize); - - VkBufferCopy copyRegion = {}; - copyRegion.size = dataSize; - copyRegion.srcOffset = GetFrameResources().resourceBuffer[cmd]->calculateOffset(dest); - copyRegion.dstOffset = 0; - - vkCmdCopyBuffer(GetDirectCommandList(cmd), (VkBuffer)GetFrameResources().resourceBuffer[cmd]->buffer.resource, - (VkBuffer)buffer->resource, 1, ©Region); - - - - // reverse barrier: - std::swap(barrier.srcAccessMask, barrier.dstAccessMask); - - vkCmdPipelineBarrier( - GetDirectCommandList(cmd), - VK_PIPELINE_STAGE_TRANSFER_BIT, - stages, - VK_DEPENDENCY_BY_REGION_BIT, - 0, nullptr, - 1, &barrier, - 0, nullptr - ); - } diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index 1ad22e1f8..e904c3e76 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -133,28 +133,41 @@ namespace wiGraphics { GraphicsDevice_Vulkan* device; VkDescriptorPool descriptorPool; - VkDescriptorSet descriptorSet_CPU[SHADERSTAGE_COUNT]; - std::vector descriptorSet_GPU[SHADERSTAGE_COUNT]; - UINT ringOffset[SHADERSTAGE_COUNT]; - bool dirty[SHADERSTAGE_COUNT]; - // default descriptor table contents: - VkDescriptorBufferInfo bufferInfo[GPU_RESOURCE_HEAP_SRV_COUNT] = {}; - VkDescriptorImageInfo imageInfo[GPU_RESOURCE_HEAP_SRV_COUNT] = {}; - VkBufferView bufferViews[GPU_RESOURCE_HEAP_SRV_COUNT] = {}; - VkDescriptorImageInfo samplerInfo[GPU_SAMPLER_HEAP_COUNT] = {}; - std::vector initWrites[SHADERSTAGE_COUNT]; + struct Table + { + const GPUBuffer* CBV[GPU_RESOURCE_HEAP_CBV_COUNT]; + const GPUResource* SRV[GPU_RESOURCE_HEAP_SRV_COUNT]; + int SRV_index[GPU_RESOURCE_HEAP_SRV_COUNT]; + const GPUResource* UAV[GPU_RESOURCE_HEAP_UAV_COUNT]; + int UAV_index[GPU_RESOURCE_HEAP_UAV_COUNT]; + const Sampler* SAM[GPU_SAMPLER_HEAP_COUNT]; - // descriptor table rename guards: - std::vector boundDescriptors[SHADERSTAGE_COUNT]; + std::vector descriptorSet_GPU; + UINT ringOffset; + bool dirty; + + void reset() + { + memset(CBV, 0, sizeof(CBV)); + memset(SRV, 0, sizeof(SRV)); + memset(SRV_index, -1, sizeof(SRV_index)); + memset(UAV, 0, sizeof(UAV)); + memset(UAV_index, -1, sizeof(UAV_index)); + memset(SAM, 0, sizeof(SAM)); + ringOffset = 0; + dirty = true; + } + + } tables[SHADERSTAGE_COUNT]; DescriptorTableFrameAllocator(GraphicsDevice_Vulkan* device, UINT maxRenameCount); ~DescriptorTableFrameAllocator(); void reset(); - void validate(VkCommandBuffer commandList); + void validate(CommandList cmd); }; - DescriptorTableFrameAllocator* ResourceDescriptorsGPU[COMMANDLIST_COUNT]; + DescriptorTableFrameAllocator* descriptors[COMMANDLIST_COUNT]; struct ResourceFrameAllocator @@ -173,11 +186,18 @@ namespace wiGraphics uint64_t calculateOffset(uint8_t* address); }; ResourceFrameAllocator* resourceBuffer[COMMANDLIST_COUNT]; + }; FrameResources frames[BACKBUFFER_COUNT]; FrameResources& GetFrameResources() { return frames[GetFrameCount() % BACKBUFFER_COUNT]; } inline VkCommandBuffer GetDirectCommandList(CommandList cmd) { return GetFrameResources().commandBuffers[cmd]; } + struct DynamicResourceState + { + GPUAllocation allocation; + bool binding[SHADERSTAGE_COUNT] = {}; + }; + std::unordered_map dynamic_constantbuffers[COMMANDLIST_COUNT]; struct UploadBuffer { diff --git a/WickedEngine/wiImage.cpp b/WickedEngine/wiImage.cpp index 38b6b0282..c50966cfe 100644 --- a/WickedEngine/wiImage.cpp +++ b/WickedEngine/wiImage.cpp @@ -267,6 +267,7 @@ namespace wiImage prcb.xPPParams0.y = params.process.params.blur.y / params.siz.y; prcb.xPPParams0.z = params.mipLevel; device->UpdateBuffer(&processCb, &prcb, cmd); + device->BindConstantBuffer(PS, &processCb, CB_GETBINDSLOT(PostProcessCB), cmd); break; case wiImageParams::PostProcess::LIGHTSHAFT: prcb.xPPParams0.x = 0.65f; // density @@ -276,6 +277,7 @@ namespace wiImage prcb.xPPParams1.x = params.process.params.sun.x; prcb.xPPParams1.y = params.process.params.sun.y; device->UpdateBuffer(&processCb, &prcb, cmd); + device->BindConstantBuffer(PS, &processCb, CB_GETBINDSLOT(PostProcessCB), cmd); break; case wiImageParams::PostProcess::OUTLINE: prcb.xPPParams0.x = params.process.params.outline.threshold; @@ -284,16 +286,19 @@ namespace wiImage prcb.xPPParams1.y = params.process.params.outline.colorG; prcb.xPPParams1.z = params.process.params.outline.colorB; device->UpdateBuffer(&processCb, &prcb, cmd); + device->BindConstantBuffer(PS, &processCb, CB_GETBINDSLOT(PostProcessCB), cmd); break; case wiImageParams::PostProcess::DEPTHOFFIELD: prcb.xPPParams0.z = params.process.params.dofFocus; device->UpdateBuffer(&processCb, &prcb, cmd); + device->BindConstantBuffer(PS, &processCb, CB_GETBINDSLOT(PostProcessCB), cmd); break; case wiImageParams::PostProcess::MOTIONBLUR: break; case wiImageParams::PostProcess::BLOOMSEPARATE: prcb.xPPParams0.x = params.process.params.bloomThreshold; device->UpdateBuffer(&processCb, &prcb, cmd); + device->BindConstantBuffer(PS, &processCb, CB_GETBINDSLOT(PostProcessCB), cmd); break; case wiImageParams::PostProcess::FXAA: break; @@ -301,11 +306,13 @@ namespace wiImage prcb.xPPParams0.x = params.process.params.ssao.range; prcb.xPPParams0.y = (float)params.process.params.ssao.sampleCount; device->UpdateBuffer(&processCb, &prcb, cmd); + device->BindConstantBuffer(PS, &processCb, CB_GETBINDSLOT(PostProcessCB), cmd); break; case wiImageParams::PostProcess::SSSS: prcb.xPPParams0.x = params.process.params.ssss.x; prcb.xPPParams0.y = params.process.params.ssss.y; device->UpdateBuffer(&processCb, &prcb, cmd); + device->BindConstantBuffer(PS, &processCb, CB_GETBINDSLOT(PostProcessCB), cmd); break; case wiImageParams::PostProcess::SSR: break; @@ -314,6 +321,7 @@ namespace wiImage case wiImageParams::PostProcess::TONEMAP: prcb.xPPParams0.x = params.process.params.exposure; device->UpdateBuffer(&processCb, &prcb, cmd); + device->BindConstantBuffer(PS, &processCb, CB_GETBINDSLOT(PostProcessCB), cmd); break; case wiImageParams::PostProcess::REPROJECTDEPTHBUFFER: break; @@ -324,6 +332,7 @@ namespace wiImage case wiImageParams::PostProcess::SHARPEN: prcb.xPPParams0.x = params.process.params.sharpen; device->UpdateBuffer(&processCb, &prcb, cmd); + device->BindConstantBuffer(PS, &processCb, CB_GETBINDSLOT(PostProcessCB), cmd); break; case wiImageParams::PostProcess::LINEARDEPTH: break; @@ -332,8 +341,6 @@ namespace wiImage break; } - device->BindConstantBuffer(PS, &processCb, CB_GETBINDSLOT(PostProcessCB), cmd); - } const GPUResource* res[] = { diff --git a/WickedEngine/wiImage.h b/WickedEngine/wiImage.h index 99978d080..6c04dc15a 100644 --- a/WickedEngine/wiImage.h +++ b/WickedEngine/wiImage.h @@ -249,17 +249,21 @@ struct wiImageParams void disableFullScreen() { _flags &= ~FULLSCREEN; } - wiImageParams() { + wiImageParams() + { init(); } - wiImageParams(float width, float height) { + wiImageParams(float width, float height) + { init(); siz = XMFLOAT2(width, height); } - wiImageParams(float posX, float posY, float width, float height) { + wiImageParams(float posX, float posY, float width, float height, const XMFLOAT4& color = XMFLOAT4(1, 1, 1, 1)) + { init(); pos.x = posX; pos.y = posY; siz = XMFLOAT2(width, height); + col = color; } }; diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 970546748..59e9dc0d4 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -8045,6 +8045,8 @@ void BindCommonResources(CommandList cmd) { GraphicsDevice* device = GetDevice(); + ResetAlphaRef(cmd); + for (int i = 0; i < SHADERSTAGE_COUNT; ++i) { SHADERSTAGE stage = (SHADERSTAGE)i; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 2054df18f..fc7146c21 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 27; // minor bug fixes, alterations, refactors, updates - const int revision = 7; + const int revision = 8; long GetVersion() diff --git a/WickedEngine/wiWidget.cpp b/WickedEngine/wiWidget.cpp index 34596a48f..2662fc4e8 100644 --- a/WickedEngine/wiWidget.cpp +++ b/WickedEngine/wiWidget.cpp @@ -126,7 +126,7 @@ void wiWidget::RenderTooltip(const wiGUI* gui, CommandList cmd) const static const float _border = 2; float fontWidth = (float)tooltipFont.textWidth() + _border * 2; float fontHeight = (float)tooltipFont.textHeight() + _border * 2; - wiImage::Draw(wiTextureHelper::getColor(wiColor(255, 234, 165)), wiImageParams(tooltipPos.x - _border, tooltipPos.y - _border, fontWidth, fontHeight), cmd); + wiImage::Draw(wiTextureHelper::getWhite(), wiImageParams(tooltipPos.x - _border, tooltipPos.y - _border, fontWidth, fontHeight, wiColor(255, 234, 165).toFloat4()), cmd); tooltipFont.SetText(tooltip); tooltipFont.Draw(cmd); if (!scriptTip.empty()) @@ -391,8 +391,8 @@ void wiButton::Render(const wiGUI* gui, CommandList cmd) const gui->ResetScissor(cmd); - wiImage::Draw(wiTextureHelper::getColor(color) - , wiImageParams(translation.x, translation.y, scale.x, scale.y), cmd); + wiImage::Draw(wiTextureHelper::getWhite() + , wiImageParams(translation.x, translation.y, scale.x, scale.y, color.toFloat4()), cmd); wiRenderer::GetDevice()->BindScissorRects(1, &scissorRect, cmd); @@ -457,8 +457,8 @@ void wiLabel::Render(const wiGUI* gui, CommandList cmd) const gui->ResetScissor(cmd); - wiImage::Draw(wiTextureHelper::getColor(color) - , wiImageParams(translation.x, translation.y, scale.x, scale.y), cmd); + wiImage::Draw(wiTextureHelper::getWhite() + , wiImageParams(translation.x, translation.y, scale.x, scale.y, color.toFloat4()), cmd); wiRenderer::GetDevice()->BindScissorRects(1, &scissorRect, cmd); @@ -608,8 +608,8 @@ void wiTextInputField::Render(const wiGUI* gui, CommandList cmd) const gui->ResetScissor(cmd); - wiImage::Draw(wiTextureHelper::getColor(color) - , wiImageParams(translation.x, translation.y, scale.x, scale.y), cmd); + wiImage::Draw(wiTextureHelper::getWhite() + , wiImageParams(translation.x, translation.y, scale.x, scale.y, color.toFloat4()), cmd); @@ -799,12 +799,12 @@ void wiSlider::Render(const wiGUI* gui, CommandList cmd) const gui->ResetScissor(cmd); // trail - wiImage::Draw(wiTextureHelper::getColor(color) - , wiImageParams(translation.x - headWidth * 0.5f, translation.y + scale.y * 0.5f - scale.y*0.1f, scale.x + headWidth, scale.y * 0.2f), cmd); + wiImage::Draw(wiTextureHelper::getWhite() + , wiImageParams(translation.x - headWidth * 0.5f, translation.y + scale.y * 0.5f - scale.y*0.1f, scale.x + headWidth, scale.y * 0.2f, color.toFloat4()), cmd); // head float headPosX = wiMath::Lerp(translation.x, translation.x + scale.x, wiMath::Clamp(wiMath::InverseLerp(start, end, value), 0, 1)); - wiImage::Draw(wiTextureHelper::getColor(color) - , wiImageParams(headPosX - headWidth * 0.5f, translation.y, headWidth, scale.y), cmd); + wiImage::Draw(wiTextureHelper::getWhite() + , wiImageParams(headPosX - headWidth * 0.5f, translation.y, headWidth, scale.y, color.toFloat4()), cmd); if (parent != gui) { @@ -932,14 +932,14 @@ void wiCheckBox::Render(const wiGUI* gui, CommandList cmd) const gui->ResetScissor(cmd); // control - wiImage::Draw(wiTextureHelper::getColor(color) - , wiImageParams(translation.x, translation.y, scale.x, scale.y), cmd); + wiImage::Draw(wiTextureHelper::getWhite() + , wiImageParams(translation.x, translation.y, scale.x, scale.y, color.toFloat4()), cmd); // check if (GetCheck()) { - wiImage::Draw(wiTextureHelper::getColor(wiColor::lerp(color, wiColor::White(), 0.8f)) - , wiImageParams(translation.x + scale.x*0.25f, translation.y + scale.y*0.25f, scale.x*0.5f, scale.y*0.5f) + wiImage::Draw(wiTextureHelper::getWhite() + , wiImageParams(translation.x + scale.x*0.25f, translation.y + scale.y*0.25f, scale.x*0.5f, scale.y*0.5f, wiColor::lerp(color, wiColor::White(), 0.8f).toFloat4()) , cmd); } @@ -1127,11 +1127,11 @@ void wiComboBox::Render(const wiGUI* gui, CommandList cmd) const gui->ResetScissor(cmd); // control-base - wiImage::Draw(wiTextureHelper::getColor(color) - , wiImageParams(translation.x, translation.y, scale.x, scale.y), cmd); + wiImage::Draw(wiTextureHelper::getWhite() + , wiImageParams(translation.x, translation.y, scale.x, scale.y, color.toFloat4()), cmd); // control-arrow - wiImage::Draw(wiTextureHelper::getColor(color) - , wiImageParams(translation.x + scale.x + 1, translation.y, scale.y, scale.y), cmd); + wiImage::Draw(wiTextureHelper::getWhite() + , wiImageParams(translation.x + scale.x + 1, translation.y, scale.y, scale.y, color.toFloat4()), cmd); wiFont("V", wiFontParams((int)(translation.x + scale.x + scale.y*0.5f), (int)(translation.y + scale.y*0.5f), WIFONTSIZE_DEFAULT, WIFALIGN_CENTER, WIFALIGN_CENTER, 0, 0, textColor, textShadowColor)).Draw(cmd); @@ -1176,8 +1176,8 @@ void wiComboBox::Render(const wiGUI* gui, CommandList cmd) const col = colors[ACTIVE]; } } - wiImage::Draw(wiTextureHelper::getColor(col) - , wiImageParams(translation.x, translation.y + _GetItemOffset(i), scale.x, scale.y), cmd); + wiImage::Draw(wiTextureHelper::getWhite() + , wiImageParams(translation.x, translation.y + _GetItemOffset(i), scale.x, scale.y, col.toFloat4()), cmd); wiFont(x, wiFontParams((int)(translation.x + scale.x*0.5f), (int)(translation.y + scale.y*0.5f + _GetItemOffset(i)), WIFONTSIZE_DEFAULT, WIFALIGN_CENTER, WIFALIGN_CENTER, 0, 0, textColor, textShadowColor)).Draw(cmd); i++; @@ -1449,8 +1449,8 @@ void wiWindow::Render(const wiGUI* gui, CommandList cmd) const // body if (!IsMinimized()) { - wiImage::Draw(wiTextureHelper::getColor(color) - , wiImageParams(translation.x, translation.y, scale.x, scale.y), cmd); + wiImage::Draw(wiTextureHelper::getWhite() + , wiImageParams(translation.x, translation.y, scale.x, scale.y, color.toFloat4()), cmd); } for (auto& x : childrenWidgets)