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:
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user