diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index 624c14edd..a08c9732a 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -3139,66 +3139,66 @@ namespace wiGraphics { if (pResource->resource != WI_NULL_HANDLE) { - ((ID3D12Resource*)pResource->resource)->Release(); + DeferredDestroy({ DestroyItem::RESOURCE, FRAMECOUNT, pResource->resource }); pResource->resource = WI_NULL_HANDLE; } - ResourceAllocator->free(pResource->SRV); + DeferredDestroy({ DestroyItem::RESOURCEVIEW, FRAMECOUNT, pResource->SRV }); pResource->SRV = WI_NULL_HANDLE; for (auto& x : pResource->additionalSRVs) { - ResourceAllocator->free(x); + DeferredDestroy({ DestroyItem::RESOURCEVIEW, FRAMECOUNT, x }); } pResource->additionalSRVs.clear(); - ResourceAllocator->free(pResource->UAV); + DeferredDestroy({ DestroyItem::RESOURCEVIEW, FRAMECOUNT, pResource->UAV }); pResource->UAV = WI_NULL_HANDLE; for (auto& x : pResource->additionalUAVs) { - ResourceAllocator->free(x); + DeferredDestroy({ DestroyItem::RESOURCEVIEW, FRAMECOUNT, x }); } pResource->additionalUAVs.clear(); } void GraphicsDevice_DX12::DestroyBuffer(GPUBuffer *pBuffer) { - ResourceAllocator->free(pBuffer->CBV); + DeferredDestroy({ DestroyItem::RESOURCEVIEW, FRAMECOUNT, pBuffer->CBV }); pBuffer->CBV = WI_NULL_HANDLE; } void GraphicsDevice_DX12::DestroyTexture1D(Texture1D *pTexture1D) { - RTAllocator->free(pTexture1D->RTV); + DeferredDestroy({ DestroyItem::RENDERTARGETVIEW, FRAMECOUNT, pTexture1D->RTV }); pTexture1D->RTV = WI_NULL_HANDLE; for (auto& x : pTexture1D->additionalRTVs) { - RTAllocator->free(x); + DeferredDestroy({ DestroyItem::RENDERTARGETVIEW, FRAMECOUNT, x }); } pTexture1D->additionalRTVs.clear(); } void GraphicsDevice_DX12::DestroyTexture2D(Texture2D *pTexture2D) { - RTAllocator->free(pTexture2D->RTV); + DeferredDestroy({ DestroyItem::RENDERTARGETVIEW, FRAMECOUNT, pTexture2D->RTV }); pTexture2D->RTV = WI_NULL_HANDLE; for (auto& x : pTexture2D->additionalRTVs) { - RTAllocator->free(x); + DeferredDestroy({ DestroyItem::RENDERTARGETVIEW, FRAMECOUNT, x }); } pTexture2D->additionalRTVs.clear(); - DSAllocator->free(pTexture2D->DSV); + DeferredDestroy({ DestroyItem::DEPTHSTENCILVIEW, FRAMECOUNT, pTexture2D->DSV }); pTexture2D->DSV = WI_NULL_HANDLE; for (auto& x : pTexture2D->additionalDSVs) { - DSAllocator->free(x); + DeferredDestroy({ DestroyItem::DEPTHSTENCILVIEW, FRAMECOUNT, x }); } pTexture2D->additionalDSVs.clear(); } void GraphicsDevice_DX12::DestroyTexture3D(Texture3D *pTexture3D) { - RTAllocator->free(pTexture3D->RTV); + DeferredDestroy({ DestroyItem::RENDERTARGETVIEW, FRAMECOUNT, pTexture3D->RTV }); pTexture3D->RTV = WI_NULL_HANDLE; for (auto& x : pTexture3D->additionalRTVs) { - RTAllocator->free(x); + DeferredDestroy({ DestroyItem::RENDERTARGETVIEW, FRAMECOUNT, x }); } pTexture3D->additionalRTVs.clear(); } @@ -3230,7 +3230,7 @@ namespace wiGraphics { if (pComputeShader->resource != WI_NULL_HANDLE) { - ((ID3D12PipelineState*)pComputeShader->resource)->Release(); + DeferredDestroy({ DestroyItem::PIPELINE, FRAMECOUNT, pComputeShader->resource }); pComputeShader->resource = WI_NULL_HANDLE; } } @@ -3248,7 +3248,7 @@ namespace wiGraphics } void GraphicsDevice_DX12::DestroySamplerState(Sampler *pSamplerState) { - SamplerAllocator->free(pSamplerState->resource); + DeferredDestroy({ DestroyItem::SAMPLER, FRAMECOUNT, pSamplerState->resource }); } void GraphicsDevice_DX12::DestroyQuery(GPUQuery *pQuery) { @@ -3258,7 +3258,7 @@ namespace wiGraphics { if (pso->pipeline != WI_NULL_HANDLE) { - ((ID3D12PipelineState*)pso->pipeline)->Release(); + DeferredDestroy({ DestroyItem::PIPELINE, FRAMECOUNT, pso->pipeline }); pso->pipeline = WI_NULL_HANDLE; } } @@ -3394,6 +3394,47 @@ namespace wiGraphics memset(prev_pt, 0, sizeof(prev_pt)); + + // Deferred destroy of resources that the GPU is already finished with: + destroylocker.lock(); + while (!destroyer.empty()) + { + if (destroyer.front().frame + BACKBUFFER_COUNT < FRAMECOUNT) + { + DestroyItem item = destroyer.front(); + destroyer.pop_front(); + + switch (item.type) + { + case DestroyItem::RESOURCE: + ((ID3D12Resource*)item.handle)->Release(); + break; + case DestroyItem::RESOURCEVIEW: + ResourceAllocator->free(item.handle); + break; + case DestroyItem::RENDERTARGETVIEW: + RTAllocator->free(item.handle); + break; + case DestroyItem::DEPTHSTENCILVIEW: + DSAllocator->free(item.handle); + break; + case DestroyItem::SAMPLER: + SamplerAllocator->free(item.handle); + break; + case DestroyItem::PIPELINE: + ((ID3D12PipelineState*)item.handle)->Release(); + break; + default: + break; + } + } + else + { + break; + } + } + destroylocker.unlock(); + RESOLUTIONCHANGED = false; } diff --git a/WickedEngine/wiGraphicsDevice_DX12.h b/WickedEngine/wiGraphicsDevice_DX12.h index 4fb041e25..db9a4a831 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.h +++ b/WickedEngine/wiGraphicsDevice_DX12.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -144,6 +145,29 @@ namespace wiGraphics wiContainers::ThreadSafeRingBuffer free_commandlists; wiContainers::ThreadSafeRingBuffer active_commandlists; + struct DestroyItem + { + enum TYPE + { + RESOURCE, + RESOURCEVIEW, + RENDERTARGETVIEW, + DEPTHSTENCILVIEW, + SAMPLER, + PIPELINE, + } type; + uint64_t frame; + wiCPUHandle handle; + }; + std::deque destroyer; + std::mutex destroylocker; + inline void DeferredDestroy(const DestroyItem& item) + { + destroylocker.lock(); + destroyer.push_back(item); + destroylocker.unlock(); + } + public: GraphicsDevice_DX12(wiWindowRegistration::window_type window, bool fullscreen = false, bool debuglayer = false); virtual ~GraphicsDevice_DX12(); diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index b811f3618..b9a41a564 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -2943,7 +2943,26 @@ namespace wiGraphics dsv_desc.viewType = VK_IMAGE_VIEW_TYPE_2D; dsv_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - dsv_desc.format = _ConvertFormat(pTexture2D->desc.Format); + switch (pTexture2D->desc.Format) + { + case FORMAT_R16_TYPELESS: + dsv_desc.format = VK_FORMAT_D16_UNORM; + break; + case FORMAT_R32_TYPELESS: + dsv_desc.format = VK_FORMAT_D32_SFLOAT; + break; + case FORMAT_R24G8_TYPELESS: + dsv_desc.format = VK_FORMAT_D24_UNORM_S8_UINT; + dsv_desc.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + break; + case FORMAT_R32G8X24_TYPELESS: + dsv_desc.format = VK_FORMAT_D32_SFLOAT_S8_UINT; + dsv_desc.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + break; + default: + dsv_desc.format = _ConvertFormat(pTexture2D->desc.Format); + break; + } if (pTexture2D->desc.MiscFlags & RESOURCE_MISC_TEXTURECUBE) { @@ -3084,14 +3103,35 @@ namespace wiGraphics srv_desc.flags = 0; srv_desc.image = (VkImage)pTexture2D->resource; srv_desc.viewType = VK_IMAGE_VIEW_TYPE_2D; - srv_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; srv_desc.subresourceRange.baseArrayLayer = 0; srv_desc.subresourceRange.layerCount = pTexture2D->desc.ArraySize; srv_desc.subresourceRange.baseMipLevel = 0; srv_desc.subresourceRange.levelCount = pTexture2D->desc.MipLevels; - srv_desc.format = _ConvertFormat(pTexture2D->desc.Format); + switch (pTexture2D->desc.Format) + { + case FORMAT_R16_TYPELESS: + srv_desc.format = VK_FORMAT_D16_UNORM; + srv_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + break; + case FORMAT_R32_TYPELESS: + srv_desc.format = VK_FORMAT_D32_SFLOAT; + srv_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + break; + case FORMAT_R24G8_TYPELESS: + srv_desc.format = VK_FORMAT_D24_UNORM_S8_UINT; + srv_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + break; + case FORMAT_R32G8X24_TYPELESS: + srv_desc.format = VK_FORMAT_D32_SFLOAT_S8_UINT; + srv_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + break; + default: + srv_desc.format = _ConvertFormat(pTexture2D->desc.Format); + srv_desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + break; + } if (arraySize > 1) @@ -4112,122 +4152,122 @@ namespace wiGraphics void GraphicsDevice_Vulkan::DestroyResource(GPUResource* pResource) { - vkFreeMemory(device, (VkDeviceMemory)pResource->resourceMemory, nullptr); + DeferredDestroy({ DestroyItem::DEVICEMEMORY, FRAMECOUNT, pResource->resourceMemory }); pResource->resourceMemory = WI_NULL_HANDLE; } void GraphicsDevice_Vulkan::DestroyBuffer(GPUBuffer *pBuffer) { - vkDestroyBuffer(device, (VkBuffer)pBuffer->resource, nullptr); + DeferredDestroy({ DestroyItem::BUFFER, FRAMECOUNT, pBuffer->resource }); pBuffer->resource = WI_NULL_HANDLE; - vkDestroyBufferView(device, (VkBufferView)pBuffer->SRV, nullptr); + DeferredDestroy({ DestroyItem::BUFFERVIEW, FRAMECOUNT, pBuffer->SRV }); pBuffer->SRV = WI_NULL_HANDLE; for (auto& x : pBuffer->additionalSRVs) { - vkDestroyBufferView(device, (VkBufferView)x, nullptr); + DeferredDestroy({ DestroyItem::BUFFERVIEW, FRAMECOUNT, x }); } pBuffer->additionalSRVs.clear(); - vkDestroyBufferView(device, (VkBufferView)pBuffer->UAV, nullptr); + DeferredDestroy({ DestroyItem::BUFFERVIEW, FRAMECOUNT, pBuffer->UAV }); pBuffer->UAV = WI_NULL_HANDLE; for (auto& x : pBuffer->additionalUAVs) { - vkDestroyBufferView(device, (VkBufferView)x, nullptr); + DeferredDestroy({ DestroyItem::BUFFERVIEW, FRAMECOUNT, x }); } pBuffer->additionalUAVs.clear(); } void GraphicsDevice_Vulkan::DestroyTexture1D(Texture1D *pTexture1D) { - vkDestroyImage(device, (VkImage)pTexture1D->resource, nullptr); + DeferredDestroy({ DestroyItem::IMAGE, FRAMECOUNT, pTexture1D->resource }); pTexture1D->resource = WI_NULL_HANDLE; - vkDestroyImageView(device, (VkImageView)pTexture1D->RTV, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, pTexture1D->RTV }); pTexture1D->RTV = WI_NULL_HANDLE; for (auto& x : pTexture1D->additionalRTVs) { - vkDestroyImageView(device, (VkImageView)x, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, x }); } pTexture1D->additionalRTVs.clear(); - vkDestroyImageView(device, (VkImageView)pTexture1D->SRV, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, pTexture1D->SRV }); pTexture1D->SRV = WI_NULL_HANDLE; for (auto& x : pTexture1D->additionalSRVs) { - vkDestroyImageView(device, (VkImageView)x, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, x }); } pTexture1D->additionalSRVs.clear(); - vkDestroyImageView(device, (VkImageView)pTexture1D->UAV, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, pTexture1D->UAV }); pTexture1D->UAV = WI_NULL_HANDLE; for (auto& x : pTexture1D->additionalUAVs) { - vkDestroyImageView(device, (VkImageView)x, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, x }); } pTexture1D->additionalUAVs.clear(); } void GraphicsDevice_Vulkan::DestroyTexture2D(Texture2D *pTexture2D) { - vkDestroyImage(device, (VkImage)pTexture2D->resource, nullptr); + DeferredDestroy({ DestroyItem::IMAGE, pTexture2D->resource }); pTexture2D->resource = WI_NULL_HANDLE; - vkDestroyImageView(device, (VkImageView)pTexture2D->RTV, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, pTexture2D->RTV }); pTexture2D->RTV = WI_NULL_HANDLE; for (auto& x : pTexture2D->additionalRTVs) { - vkDestroyImageView(device, (VkImageView)x, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, x }); } pTexture2D->additionalRTVs.clear(); - vkDestroyImageView(device, (VkImageView)pTexture2D->DSV, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, pTexture2D->DSV }); pTexture2D->DSV = WI_NULL_HANDLE; for (auto& x : pTexture2D->additionalDSVs) { - vkDestroyImageView(device, (VkImageView)x, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, x }); } pTexture2D->additionalDSVs.clear(); - vkDestroyImageView(device, (VkImageView)pTexture2D->SRV, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, pTexture2D->SRV }); pTexture2D->SRV = WI_NULL_HANDLE; for (auto& x : pTexture2D->additionalSRVs) { - vkDestroyImageView(device, (VkImageView)x, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, x }); } pTexture2D->additionalSRVs.clear(); - vkDestroyImageView(device, (VkImageView)pTexture2D->UAV, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, pTexture2D->UAV }); pTexture2D->UAV = WI_NULL_HANDLE; for (auto& x : pTexture2D->additionalUAVs) { - vkDestroyImageView(device, (VkImageView)x, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, x }); } pTexture2D->additionalUAVs.clear(); } void GraphicsDevice_Vulkan::DestroyTexture3D(Texture3D *pTexture3D) { - vkDestroyImage(device, (VkImage)pTexture3D->resource, nullptr); + DeferredDestroy({ DestroyItem::IMAGE, pTexture3D->resource }); pTexture3D->resource = WI_NULL_HANDLE; - vkDestroyImageView(device, (VkImageView)pTexture3D->RTV, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, pTexture3D->RTV }); pTexture3D->RTV = WI_NULL_HANDLE; for (auto& x : pTexture3D->additionalRTVs) { - vkDestroyImageView(device, (VkImageView)x, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, x }); } pTexture3D->additionalRTVs.clear(); - vkDestroyImageView(device, (VkImageView)pTexture3D->SRV, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, pTexture3D->SRV }); pTexture3D->SRV = WI_NULL_HANDLE; for (auto& x : pTexture3D->additionalSRVs) { - vkDestroyImageView(device, (VkImageView)x, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, x }); } pTexture3D->additionalSRVs.clear(); - vkDestroyImageView(device, (VkImageView)pTexture3D->UAV, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, pTexture3D->UAV }); pTexture3D->UAV = WI_NULL_HANDLE; for (auto& x : pTexture3D->additionalUAVs) { - vkDestroyImageView(device, (VkImageView)x, nullptr); + DeferredDestroy({ DestroyItem::IMAGEVIEW, x }); } pTexture3D->additionalUAVs.clear(); } @@ -4257,7 +4297,7 @@ namespace wiGraphics } void GraphicsDevice_Vulkan::DestroyComputeShader(ComputeShader *pComputeShader) { - vkDestroyPipeline(device, (VkPipeline)pComputeShader->resource, nullptr); + DeferredDestroy({ DestroyItem::PIPELINE, pComputeShader->resource }); pComputeShader->resource = WI_NULL_HANDLE; } void GraphicsDevice_Vulkan::DestroyBlendState(BlendState *pBlendState) @@ -4274,7 +4314,7 @@ namespace wiGraphics } void GraphicsDevice_Vulkan::DestroySamplerState(Sampler *pSamplerState) { - vkDestroySampler(device, (VkSampler)pSamplerState->resource, nullptr); + DeferredDestroy({ DestroyItem::SAMPLER, pSamplerState->resource }); } void GraphicsDevice_Vulkan::DestroyQuery(GPUQuery *pQuery) { @@ -4282,7 +4322,7 @@ namespace wiGraphics } void GraphicsDevice_Vulkan::DestroyPipelineState(PipelineState* pso) { - vkDestroyPipeline(device, (VkPipeline)pso->pipeline, nullptr); + DeferredDestroy({ DestroyItem::PIPELINE, pso->pipeline }); pso->pipeline = WI_NULL_HANDLE; } @@ -4476,6 +4516,51 @@ namespace wiGraphics assert(res == VK_SUCCESS); } + + // Deferred destroy of resources that the GPU is already finished with: + destroylocker.lock(); + while (!destroyer.empty()) + { + if (destroyer.front().frame + BACKBUFFER_COUNT < FRAMECOUNT) + { + DestroyItem item = destroyer.front(); + destroyer.pop_front(); + + switch (item.type) + { + case DestroyItem::DEVICEMEMORY: + vkFreeMemory(device, (VkDeviceMemory)item.handle, nullptr); + break; + case DestroyItem::IMAGE: + vkDestroyImage(device, (VkImage)item.handle, nullptr); + break; + case DestroyItem::IMAGEVIEW: + vkDestroyImageView(device, (VkImageView)item.handle, nullptr); + break; + case DestroyItem::BUFFER: + vkDestroyBuffer(device, (VkBuffer)item.handle, nullptr); + break; + case DestroyItem::BUFFERVIEW: + vkDestroyBufferView(device, (VkBufferView)item.handle, nullptr); + break; + case DestroyItem::SAMPLER: + vkDestroySampler(device, (VkSampler)item.handle, nullptr); + break; + case DestroyItem::PIPELINE: + vkDestroyPipeline(device, (VkPipeline)item.handle, nullptr); + break; + default: + break; + } + } + else + { + break; + } + } + destroylocker.unlock(); + + RESOLUTIONCHANGED = false; } @@ -4683,111 +4768,105 @@ namespace wiGraphics if (resource != nullptr && resource->resource != VK_NULL_HANDLE) { - if (arrayIndex < 0) + wiCPUHandle SRV = arrayIndex < 0 ? resource->SRV : resource->additionalSRVs[arrayIndex]; + + if (resource->IsTexture() && resource->SRV != VK_NULL_HANDLE) { - if (resource->IsTexture() && resource->SRV != VK_NULL_HANDLE) + // Texture: + + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TEXTURE + slot; + + if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == SRV) { - // Texture: + return; + } - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TEXTURE + slot; + VkDescriptorImageInfo imageInfo = {}; + imageInfo.imageView = (VkImageView)resource->SRV; + imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == resource->SRV) + VkWriteDescriptorSet descriptorWrite = {}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pBufferInfo = nullptr; + descriptorWrite.pImageInfo = &imageInfo; + descriptorWrite.pTexelBufferView = nullptr; + + vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); + GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; + GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = SRV; + } + else + { + // Buffer: + const GPUBuffer* buffer = (const GPUBuffer*)resource; + + if (buffer->desc.Format == FORMAT_UNKNOWN) + { + // structured buffer, raw buffer: + + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_UNTYPEDBUFFER + slot; + + if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == buffer->resource) { return; } - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageView = (VkImageView)resource->SRV; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + VkDescriptorBufferInfo bufferInfo = {}; + bufferInfo.buffer = (VkBuffer)buffer->resource; + bufferInfo.offset = 0; + bufferInfo.range = buffer->desc.ByteWidth; VkWriteDescriptorSet descriptorWrite = {}; descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; descriptorWrite.dstBinding = binding; descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = nullptr; - descriptorWrite.pImageInfo = &imageInfo; + descriptorWrite.pBufferInfo = &bufferInfo; + descriptorWrite.pImageInfo = nullptr; descriptorWrite.pTexelBufferView = nullptr; vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = resource->SRV; + GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = buffer->resource; + } - else + else if (resource->SRV != VK_NULL_HANDLE) { - // Buffer: - const GPUBuffer* buffer = (const GPUBuffer*)resource; + // typed buffer: - if (buffer->desc.Format == FORMAT_UNKNOWN) + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TYPEDBUFFER + slot; + + if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == SRV) { - // structured buffer, raw buffer: - - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_UNTYPEDBUFFER + slot; - - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == buffer->resource) - { - return; - } - - VkDescriptorBufferInfo bufferInfo = {}; - bufferInfo.buffer = (VkBuffer)buffer->resource; - bufferInfo.offset = 0; - bufferInfo.range = buffer->desc.ByteWidth; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = &bufferInfo; - descriptorWrite.pImageInfo = nullptr; - descriptorWrite.pTexelBufferView = nullptr; - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); - GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = buffer->resource; - - } - else if (resource->SRV != VK_NULL_HANDLE) - { - // typed buffer: - - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_SRV_TYPEDBUFFER + slot; - - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == resource->SRV) - { - return; - } - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = nullptr; - descriptorWrite.pImageInfo = nullptr; - descriptorWrite.pTexelBufferView = reinterpret_cast(&resource->SRV); - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); - GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = resource->SRV; + return; } + VkWriteDescriptorSet descriptorWrite = {}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pBufferInfo = nullptr; + descriptorWrite.pImageInfo = nullptr; + descriptorWrite.pTexelBufferView = reinterpret_cast(&SRV); + + vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); + GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; + GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = SRV; } } - else - { - assert(resource->additionalSRVs.size() > static_cast(arrayIndex) && "Invalid arrayIndex!"); - - } } + } void GraphicsDevice_Vulkan::BindResources(SHADERSTAGE stage, const GPUResource *const* resources, UINT slot, UINT count, CommandList cmd) { @@ -4805,111 +4884,105 @@ namespace wiGraphics if (resource != nullptr && resource->resource != VK_NULL_HANDLE) { - if (arrayIndex < 0) - { - if (resource->IsTexture() && resource->UAV != VK_NULL_HANDLE) - { - // Texture: - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TEXTURE + slot; + wiCPUHandle UAV = arrayIndex < 0 ? resource->UAV : resource->additionalUAVs[arrayIndex]; - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == resource->UAV) + if (resource->IsTexture() && resource->UAV != VK_NULL_HANDLE) + { + // Texture: + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TEXTURE + slot; + + if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == UAV) + { + return; + } + + VkDescriptorImageInfo imageInfo = {}; + imageInfo.imageView = (VkImageView)UAV; + imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + + VkWriteDescriptorSet descriptorWrite = {}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pBufferInfo = nullptr; + descriptorWrite.pImageInfo = &imageInfo; + descriptorWrite.pTexelBufferView = nullptr; + + vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); + GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; + GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = UAV; + } + else + { + // Buffer: + const GPUBuffer* buffer = (const GPUBuffer*)resource; + + if (buffer->desc.Format == FORMAT_UNKNOWN) + { + // structured buffer, raw buffer: + + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_UNTYPEDBUFFER + slot; + + if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == buffer->resource) { return; } - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageView = (VkImageView)resource->UAV; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + VkDescriptorBufferInfo bufferInfo = {}; + bufferInfo.buffer = (VkBuffer)buffer->resource; + bufferInfo.offset = 0; + bufferInfo.range = buffer->desc.ByteWidth; VkWriteDescriptorSet descriptorWrite = {}; descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; descriptorWrite.dstBinding = binding; descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = nullptr; - descriptorWrite.pImageInfo = &imageInfo; + descriptorWrite.pBufferInfo = &bufferInfo; + descriptorWrite.pImageInfo = nullptr; descriptorWrite.pTexelBufferView = nullptr; vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = resource->UAV; + GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = buffer->resource; + } - else + else if (resource->UAV != VK_NULL_HANDLE) { - // Buffer: - const GPUBuffer* buffer = (const GPUBuffer*)resource; + // typed buffer: - if (buffer->desc.Format == FORMAT_UNKNOWN) + uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TYPEDBUFFER + slot; + + if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == UAV) { - // structured buffer, raw buffer: - - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_UNTYPEDBUFFER + slot; - - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == buffer->resource) - { - return; - } - - VkDescriptorBufferInfo bufferInfo = {}; - bufferInfo.buffer = (VkBuffer)buffer->resource; - bufferInfo.offset = 0; - bufferInfo.range = buffer->desc.ByteWidth; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = &bufferInfo; - descriptorWrite.pImageInfo = nullptr; - descriptorWrite.pTexelBufferView = nullptr; - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); - GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = buffer->resource; - + return; } - else if (resource->UAV != VK_NULL_HANDLE) - { - // typed buffer: - uint32_t binding = VULKAN_DESCRIPTOR_SET_OFFSET_UAV_TYPEDBUFFER + slot; + VkWriteDescriptorSet descriptorWrite = {}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pBufferInfo = nullptr; + descriptorWrite.pImageInfo = nullptr; + descriptorWrite.pTexelBufferView = reinterpret_cast(&UAV); - if (GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] == resource->UAV) - { - return; - } - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = GetFrameResources().ResourceDescriptorsGPU[cmd]->descriptorSet_CPU[stage]; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = nullptr; - descriptorWrite.pImageInfo = nullptr; - descriptorWrite.pTexelBufferView = reinterpret_cast(&resource->UAV); - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); - GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; - GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = resource->UAV; - - } + vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); + GetFrameResources().ResourceDescriptorsGPU[cmd]->dirty[stage] = true; + GetFrameResources().ResourceDescriptorsGPU[cmd]->boundDescriptors[stage][binding] = UAV; } } - else - { - //assert(resource->additionalUAVs.size() > static_cast(arrayIndex) && "Invalid arrayIndex!"); - - } } + } void GraphicsDevice_Vulkan::BindUAVs(SHADERSTAGE stage, const GPUResource *const* resources, UINT slot, UINT count, CommandList cmd) { diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index 0fa3bbdd5..1ad22e1f8 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -202,6 +203,30 @@ namespace wiGraphics wiContainers::ThreadSafeRingBuffer free_commandlists; wiContainers::ThreadSafeRingBuffer active_commandlists; + struct DestroyItem + { + enum TYPE + { + DEVICEMEMORY, + IMAGE, + IMAGEVIEW, + BUFFER, + BUFFERVIEW, + SAMPLER, + PIPELINE, + } type; + uint64_t frame; + wiCPUHandle handle; + }; + std::deque destroyer; + std::mutex destroylocker; + inline void DeferredDestroy(const DestroyItem& item) + { + destroylocker.lock(); + destroyer.push_back(item); + destroylocker.unlock(); + } + public: GraphicsDevice_Vulkan(wiWindowRegistration::window_type window, bool fullscreen = false, bool debuglayer = false); virtual ~GraphicsDevice_Vulkan(); diff --git a/WickedEngine/wiResourceManager.cpp b/WickedEngine/wiResourceManager.cpp index 85c951cde..cc98b12af 100644 --- a/WickedEngine/wiResourceManager.cpp +++ b/WickedEngine/wiResourceManager.cpp @@ -249,10 +249,10 @@ const void* wiResourceManager::add(const wiHashString& name, Data_Type newType) desc.Usage = USAGE_DEFAULT; UINT mipwidth = width; - SubresourceData* InitData = new SubresourceData[desc.MipLevels]; + std::vector InitData(desc.MipLevels); for (UINT mip = 0; mip < desc.MipLevels; ++mip) { - InitData[mip].pSysMem = rgb; + InitData[mip].pSysMem = rgb; // attention! we don't fill the mips here correctly, just always point to the mip0 data by default. Mip levels will be created using compute shader when needed! InitData[mip].SysMemPitch = static_cast(mipwidth * channelCount); mipwidth = std::max(1u, mipwidth / 2); } @@ -260,7 +260,7 @@ const void* wiResourceManager::add(const wiHashString& name, Data_Type newType) Texture2D* image = new Texture2D; image->RequestIndependentShaderResourcesForMIPs(true); image->RequestIndependentUnorderedAccessResourcesForMIPs(true); - HRESULT hr = wiRenderer::GetDevice()->CreateTexture2D(&desc, InitData, image); + HRESULT hr = wiRenderer::GetDevice()->CreateTexture2D(&desc, InitData.data(), image); assert(SUCCEEDED(hr)); wiRenderer::GetDevice()->SetName(image, nameStr); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 7a3c0611d..2054df18f 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 27; // minor bug fixes, alterations, refactors, updates - const int revision = 6; + const int revision = 7; long GetVersion()