diff --git a/bin/data/config.json b/bin/data/config.json index c8e01f76..fa984d14 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -118,7 +118,7 @@ "gui": true, "vsync": true, // vsync on vulkan side rather than engine-side "hdr": true, - "vxgi": false, + "vxgi": true, "culling": false, "bloom": false, "dof": false, diff --git a/engine/inc/uf/ext/vulkan/device.h b/engine/inc/uf/ext/vulkan/device.h index 42083858..c2330561 100644 --- a/engine/inc/uf/ext/vulkan/device.h +++ b/engine/inc/uf/ext/vulkan/device.h @@ -29,6 +29,30 @@ namespace ext { operator VkCommandBuffer() { return handle; } }; + struct DescriptorAllocator { + VkDevice device = VK_NULL_HANDLE; + VkDescriptorPool currentPool = VK_NULL_HANDLE; + uf::stl::vector usedPools; + + uf::stl::vector poolSizes = { + { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4000 }, + { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 4000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 }, + { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 500 }, + { VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 100 } + }; + + void initialize( VkDevice ); + void destroy(); + VkDescriptorPool createPool(); + bool allocate( VkDescriptorSet* set, VkDescriptorSetLayout layout ); + }; + struct Texture; struct UF_API Device { @@ -69,6 +93,7 @@ namespace ext { } extensions; VkPipelineCache pipelineCache; + DescriptorAllocator descriptorAllocator; uf::stl::vector queueFamilyProperties; diff --git a/engine/inc/uf/ext/vulkan/graphic.h b/engine/inc/uf/ext/vulkan/graphic.h index 1a7e438b..712e4ad3 100644 --- a/engine/inc/uf/ext/vulkan/graphic.h +++ b/engine/inc/uf/ext/vulkan/graphic.h @@ -12,6 +12,8 @@ namespace ext { struct Graphic; struct UF_API Pipeline : public Buffers { + static uf::stl::unordered_map pipelines; + bool aliased = false; Device* device = NULL; @@ -42,9 +44,6 @@ namespace ext { void record( const Graphic& graphic, const GraphicDescriptor& descriptor, VkCommandBuffer, size_t = 0, size_t = 0, size_t = 0 ) const; void destroy(); - uf::stl::vector getShaders( uf::stl::vector&, const uf::stl::string& = "" ); - uf::stl::vector getShaders( const uf::stl::vector&, const uf::stl::string& = "" ) const; - void collectBuffers( const Shader& shader, const RenderMode& renderMode, const Graphic& graphic, const std::function& lambda ) const; }; @@ -73,6 +72,8 @@ namespace ext { Shader& getShader( const uf::stl::string& type, const uf::stl::string& pipeline = "" ); const Shader& getShader( const uf::stl::string& type, const uf::stl::string& pipeline = "" ) const; + uf::stl::vector getShaders( const uf::stl::string& = "" ) const; + bool validate(); }; diff --git a/engine/src/ext/vulkan/device.cpp b/engine/src/ext/vulkan/device.cpp index 2b029bd8..d6820d62 100644 --- a/engine/src/ext/vulkan/device.cpp +++ b/engine/src/ext/vulkan/device.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -1178,8 +1179,8 @@ void ext::vulkan::Device::initialize() { } struct BaseStructure { - VkStructureType sType; - void* pNext; + VkStructureType sType; + void* pNext; }; std::queue chain = {}; @@ -1457,7 +1458,7 @@ void ext::vulkan::Device::initialize() { if ( uf::io::exists( uf::io::root + "/cache/vulkan/cache.bin" ) ) { uf::io::readAsBuffer( buffer, uf::io::root + "/cache/vulkan/cache.bin" ); pipelineCacheCreateInfo.initialDataSize = buffer.size(); - pipelineCacheCreateInfo.pInitialData = buffer.data(); + pipelineCacheCreateInfo.pInitialData = buffer.data(); } VK_CHECK_RESULT(vkCreatePipelineCache( device, &pipelineCacheCreateInfo, nullptr, &this->pipelineCache)); @@ -1507,6 +1508,10 @@ void ext::vulkan::Device::initialize() { VK_REGISTER_HANDLE( allocator ); } + { + descriptorAllocator.initialize( logicalDevice ); + } + { vkGetBufferDeviceAddressKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR")); vkCmdBuildAccelerationStructuresKHR = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR")); @@ -1569,6 +1574,12 @@ void ext::vulkan::Device::destroy() { VK_UNREGISTER_HANDLE( this->pipelineCache ); this->pipelineCache = nullptr; } + + for ( auto& pair : Pipeline::pipelines ) pair.second.destroy(); + Pipeline::pipelines.clear(); + + descriptorAllocator.destroy(); + for ( auto& pair : this->commandPool.graphics.container() ) { vkDestroyCommandPool( this->logicalDevice, pair.second, nullptr ); VK_UNREGISTER_HANDLE( pair.second ); @@ -1608,4 +1619,50 @@ void ext::vulkan::Device::destroy() { VK_UNREGISTER_HANDLE( allocator ); } +void ext::vulkan::DescriptorAllocator::initialize(VkDevice inDevice) { + device = inDevice; + currentPool = createPool(); +} + +void ext::vulkan::DescriptorAllocator::destroy() { + if ( currentPool ) vkDestroyDescriptorPool(device, currentPool, nullptr); + for ( auto p : usedPools ) vkDestroyDescriptorPool(device, p, nullptr); + usedPools.clear(); +} + +VkDescriptorPool ext::vulkan::DescriptorAllocator::createPool() { + VkDescriptorPoolCreateInfo poolInfo = {}; + poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; + poolInfo.maxSets = 1000; + poolInfo.poolSizeCount = (uint32_t) poolSizes.size(); + poolInfo.pPoolSizes = poolSizes.data(); + + VkDescriptorPool pool; + VK_CHECK_RESULT(vkCreateDescriptorPool(device, &poolInfo, nullptr, &pool)); + return pool; +} + +bool ext::vulkan::DescriptorAllocator::allocate( VkDescriptorSet* set, VkDescriptorSetLayout layout ) { + if ( currentPool == VK_NULL_HANDLE ) currentPool = createPool(); + + VkDescriptorSetAllocateInfo allocInfo = {}; + allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocInfo.descriptorPool = currentPool; + allocInfo.descriptorSetCount = 1; + allocInfo.pSetLayouts = &layout; + + VkResult result = vkAllocateDescriptorSets(device, &allocInfo, set); + + if ( result == VK_ERROR_OUT_OF_POOL_MEMORY || result == VK_ERROR_FRAGMENTED_POOL ) { + usedPools.push_back(currentPool); + currentPool = createPool(); + allocInfo.descriptorPool = currentPool; + + result = vkAllocateDescriptorSets(device, &allocInfo, set); + } + + return result == VK_SUCCESS; +} + #endif \ No newline at end of file diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index 1afa9283..bcf87cac 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -19,6 +19,8 @@ namespace { uint32_t VERTEX_BUFFER_BIND_ID = 0; } +uf::stl::unordered_map ext::vulkan::Pipeline::pipelines; + PFN_vkGetBufferDeviceAddressKHR ext::vulkan::vkGetBufferDeviceAddressKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR")); PFN_vkCmdBuildAccelerationStructuresKHR ext::vulkan::vkCmdBuildAccelerationStructuresKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructuresKHR")); PFN_vkBuildAccelerationStructuresKHR ext::vulkan::vkBuildAccelerationStructuresKHR = NULL; // = reinterpret_cast(vkGetDeviceProcAddr(device, "vkBuildAccelerationStructuresKHR")); @@ -41,7 +43,7 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes this->metadata.type = descriptor.pipeline; Device& device = *graphic.device; - auto shaders = getShaders( graphic.material.shaders, descriptor.pipeline ); + auto shaders = graphic.material.getShaders( descriptor.pipeline ); assert( shaders.size() > 0 ); uint32_t subpass = descriptor.subpass; @@ -78,6 +80,7 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes offset += len; } } + /* for ( auto& descriptor : descriptorSetLayoutBindings ) { if ( descriptorTypes.count( descriptor.descriptorType ) < 0 ) descriptorTypes[descriptor.descriptorType] = 0; descriptorTypes[descriptor.descriptorType] += descriptor.descriptorCount; @@ -92,6 +95,7 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes ); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); VK_REGISTER_HANDLE( descriptorPool ); + */ VkDescriptorSetLayoutCreateInfo descriptorLayout = ext::vulkan::initializers::descriptorSetLayoutCreateInfo( descriptorSetLayoutBindings.data(), @@ -100,12 +104,16 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes VK_CHECK_RESULT(vkCreateDescriptorSetLayout( device, &descriptorLayout, nullptr, &descriptorSetLayout )); VK_REGISTER_HANDLE( descriptorSetLayout ); + UF_ASSERT(device.descriptorAllocator.allocate( &descriptorSet, descriptorSetLayout )); + + /* VkDescriptorSetAllocateInfo allocInfo = ext::vulkan::initializers::descriptorSetAllocateInfo( descriptorPool, &descriptorSetLayout, 1 ); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); + */ VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = ext::vulkan::initializers::pipelineLayoutCreateInfo( &descriptorSetLayout, @@ -396,7 +404,7 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, VkCommandBuffer comm return record( graphic, descriptor, commandBuffer, pass, draw, offset ); } void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescriptor& descriptor, VkCommandBuffer commandBuffer, size_t pass, size_t draw, size_t offset ) const { - auto shaders = getShaders( graphic.material.shaders, descriptor.pipeline ); + auto shaders = graphic.material.getShaders( descriptor.pipeline ); // create dynamic offset ranges STATIC_THREAD_LOCAL(uf::stl::vector, dynamicOffsets); @@ -507,7 +515,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip RenderMode& renderMode = ext::vulkan::getRenderMode(descriptor.renderMode, true); auto& renderTarget = renderMode.getRenderTarget(/*descriptor.renderTarget*/); - auto shaders = getShaders( graphic.material.shaders, descriptor.pipeline ); + auto shaders = graphic.material.getShaders( descriptor.pipeline ); uf::stl::vector writeDescriptorSets; uf::stl::vector tlases; @@ -948,32 +956,17 @@ void ext::vulkan::Pipeline::destroy() { } */ } -uf::stl::vector ext::vulkan::Pipeline::getShaders( uf::stl::vector& shaders, const uf::stl::string& type ) { - uf::stl::unordered_map map; - uf::stl::vector res; - bool isCompute = false; - for ( auto& shader : shaders ) { - if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != (type == "" ? metadata.type : type) ) continue; - if ( shader.descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) isCompute = true; - } - for ( auto& shader : shaders ) { - if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != (type == "" ? metadata.type : type) ) continue; - if ( isCompute && shader.descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue; - map[shader.metadata.type] = &shader; - } - for ( auto pair : map ) res.insert( res.begin(), pair.second); - return res; -} -uf::stl::vector ext::vulkan::Pipeline::getShaders( const uf::stl::vector& shaders, const uf::stl::string& type ) const { + +uf::stl::vector ext::vulkan::Material::getShaders( const uf::stl::string& type ) const { uf::stl::unordered_map map; uf::stl::vector res; bool isCompute = false; for ( auto& shader : shaders ) { - if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != (type == "" ? metadata.type : type) ) continue; + if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != type ) continue; if ( shader.descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) isCompute = true; } for ( auto& shader : shaders ) { - if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != (type == "" ? metadata.type : type) ) continue; + if ( shader.metadata.pipeline != "" && shader.metadata.pipeline != type ) continue; if ( isCompute && shader.descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue; map[shader.metadata.type] = &shader; } @@ -1852,7 +1845,7 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD if ( !pipeline.metadata.process ) return; pipeline.record(*this, descriptor, commandBuffer, pass, draw, offset); - auto shaders = pipeline.getShaders( material.shaders, descriptor.pipeline ); + auto shaders = material.getShaders( descriptor.pipeline ); for ( auto* shader : shaders ) { if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) return; if (