vulkan and dx12 improvements (#216)

- dx12: improved descriptor heap allocator: drastically reduce the amount of SetDescriptorHeaps() calls
- vulkan: improved loading of extension functions
- wiHelper::messageBox improvement
This commit is contained in:
Turánszki János
2021-01-14 00:08:01 +01:00
committed by GitHub
parent 02de8f36d4
commit b132056904
10 changed files with 187 additions and 263 deletions
-2
View File
@@ -162,8 +162,6 @@ void MainComponent::Run()
wiLua::RunFile("startup.lua");
}
wiPlatform::PopMessages();
wiProfiler::BeginFrame();
deltaTime = float(std::max(0.0, timer.elapsed() / 1000.0));
+1 -3
View File
@@ -60,7 +60,7 @@ private:
uint32_t msaaSampleCount = 1;
protected:
public:
wiGraphics::Texture rtGbuffer[GBUFFER_COUNT];
wiGraphics::Texture rtGbuffer_resolved[GBUFFER_COUNT];
wiGraphics::Texture rtReflection; // contains the scene rendered for planar reflections
@@ -148,8 +148,6 @@ protected:
virtual void RenderSceneMIPChain(wiGraphics::CommandList cmd) const;
virtual void RenderTransparents(wiGraphics::CommandList cmd) const;
virtual void RenderPostprocessChain(wiGraphics::CommandList cmd) const;
public:
void ResizeBuffers() override;
+122 -122
View File
@@ -1427,25 +1427,13 @@ using namespace DX12_Internal;
// Reset state to empty:
reset();
heaps_resource.resize(1);
heaps_sampler.resize(1);
}
void GraphicsDevice_DX12::FrameResources::DescriptorTableFrameAllocator::reset()
{
dirty_res = true;
dirty_sam = true;
heaps_bound = false;
for (auto& x : heaps_resource)
{
x.ringOffset = 0;
}
for (auto& x : heaps_sampler)
{
x.ringOffset = 0;
}
current_resource_heap = 0;
current_sampler_heap = 0;
ringOffset_res = 0;
ringOffset_sam = 0;
memset(CBV, 0, sizeof(CBV));
memset(SRV, 0, sizeof(SRV));
@@ -1456,111 +1444,67 @@ using namespace DX12_Internal;
}
void GraphicsDevice_DX12::FrameResources::DescriptorTableFrameAllocator::request_heaps(uint32_t resources, uint32_t samplers, CommandList cmd)
{
// This function allocatesGPU visible descriptor heaps that can fit the requested table sizes.
// First, they grow the heaps until the size fits the dx12 resource limits (tier 1 resource limit = 1 million, sampler limit is 2048)
// When the limits are reached, and there is still a need to allocate, then completely new heap blocks are started
//
// The function will automatically bind descriptor heaps when there was a new (growing or block allocation)
// Remarks:
// This is allocating from the global shader visible descriptor heaps in a simple incrementing
// lockless ring buffer fashion.
// In this lockless method, a descriptor array that is to be allocated might not fit without
// completely wrapping the beginning of the allocation.
// But completely wrapping after the fact we discovered that the array couldn't fit,
// it wouldn't be thread safe any more without introducing locks
// For that reason, we are reserving an excess amount of descriptors at the end which can't be normally
// allocated, but any out of bounds descriptors can still be safely written into it
//
// This method wastes a number of descriptors essentially at the end of the heap, but it is simple
// and safe to implement
//
// The excess amount is essentially equal to the maximum number of descriptors that can be allocated at once.
DescriptorHeap& heap_resource = heaps_resource[current_resource_heap];
uint32_t allocation = heap_resource.ringOffset + resources;
if (heap_resource.heapDesc.NumDescriptors < allocation || heap_resource.heapDesc.NumDescriptors == 0)
if (resources > 0)
{
if (allocation > 1000000) // tier 1 limit
// The reservation is the maximum amount of descriptors that can be allocated once
// It can be increased if needed
const uint32_t wrap_reservation = 100000;
const uint32_t wrap_effective_size = device->descriptorheap_res.heapDesc.NumDescriptors - wrap_reservation;
assert(wrap_reservation > resources); // for correct lockless wrap behaviour
uint64_t offset = device->descriptorheap_res.allocationOffset.fetch_add(resources);
uint64_t wrapped_offset = offset % wrap_effective_size;
ringOffset_res = (uint32_t)wrapped_offset;
uint64_t wrapped_offset_end = wrapped_offset + resources;
uint64_t gpu_offset = device->descriptorheap_res.fence->GetCompletedValue();
uint64_t wrapped_gpu_offset = gpu_offset % wrap_effective_size;
if (wrapped_offset < wrapped_gpu_offset && wrapped_offset_end > wrapped_gpu_offset)
{
// need new block
allocation -= heap_resource.ringOffset;
current_resource_heap++;
if (heaps_resource.size() <= current_resource_heap)
{
heaps_resource.resize(current_resource_heap + 1);
}
}
DescriptorHeap& heap = heaps_resource[current_resource_heap];
// Need to re-check if growing is necessary (maybe step into new block is enough):
if (heap.heapDesc.NumDescriptors < allocation || heap.heapDesc.NumDescriptors == 0)
{
// grow rate is controlled here:
allocation = std::max(512u, allocation);
allocation = wiMath::GetNextPowerOfTwo(allocation);
allocation = std::min(1000000u, allocation);
// Issue destruction of the old heap:
device->allocationhandler->destroylocker.lock();
uint64_t framecount = device->allocationhandler->framecount;
device->allocationhandler->destroyer_descriptorHeaps.push_back(std::make_pair(heap.heap_GPU, framecount));
device->allocationhandler->destroylocker.unlock();
heap.heapDesc.NodeMask = 0;
heap.heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
heap.heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
heap.heapDesc.NumDescriptors = allocation;
HRESULT hr = device->device->CreateDescriptorHeap(&heap.heapDesc, IID_PPV_ARGS(&heap.heap_GPU));
assert(device->descriptorheap_res.fenceValue > wrapped_offset_end); // simply not enough space, even with GPU drain
HRESULT hr = device->descriptorheap_res.fence->SetEventOnCompletion(device->descriptorheap_res.fenceValue, device->descriptorheap_res.fenceEvent);
assert(SUCCEEDED(hr));
// Save heap properties:
heap.start_cpu = heap.heap_GPU->GetCPUDescriptorHandleForHeapStart();
heap.start_gpu = heap.heap_GPU->GetGPUDescriptorHandleForHeapStart();
WaitForSingleObject(device->descriptorheap_res.fenceEvent, INFINITE);
}
heaps_bound = false;
}
DescriptorHeap& heap_sampler = heaps_sampler[current_sampler_heap];
allocation = heap_sampler.ringOffset + samplers;
if (heap_sampler.heapDesc.NumDescriptors < allocation || heap_sampler.heapDesc.NumDescriptors == 0)
if (samplers > 0)
{
if (allocation > 2048) // sampler limit
// The reservation is the maximum amount of descriptors that can be allocated once
// It can be increased if needed
const uint32_t wrap_reservation = 16;
const uint32_t wrap_effective_size = device->descriptorheap_sam.heapDesc.NumDescriptors - wrap_reservation;
assert(wrap_reservation > samplers); // for correct lockless wrap behaviour
uint64_t offset = device->descriptorheap_sam.allocationOffset.fetch_add(samplers);
uint64_t wrapped_offset = offset % wrap_effective_size;
ringOffset_sam = (uint32_t)wrapped_offset;
uint64_t wrapped_offset_end = wrapped_offset + samplers;
uint64_t gpu_offset = device->descriptorheap_sam.fence->GetCompletedValue();
uint64_t wrapped_gpu_offset = gpu_offset % wrap_effective_size;
if (wrapped_offset < wrapped_gpu_offset && wrapped_offset_end > wrapped_gpu_offset)
{
// need new block
allocation -= heap_sampler.ringOffset;
current_sampler_heap++;
if (heaps_sampler.size() <= current_sampler_heap)
{
heaps_sampler.resize(current_sampler_heap + 1);
}
}
DescriptorHeap& heap = heaps_sampler[current_sampler_heap];
// Need to re-check if growing is necessary (maybe step into new block is enough):
if (heap.heapDesc.NumDescriptors < allocation || heap.heapDesc.NumDescriptors == 0)
{
// grow rate is controlled here:
allocation = std::max(512u, allocation);
allocation = wiMath::GetNextPowerOfTwo(allocation);
allocation = std::min(2048u, allocation);
// Issue destruction of the old heap:
device->allocationhandler->destroylocker.lock();
uint64_t framecount = device->allocationhandler->framecount;
device->allocationhandler->destroyer_descriptorHeaps.push_back(std::make_pair(heap.heap_GPU, framecount));
device->allocationhandler->destroylocker.unlock();
heap.heapDesc.NodeMask = 0;
heap.heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
heap.heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
heap.heapDesc.NumDescriptors = allocation;
HRESULT hr = device->device->CreateDescriptorHeap(&heap.heapDesc, IID_PPV_ARGS(&heap.heap_GPU));
assert(device->descriptorheap_sam.fenceValue > wrapped_offset_end); // simply not enough space, even with GPU drain
HRESULT hr = device->descriptorheap_sam.fence->SetEventOnCompletion(device->descriptorheap_sam.fenceValue, device->descriptorheap_sam.fenceEvent);
assert(SUCCEEDED(hr));
// Save heap properties:
heap.start_cpu = heap.heap_GPU->GetCPUDescriptorHandleForHeapStart();
heap.start_gpu = heap.heap_GPU->GetGPUDescriptorHandleForHeapStart();
WaitForSingleObject(device->descriptorheap_sam.fenceEvent, INFINITE);
}
heaps_bound = false;
}
if (!heaps_bound)
{
heaps_bound = true;
// definitely re-index the heap blocks!
ID3D12DescriptorHeap* heaps[2] = {
heaps_resource[current_resource_heap].heap_GPU.Get(),
heaps_sampler[current_sampler_heap].heap_GPU.Get()
};
device->GetDirectCommandList(cmd)->SetDescriptorHeaps(arraysize(heaps), heaps);
}
}
void GraphicsDevice_DX12::FrameResources::DescriptorTableFrameAllocator::validate(bool graphics, CommandList cmd)
@@ -1578,14 +1522,14 @@ using namespace DX12_Internal;
if (!pso_internal->resources.empty() && dirty_res)
{
dirty_res = false;
DescriptorHeap& heap = heaps_resource[current_resource_heap];
auto& heap = device->descriptorheap_res;
D3D12_GPU_DESCRIPTOR_HANDLE binding_table = heap.start_gpu;
binding_table.ptr += (UINT64)heap.ringOffset * (UINT64)device->resource_descriptor_size;
binding_table.ptr += (UINT64)ringOffset_res * (UINT64)device->resource_descriptor_size;
for (auto& x : pso_internal->resources)
{
D3D12_CPU_DESCRIPTOR_HANDLE dst = heap.start_cpu;
uint32_t ringOffset = heap.ringOffset++;
uint32_t ringOffset = ringOffset_res++;
dst.ptr += ringOffset * device->resource_descriptor_size;
switch (x.RangeType)
@@ -1691,14 +1635,14 @@ using namespace DX12_Internal;
if (!pso_internal->samplers.empty() && dirty_sam)
{
dirty_sam = false;
DescriptorHeap& heap = heaps_sampler[current_sampler_heap];
auto& heap = device->descriptorheap_sam;
D3D12_GPU_DESCRIPTOR_HANDLE binding_table = heap.start_gpu;
binding_table.ptr += (UINT64)heap.ringOffset * (UINT64)device->sampler_descriptor_size;
binding_table.ptr += (UINT64)ringOffset_sam * (UINT64)device->sampler_descriptor_size;
for (auto& x : pso_internal->samplers)
{
D3D12_CPU_DESCRIPTOR_HANDLE dst = heap.start_cpu;
uint32_t ringOffset = heap.ringOffset++;
uint32_t ringOffset = ringOffset_sam++;
dst.ptr += ringOffset * device->sampler_descriptor_size;
const Sampler* sampler = SAM[x.BaseShaderRegister];
@@ -1735,12 +1679,11 @@ using namespace DX12_Internal;
if (!internal_state->sampler_heap.ranges.empty())
{
DescriptorHeap& heap = heaps_sampler[current_sampler_heap];
auto& heap = device->descriptorheap_sam;
D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle = heap.start_cpu;
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle = heap.start_gpu;
cpu_handle.ptr += heap.ringOffset * device->sampler_descriptor_size;
gpu_handle.ptr += heap.ringOffset * device->sampler_descriptor_size;
heap.ringOffset += internal_state->sampler_heap.desc.NumDescriptors;
cpu_handle.ptr += ringOffset_sam * device->sampler_descriptor_size;
gpu_handle.ptr += ringOffset_sam * device->sampler_descriptor_size;
device->device->CopyDescriptorsSimple(
internal_state->sampler_heap.desc.NumDescriptors,
cpu_handle,
@@ -1752,12 +1695,11 @@ using namespace DX12_Internal;
if (!internal_state->resource_heap.ranges.empty())
{
DescriptorHeap& heap = heaps_resource[current_resource_heap];
auto& heap = device->descriptorheap_res;
D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle = heap.start_cpu;
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle = heap.start_gpu;
cpu_handle.ptr += heap.ringOffset * device->resource_descriptor_size;
gpu_handle.ptr += heap.ringOffset * device->resource_descriptor_size;
heap.ringOffset += internal_state->resource_heap.desc.NumDescriptors;
cpu_handle.ptr += ringOffset_res * device->resource_descriptor_size;
gpu_handle.ptr += ringOffset_res * device->resource_descriptor_size;
device->device->CopyDescriptorsSimple(
internal_state->resource_heap.desc.NumDescriptors,
cpu_handle,
@@ -2352,6 +2294,42 @@ using namespace DX12_Internal;
resource_descriptor_size = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
sampler_descriptor_size = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
// Resource descriptor heap (shader visible):
{
descriptorheap_res.heapDesc.NodeMask = 0;
descriptorheap_res.heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
descriptorheap_res.heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
descriptorheap_res.heapDesc.NumDescriptors = 1000000; // tier 1 limit
hr = device->CreateDescriptorHeap(&descriptorheap_res.heapDesc, IID_PPV_ARGS(&descriptorheap_res.heap_GPU));
assert(SUCCEEDED(hr));
descriptorheap_res.start_cpu = descriptorheap_res.heap_GPU->GetCPUDescriptorHandleForHeapStart();
descriptorheap_res.start_gpu = descriptorheap_res.heap_GPU->GetGPUDescriptorHandleForHeapStart();
hr = device->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&descriptorheap_res.fence));
assert(SUCCEEDED(hr));
descriptorheap_res.fenceEvent = CreateEventEx(NULL, FALSE, FALSE, EVENT_ALL_ACCESS);
descriptorheap_res.fenceValue = descriptorheap_res.fence->GetCompletedValue();
}
// Sampler descriptor heap (shader visible):
{
descriptorheap_sam.heapDesc.NodeMask = 0;
descriptorheap_sam.heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
descriptorheap_sam.heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
descriptorheap_sam.heapDesc.NumDescriptors = 2048; // tier 1 limit
hr = device->CreateDescriptorHeap(&descriptorheap_sam.heapDesc, IID_PPV_ARGS(&descriptorheap_sam.heap_GPU));
assert(SUCCEEDED(hr));
descriptorheap_sam.start_cpu = descriptorheap_sam.heap_GPU->GetCPUDescriptorHandleForHeapStart();
descriptorheap_sam.start_gpu = descriptorheap_sam.heap_GPU->GetGPUDescriptorHandleForHeapStart();
hr = device->CreateFence(0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&descriptorheap_sam.fence));
assert(SUCCEEDED(hr));
descriptorheap_sam.fenceEvent = CreateEventEx(NULL, FALSE, FALSE, EVENT_ALL_ACCESS);
descriptorheap_sam.fenceValue = descriptorheap_sam.fence->GetCompletedValue();
}
D3D12_COMMAND_QUEUE_DESC copyQueueDesc = {};
copyQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_COPY;
copyQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
@@ -2366,6 +2344,8 @@ using namespace DX12_Internal;
hr = swapChain->GetBuffer(fr, IID_PPV_ARGS(&backBuffers[fr]));
assert(SUCCEEDED(hr));
auto& frame = frames[fr];
hr = device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COPY, IID_PPV_ARGS(&frames[fr].copyAllocator));
assert(SUCCEEDED(hr));
hr = device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COPY, frames[fr].copyAllocator.Get(), nullptr, IID_PPV_ARGS(&frames[fr].copyCommandList));
@@ -5195,6 +5175,12 @@ using namespace DX12_Internal;
hr = GetDirectCommandList(cmd)->Reset(GetFrameResources().commandAllocators[cmd].Get(), nullptr);
assert(SUCCEEDED(hr));
ID3D12DescriptorHeap* heaps[2] = {
descriptorheap_res.heap_GPU.Get(),
descriptorheap_sam.heap_GPU.Get()
};
GetDirectCommandList(cmd)->SetDescriptorHeaps(arraysize(heaps), heaps);
GetFrameResources().descriptors[cmd].reset();
GetFrameResources().resourceBuffer[cmd].clear();
@@ -5291,6 +5277,15 @@ using namespace DX12_Internal;
// This acts as a barrier, following this we will be using the next frame's resources when calling GetFrameResources()!
FRAMECOUNT++;
HRESULT hr = directQueue->Signal(frameFence.Get(), FRAMECOUNT);
assert(SUCCEEDED(hr));
// Descriptor heaps' progress is recorded by the GPU:
descriptorheap_res.fenceValue = descriptorheap_res.allocationOffset.load();
hr = directQueue->Signal(descriptorheap_res.fence.Get(), descriptorheap_res.fenceValue);
assert(SUCCEEDED(hr));
descriptorheap_sam.fenceValue = descriptorheap_sam.allocationOffset.load();
hr = directQueue->Signal(descriptorheap_sam.fence.Get(), descriptorheap_sam.fenceValue);
assert(SUCCEEDED(hr));
// Determine the last frame that we should not wait on:
const uint64_t lastFrameToAllowLatency = std::max(uint64_t(BACKBUFFER_COUNT - 1u), FRAMECOUNT) - (BACKBUFFER_COUNT - 1);
@@ -5302,6 +5297,11 @@ using namespace DX12_Internal;
WaitForSingleObject(frameFenceEvent, INFINITE);
}
//WaitForGPU();
//descriptorheap_res.allocationOffset.store(0);
//descriptorheap_sam.allocationOffset.store(0);
allocationhandler->Update(FRAMECOUNT, BACKBUFFER_COUNT);
copyQueueLock.unlock();
+20 -13
View File
@@ -87,6 +87,24 @@ namespace wiGraphics
RenderPass dummyRenderpass;
struct DescriptorHeap
{
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> heap_GPU;
D3D12_CPU_DESCRIPTOR_HANDLE start_cpu = {};
D3D12_GPU_DESCRIPTOR_HANDLE start_gpu = {};
// CPU status:
std::atomic<uint64_t> allocationOffset{ 0 };
// GPU status:
Microsoft::WRL::ComPtr<ID3D12Fence> fence;
HANDLE fenceEvent;
uint64_t fenceValue = 0;
};
DescriptorHeap descriptorheap_res;
DescriptorHeap descriptorheap_sam;
struct FrameResources
{
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> commandAllocators[COMMANDLIST_COUNT];
@@ -98,19 +116,8 @@ namespace wiGraphics
struct DescriptorTableFrameAllocator
{
GraphicsDevice_DX12* device = nullptr;
struct DescriptorHeap
{
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> heap_GPU;
D3D12_CPU_DESCRIPTOR_HANDLE start_cpu = {};
D3D12_GPU_DESCRIPTOR_HANDLE start_gpu = {};
uint32_t ringOffset = 0;
};
std::vector<DescriptorHeap> heaps_resource;
std::vector<DescriptorHeap> heaps_sampler;
uint32_t current_resource_heap = 0;
uint32_t current_sampler_heap = 0;
bool heaps_bound = false;
uint32_t ringOffset_res = 0;
uint32_t ringOffset_sam = 0;
bool dirty_res = false;
bool dirty_sam = false;
+25 -69
View File
@@ -37,21 +37,6 @@
namespace wiGraphics
{
PFN_vkCreateRayTracingPipelinesKHR GraphicsDevice_Vulkan::createRayTracingPipelinesKHR = nullptr;
PFN_vkCreateAccelerationStructureKHR GraphicsDevice_Vulkan::createAccelerationStructureKHR = nullptr;
PFN_vkDestroyAccelerationStructureKHR GraphicsDevice_Vulkan::destroyAccelerationStructureKHR = nullptr;
PFN_vkGetAccelerationStructureBuildSizesKHR GraphicsDevice_Vulkan::getAccelerationStructureBuildSizesKHR = nullptr;
PFN_vkGetAccelerationStructureDeviceAddressKHR GraphicsDevice_Vulkan::getAccelerationStructureDeviceAddressKHR = nullptr;
PFN_vkGetRayTracingShaderGroupHandlesKHR GraphicsDevice_Vulkan::getRayTracingShaderGroupHandlesKHR = nullptr;
PFN_vkCmdBuildAccelerationStructuresKHR GraphicsDevice_Vulkan::cmdBuildAccelerationStructuresKHR = nullptr;
PFN_vkBuildAccelerationStructuresKHR GraphicsDevice_Vulkan::buildAccelerationStructuresKHR = nullptr;
PFN_vkCmdTraceRaysKHR GraphicsDevice_Vulkan::cmdTraceRaysKHR = nullptr;
PFN_vkCmdDrawMeshTasksNV GraphicsDevice_Vulkan::cmdDrawMeshTasksNV = nullptr;
PFN_vkCmdDrawMeshTasksIndirectNV GraphicsDevice_Vulkan::cmdDrawMeshTasksIndirectNV = nullptr;
PFN_vkCmdSetFragmentShadingRateKHR GraphicsDevice_Vulkan::cmdSetFragmentShadingRateKHR = nullptr;
namespace Vulkan_Internal
{
// Converters:
@@ -586,12 +571,6 @@ namespace Vulkan_Internal
return flags;
}
// Extension functions:
PFN_vkSetDebugUtilsObjectNameEXT setDebugUtilsObjectNameEXT = nullptr;
PFN_vkCmdBeginDebugUtilsLabelEXT cmdBeginDebugUtilsLabelEXT = nullptr;
PFN_vkCmdEndDebugUtilsLabelEXT cmdEndDebugUtilsLabelEXT = nullptr;
PFN_vkCmdInsertDebugUtilsLabelEXT cmdInsertDebugUtilsLabelEXT = nullptr;
bool checkDeviceExtensionSupport(const char* checkExtension,
const std::vector<VkExtensionProperties>& available_deviceExtensions) {
@@ -2234,7 +2213,7 @@ using namespace Vulkan_Internal;
res = vkCreateInstance(&createInfo, nullptr, &instance);
assert(res == VK_SUCCESS);
volkLoadInstance(instance);
volkLoadInstanceOnly(instance);
}
// Register validation layer callback:
@@ -2527,6 +2506,7 @@ using namespace Vulkan_Internal;
{
assert(acceleration_structure_features.accelerationStructure == VK_TRUE);
assert(features_1_2.bufferDeviceAddress == VK_TRUE);
// Shader compiler has bug with vk inline raytracing now:
//capabilities |= GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE;
}
if (mesh_shader_features.meshShader == VK_TRUE && mesh_shader_features.taskShader == VK_TRUE)
@@ -2606,35 +2586,11 @@ using namespace Vulkan_Internal;
res = vmaCreateAllocator(&allocatorInfo, &allocationhandler->allocator);
assert(res == VK_SUCCESS);
// Extension functions:
setDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetDeviceProcAddr(device, "vkSetDebugUtilsObjectNameEXT");
cmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetDeviceProcAddr(device, "vkCmdBeginDebugUtilsLabelEXT");
cmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)vkGetDeviceProcAddr(device, "vkCmdEndDebugUtilsLabelEXT");
cmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT)vkGetDeviceProcAddr(device, "vkCmdInsertDebugUtilsLabelEXT");
if (CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING))
{
createRayTracingPipelinesKHR = (PFN_vkCreateRayTracingPipelinesKHR)vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR");
createAccelerationStructureKHR = (PFN_vkCreateAccelerationStructureKHR)vkGetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR");
destroyAccelerationStructureKHR = (PFN_vkDestroyAccelerationStructureKHR)vkGetDeviceProcAddr(device, "vkDestroyAccelerationStructureKHR");
getAccelerationStructureBuildSizesKHR = (PFN_vkGetAccelerationStructureBuildSizesKHR)vkGetDeviceProcAddr(device, "vkGetAccelerationStructureBuildSizesKHR");
getAccelerationStructureDeviceAddressKHR = (PFN_vkGetAccelerationStructureDeviceAddressKHR)vkGetDeviceProcAddr(device, "vkGetAccelerationStructureDeviceAddressKHR");
getRayTracingShaderGroupHandlesKHR = (PFN_vkGetRayTracingShaderGroupHandlesKHR)vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR");
cmdBuildAccelerationStructuresKHR = (PFN_vkCmdBuildAccelerationStructuresKHR)vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR");
buildAccelerationStructuresKHR = (PFN_vkBuildAccelerationStructuresKHR)vkGetDeviceProcAddr(device, "vkBuildAccelerationStructuresKHR");
cmdTraceRaysKHR = (PFN_vkCmdTraceRaysKHR)vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR");
}
if (CheckCapability(GRAPHICSDEVICE_CAPABILITY_MESH_SHADER))
{
cmdDrawMeshTasksNV = (PFN_vkCmdDrawMeshTasksNV)vkGetDeviceProcAddr(device, "vkCmdDrawMeshTasksNV");
cmdDrawMeshTasksIndirectNV = (PFN_vkCmdDrawMeshTasksIndirectNV)vkGetDeviceProcAddr(device, "vkCmdDrawMeshTasksIndirectNV");
}
if (CheckCapability(GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING))
{
cmdSetFragmentShadingRateKHR = (PFN_vkCmdSetFragmentShadingRateKHR)vkGetDeviceProcAddr(device, "vkCmdSetFragmentShadingRateKHR");
}
// looks like volk doesn't get these properly:
vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetDeviceProcAddr(device, "vkSetDebugUtilsObjectNameEXT");
vkCmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetDeviceProcAddr(device, "vkCmdBeginDebugUtilsLabelEXT");
vkCmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)vkGetDeviceProcAddr(device, "vkCmdEndDebugUtilsLabelEXT");
vkCmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT)vkGetDeviceProcAddr(device, "vkCmdInsertDebugUtilsLabelEXT");
CreateBackBufferResources();
@@ -3065,7 +3021,7 @@ using namespace Vulkan_Internal;
{
info.objectHandle = (uint64_t)x;
res = setDebugUtilsObjectNameEXT(device, &info);
res = vkSetDebugUtilsObjectNameEXT(device, &info);
assert(res == VK_SUCCESS);
}
@@ -4661,7 +4617,7 @@ using namespace Vulkan_Internal;
internal_state->sizeInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
// Compute memory requirements:
getAccelerationStructureBuildSizesKHR(
vkGetAccelerationStructureBuildSizesKHR(
device,
VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
&internal_state->buildInfo,
@@ -4700,7 +4656,7 @@ using namespace Vulkan_Internal;
internal_state->createInfo.buffer = internal_state->buffer;
internal_state->createInfo.size = internal_state->sizeInfo.accelerationStructureSize;
res = createAccelerationStructureKHR(
res = vkCreateAccelerationStructureKHR(
device,
&internal_state->createInfo,
nullptr,
@@ -4712,7 +4668,7 @@ using namespace Vulkan_Internal;
VkAccelerationStructureDeviceAddressInfoKHR addrinfo = {};
addrinfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
addrinfo.accelerationStructure = internal_state->resource;
internal_state->as_address = getAccelerationStructureDeviceAddressKHR(device, &addrinfo);
internal_state->as_address = vkGetAccelerationStructureDeviceAddressKHR(device, &addrinfo);
// Get scratch address:
VkBufferDeviceAddressInfo addressinfo = {};
@@ -4826,7 +4782,7 @@ using namespace Vulkan_Internal;
info.basePipelineHandle = VK_NULL_HANDLE;
info.basePipelineIndex = 0;
VkResult res = createRayTracingPipelinesKHR(
VkResult res = vkCreateRayTracingPipelinesKHR(
device,
VK_NULL_HANDLE,
VK_NULL_HANDLE,
@@ -5408,7 +5364,7 @@ using namespace Vulkan_Internal;
}
void GraphicsDevice_Vulkan::WriteShaderIdentifier(const RaytracingPipelineState* rtpso, uint32_t group_index, void* dest)
{
VkResult res = getRayTracingShaderGroupHandlesKHR(device, to_internal(rtpso)->pipeline, group_index, 1, SHADER_IDENTIFIER_SIZE, dest);
VkResult res = vkGetRayTracingShaderGroupHandlesKHR(device, to_internal(rtpso)->pipeline, group_index, 1, SHADER_IDENTIFIER_SIZE, dest);
assert(res == VK_SUCCESS);
}
void GraphicsDevice_Vulkan::WriteDescriptor(const DescriptorTable* table, uint32_t rangeIndex, uint32_t arrayIndex, const GPUResource* resource, int subresource, uint64_t offset)
@@ -5762,7 +5718,7 @@ using namespace Vulkan_Internal;
return;
}
VkResult res = setDebugUtilsObjectNameEXT(device, &info);
VkResult res = vkSetDebugUtilsObjectNameEXT(device, &info);
assert(res == VK_SUCCESS);
}
@@ -6298,7 +6254,7 @@ using namespace Vulkan_Internal;
}
}
cmdSetFragmentShadingRateKHR(
vkCmdSetFragmentShadingRateKHR(
GetDirectCommandList(cmd),
&fragmentSize,
combiner
@@ -6406,13 +6362,13 @@ using namespace Vulkan_Internal;
void GraphicsDevice_Vulkan::DispatchMesh(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ, CommandList cmd)
{
predraw(cmd);
cmdDrawMeshTasksNV(GetDirectCommandList(cmd), threadGroupCountX * threadGroupCountY * threadGroupCountZ, 0);
vkCmdDrawMeshTasksNV(GetDirectCommandList(cmd), threadGroupCountX * threadGroupCountY * threadGroupCountZ, 0);
}
void GraphicsDevice_Vulkan::DispatchMeshIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd)
{
predraw(cmd);
auto internal_state = to_internal(args);
cmdDrawMeshTasksIndirectNV(GetDirectCommandList(cmd), internal_state->resource, (VkDeviceSize)args_offset,1,sizeof(IndirectDispatchArgs));
vkCmdDrawMeshTasksIndirectNV(GetDirectCommandList(cmd), internal_state->resource, (VkDeviceSize)args_offset,1,sizeof(IndirectDispatchArgs));
}
void GraphicsDevice_Vulkan::CopyResource(const GPUResource* pDst, const GPUResource* pSrc, CommandList cmd)
{
@@ -6877,7 +6833,7 @@ using namespace Vulkan_Internal;
VkAccelerationStructureBuildRangeInfoKHR* pRangeInfo = ranges.data();
cmdBuildAccelerationStructuresKHR(
vkCmdBuildAccelerationStructuresKHR(
GetDirectCommandList(cmd),
1,
&info,
@@ -6921,7 +6877,7 @@ using namespace Vulkan_Internal;
callable.size = desc->callable.size;
callable.stride = desc->callable.stride;
cmdTraceRaysKHR(
vkCmdTraceRaysKHR(
GetDirectCommandList(cmd),
&raygen,
&miss,
@@ -7077,7 +7033,7 @@ using namespace Vulkan_Internal;
void GraphicsDevice_Vulkan::EventBegin(const char* name, CommandList cmd)
{
if (cmdBeginDebugUtilsLabelEXT != nullptr)
if (vkCmdBeginDebugUtilsLabelEXT != nullptr)
{
VkDebugUtilsLabelEXT label = {};
label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
@@ -7086,19 +7042,19 @@ using namespace Vulkan_Internal;
label.color[1] = 0;
label.color[2] = 0;
label.color[3] = 1;
cmdBeginDebugUtilsLabelEXT(GetDirectCommandList(cmd), &label);
vkCmdBeginDebugUtilsLabelEXT(GetDirectCommandList(cmd), &label);
}
}
void GraphicsDevice_Vulkan::EventEnd(CommandList cmd)
{
if (cmdEndDebugUtilsLabelEXT != nullptr)
if (vkCmdEndDebugUtilsLabelEXT != nullptr)
{
cmdEndDebugUtilsLabelEXT(GetDirectCommandList(cmd));
vkCmdEndDebugUtilsLabelEXT(GetDirectCommandList(cmd));
}
}
void GraphicsDevice_Vulkan::SetMarker(const char* name, CommandList cmd)
{
if (cmdInsertDebugUtilsLabelEXT != nullptr)
if (vkCmdInsertDebugUtilsLabelEXT != nullptr)
{
VkDebugUtilsLabelEXT label = {};
label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
@@ -7107,7 +7063,7 @@ using namespace Vulkan_Internal;
label.color[1] = 0;
label.color[2] = 0;
label.color[3] = 1;
cmdInsertDebugUtilsLabelEXT(GetDirectCommandList(cmd), &label);
vkCmdInsertDebugUtilsLabelEXT(GetDirectCommandList(cmd), &label);
}
}
+2 -17
View File
@@ -32,7 +32,7 @@ namespace wiGraphics
{
private:
VkInstance instance = VK_NULL_HANDLE;
VkDebugUtilsMessengerEXT debugUtilsMessenger{VK_NULL_HANDLE};
VkDebugUtilsMessengerEXT debugUtilsMessenger = VK_NULL_HANDLE;
VkDebugReportCallbackEXT debugReportCallback = VK_NULL_HANDLE; // Deprecated
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
@@ -186,21 +186,6 @@ namespace wiGraphics
std::atomic<CommandList> cmd_count{ 0 };
static PFN_vkCreateRayTracingPipelinesKHR createRayTracingPipelinesKHR;
static PFN_vkCreateAccelerationStructureKHR createAccelerationStructureKHR;
static PFN_vkDestroyAccelerationStructureKHR destroyAccelerationStructureKHR;
static PFN_vkGetAccelerationStructureBuildSizesKHR getAccelerationStructureBuildSizesKHR;
static PFN_vkGetAccelerationStructureDeviceAddressKHR getAccelerationStructureDeviceAddressKHR;
static PFN_vkGetRayTracingShaderGroupHandlesKHR getRayTracingShaderGroupHandlesKHR;
static PFN_vkCmdBuildAccelerationStructuresKHR cmdBuildAccelerationStructuresKHR;
static PFN_vkBuildAccelerationStructuresKHR buildAccelerationStructuresKHR;
static PFN_vkCmdTraceRaysKHR cmdTraceRaysKHR;
static PFN_vkCmdDrawMeshTasksNV cmdDrawMeshTasksNV;
static PFN_vkCmdDrawMeshTasksIndirectNV cmdDrawMeshTasksIndirectNV;
static PFN_vkCmdSetFragmentShadingRateKHR cmdSetFragmentShadingRateKHR;
public:
GraphicsDevice_Vulkan(wiPlatform::window_type window, bool fullscreen = false, bool debuglayer = false);
virtual ~GraphicsDevice_Vulkan();
@@ -464,7 +449,7 @@ namespace wiGraphics
{
auto item = destroyer_bvhs.front();
destroyer_bvhs.pop_front();
destroyAccelerationStructureKHR(device, item.first, nullptr);
vkDestroyAccelerationStructureKHR(device, item.first, nullptr);
}
else
{
+16 -6
View File
@@ -2,6 +2,7 @@
#include "wiPlatform.h"
#include "wiRenderer.h"
#include "wiBackLog.h"
#include "wiEvent.h"
#include "Utility/stb_image_write.h"
@@ -45,12 +46,21 @@ namespace wiHelper
void messageBox(const std::string& msg, const std::string& caption)
{
auto& state = wiPlatform::GetWindowState();
state.messagemutex.lock();
state.messages.emplace_back();
StringConvert(msg, state.messages.back().message);
StringConvert(caption, state.messages.back().caption);
state.messagemutex.unlock();
#ifdef _WIN32
#ifndef PLATFORM_UWP
MessageBoxA(wiPlatform::GetWindow(), msg.c_str(), caption.c_str(), 0);
#else
wstring wmessage, wcaption;
StringConvert(msg, wmessage);
StringConvert(caption, wcaption);
// UWP can only show message box on main thread:
wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) {
Windows::UI::Popups::MessageDialog(ref new Platform::String(wmessage.c_str()), ref new Platform::String(wcaption.c_str())).ShowAsync();
});
#endif // PLATFORM_UWP
#elif SDL2
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, caption.c_str(), msg.c_str(), NULL);
#endif // _WIN32
}
void screenshot(const std::string& name)
-29
View File
@@ -44,18 +44,10 @@ namespace wiPlatform
using window_type = int;
#endif // _WIN32
struct DeferredMessageBox
{
std::wstring caption;
std::wstring message;
};
struct WindowState
{
window_type window;
int dpi = 96;
std::vector<DeferredMessageBox> messages;
std::mutex messagemutex;
};
inline WindowState& GetWindowState()
{
@@ -121,25 +113,4 @@ namespace wiPlatform
#endif // PLATFORM_UWP
#endif // _WIN32
}
inline void PopMessages()
{
auto& state = GetWindowState();
state.messagemutex.lock();
for (auto& x : state.messages)
{
#ifdef _WIN32
#ifndef PLATFORM_UWP
MessageBox(wiPlatform::GetWindow(), x.message.c_str(), x.caption.c_str(), 0);
#else
Windows::UI::Popups::MessageDialog(ref new Platform::String(x.message.c_str()), ref new Platform::String(x.caption.c_str())).ShowAsync();
#endif // PLATFORM_UWP
#elif SDL2
std::string title(x.caption.begin(), x.caption.end());
std::string message(x.message.begin(), x.message.end());
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title.c_str(), message.c_str(), NULL);
#endif // _WIN32
}
state.messages.clear();
state.messagemutex.unlock();
}
}
-1
View File
@@ -769,7 +769,6 @@ bool LoadShader(SHADERSTAGE stage, Shader& shader, const std::string& filename)
{
return device->CreateShader(stage, buffer.data(), buffer.size(), &shader);
}
wiHelper::messageBox("Shader not found: " + SHADERPATH + filename);
return false;
}
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates, breaking compatibility changes
const int minor = 51;
// minor bug fixes, alterations, refactors, updates
const int revision = 48;
const int revision = 49;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);