From b1320569048a8fdf1f24b4507320fc06b5ba4ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Thu, 14 Jan 2021 00:08:01 +0100 Subject: [PATCH] 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 --- WickedEngine/MainComponent.cpp | 2 - WickedEngine/RenderPath3D.h | 4 +- WickedEngine/wiGraphicsDevice_DX12.cpp | 244 +++++++++++------------ WickedEngine/wiGraphicsDevice_DX12.h | 33 +-- WickedEngine/wiGraphicsDevice_Vulkan.cpp | 94 +++------ WickedEngine/wiGraphicsDevice_Vulkan.h | 19 +- WickedEngine/wiHelper.cpp | 22 +- WickedEngine/wiPlatform.h | 29 --- WickedEngine/wiRenderer.cpp | 1 - WickedEngine/wiVersion.cpp | 2 +- 10 files changed, 187 insertions(+), 263 deletions(-) diff --git a/WickedEngine/MainComponent.cpp b/WickedEngine/MainComponent.cpp index 43d32b1a7..7fe2dad06 100644 --- a/WickedEngine/MainComponent.cpp +++ b/WickedEngine/MainComponent.cpp @@ -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)); diff --git a/WickedEngine/RenderPath3D.h b/WickedEngine/RenderPath3D.h index 1a060e4ef..201960076 100644 --- a/WickedEngine/RenderPath3D.h +++ b/WickedEngine/RenderPath3D.h @@ -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; diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index 0c0e32e55..8ee0c557d 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -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(); diff --git a/WickedEngine/wiGraphicsDevice_DX12.h b/WickedEngine/wiGraphicsDevice_DX12.h index d320cf453..a773b3f85 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.h +++ b/WickedEngine/wiGraphicsDevice_DX12.h @@ -87,6 +87,24 @@ namespace wiGraphics RenderPass dummyRenderpass; + struct DescriptorHeap + { + D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {}; + Microsoft::WRL::ComPtr heap_GPU; + D3D12_CPU_DESCRIPTOR_HANDLE start_cpu = {}; + D3D12_GPU_DESCRIPTOR_HANDLE start_gpu = {}; + + // CPU status: + std::atomic allocationOffset{ 0 }; + + // GPU status: + Microsoft::WRL::ComPtr fence; + HANDLE fenceEvent; + uint64_t fenceValue = 0; + }; + DescriptorHeap descriptorheap_res; + DescriptorHeap descriptorheap_sam; + struct FrameResources { Microsoft::WRL::ComPtr 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 heap_GPU; - D3D12_CPU_DESCRIPTOR_HANDLE start_cpu = {}; - D3D12_GPU_DESCRIPTOR_HANDLE start_gpu = {}; - uint32_t ringOffset = 0; - }; - std::vector heaps_resource; - std::vector 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; diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index 570710b0a..8c3fd864e 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -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& 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); } } diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index a453ef929..7a04fa7c0 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -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 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 { diff --git a/WickedEngine/wiHelper.cpp b/WickedEngine/wiHelper.cpp index 18314b28e..31451da8b 100644 --- a/WickedEngine/wiHelper.cpp +++ b/WickedEngine/wiHelper.cpp @@ -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) diff --git a/WickedEngine/wiPlatform.h b/WickedEngine/wiPlatform.h index 3eaa5f779..9c95621a6 100644 --- a/WickedEngine/wiPlatform.h +++ b/WickedEngine/wiPlatform.h @@ -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 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(); - } } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 04a21da3b..7dc272ebd 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -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; } diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index c97f70b42..513d3a192 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -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);