From d88c2ef41c9404c09b6260ca42813db1997306dd Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 29 Jun 2022 20:12:36 +0200 Subject: [PATCH] Update builders to use the new form also used by the gzd backend --- src/lightmap/gpuraytracer.cpp | 432 ++++----- src/lightmap/vulkanbuilders.cpp | 1614 ++++++++++++++++++++++++++++--- src/lightmap/vulkanbuilders.h | 1458 +++------------------------- src/lightmap/vulkandevice.cpp | 4 +- src/lightmap/vulkandevice.h | 2 + src/lightmap/vulkanobjects.h | 5 +- 6 files changed, 1855 insertions(+), 1660 deletions(-) diff --git a/src/lightmap/gpuraytracer.cpp b/src/lightmap/gpuraytracer.cpp index 333fce2..1a0ccc9 100644 --- a/src/lightmap/gpuraytracer.cpp +++ b/src/lightmap/gpuraytracer.cpp @@ -167,9 +167,9 @@ void GPURaytracer::CreateVulkanObjects() CreatePipeline(); CreateDescriptorSet(); - PipelineBarrier finishbuildbarrier; - finishbuildbarrier.addMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR); - finishbuildbarrier.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); + PipelineBarrier() + .AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR) + .Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); } void GPURaytracer::UploadTasks(const TraceTask* tasks, size_t size) @@ -210,9 +210,9 @@ void GPURaytracer::UploadTasks(const TraceTask* tasks, size_t size) } imageTransferBuffer->Unmap(); - PipelineBarrier barrier1; - barrier1.addImage(startPositionsImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT); - barrier1.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + PipelineBarrier() + .AddImage(startPositionsImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT) + .Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); VkBufferImageCopy region = {}; region.bufferOffset = 0; @@ -223,12 +223,12 @@ void GPURaytracer::UploadTasks(const TraceTask* tasks, size_t size) region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; cmdbuffer->copyBufferToImage(imageTransferBuffer->buffer, startPositionsImage->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - PipelineBarrier barrier2; - barrier2.addBuffer(uniformBuffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); - barrier2.addImage(startPositionsImage.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); - barrier2.addImage(positionsImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 0, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); - barrier2.addImage(outputImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 0, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); - barrier2.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); + PipelineBarrier() + .AddBuffer(uniformBuffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) + .AddImage(startPositionsImage.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) + .AddImage(positionsImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 0, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT) + .AddImage(outputImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 0, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT) + .Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); } void GPURaytracer::BeginTracing() @@ -256,10 +256,10 @@ void GPURaytracer::RunTrace(const Uniforms& uniforms, const VkStridedDeviceAddre bool needbarrier = true; if (uniformsIndex == 0) { - PipelineBarrier barrier; - barrier.addBuffer(uniformBuffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); - barrier.addImage(positionsImage.get(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); - barrier.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); + PipelineBarrier() + .AddBuffer(uniformBuffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) + .AddImage(positionsImage.get(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT) + .Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); needbarrier = false; } uniformsIndex++; @@ -272,9 +272,9 @@ void GPURaytracer::RunTrace(const Uniforms& uniforms, const VkStridedDeviceAddre if (needbarrier) { - PipelineBarrier barrier; - barrier.addImage(positionsImage.get(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); - barrier.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); + PipelineBarrier() + .AddImage(positionsImage.get(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT) + .Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); } PushConstants constants = {}; @@ -304,9 +304,9 @@ void GPURaytracer::SubmitCommands() { auto submitFence = std::make_unique(device.get()); - QueueSubmit submit; - submit.addCommandBuffer(cmdbuffer.get()); - submit.execute(device.get(), device->graphicsQueue, submitFence.get()); + QueueSubmit() + .AddCommandBuffer(cmdbuffer.get()) + .Execute(device.get(), device->graphicsQueue, submitFence.get()); VkResult result = vkWaitForFences(device->device, 1, &submitFence->fence, VK_TRUE, std::numeric_limits::max()); if (result != VK_SUCCESS) @@ -319,9 +319,9 @@ void GPURaytracer::SubmitCommands() void GPURaytracer::DownloadTasks(const TraceTask* tasks, size_t size) { - PipelineBarrier barrier4; - barrier4.addImage(outputImage.get(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT); - barrier4.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT); + PipelineBarrier() + .AddImage(outputImage.get(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT) + .Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT); VkBufferImageCopy region = {}; region.bufferOffset = 0; @@ -438,41 +438,42 @@ void GPURaytracer::CreateVertexAndIndexBuffers() size_t surfaceoffset = surfaceindexoffset + surfaceindexbuffersize; size_t lightoffset = surfaceoffset + surfacebuffersize; - BufferBuilder vbuilder; - vbuilder.setUsage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); - vbuilder.setSize(vertexbuffersize); - vertexBuffer = vbuilder.create(device.get()); - vertexBuffer->SetDebugName("vertexBuffer"); + vertexBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + .Size(vertexbuffersize) + .DebugName("vertexBuffer") + .Create(device.get()); - BufferBuilder ibuilder; - ibuilder.setUsage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); - ibuilder.setSize(indexbuffersize); - indexBuffer = ibuilder.create(device.get()); - indexBuffer->SetDebugName("indexBuffer"); + indexBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + .Size(indexbuffersize) + .DebugName("indexBuffer") + .Create(device.get()); - BufferBuilder sibuilder; - sibuilder.setUsage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); - sibuilder.setSize(surfaceindexbuffersize); - surfaceIndexBuffer = sibuilder.create(device.get()); - surfaceIndexBuffer->SetDebugName("surfaceIndexBuffer"); + surfaceIndexBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(surfaceindexbuffersize) + .DebugName("surfaceIndexBuffer") + .Create(device.get()); - BufferBuilder sbuilder; - sbuilder.setUsage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); - sbuilder.setSize(surfacebuffersize); - surfaceBuffer = sbuilder.create(device.get()); - surfaceBuffer->SetDebugName("surfaceBuffer"); + surfaceBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(surfacebuffersize) + .DebugName("surfaceBuffer") + .Create(device.get()); - BufferBuilder lbuilder; - lbuilder.setUsage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); - lbuilder.setSize(lightbuffersize); - lightBuffer = lbuilder.create(device.get()); - lightBuffer->SetDebugName("lightBuffer"); + lightBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(lightbuffersize) + .DebugName("lightBuffer") + .Create(device.get()); + + transferBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .Size(transferbuffersize) + .DebugName("transferBuffer") + .Create(device.get()); - BufferBuilder tbuilder; - tbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - tbuilder.setSize(transferbuffersize); - transferBuffer = tbuilder.create(device.get()); - transferBuffer->SetDebugName("transferBuffer"); uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferbuffersize); memcpy(data + vertexoffset, mesh->MeshVertices.Data(), vertexbuffersize); memcpy(data + indexoffset, mesh->MeshElements.Data(), indexbuffersize); @@ -531,11 +532,11 @@ void GPURaytracer::CreateBottomLevelAccelerationStructure() VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR }; vkGetAccelerationStructureBuildSizesKHR(device->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxPrimitiveCount, &sizeInfo); - BufferBuilder blbufbuilder; - blbufbuilder.setUsage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); - blbufbuilder.setSize(sizeInfo.accelerationStructureSize); - blAccelStructBuffer = blbufbuilder.create(device.get()); - blAccelStructBuffer->SetDebugName("blAccelStructBuffer"); + blAccelStructBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) + .Size(sizeInfo.accelerationStructureSize) + .DebugName("blAccelStructBuffer") + .Create(device.get()); VkAccelerationStructureKHR blAccelStructHandle = {}; VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR }; @@ -547,11 +548,11 @@ void GPURaytracer::CreateBottomLevelAccelerationStructure() throw std::runtime_error("vkCreateAccelerationStructureKHR failed"); blAccelStruct = std::make_unique(device.get(), blAccelStructHandle); - BufferBuilder sbuilder; - sbuilder.setUsage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); - sbuilder.setSize(sizeInfo.buildScratchSize); - blScratchBuffer = sbuilder.create(device.get()); - blScratchBuffer->SetDebugName("blScratchBuffer"); + blScratchBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + .Size(sizeInfo.buildScratchSize) + .DebugName("blScratchBuffer") + .Create(device.get()); info = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO }; info.buffer = blScratchBuffer->buffer; @@ -579,20 +580,21 @@ void GPURaytracer::CreateTopLevelAccelerationStructure() instance.mask = 0xff; instance.instanceShaderBindingTableRecordOffset = 0; - BufferBuilder tbuilder; - tbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - tbuilder.setSize(sizeof(VkAccelerationStructureInstanceKHR)); - tlTransferBuffer = tbuilder.create(device.get()); - tlTransferBuffer->SetDebugName("tlTransferBuffer"); + tlTransferBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .Size(sizeof(VkAccelerationStructureInstanceKHR)) + .DebugName("tlTransferBuffer") + .Create(device.get()); + auto data = (uint8_t*)tlTransferBuffer->Map(0, sizeof(VkAccelerationStructureInstanceKHR)); memcpy(data, &instance, sizeof(VkAccelerationStructureInstanceKHR)); tlTransferBuffer->Unmap(); - BufferBuilder instbufbuilder; - instbufbuilder.setUsage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_DST_BIT); - instbufbuilder.setSize(sizeof(VkAccelerationStructureInstanceKHR)); - tlInstanceBuffer = instbufbuilder.create(device.get()); - tlInstanceBuffer->SetDebugName("tlInstanceBuffer"); + tlInstanceBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(sizeof(VkAccelerationStructureInstanceKHR)) + .DebugName("tlInstanceBuffer") + .Create(device.get()); cmdbuffer->copyBuffer(tlTransferBuffer.get(), tlInstanceBuffer.get()); @@ -628,11 +630,11 @@ void GPURaytracer::CreateTopLevelAccelerationStructure() VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR }; vkGetAccelerationStructureBuildSizesKHR(device->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxInstanceCount, &sizeInfo); - BufferBuilder tlbufbuilder; - tlbufbuilder.setUsage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); - tlbufbuilder.setSize(sizeInfo.accelerationStructureSize); - tlAccelStructBuffer = tlbufbuilder.create(device.get()); - tlAccelStructBuffer->SetDebugName("tlAccelStructBuffer"); + tlAccelStructBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) + .Size(sizeInfo.accelerationStructureSize) + .DebugName("tlAccelStructBuffer") + .Create(device.get()); VkAccelerationStructureKHR tlAccelStructHandle = {}; VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR }; @@ -644,11 +646,11 @@ void GPURaytracer::CreateTopLevelAccelerationStructure() throw std::runtime_error("vkCreateAccelerationStructureKHR failed"); tlAccelStruct = std::make_unique(device.get(), tlAccelStructHandle); - BufferBuilder sbuilder; - sbuilder.setUsage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); - sbuilder.setSize(sizeInfo.buildScratchSize); - tlScratchBuffer = sbuilder.create(device.get()); - tlScratchBuffer->SetDebugName("tlScratchBuffer"); + tlScratchBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + .Size(sizeInfo.buildScratchSize) + .DebugName("tlScratchBuffer") + .Create(device.get()); info = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO }; info.buffer = tlScratchBuffer->buffer; @@ -680,11 +682,10 @@ std::unique_ptr GPURaytracer::CompileRayGenShader(const char* code { try { - ShaderBuilder builder; - builder.setRayGenShader(code); - auto shader = builder.create(device.get()); - shader->SetDebugName(name); - return shader; + return ShaderBuilder() + .RayGenShader(code) + .DebugName(name) + .Create(name, device.get()); } catch (const std::exception& e) { @@ -696,11 +697,10 @@ std::unique_ptr GPURaytracer::CompileClosestHitShader(const char* { try { - ShaderBuilder builder; - builder.setClosestHitShader(code); - auto shader = builder.create(device.get()); - shader->SetDebugName(name); - return shader; + return ShaderBuilder() + .ClosestHitShader(code) + .DebugName(name) + .Create(name, device.get()); } catch (const std::exception& e) { @@ -712,11 +712,10 @@ std::unique_ptr GPURaytracer::CompileMissShader(const char* code, { try { - ShaderBuilder builder; - builder.setMissShader(code); - auto shader = builder.create(device.get()); - shader->SetDebugName(name); - return shader; + return ShaderBuilder() + .MissShader(code) + .DebugName(name) + .Create(name, device.get()); } catch (const std::exception& e) { @@ -726,51 +725,51 @@ std::unique_ptr GPURaytracer::CompileMissShader(const char* code, void GPURaytracer::CreatePipeline() { - DescriptorSetLayoutBuilder setbuilder; - setbuilder.addBinding(0, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR); - setbuilder.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR); - setbuilder.addBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR); - setbuilder.addBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR); - setbuilder.addBinding(4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR); - setbuilder.addBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR); - setbuilder.addBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR); - setbuilder.addBinding(7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR); - descriptorSetLayout = setbuilder.create(device.get()); - descriptorSetLayout->SetDebugName("descriptorSetLayout"); + descriptorSetLayout = DescriptorSetLayoutBuilder() + .AddBinding(0, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR) + .AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR) + .AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR) + .AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR) + .AddBinding(4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR) + .AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR) + .AddBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR) + .AddBinding(7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR) + .DebugName("descriptorSetLayout") + .Create(device.get()); - PipelineLayoutBuilder layoutbuilder; - layoutbuilder.addSetLayout(descriptorSetLayout.get()); - layoutbuilder.addPushConstantRange(VK_SHADER_STAGE_RAYGEN_BIT_KHR, 0, sizeof(PushConstants)); - pipelineLayout = layoutbuilder.create(device.get()); - pipelineLayout->SetDebugName("pipelineLayout"); + pipelineLayout = PipelineLayoutBuilder() + .AddSetLayout(descriptorSetLayout.get()) + .AddPushConstantRange(VK_SHADER_STAGE_RAYGEN_BIT_KHR, 0, sizeof(PushConstants)) + .DebugName("pipelineLayout") + .Create(device.get()); - RayTracingPipelineBuilder builder; - builder.setLayout(pipelineLayout.get()); - builder.setMaxPipelineRayRecursionDepth(1); - builder.addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenBounce.get()); - builder.addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenLight.get()); - builder.addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenAmbient.get()); - builder.addShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissBounce.get()); - builder.addShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissLight.get()); - builder.addShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissSun.get()); - builder.addShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissAmbient.get()); - builder.addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, rchitBounce.get()); - builder.addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, rchitLight.get()); - builder.addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, rchitSun.get()); - builder.addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, rchitAmbient.get()); - builder.addRayGenGroup(0); - builder.addRayGenGroup(1); - builder.addRayGenGroup(2); - builder.addMissGroup(3); - builder.addMissGroup(4); - builder.addMissGroup(5); - builder.addMissGroup(6); - builder.addTrianglesHitGroup(7); - builder.addTrianglesHitGroup(8); - builder.addTrianglesHitGroup(9); - builder.addTrianglesHitGroup(10); - pipeline = builder.create(device.get()); - pipeline->SetDebugName("pipeline"); + pipeline = RayTracingPipelineBuilder() + .Layout(pipelineLayout.get()) + .MaxPipelineRayRecursionDepth(1) + .AddShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenBounce.get()) + .AddShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenLight.get()) + .AddShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenAmbient.get()) + .AddShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissBounce.get()) + .AddShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissLight.get()) + .AddShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissSun.get()) + .AddShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissAmbient.get()) + .AddShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, rchitBounce.get()) + .AddShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, rchitLight.get()) + .AddShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, rchitSun.get()) + .AddShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, rchitAmbient.get()) + .AddRayGenGroup(0) + .AddRayGenGroup(1) + .AddRayGenGroup(2) + .AddMissGroup(3) + .AddMissGroup(4) + .AddMissGroup(5) + .AddMissGroup(6) + .AddTrianglesHitGroup(7) + .AddTrianglesHitGroup(8) + .AddTrianglesHitGroup(9) + .AddTrianglesHitGroup(10) + .DebugName("pipeline") + .Create(device.get()); const auto& rtProperties = device->physicalDevice.rayTracingProperties; @@ -804,17 +803,18 @@ void GPURaytracer::CreatePipeline() VkDeviceSize sbtBufferSize = rgenSize + missRegion.size + hitRegion.size; - BufferBuilder bufbuilder; - bufbuilder.setUsage(VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); - bufbuilder.setSize(sbtBufferSize); - shaderBindingTable = bufbuilder.create(device.get()); - shaderBindingTable->SetDebugName("shaderBindingTable"); + shaderBindingTable = BufferBuilder() + .Usage(VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(sbtBufferSize) + .DebugName("shaderBindingTable") + .Create(device.get()); + + sbtTransferBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .Size(sbtBufferSize) + .DebugName("sbtTransferBuffer") + .Create(device.get()); - BufferBuilder tbuilder; - tbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - tbuilder.setSize(sbtBufferSize); - sbtTransferBuffer = tbuilder.create(device.get()); - sbtTransferBuffer->SetDebugName("sbtTransferBuffer"); uint8_t* src = (uint8_t*)pipeline->shaderGroupHandles.data(); uint8_t* dest = (uint8_t*)sbtTransferBuffer->Map(0, sbtBufferSize); for (VkDeviceSize i = 0; i < raygenCount; i++) @@ -857,82 +857,82 @@ void GPURaytracer::CreateDescriptorSet() VkDeviceSize align = device->physicalDevice.properties.limits.minUniformBufferOffsetAlignment; uniformStructStride = (sizeof(Uniforms) + align - 1) / align * align; - BufferBuilder uniformbuilder; - uniformbuilder.setUsage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); - uniformbuilder.setSize(uniformStructs * uniformStructStride); - uniformBuffer = uniformbuilder.create(device.get()); - uniformBuffer->SetDebugName("uniformBuffer"); + uniformBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + .Size(uniformStructs * uniformStructStride) + .DebugName("uniformBuffer") + .Create(device.get()); - BufferBuilder uniformtransferbuilder; - uniformtransferbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); - uniformtransferbuilder.setSize(uniformStructs * uniformStructStride); - uniformTransferBuffer = uniformtransferbuilder.create(device.get()); - uniformTransferBuffer->SetDebugName("uniformTransferBuffer"); + uniformTransferBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU) + .Size(uniformStructs * uniformStructStride) + .DebugName("uniformTransferBuffer") + .Create(device.get()); - BufferBuilder itbuilder; - itbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - itbuilder.setSize(2 * sizeof(vec4) * rayTraceImageSize * rayTraceImageSize); - imageTransferBuffer = itbuilder.create(device.get()); - imageTransferBuffer->SetDebugName("imageTransferBuffer"); + imageTransferBuffer = BufferBuilder() + .Usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) + .Size(2 * sizeof(vec4) * rayTraceImageSize * rayTraceImageSize) + .DebugName("imageTransferBuffer") + .Create(device.get()); - ImageBuilder imgbuilder1; - imgbuilder1.setUsage(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); - imgbuilder1.setFormat(VK_FORMAT_R32G32B32A32_SFLOAT); - imgbuilder1.setSize(rayTraceImageSize, rayTraceImageSize); - startPositionsImage = imgbuilder1.create(device.get()); - startPositionsImage->SetDebugName("startPositionsImage"); + startPositionsImage = ImageBuilder() + .Usage(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) + .Format(VK_FORMAT_R32G32B32A32_SFLOAT) + .Size(rayTraceImageSize, rayTraceImageSize) + .DebugName("startPositionsImage") + .Create(device.get()); - ImageBuilder imgbuilder2; - imgbuilder2.setUsage(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); - imgbuilder2.setFormat(VK_FORMAT_R32G32B32A32_SFLOAT); - imgbuilder2.setSize(rayTraceImageSize, rayTraceImageSize); - positionsImage = imgbuilder2.create(device.get()); - positionsImage->SetDebugName("positionsImage"); + positionsImage = ImageBuilder() + .Usage(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) + .Format(VK_FORMAT_R32G32B32A32_SFLOAT) + .Size(rayTraceImageSize, rayTraceImageSize) + .DebugName("positionsImage") + .Create(device.get()); - ImageBuilder imgbuilder3; - imgbuilder3.setUsage(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); - imgbuilder3.setFormat(VK_FORMAT_R32G32B32A32_SFLOAT); - imgbuilder3.setSize(rayTraceImageSize, rayTraceImageSize); - outputImage = imgbuilder3.create(device.get()); - outputImage->SetDebugName("outputImage"); + outputImage = ImageBuilder() + .Usage(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT) + .Format(VK_FORMAT_R32G32B32A32_SFLOAT) + .Size(rayTraceImageSize, rayTraceImageSize) + .DebugName("outputImage") + .Create(device.get()); - ImageViewBuilder viewbuilder1; - viewbuilder1.setImage(startPositionsImage.get(), VK_FORMAT_R32G32B32A32_SFLOAT); - startPositionsImageView = viewbuilder1.create(device.get()); - startPositionsImageView->SetDebugName("startPositionsImageView"); + startPositionsImageView = ImageViewBuilder() + .Image(startPositionsImage.get(), VK_FORMAT_R32G32B32A32_SFLOAT) + .DebugName("startPositionsImageView") + .Create(device.get()); - ImageViewBuilder viewbuilder2; - viewbuilder2.setImage(positionsImage.get(), VK_FORMAT_R32G32B32A32_SFLOAT); - positionsImageView = viewbuilder2.create(device.get()); - positionsImageView->SetDebugName("positionsImageView"); + positionsImageView = ImageViewBuilder() + .Image(positionsImage.get(), VK_FORMAT_R32G32B32A32_SFLOAT) + .DebugName("positionsImageView") + .Create(device.get()); - ImageViewBuilder viewbuilder3; - viewbuilder3.setImage(outputImage.get(), VK_FORMAT_R32G32B32A32_SFLOAT); - outputImageView = viewbuilder3.create(device.get()); - outputImageView->SetDebugName("outputImageView"); + outputImageView = ImageViewBuilder() + .Image(outputImage.get(), VK_FORMAT_R32G32B32A32_SFLOAT) + .DebugName("outputImageView") + .Create(device.get()); - DescriptorPoolBuilder poolbuilder; - poolbuilder.addPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1); - poolbuilder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 3); - poolbuilder.addPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1); - poolbuilder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3); - poolbuilder.setMaxSets(1); - descriptorPool = poolbuilder.create(device.get()); - descriptorPool->SetDebugName("descriptorPool"); + descriptorPool = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1) + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 3) + .AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1) + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3) + .MaxSets(1) + .DebugName("descriptorPool") + .Create(device.get()); descriptorSet = descriptorPool->allocate(descriptorSetLayout.get()); descriptorSet->SetDebugName("descriptorSet"); - WriteDescriptors write; - write.addAccelerationStructure(descriptorSet.get(), 0, tlAccelStruct.get()); - write.addStorageImage(descriptorSet.get(), 1, startPositionsImageView.get(), VK_IMAGE_LAYOUT_GENERAL); - write.addStorageImage(descriptorSet.get(), 2, positionsImageView.get(), VK_IMAGE_LAYOUT_GENERAL); - write.addStorageImage(descriptorSet.get(), 3, outputImageView.get(), VK_IMAGE_LAYOUT_GENERAL); - write.addBuffer(descriptorSet.get(), 4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, uniformBuffer.get(), 0, sizeof(Uniforms)); - write.addBuffer(descriptorSet.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceIndexBuffer.get()); - write.addBuffer(descriptorSet.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceBuffer.get()); - write.addBuffer(descriptorSet.get(), 7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, lightBuffer.get()); - write.updateSets(device.get()); + WriteDescriptors() + .AddAccelerationStructure(descriptorSet.get(), 0, tlAccelStruct.get()) + .AddStorageImage(descriptorSet.get(), 1, startPositionsImageView.get(), VK_IMAGE_LAYOUT_GENERAL) + .AddStorageImage(descriptorSet.get(), 2, positionsImageView.get(), VK_IMAGE_LAYOUT_GENERAL) + .AddStorageImage(descriptorSet.get(), 3, outputImageView.get(), VK_IMAGE_LAYOUT_GENERAL) + .AddBuffer(descriptorSet.get(), 4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, uniformBuffer.get(), 0, sizeof(Uniforms)) + .AddBuffer(descriptorSet.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceIndexBuffer.get()) + .AddBuffer(descriptorSet.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceBuffer.get()) + .AddBuffer(descriptorSet.get(), 7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, lightBuffer.get()) + .Execute(device.get()); } void GPURaytracer::PrintVulkanInfo() diff --git a/src/lightmap/vulkanbuilders.cpp b/src/lightmap/vulkanbuilders.cpp index b632af2..24d0fb6 100644 --- a/src/lightmap/vulkanbuilders.cpp +++ b/src/lightmap/vulkanbuilders.cpp @@ -2,160 +2,193 @@ #include "vulkanbuilders.h" static const TBuiltInResource DefaultTBuiltInResource = { - /* .MaxLights = */ 32, - /* .MaxClipPlanes = */ 6, - /* .MaxTextureUnits = */ 32, - /* .MaxTextureCoords = */ 32, - /* .MaxVertexAttribs = */ 64, - /* .MaxVertexUniformComponents = */ 4096, - /* .MaxVaryingFloats = */ 64, - /* .MaxVertexTextureImageUnits = */ 32, - /* .MaxCombinedTextureImageUnits = */ 80, - /* .MaxTextureImageUnits = */ 32, - /* .MaxFragmentUniformComponents = */ 4096, - /* .MaxDrawBuffers = */ 32, - /* .MaxVertexUniformVectors = */ 128, - /* .MaxVaryingVectors = */ 8, - /* .MaxFragmentUniformVectors = */ 16, - /* .MaxVertexOutputVectors = */ 16, - /* .MaxFragmentInputVectors = */ 15, - /* .MinProgramTexelOffset = */ -8, - /* .MaxProgramTexelOffset = */ 7, - /* .MaxClipDistances = */ 8, - /* .MaxComputeWorkGroupCountX = */ 65535, - /* .MaxComputeWorkGroupCountY = */ 65535, - /* .MaxComputeWorkGroupCountZ = */ 65535, - /* .MaxComputeWorkGroupSizeX = */ 1024, - /* .MaxComputeWorkGroupSizeY = */ 1024, - /* .MaxComputeWorkGroupSizeZ = */ 64, - /* .MaxComputeUniformComponents = */ 1024, - /* .MaxComputeTextureImageUnits = */ 16, - /* .MaxComputeImageUniforms = */ 8, - /* .MaxComputeAtomicCounters = */ 8, - /* .MaxComputeAtomicCounterBuffers = */ 1, - /* .MaxVaryingComponents = */ 60, - /* .MaxVertexOutputComponents = */ 64, - /* .MaxGeometryInputComponents = */ 64, - /* .MaxGeometryOutputComponents = */ 128, - /* .MaxFragmentInputComponents = */ 128, - /* .MaxImageUnits = */ 8, - /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, - /* .MaxCombinedShaderOutputResources = */ 8, - /* .MaxImageSamples = */ 0, - /* .MaxVertexImageUniforms = */ 0, - /* .MaxTessControlImageUniforms = */ 0, - /* .MaxTessEvaluationImageUniforms = */ 0, - /* .MaxGeometryImageUniforms = */ 0, - /* .MaxFragmentImageUniforms = */ 8, - /* .MaxCombinedImageUniforms = */ 8, - /* .MaxGeometryTextureImageUnits = */ 16, - /* .MaxGeometryOutputVertices = */ 256, - /* .MaxGeometryTotalOutputComponents = */ 1024, - /* .MaxGeometryUniformComponents = */ 1024, - /* .MaxGeometryVaryingComponents = */ 64, - /* .MaxTessControlInputComponents = */ 128, - /* .MaxTessControlOutputComponents = */ 128, - /* .MaxTessControlTextureImageUnits = */ 16, - /* .MaxTessControlUniformComponents = */ 1024, - /* .MaxTessControlTotalOutputComponents = */ 4096, - /* .MaxTessEvaluationInputComponents = */ 128, - /* .MaxTessEvaluationOutputComponents = */ 128, - /* .MaxTessEvaluationTextureImageUnits = */ 16, - /* .MaxTessEvaluationUniformComponents = */ 1024, - /* .MaxTessPatchComponents = */ 120, - /* .MaxPatchVertices = */ 32, - /* .MaxTessGenLevel = */ 64, - /* .MaxViewports = */ 16, - /* .MaxVertexAtomicCounters = */ 0, - /* .MaxTessControlAtomicCounters = */ 0, - /* .MaxTessEvaluationAtomicCounters = */ 0, - /* .MaxGeometryAtomicCounters = */ 0, - /* .MaxFragmentAtomicCounters = */ 8, - /* .MaxCombinedAtomicCounters = */ 8, - /* .MaxAtomicCounterBindings = */ 1, - /* .MaxVertexAtomicCounterBuffers = */ 0, - /* .MaxTessControlAtomicCounterBuffers = */ 0, - /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, - /* .MaxGeometryAtomicCounterBuffers = */ 0, - /* .MaxFragmentAtomicCounterBuffers = */ 1, - /* .MaxCombinedAtomicCounterBuffers = */ 1, - /* .MaxAtomicCounterBufferSize = */ 16384, - /* .MaxTransformFeedbackBuffers = */ 4, - /* .MaxTransformFeedbackInterleavedComponents = */ 64, - /* .MaxCullDistances = */ 8, - /* .MaxCombinedClipAndCullDistances = */ 8, - /* .MaxSamples = */ 4, - /* .maxMeshOutputVerticesNV = */ 256, - /* .maxMeshOutputPrimitivesNV = */ 512, - /* .maxMeshWorkGroupSizeX_NV = */ 32, - /* .maxMeshWorkGroupSizeY_NV = */ 1, - /* .maxMeshWorkGroupSizeZ_NV = */ 1, - /* .maxTaskWorkGroupSizeX_NV = */ 32, - /* .maxTaskWorkGroupSizeY_NV = */ 1, - /* .maxTaskWorkGroupSizeZ_NV = */ 1, - /* .maxMeshViewCountNV = */ 4, - /* .maxDualSourceDrawBuffersEXT = */ 1, + /* .MaxLights = */ 32, + /* .MaxClipPlanes = */ 6, + /* .MaxTextureUnits = */ 32, + /* .MaxTextureCoords = */ 32, + /* .MaxVertexAttribs = */ 64, + /* .MaxVertexUniformComponents = */ 4096, + /* .MaxVaryingFloats = */ 64, + /* .MaxVertexTextureImageUnits = */ 32, + /* .MaxCombinedTextureImageUnits = */ 80, + /* .MaxTextureImageUnits = */ 32, + /* .MaxFragmentUniformComponents = */ 4096, + /* .MaxDrawBuffers = */ 32, + /* .MaxVertexUniformVectors = */ 128, + /* .MaxVaryingVectors = */ 8, + /* .MaxFragmentUniformVectors = */ 16, + /* .MaxVertexOutputVectors = */ 16, + /* .MaxFragmentInputVectors = */ 15, + /* .MinProgramTexelOffset = */ -8, + /* .MaxProgramTexelOffset = */ 7, + /* .MaxClipDistances = */ 8, + /* .MaxComputeWorkGroupCountX = */ 65535, + /* .MaxComputeWorkGroupCountY = */ 65535, + /* .MaxComputeWorkGroupCountZ = */ 65535, + /* .MaxComputeWorkGroupSizeX = */ 1024, + /* .MaxComputeWorkGroupSizeY = */ 1024, + /* .MaxComputeWorkGroupSizeZ = */ 64, + /* .MaxComputeUniformComponents = */ 1024, + /* .MaxComputeTextureImageUnits = */ 16, + /* .MaxComputeImageUniforms = */ 8, + /* .MaxComputeAtomicCounters = */ 8, + /* .MaxComputeAtomicCounterBuffers = */ 1, + /* .MaxVaryingComponents = */ 60, + /* .MaxVertexOutputComponents = */ 64, + /* .MaxGeometryInputComponents = */ 64, + /* .MaxGeometryOutputComponents = */ 128, + /* .MaxFragmentInputComponents = */ 128, + /* .MaxImageUnits = */ 8, + /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, + /* .MaxCombinedShaderOutputResources = */ 8, + /* .MaxImageSamples = */ 0, + /* .MaxVertexImageUniforms = */ 0, + /* .MaxTessControlImageUniforms = */ 0, + /* .MaxTessEvaluationImageUniforms = */ 0, + /* .MaxGeometryImageUniforms = */ 0, + /* .MaxFragmentImageUniforms = */ 8, + /* .MaxCombinedImageUniforms = */ 8, + /* .MaxGeometryTextureImageUnits = */ 16, + /* .MaxGeometryOutputVertices = */ 256, + /* .MaxGeometryTotalOutputComponents = */ 1024, + /* .MaxGeometryUniformComponents = */ 1024, + /* .MaxGeometryVaryingComponents = */ 64, + /* .MaxTessControlInputComponents = */ 128, + /* .MaxTessControlOutputComponents = */ 128, + /* .MaxTessControlTextureImageUnits = */ 16, + /* .MaxTessControlUniformComponents = */ 1024, + /* .MaxTessControlTotalOutputComponents = */ 4096, + /* .MaxTessEvaluationInputComponents = */ 128, + /* .MaxTessEvaluationOutputComponents = */ 128, + /* .MaxTessEvaluationTextureImageUnits = */ 16, + /* .MaxTessEvaluationUniformComponents = */ 1024, + /* .MaxTessPatchComponents = */ 120, + /* .MaxPatchVertices = */ 32, + /* .MaxTessGenLevel = */ 64, + /* .MaxViewports = */ 16, + /* .MaxVertexAtomicCounters = */ 0, + /* .MaxTessControlAtomicCounters = */ 0, + /* .MaxTessEvaluationAtomicCounters = */ 0, + /* .MaxGeometryAtomicCounters = */ 0, + /* .MaxFragmentAtomicCounters = */ 8, + /* .MaxCombinedAtomicCounters = */ 8, + /* .MaxAtomicCounterBindings = */ 1, + /* .MaxVertexAtomicCounterBuffers = */ 0, + /* .MaxTessControlAtomicCounterBuffers = */ 0, + /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, + /* .MaxGeometryAtomicCounterBuffers = */ 0, + /* .MaxFragmentAtomicCounterBuffers = */ 1, + /* .MaxCombinedAtomicCounterBuffers = */ 1, + /* .MaxAtomicCounterBufferSize = */ 16384, + /* .MaxTransformFeedbackBuffers = */ 4, + /* .MaxTransformFeedbackInterleavedComponents = */ 64, + /* .MaxCullDistances = */ 8, + /* .MaxCombinedClipAndCullDistances = */ 8, + /* .MaxSamples = */ 4, + /* .maxMeshOutputVerticesNV = */ 256, + /* .maxMeshOutputPrimitivesNV = */ 512, + /* .maxMeshWorkGroupSizeX_NV = */ 32, + /* .maxMeshWorkGroupSizeY_NV = */ 1, + /* .maxMeshWorkGroupSizeZ_NV = */ 1, + /* .maxTaskWorkGroupSizeX_NV = */ 32, + /* .maxTaskWorkGroupSizeY_NV = */ 1, + /* .maxTaskWorkGroupSizeZ_NV = */ 1, + /* .maxMeshViewCountNV = */ 4, + /* .maxDualSourceDrawBuffersEXT = */ 1, - /* .limits = */ { - /* .nonInductiveForLoops = */ 1, - /* .whileLoops = */ 1, - /* .doWhileLoops = */ 1, - /* .generalUniformIndexing = */ 1, - /* .generalAttributeMatrixVectorIndexing = */ 1, - /* .generalVaryingIndexing = */ 1, - /* .generalSamplerIndexing = */ 1, - /* .generalVariableIndexing = */ 1, - /* .generalConstantMatrixVectorIndexing = */ 1, - } + /* .limits = */ { + /* .nonInductiveForLoops = */ 1, + /* .whileLoops = */ 1, + /* .doWhileLoops = */ 1, + /* .generalUniformIndexing = */ 1, + /* .generalAttributeMatrixVectorIndexing = */ 1, + /* .generalVaryingIndexing = */ 1, + /* .generalSamplerIndexing = */ 1, + /* .generalVariableIndexing = */ 1, + /* .generalConstantMatrixVectorIndexing = */ 1, + } }; -void ShaderBuilder::init() -{ - ShInitialize(); -} - -void ShaderBuilder::deinit() -{ - ShFinalize(); -} - ShaderBuilder::ShaderBuilder() { - class InitShaderLib - { - public: - InitShaderLib() { ShaderBuilder::init(); } - ~InitShaderLib() { ShaderBuilder::deinit(); } - }; - - static InitShaderLib init; } -void ShaderBuilder::setVertexShader(const std::string &c) { code = c; stage = EShLanguage::EShLangVertex; } -void ShaderBuilder::setTessControlShader(const std::string &c) { code = c; stage = EShLanguage::EShLangTessControl; } -void ShaderBuilder::setTessEvaluationShader(const std::string &c) { code = c; stage = EShLanguage::EShLangTessEvaluation; } -void ShaderBuilder::setGeometryShader(const std::string &c) { code = c; stage = EShLanguage::EShLangGeometry; } -void ShaderBuilder::setFragmentShader(const std::string &c) { code = c; stage = EShLanguage::EShLangFragment; } -void ShaderBuilder::setComputeShader(const std::string &c) { code = c; stage = EShLanguage::EShLangCompute; } -void ShaderBuilder::setRayGenShader(const std::string &c) { code = c; stage = EShLanguage::EShLangRayGen; } -void ShaderBuilder::setIntersectShader(const std::string &c) { code = c; stage = EShLanguage::EShLangIntersect; } -void ShaderBuilder::setAnyHitShader(const std::string &c) { code = c; stage = EShLanguage::EShLangAnyHit; } -void ShaderBuilder::setClosestHitShader(const std::string &c) { code = c; stage = EShLanguage::EShLangClosestHit; } -void ShaderBuilder::setMissShader(const std::string &c) { code = c; stage = EShLanguage::EShLangMiss; } -void ShaderBuilder::setCallableShader(const std::string &c) { code = c; stage = EShLanguage::EShLangCallable; } +ShaderBuilder& ShaderBuilder::VertexShader(const FString &c) +{ + code = c; + stage = EShLanguage::EShLangVertex; + return *this; +} -std::unique_ptr ShaderBuilder::create(VulkanDevice *device) +ShaderBuilder& ShaderBuilder::FragmentShader(const FString &c) +{ + code = c; + stage = EShLanguage::EShLangFragment; + return *this; +} + +ShaderBuilder& ShaderBuilder::RayGenShader(const FString& c) +{ + code = c; + stage = EShLanguage::EShLangRayGen; + return *this; +} + +ShaderBuilder& ShaderBuilder::IntersectShader(const FString& c) +{ + code = c; + stage = EShLanguage::EShLangIntersect; + return *this; +} + +ShaderBuilder& ShaderBuilder::AnyHitShader(const FString& c) +{ + code = c; + stage = EShLanguage::EShLangAnyHit; + return *this; +} + +ShaderBuilder& ShaderBuilder::ClosestHitShader(const FString& c) +{ + code = c; + stage = EShLanguage::EShLangClosestHit; + return *this; +} + +ShaderBuilder& ShaderBuilder::MissShader(const FString& c) +{ + code = c; + stage = EShLanguage::EShLangMiss; + return *this; +} + +ShaderBuilder& ShaderBuilder::CallableShader(const FString& c) +{ + code = c; + stage = EShLanguage::EShLangCallable; + return *this; +} + +std::unique_ptr ShaderBuilder::Create(const char *shadername, VulkanDevice *device) { EShLanguage stage = (EShLanguage)this->stage; - const char *sources[] = { code.c_str() }; + const char *sources[] = { code.GetChars() }; TBuiltInResource resources = DefaultTBuiltInResource; glslang::TShader shader(stage); shader.setStrings(sources, 1); shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100); - shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_2); - shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_5); + if (device->ApiVersion >= VK_API_VERSION_1_2) + { + shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_2); + shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_4); + } + else + { + shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0); + shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0); + } bool compileSuccess = shader.parse(&resources, 110, false, EShMsgVulkanRules); if (!compileSuccess) { @@ -173,7 +206,7 @@ std::unique_ptr ShaderBuilder::create(VulkanDevice *device) glslang::TIntermediate *intermediate = program.getIntermediate(stage); if (!intermediate) { - throw std::runtime_error("Internal shader compiler error"); + throw std::runtime_error(std::string("Internal shader compile error while processing: ") + shadername); } glslang::SpvOptions spvOptions; @@ -193,7 +226,1308 @@ std::unique_ptr ShaderBuilder::create(VulkanDevice *device) VkShaderModule shaderModule; VkResult result = vkCreateShaderModule(device->device, &createInfo, nullptr, &shaderModule); if (result != VK_SUCCESS) + { throw std::runtime_error("Could not create vulkan shader module"); + } - return std::make_unique(device, shaderModule); + auto obj = std::make_unique(device, shaderModule); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +ImageBuilder::ImageBuilder() +{ + imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.extent.depth = 1; + imageInfo.arrayLayers = 1; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Note: must either be VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_PREINITIALIZED + imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageInfo.flags = 0; +} + +ImageBuilder& ImageBuilder::Size(int width, int height, int mipLevels, int arrayLayers) +{ + imageInfo.extent.width = width; + imageInfo.extent.height = height; + imageInfo.mipLevels = mipLevels; + imageInfo.arrayLayers = arrayLayers; + return *this; +} + +ImageBuilder& ImageBuilder::Samples(VkSampleCountFlagBits samples) +{ + imageInfo.samples = samples; + return *this; +} + +ImageBuilder& ImageBuilder::Format(VkFormat format) +{ + imageInfo.format = format; + return *this; +} + +ImageBuilder& ImageBuilder::LinearTiling() +{ + imageInfo.tiling = VK_IMAGE_TILING_LINEAR; + return *this; +} + +ImageBuilder& ImageBuilder::Usage(VkImageUsageFlags usage, VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocFlags) +{ + imageInfo.usage = usage; + allocInfo.usage = memoryUsage; + allocInfo.flags = allocFlags; + return *this; +} + +ImageBuilder& ImageBuilder::MemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits) +{ + allocInfo.requiredFlags = requiredFlags; + allocInfo.preferredFlags = preferredFlags; + allocInfo.memoryTypeBits = memoryTypeBits; + return *this; +} + +bool ImageBuilder::IsFormatSupported(VulkanDevice* device, VkFormatFeatureFlags bufferFeatures) +{ + VkImageFormatProperties properties = { }; + VkResult result = vkGetPhysicalDeviceImageFormatProperties(device->physicalDevice.device, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &properties); + if (result != VK_SUCCESS) return false; + if (imageInfo.extent.width > properties.maxExtent.width) return false; + if (imageInfo.extent.height > properties.maxExtent.height) return false; + if (imageInfo.extent.depth > properties.maxExtent.depth) return false; + if (imageInfo.mipLevels > properties.maxMipLevels) return false; + if (imageInfo.arrayLayers > properties.maxArrayLayers) return false; + if ((imageInfo.samples & properties.sampleCounts) != imageInfo.samples) return false; + if (bufferFeatures != 0) + { + VkFormatProperties formatProperties = { }; + vkGetPhysicalDeviceFormatProperties(device->physicalDevice.device, imageInfo.format, &formatProperties); + if ((formatProperties.bufferFeatures & bufferFeatures) != bufferFeatures) + return false; + } + return true; +} + +std::unique_ptr ImageBuilder::Create(VulkanDevice* device, VkDeviceSize* allocatedBytes) +{ + VkImage image; + VmaAllocation allocation; + + VkResult result = vmaCreateImage(device->allocator, &imageInfo, &allocInfo, &image, &allocation, nullptr); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not create vulkan image"); + + if (allocatedBytes != nullptr) + { + VmaAllocationInfo allocatedInfo; + vmaGetAllocationInfo(device->allocator, allocation, &allocatedInfo); + + *allocatedBytes = allocatedInfo.size; + } + + auto obj = std::make_unique(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels, imageInfo.arrayLayers); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +std::unique_ptr ImageBuilder::TryCreate(VulkanDevice* device) +{ + VkImage image; + VmaAllocation allocation; + + VkResult result = vmaCreateImage(device->allocator, &imageInfo, &allocInfo, &image, &allocation, nullptr); + if (result != VK_SUCCESS) + return nullptr; + + auto obj = std::make_unique(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels, imageInfo.arrayLayers); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +ImageViewBuilder::ImageViewBuilder() +{ + viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.subresourceRange.baseMipLevel = 0; + viewInfo.subresourceRange.baseArrayLayer = 0; + viewInfo.subresourceRange.layerCount = 1; + viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; +} + +ImageViewBuilder& ImageViewBuilder::Type(VkImageViewType type) +{ + viewInfo.viewType = type; + return *this; +} + +ImageViewBuilder& ImageViewBuilder::Image(VulkanImage* image, VkFormat format, VkImageAspectFlags aspectMask) +{ + viewInfo.image = image->image; + viewInfo.format = format; + viewInfo.subresourceRange.levelCount = image->mipLevels; + viewInfo.subresourceRange.aspectMask = aspectMask; + viewInfo.subresourceRange.layerCount = image->layerCount; + return *this; +} + +std::unique_ptr ImageViewBuilder::Create(VulkanDevice* device) +{ + VkImageView view; + VkResult result = vkCreateImageView(device->device, &viewInfo, nullptr, &view); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not create texture image view"); + + auto obj = std::make_unique(device, view); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +SamplerBuilder::SamplerBuilder() +{ + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.anisotropyEnable = VK_FALSE; + samplerInfo.maxAnisotropy = 1.0f; + samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + samplerInfo.unnormalizedCoordinates = VK_FALSE; + samplerInfo.compareEnable = VK_FALSE; + samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.mipLodBias = 0.0f; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = 100.0f; +} + +SamplerBuilder& SamplerBuilder::AddressMode(VkSamplerAddressMode addressMode) +{ + samplerInfo.addressModeU = addressMode; + samplerInfo.addressModeV = addressMode; + samplerInfo.addressModeW = addressMode; + return *this; +} + +SamplerBuilder& SamplerBuilder::AddressMode(VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w) +{ + samplerInfo.addressModeU = u; + samplerInfo.addressModeV = v; + samplerInfo.addressModeW = w; + return *this; +} + +SamplerBuilder& SamplerBuilder::MinFilter(VkFilter minFilter) +{ + samplerInfo.minFilter = minFilter; + return *this; +} + +SamplerBuilder& SamplerBuilder::MagFilter(VkFilter magFilter) +{ + samplerInfo.magFilter = magFilter; + return *this; +} + +SamplerBuilder& SamplerBuilder::MipmapMode(VkSamplerMipmapMode mode) +{ + samplerInfo.mipmapMode = mode; + return *this; +} + +SamplerBuilder& SamplerBuilder::Anisotropy(float maxAnisotropy) +{ + samplerInfo.anisotropyEnable = VK_TRUE; + samplerInfo.maxAnisotropy = maxAnisotropy; + return *this; +} + +SamplerBuilder& SamplerBuilder::MaxLod(float value) +{ + samplerInfo.maxLod = value; + return *this; +} + +std::unique_ptr SamplerBuilder::Create(VulkanDevice* device) +{ + VkSampler sampler; + VkResult result = vkCreateSampler(device->device, &samplerInfo, nullptr, &sampler); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not create texture sampler"); + auto obj = std::make_unique(device, sampler); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +BufferBuilder::BufferBuilder() +{ + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; +} + +BufferBuilder& BufferBuilder::Size(size_t size) +{ + bufferInfo.size = std::max(size, (size_t)16); + return *this; +} + +BufferBuilder& BufferBuilder::Usage(VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocFlags) +{ + bufferInfo.usage = bufferUsage; + allocInfo.usage = memoryUsage; + allocInfo.flags = allocFlags; + return *this; +} + +BufferBuilder& BufferBuilder::MemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits) +{ + allocInfo.requiredFlags = requiredFlags; + allocInfo.preferredFlags = preferredFlags; + allocInfo.memoryTypeBits = memoryTypeBits; + return *this; +} + +std::unique_ptr BufferBuilder::Create(VulkanDevice* device) +{ + VkBuffer buffer; + VmaAllocation allocation; + + VkResult result = vmaCreateBuffer(device->allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not allocate memory for vulkan buffer"); + + auto obj = std::make_unique(device, buffer, allocation, bufferInfo.size); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +RayTracingPipelineBuilder::RayTracingPipelineBuilder() +{ + pipelineInfo.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR; +} + +RayTracingPipelineBuilder& RayTracingPipelineBuilder::Layout(VulkanPipelineLayout* layout) +{ + pipelineInfo.layout = layout->layout; + return *this; +} + +RayTracingPipelineBuilder& RayTracingPipelineBuilder::MaxPipelineRayRecursionDepth(int depth) +{ + pipelineInfo.maxPipelineRayRecursionDepth = depth; + return *this; +} + +RayTracingPipelineBuilder& RayTracingPipelineBuilder::AddShader(VkShaderStageFlagBits stage, VulkanShader* shader) +{ + VkPipelineShaderStageCreateInfo stageInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO }; + stageInfo.stage = stage; + stageInfo.module = shader->module; + stageInfo.pName = "main"; + stages.push_back(stageInfo); + + pipelineInfo.pStages = stages.data(); + pipelineInfo.stageCount = (uint32_t)stages.size(); + + return *this; +} + +RayTracingPipelineBuilder& RayTracingPipelineBuilder::AddRayGenGroup(int rayGenShader) +{ + VkRayTracingShaderGroupCreateInfoKHR group = {}; + group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + group.generalShader = rayGenShader; + group.closestHitShader = VK_SHADER_UNUSED_KHR; + group.anyHitShader = VK_SHADER_UNUSED_KHR; + group.intersectionShader = VK_SHADER_UNUSED_KHR; + groups.push_back(group); + + pipelineInfo.pGroups = groups.data(); + pipelineInfo.groupCount = (uint32_t)groups.size(); + + return *this; +} + +RayTracingPipelineBuilder& RayTracingPipelineBuilder::AddMissGroup(int missShader) +{ + VkRayTracingShaderGroupCreateInfoKHR group = {}; + group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + group.generalShader = missShader; + group.closestHitShader = VK_SHADER_UNUSED_KHR; + group.anyHitShader = VK_SHADER_UNUSED_KHR; + group.intersectionShader = VK_SHADER_UNUSED_KHR; + groups.push_back(group); + + pipelineInfo.pGroups = groups.data(); + pipelineInfo.groupCount = (uint32_t)groups.size(); + + return *this; +} + +RayTracingPipelineBuilder& RayTracingPipelineBuilder::AddTrianglesHitGroup(int closestHitShader, int anyHitShader) +{ + VkRayTracingShaderGroupCreateInfoKHR group = {}; + group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; + group.generalShader = VK_SHADER_UNUSED_KHR; + group.closestHitShader = closestHitShader; + group.anyHitShader = anyHitShader; + group.intersectionShader = VK_SHADER_UNUSED_KHR; + groups.push_back(group); + + pipelineInfo.pGroups = groups.data(); + pipelineInfo.groupCount = (uint32_t)groups.size(); + + return *this; +} + +RayTracingPipelineBuilder& RayTracingPipelineBuilder::AddProceduralHitGroup(int intersectionShader, int closestHitShader, int anyHitShader) +{ + VkRayTracingShaderGroupCreateInfoKHR group = {}; + group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; + group.generalShader = VK_SHADER_UNUSED_KHR; + group.closestHitShader = closestHitShader; + group.anyHitShader = anyHitShader; + group.intersectionShader = intersectionShader; + groups.push_back(group); + + pipelineInfo.pGroups = groups.data(); + pipelineInfo.groupCount = (uint32_t)groups.size(); + + return *this; +} + +std::unique_ptr RayTracingPipelineBuilder::Create(VulkanDevice* device) +{ + VkPipeline pipeline; + VkResult result = vkCreateRayTracingPipelinesKHR(device->device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline); + if (result != VK_SUCCESS) + throw std::runtime_error("vkCreateRayTracingPipelinesKHR failed"); + + std::vector shaderGroupHandles(device->physicalDevice.rayTracingProperties.shaderGroupHandleSize * groups.size()); + if (!groups.empty()) + { + result = vkGetRayTracingShaderGroupHandlesKHR(device->device, pipeline, 0, (uint32_t)groups.size(), shaderGroupHandles.size(), shaderGroupHandles.data()); + if (result != VK_SUCCESS) + { + vkDestroyPipeline(device->device, pipeline, nullptr); + throw std::runtime_error("vkGetRayTracingShaderGroupHandlesKHR failed"); + } + } + + auto obj = std::make_unique(device, pipeline, shaderGroupHandles); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +ComputePipelineBuilder::ComputePipelineBuilder() +{ + pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + stageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; +} + +ComputePipelineBuilder& ComputePipelineBuilder::Layout(VulkanPipelineLayout* layout) +{ + pipelineInfo.layout = layout->layout; + return *this; +} + +ComputePipelineBuilder& ComputePipelineBuilder::ComputeShader(VulkanShader* shader) +{ + stageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; + stageInfo.module = shader->module; + stageInfo.pName = "main"; + + pipelineInfo.stage = stageInfo; + return *this; +} + +std::unique_ptr ComputePipelineBuilder::Create(VulkanDevice* device) +{ + VkPipeline pipeline; + vkCreateComputePipelines(device->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline); + auto obj = std::make_unique(device, pipeline); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +DescriptorSetLayoutBuilder::DescriptorSetLayoutBuilder() +{ + layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; +} + +DescriptorSetLayoutBuilder& DescriptorSetLayoutBuilder::AddBinding(int index, VkDescriptorType type, int arrayCount, VkShaderStageFlags stageFlags) +{ + VkDescriptorSetLayoutBinding binding = { }; + binding.binding = index; + binding.descriptorType = type; + binding.descriptorCount = arrayCount; + binding.stageFlags = stageFlags; + binding.pImmutableSamplers = nullptr; + bindings.Push(binding); + + layoutInfo.bindingCount = (uint32_t)bindings.Size(); + layoutInfo.pBindings = &bindings[0]; + return *this; +} + +std::unique_ptr DescriptorSetLayoutBuilder::Create(VulkanDevice* device) +{ + VkDescriptorSetLayout layout; + VkResult result = vkCreateDescriptorSetLayout(device->device, &layoutInfo, nullptr, &layout); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not create descriptor set layout"); + auto obj = std::make_unique(device, layout); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +DescriptorPoolBuilder::DescriptorPoolBuilder() +{ + poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + poolInfo.maxSets = 1; + poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; +} + +DescriptorPoolBuilder& DescriptorPoolBuilder::MaxSets(int value) +{ + poolInfo.maxSets = value; + return *this; +} + +DescriptorPoolBuilder& DescriptorPoolBuilder::AddPoolSize(VkDescriptorType type, int count) +{ + VkDescriptorPoolSize size; + size.type = type; + size.descriptorCount = count; + poolSizes.push_back(size); + + poolInfo.poolSizeCount = (uint32_t)poolSizes.size(); + poolInfo.pPoolSizes = poolSizes.data(); + return *this; +} + +std::unique_ptr DescriptorPoolBuilder::Create(VulkanDevice* device) +{ + VkDescriptorPool descriptorPool; + VkResult result = vkCreateDescriptorPool(device->device, &poolInfo, nullptr, &descriptorPool); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not create descriptor pool"); + auto obj = std::make_unique(device, descriptorPool); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +QueryPoolBuilder::QueryPoolBuilder() +{ + poolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; +} + +QueryPoolBuilder& QueryPoolBuilder::QueryType(VkQueryType type, int count, VkQueryPipelineStatisticFlags pipelineStatistics) +{ + poolInfo.queryType = type; + poolInfo.queryCount = count; + poolInfo.pipelineStatistics = pipelineStatistics; + return *this; +} + +std::unique_ptr QueryPoolBuilder::Create(VulkanDevice* device) +{ + VkQueryPool queryPool; + VkResult result = vkCreateQueryPool(device->device, &poolInfo, nullptr, &queryPool); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not create query pool"); + auto obj = std::make_unique(device, queryPool); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +FramebufferBuilder::FramebufferBuilder() +{ + framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; +} + +FramebufferBuilder& FramebufferBuilder::RenderPass(VulkanRenderPass* renderPass) +{ + framebufferInfo.renderPass = renderPass->renderPass; + return *this; +} + +FramebufferBuilder& FramebufferBuilder::AddAttachment(VulkanImageView* view) +{ + attachments.push_back(view->view); + + framebufferInfo.attachmentCount = (uint32_t)attachments.size(); + framebufferInfo.pAttachments = attachments.data(); + return *this; +} + +FramebufferBuilder& FramebufferBuilder::AddAttachment(VkImageView view) +{ + attachments.push_back(view); + + framebufferInfo.attachmentCount = (uint32_t)attachments.size(); + framebufferInfo.pAttachments = attachments.data(); + return *this; +} + +FramebufferBuilder& FramebufferBuilder::Size(int width, int height, int layers) +{ + framebufferInfo.width = width; + framebufferInfo.height = height; + framebufferInfo.layers = 1; + return *this; +} + +std::unique_ptr FramebufferBuilder::Create(VulkanDevice* device) +{ + VkFramebuffer framebuffer = 0; + VkResult result = vkCreateFramebuffer(device->device, &framebufferInfo, nullptr, &framebuffer); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not create framebuffer"); + auto obj = std::make_unique(device, framebuffer); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +GraphicsPipelineBuilder::GraphicsPipelineBuilder() +{ + pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineInfo.pVertexInputState = &vertexInputInfo; + pipelineInfo.pInputAssemblyState = &inputAssembly; + pipelineInfo.pViewportState = &viewportState; + pipelineInfo.pRasterizationState = &rasterizer; + pipelineInfo.pMultisampleState = &multisampling; + pipelineInfo.pDepthStencilState = &depthStencil; + pipelineInfo.pColorBlendState = &colorBlending; + pipelineInfo.pDynamicState = &dynamicState; + pipelineInfo.subpass = 0; + pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; + pipelineInfo.basePipelineIndex = -1; + + vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertexInputInfo.vertexBindingDescriptionCount = 0; + vertexInputInfo.pVertexBindingDescriptions = nullptr; + vertexInputInfo.vertexAttributeDescriptionCount = 0; + vertexInputInfo.pVertexAttributeDescriptions = nullptr; + + inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + inputAssembly.primitiveRestartEnable = VK_FALSE; + + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + + depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; + depthStencil.depthBoundsTestEnable = VK_FALSE; + depthStencil.minDepthBounds = 0.0f; + depthStencil.maxDepthBounds = 1.0f; + depthStencil.stencilTestEnable = VK_FALSE; + depthStencil.front = {}; + depthStencil.back = {}; + + rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizer.depthClampEnable = VK_FALSE; + rasterizer.rasterizerDiscardEnable = VK_FALSE; + rasterizer.polygonMode = VK_POLYGON_MODE_FILL; + rasterizer.lineWidth = 1.0f; + rasterizer.cullMode = VK_CULL_MODE_NONE; + rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; + rasterizer.depthBiasEnable = VK_FALSE; + rasterizer.depthBiasConstantFactor = 0.0f; + rasterizer.depthBiasClamp = 0.0f; + rasterizer.depthBiasSlopeFactor = 0.0f; + + multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampling.sampleShadingEnable = VK_FALSE; + multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + multisampling.minSampleShading = 1.0f; + multisampling.pSampleMask = nullptr; + multisampling.alphaToCoverageEnable = VK_FALSE; + multisampling.alphaToOneEnable = VK_FALSE; + + colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + colorBlendAttachment.blendEnable = VK_FALSE; + colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; + colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + + colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlending.logicOpEnable = VK_FALSE; + colorBlending.logicOp = VK_LOGIC_OP_COPY; + colorBlending.attachmentCount = 1; + colorBlending.pAttachments = &colorBlendAttachment; + colorBlending.blendConstants[0] = 0.0f; + colorBlending.blendConstants[1] = 0.0f; + colorBlending.blendConstants[2] = 0.0f; + colorBlending.blendConstants[3] = 0.0f; + + dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::RasterizationSamples(VkSampleCountFlagBits samples) +{ + multisampling.rasterizationSamples = samples; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Subpass(int subpass) +{ + pipelineInfo.subpass = subpass; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Layout(VulkanPipelineLayout* layout) +{ + pipelineInfo.layout = layout->layout; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::RenderPass(VulkanRenderPass* renderPass) +{ + pipelineInfo.renderPass = renderPass->renderPass; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Topology(VkPrimitiveTopology topology) +{ + inputAssembly.topology = topology; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Viewport(float x, float y, float width, float height, float minDepth, float maxDepth) +{ + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = width; + viewport.height = height; + viewport.minDepth = minDepth; + viewport.maxDepth = maxDepth; + + viewportState.viewportCount = 1; + viewportState.pViewports = &viewport; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Scissor(int x, int y, int width, int height) +{ + scissor.offset.x = x; + scissor.offset.y = y; + scissor.extent.width = width; + scissor.extent.height = height; + + viewportState.scissorCount = 1; + viewportState.pScissors = &scissor; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Cull(VkCullModeFlags cullMode, VkFrontFace frontFace) +{ + rasterizer.cullMode = cullMode; + rasterizer.frontFace = frontFace; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::DepthStencilEnable(bool test, bool write, bool stencil) +{ + depthStencil.depthTestEnable = test ? VK_TRUE : VK_FALSE; + depthStencil.depthWriteEnable = write ? VK_TRUE : VK_FALSE; + depthStencil.stencilTestEnable = stencil ? VK_TRUE : VK_FALSE; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::Stencil(VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp, uint32_t compareMask, uint32_t writeMask, uint32_t reference) +{ + depthStencil.front.failOp = failOp; + depthStencil.front.passOp = passOp; + depthStencil.front.depthFailOp = depthFailOp; + depthStencil.front.compareOp = compareOp; + depthStencil.front.compareMask = compareMask; + depthStencil.front.writeMask = writeMask; + depthStencil.front.reference = reference; + + depthStencil.back.failOp = failOp; + depthStencil.back.passOp = passOp; + depthStencil.back.depthFailOp = depthFailOp; + depthStencil.back.compareOp = compareOp; + depthStencil.back.compareMask = compareMask; + depthStencil.back.writeMask = writeMask; + depthStencil.back.reference = reference; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::DepthFunc(VkCompareOp func) +{ + depthStencil.depthCompareOp = func; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::DepthClampEnable(bool value) +{ + rasterizer.depthClampEnable = value ? VK_TRUE : VK_FALSE; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::DepthBias(bool enable, float biasConstantFactor, float biasClamp, float biasSlopeFactor) +{ + rasterizer.depthBiasEnable = enable ? VK_TRUE : VK_FALSE; + rasterizer.depthBiasConstantFactor = biasConstantFactor; + rasterizer.depthBiasClamp = biasClamp; + rasterizer.depthBiasSlopeFactor = biasSlopeFactor; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::ColorWriteMask(VkColorComponentFlags mask) +{ + colorBlendAttachment.colorWriteMask = mask; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AdditiveBlendMode() +{ + colorBlendAttachment.blendEnable = VK_TRUE; + colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; + colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AlphaBlendMode() +{ + colorBlendAttachment.blendEnable = VK_TRUE; + colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; + colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::BlendMode(VkBlendOp op, VkBlendFactor src, VkBlendFactor dst) +{ + colorBlendAttachment.blendEnable = VK_TRUE; + colorBlendAttachment.srcColorBlendFactor = src; + colorBlendAttachment.dstColorBlendFactor = dst; + colorBlendAttachment.colorBlendOp = op; + colorBlendAttachment.srcAlphaBlendFactor = src; + colorBlendAttachment.dstAlphaBlendFactor = dst; + colorBlendAttachment.alphaBlendOp = op; + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::SubpassColorAttachmentCount(int count) +{ + colorBlendAttachments.resize(count, colorBlendAttachment); + colorBlending.pAttachments = colorBlendAttachments.data(); + colorBlending.attachmentCount = (uint32_t)colorBlendAttachments.size(); + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AddVertexShader(VulkanShader* shader) +{ + VkPipelineShaderStageCreateInfo vertShaderStageInfo = {}; + vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + vertShaderStageInfo.module = shader->module; + vertShaderStageInfo.pName = "main"; + shaderStages.push_back(vertShaderStageInfo); + + pipelineInfo.stageCount = (uint32_t)shaderStages.size(); + pipelineInfo.pStages = shaderStages.data(); + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AddFragmentShader(VulkanShader* shader) +{ + VkPipelineShaderStageCreateInfo fragShaderStageInfo = {}; + fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fragShaderStageInfo.module = shader->module; + fragShaderStageInfo.pName = "main"; + shaderStages.push_back(fragShaderStageInfo); + + pipelineInfo.stageCount = (uint32_t)shaderStages.size(); + pipelineInfo.pStages = shaderStages.data(); + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AddVertexBufferBinding(int index, size_t stride) +{ + VkVertexInputBindingDescription desc = {}; + desc.binding = index; + desc.stride = (uint32_t)stride; + desc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + vertexInputBindings.push_back(desc); + + vertexInputInfo.vertexBindingDescriptionCount = (uint32_t)vertexInputBindings.size(); + vertexInputInfo.pVertexBindingDescriptions = vertexInputBindings.data(); + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AddVertexAttribute(int location, int binding, VkFormat format, size_t offset) +{ + VkVertexInputAttributeDescription desc = { }; + desc.location = location; + desc.binding = binding; + desc.format = format; + desc.offset = (uint32_t)offset; + vertexInputAttributes.push_back(desc); + + vertexInputInfo.vertexAttributeDescriptionCount = (uint32_t)vertexInputAttributes.size(); + vertexInputInfo.pVertexAttributeDescriptions = vertexInputAttributes.data(); + return *this; +} + +GraphicsPipelineBuilder& GraphicsPipelineBuilder::AddDynamicState(VkDynamicState state) +{ + dynamicStates.push_back(state); + dynamicState.dynamicStateCount = (uint32_t)dynamicStates.size(); + dynamicState.pDynamicStates = dynamicStates.data(); + return *this; +} + +std::unique_ptr GraphicsPipelineBuilder::Create(VulkanDevice* device) +{ + VkPipeline pipeline = 0; + VkResult result = vkCreateGraphicsPipelines(device->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not create graphics pipeline"); + auto obj = std::make_unique(device, pipeline); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +PipelineLayoutBuilder::PipelineLayoutBuilder() +{ + pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; +} + +PipelineLayoutBuilder& PipelineLayoutBuilder::AddSetLayout(VulkanDescriptorSetLayout* setLayout) +{ + setLayouts.push_back(setLayout->layout); + pipelineLayoutInfo.setLayoutCount = (uint32_t)setLayouts.size(); + pipelineLayoutInfo.pSetLayouts = setLayouts.data(); + return *this; +} + +PipelineLayoutBuilder& PipelineLayoutBuilder::AddPushConstantRange(VkShaderStageFlags stageFlags, size_t offset, size_t size) +{ + VkPushConstantRange range = { }; + range.stageFlags = stageFlags; + range.offset = (uint32_t)offset; + range.size = (uint32_t)size; + pushConstantRanges.push_back(range); + pipelineLayoutInfo.pushConstantRangeCount = (uint32_t)pushConstantRanges.size(); + pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges.data(); + return *this; +} + +std::unique_ptr PipelineLayoutBuilder::Create(VulkanDevice* device) +{ + VkPipelineLayout pipelineLayout; + VkResult result = vkCreatePipelineLayout(device->device, &pipelineLayoutInfo, nullptr, &pipelineLayout); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not create pipeline layout"); + auto obj = std::make_unique(device, pipelineLayout); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +RenderPassBuilder::RenderPassBuilder() +{ + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; +} + +RenderPassBuilder& RenderPassBuilder::AddAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkImageLayout initialLayout, VkImageLayout finalLayout) +{ + VkAttachmentDescription attachment = {}; + attachment.format = format; + attachment.samples = samples; + attachment.loadOp = load; + attachment.storeOp = store; + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachment.initialLayout = initialLayout; + attachment.finalLayout = finalLayout; + attachments.push_back(attachment); + renderPassInfo.pAttachments = attachments.data(); + renderPassInfo.attachmentCount = (uint32_t)attachments.size(); + return *this; +} + +RenderPassBuilder& RenderPassBuilder::AddDepthStencilAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkAttachmentLoadOp stencilLoad, VkAttachmentStoreOp stencilStore, VkImageLayout initialLayout, VkImageLayout finalLayout) +{ + VkAttachmentDescription attachment = {}; + attachment.format = format; + attachment.samples = samples; + attachment.loadOp = load; + attachment.storeOp = store; + attachment.stencilLoadOp = stencilLoad; + attachment.stencilStoreOp = stencilStore; + attachment.initialLayout = initialLayout; + attachment.finalLayout = finalLayout; + attachments.push_back(attachment); + renderPassInfo.pAttachments = attachments.data(); + renderPassInfo.attachmentCount = (uint32_t)attachments.size(); + return *this; +} + +RenderPassBuilder& RenderPassBuilder::AddExternalSubpassDependency(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) +{ + VkSubpassDependency dependency = {}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = srcStageMask; + dependency.srcAccessMask = srcAccessMask; + dependency.dstStageMask = dstStageMask; + dependency.dstAccessMask = dstAccessMask; + + dependencies.push_back(dependency); + renderPassInfo.pDependencies = dependencies.data(); + renderPassInfo.dependencyCount = (uint32_t)dependencies.size(); + return *this; +} + +RenderPassBuilder& RenderPassBuilder::AddSubpass() +{ + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + + subpasses.push_back(subpass); + renderPassInfo.pSubpasses = subpasses.data(); + renderPassInfo.subpassCount = (uint32_t)subpasses.size(); + + subpassData.push_back(std::make_unique()); + return *this; +} + +RenderPassBuilder& RenderPassBuilder::AddSubpassColorAttachmentRef(uint32_t index, VkImageLayout layout) +{ + VkAttachmentReference colorAttachmentRef = {}; + colorAttachmentRef.attachment = index; + colorAttachmentRef.layout = layout; + + subpassData.back()->colorRefs.push_back(colorAttachmentRef); + subpasses.back().pColorAttachments = subpassData.back()->colorRefs.data(); + subpasses.back().colorAttachmentCount = (uint32_t)subpassData.back()->colorRefs.size(); + return *this; +} + +RenderPassBuilder& RenderPassBuilder::AddSubpassDepthStencilAttachmentRef(uint32_t index, VkImageLayout layout) +{ + VkAttachmentReference& depthAttachmentRef = subpassData.back()->depthRef; + depthAttachmentRef.attachment = index; + depthAttachmentRef.layout = layout; + + VkSubpassDescription& subpass = subpasses.back(); + subpass.pDepthStencilAttachment = &depthAttachmentRef; + return *this; +} + +std::unique_ptr RenderPassBuilder::Create(VulkanDevice* device) +{ + VkRenderPass renderPass = 0; + VkResult result = vkCreateRenderPass(device->device, &renderPassInfo, nullptr, &renderPass); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not create render pass"); + auto obj = std::make_unique(device, renderPass); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + +PipelineBarrier& PipelineBarrier::AddMemory(VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) +{ + VkMemoryBarrier barrier = { }; + barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + barrier.srcAccessMask = srcAccessMask; + barrier.dstAccessMask = dstAccessMask; + memoryBarriers.push_back(barrier); + return *this; +} + +PipelineBarrier& PipelineBarrier::AddBuffer(VulkanBuffer* buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) +{ + return AddBuffer(buffer, 0, buffer->size, srcAccessMask, dstAccessMask); +} + +PipelineBarrier& PipelineBarrier::AddBuffer(VulkanBuffer* buffer, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) +{ + VkBufferMemoryBarrier barrier = { }; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.srcAccessMask = srcAccessMask; + barrier.dstAccessMask = dstAccessMask; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.buffer = buffer->buffer; + barrier.offset = offset; + barrier.size = size; + bufferMemoryBarriers.push_back(barrier); + return *this; +} + +PipelineBarrier& PipelineBarrier::AddImage(VulkanImage* image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) +{ + return AddImage(image->image, oldLayout, newLayout, srcAccessMask, dstAccessMask, aspectMask, baseMipLevel, levelCount); +} + +PipelineBarrier& PipelineBarrier::AddImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) +{ + VkImageMemoryBarrier barrier = { }; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.srcAccessMask = srcAccessMask; + barrier.dstAccessMask = dstAccessMask; + barrier.oldLayout = oldLayout; + barrier.newLayout = newLayout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image; + barrier.subresourceRange.aspectMask = aspectMask; + barrier.subresourceRange.baseMipLevel = baseMipLevel; + barrier.subresourceRange.levelCount = levelCount; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + imageMemoryBarriers.push_back(barrier); + return *this; +} + +PipelineBarrier& PipelineBarrier::AddQueueTransfer(int srcFamily, int dstFamily, VulkanBuffer* buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) +{ + VkBufferMemoryBarrier barrier = { }; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.srcAccessMask = srcAccessMask; + barrier.dstAccessMask = dstAccessMask; + barrier.srcQueueFamilyIndex = srcFamily; + barrier.dstQueueFamilyIndex = dstFamily; + barrier.buffer = buffer->buffer; + barrier.offset = 0; + barrier.size = buffer->size; + bufferMemoryBarriers.push_back(barrier); + return *this; +} + +PipelineBarrier& PipelineBarrier::AddQueueTransfer(int srcFamily, int dstFamily, VulkanImage* image, VkImageLayout layout, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) +{ + VkImageMemoryBarrier barrier = { }; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.oldLayout = layout; + barrier.newLayout = layout; + barrier.srcQueueFamilyIndex = srcFamily; + barrier.dstQueueFamilyIndex = dstFamily; + barrier.image = image->image; + barrier.subresourceRange.aspectMask = aspectMask; + barrier.subresourceRange.baseMipLevel = baseMipLevel; + barrier.subresourceRange.levelCount = levelCount; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + imageMemoryBarriers.push_back(barrier); + return *this; +} + +void PipelineBarrier::Execute(VulkanCommandBuffer* commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags) +{ + commandBuffer->pipelineBarrier( + srcStageMask, dstStageMask, dependencyFlags, + (uint32_t)memoryBarriers.size(), memoryBarriers.data(), + (uint32_t)bufferMemoryBarriers.size(), bufferMemoryBarriers.data(), + (uint32_t)imageMemoryBarriers.size(), imageMemoryBarriers.data()); +} + +///////////////////////////////////////////////////////////////////////////// + +QueueSubmit::QueueSubmit() +{ + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; +} + +QueueSubmit& QueueSubmit::AddCommandBuffer(VulkanCommandBuffer* buffer) +{ + commandBuffers.push_back(buffer->buffer); + submitInfo.pCommandBuffers = commandBuffers.data(); + submitInfo.commandBufferCount = (uint32_t)commandBuffers.size(); + return *this; +} + +QueueSubmit& QueueSubmit::AddWait(VkPipelineStageFlags waitStageMask, VulkanSemaphore* semaphore) +{ + waitStages.push_back(waitStageMask); + waitSemaphores.push_back(semaphore->semaphore); + + submitInfo.pWaitDstStageMask = waitStages.data(); + submitInfo.pWaitSemaphores = waitSemaphores.data(); + submitInfo.waitSemaphoreCount = (uint32_t)waitSemaphores.size(); + return *this; +} + +QueueSubmit& QueueSubmit::AddSignal(VulkanSemaphore* semaphore) +{ + signalSemaphores.push_back(semaphore->semaphore); + submitInfo.pSignalSemaphores = signalSemaphores.data(); + submitInfo.signalSemaphoreCount = (uint32_t)signalSemaphores.size(); + return *this; +} + +void QueueSubmit::Execute(VulkanDevice* device, VkQueue queue, VulkanFence* fence) +{ + VkResult result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, fence ? fence->fence : VK_NULL_HANDLE); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not submit command buffer"); +} + +///////////////////////////////////////////////////////////////////////////// + +WriteDescriptors& WriteDescriptors::AddBuffer(VulkanDescriptorSet* descriptorSet, int binding, VkDescriptorType type, VulkanBuffer* buffer) +{ + return AddBuffer(descriptorSet, binding, type, buffer, 0, buffer->size); +} + +WriteDescriptors& WriteDescriptors::AddBuffer(VulkanDescriptorSet* descriptorSet, int binding, VkDescriptorType type, VulkanBuffer* buffer, size_t offset, size_t range) +{ + VkDescriptorBufferInfo bufferInfo = {}; + bufferInfo.buffer = buffer->buffer; + bufferInfo.offset = offset; + bufferInfo.range = range; + + auto extra = std::make_unique(); + extra->bufferInfo = bufferInfo; + + VkWriteDescriptorSet descriptorWrite = {}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = descriptorSet->set; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = type; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pBufferInfo = &extra->bufferInfo; + writes.push_back(descriptorWrite); + writeExtras.push_back(std::move(extra)); + return *this; +} + +WriteDescriptors& WriteDescriptors::AddStorageImage(VulkanDescriptorSet* descriptorSet, int binding, VulkanImageView* view, VkImageLayout imageLayout) +{ + VkDescriptorImageInfo imageInfo = {}; + imageInfo.imageView = view->view; + imageInfo.imageLayout = imageLayout; + + auto extra = std::make_unique(); + extra->imageInfo = imageInfo; + + VkWriteDescriptorSet descriptorWrite = {}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = descriptorSet->set; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pImageInfo = &extra->imageInfo; + writes.push_back(descriptorWrite); + writeExtras.push_back(std::move(extra)); + return *this; +} + +WriteDescriptors& WriteDescriptors::AddCombinedImageSampler(VulkanDescriptorSet* descriptorSet, int binding, VulkanImageView* view, VulkanSampler* sampler, VkImageLayout imageLayout) +{ + VkDescriptorImageInfo imageInfo = {}; + imageInfo.imageView = view->view; + imageInfo.sampler = sampler->sampler; + imageInfo.imageLayout = imageLayout; + + auto extra = std::make_unique(); + extra->imageInfo = imageInfo; + + VkWriteDescriptorSet descriptorWrite = {}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = descriptorSet->set; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pImageInfo = &extra->imageInfo; + writes.push_back(descriptorWrite); + writeExtras.push_back(std::move(extra)); + return *this; +} + +WriteDescriptors& WriteDescriptors::AddAccelerationStructure(VulkanDescriptorSet* descriptorSet, int binding, VulkanAccelerationStructure* accelStruct) +{ + auto extra = std::make_unique(); + extra->accelStruct = {}; + extra->accelStruct.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; + extra->accelStruct.accelerationStructureCount = 1; + extra->accelStruct.pAccelerationStructures = &accelStruct->accelstruct; + + VkWriteDescriptorSet descriptorWrite = {}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = descriptorSet->set; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pNext = &extra->accelStruct; + writes.push_back(descriptorWrite); + writeExtras.push_back(std::move(extra)); + return *this; +} + +void WriteDescriptors::Execute(VulkanDevice* device) +{ + vkUpdateDescriptorSets(device->device, (uint32_t)writes.size(), writes.data(), 0, nullptr); } diff --git a/src/lightmap/vulkanbuilders.h b/src/lightmap/vulkanbuilders.h index b030ea1..0289d60 100644 --- a/src/lightmap/vulkanbuilders.h +++ b/src/lightmap/vulkanbuilders.h @@ -1,56 +1,31 @@ #pragma once #include "vulkanobjects.h" +#include "framework/zstring.h" #include -template -class FixedSizeVector -{ -public: - const T *data() const { return mItems; } - T *data() { return mItems; } - - size_t size() const { return mCount; } - - const T &back() const { return mItems[mCount - 1]; } - T &back() { return mItems[mCount - 1]; } - - void push_back(T && value) - { - assert(mCount != maxsize && "FixedSizeVector is too small"); - mItems[mCount++] = std::move(value); - } - - void push_back(const T &value) - { - assert(mCount != maxsize && "FixedSizeVector is too small"); - mItems[mCount++] = value; - } - -private: - T mItems[maxsize]; - size_t mCount = 0; -}; - class ImageBuilder { public: ImageBuilder(); - void setSize(int width, int height, int miplevels = 1); - void setSamples(VkSampleCountFlagBits samples); - void setFormat(VkFormat format); - void setUsage(VkImageUsageFlags imageUsage, VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_GPU_ONLY, VmaAllocationCreateFlags allocFlags = 0); - void setMemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits = 0); - void setLinearTiling(); + ImageBuilder& Size(int width, int height, int miplevels = 1, int arrayLayers = 1); + ImageBuilder& Samples(VkSampleCountFlagBits samples); + ImageBuilder& Format(VkFormat format); + ImageBuilder& Usage(VkImageUsageFlags imageUsage, VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_GPU_ONLY, VmaAllocationCreateFlags allocFlags = 0); + ImageBuilder& MemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits = 0); + ImageBuilder& LinearTiling(); + ImageBuilder& DebugName(const char* name) { debugName = name; return *this; } - bool isFormatSupported(VulkanDevice *device); + bool IsFormatSupported(VulkanDevice *device, VkFormatFeatureFlags bufferFeatures = 0); - std::unique_ptr create(VulkanDevice *device); + std::unique_ptr Create(VulkanDevice *device, VkDeviceSize* allocatedBytes = nullptr); + std::unique_ptr TryCreate(VulkanDevice *device); private: VkImageCreateInfo imageInfo = {}; VmaAllocationCreateInfo allocInfo = {}; + const char* debugName = nullptr; }; class ImageViewBuilder @@ -58,12 +33,15 @@ class ImageViewBuilder public: ImageViewBuilder(); - void setImage(VulkanImage *image, VkFormat format, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT); + ImageViewBuilder& Type(VkImageViewType type); + ImageViewBuilder& Image(VulkanImage *image, VkFormat format, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT); + ImageViewBuilder& DebugName(const char* name) { debugName = name; return *this; } - std::unique_ptr create(VulkanDevice *device); + std::unique_ptr Create(VulkanDevice *device); private: VkImageViewCreateInfo viewInfo = {}; + const char* debugName = nullptr; }; class SamplerBuilder @@ -71,18 +49,20 @@ class SamplerBuilder public: SamplerBuilder(); - void setAddressMode(VkSamplerAddressMode addressMode); - void setAddressMode(VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w); - void setMinFilter(VkFilter minFilter); - void setMagFilter(VkFilter magFilter); - void setMipmapMode(VkSamplerMipmapMode mode); - void setAnisotropy(float maxAnisotropy); - void setMaxLod(float value); + SamplerBuilder& AddressMode(VkSamplerAddressMode addressMode); + SamplerBuilder& AddressMode(VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w); + SamplerBuilder& MinFilter(VkFilter minFilter); + SamplerBuilder& MagFilter(VkFilter magFilter); + SamplerBuilder& MipmapMode(VkSamplerMipmapMode mode); + SamplerBuilder& Anisotropy(float maxAnisotropy); + SamplerBuilder& MaxLod(float value); + SamplerBuilder& DebugName(const char* name) { debugName = name; return *this; } - std::unique_ptr create(VulkanDevice *device); + std::unique_ptr Create(VulkanDevice *device); private: VkSamplerCreateInfo samplerInfo = {}; + const char* debugName = nullptr; }; class BufferBuilder @@ -90,15 +70,17 @@ class BufferBuilder public: BufferBuilder(); - void setSize(size_t size); - void setUsage(VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_GPU_ONLY, VmaAllocationCreateFlags allocFlags = 0); - void setMemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits = 0); + BufferBuilder& Size(size_t size); + BufferBuilder& Usage(VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_GPU_ONLY, VmaAllocationCreateFlags allocFlags = 0); + BufferBuilder& MemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits = 0); + BufferBuilder& DebugName(const char* name) { debugName = name; return *this; } - std::unique_ptr create(VulkanDevice *device); + std::unique_ptr Create(VulkanDevice *device); private: VkBufferCreateInfo bufferInfo = {}; VmaAllocationCreateInfo allocInfo = {}; + const char* debugName = nullptr; }; class ShaderBuilder @@ -106,27 +88,22 @@ class ShaderBuilder public: ShaderBuilder(); - static void init(); - static void deinit(); + ShaderBuilder& VertexShader(const FString &code); + ShaderBuilder& FragmentShader(const FString &code); + ShaderBuilder& RayGenShader(const FString& code); + ShaderBuilder& IntersectShader(const FString& code); + ShaderBuilder& AnyHitShader(const FString& code); + ShaderBuilder& ClosestHitShader(const FString& code); + ShaderBuilder& MissShader(const FString& code); + ShaderBuilder& CallableShader(const FString& code); + ShaderBuilder& DebugName(const char* name) { debugName = name; return *this; } - void setVertexShader(const std::string &code); - void setTessControlShader(const std::string &code); - void setTessEvaluationShader(const std::string &code); - void setGeometryShader(const std::string &code); - void setFragmentShader(const std::string &code); - void setComputeShader(const std::string &code); - void setRayGenShader(const std::string &code); - void setIntersectShader(const std::string &code); - void setAnyHitShader(const std::string &code); - void setClosestHitShader(const std::string &code); - void setMissShader(const std::string &code); - void setCallableShader(const std::string &code); - - std::unique_ptr create(VulkanDevice *device); + std::unique_ptr Create(const char *shadername, VulkanDevice *device); private: - std::string code; + FString code; int stage = 0; + const char* debugName = nullptr; }; class RayTracingPipelineBuilder @@ -134,20 +111,22 @@ class RayTracingPipelineBuilder public: RayTracingPipelineBuilder(); - void setLayout(VulkanPipelineLayout *layout); - void setMaxPipelineRayRecursionDepth(int depth); - void addShader(VkShaderStageFlagBits stage, VulkanShader *shader); - void addRayGenGroup(int rayGenShader); - void addMissGroup(int missShader); - void addTrianglesHitGroup(int closestHitShader, int anyHitShader = VK_SHADER_UNUSED_KHR); - void addProceduralHitGroup(int intersectionShader, int closestHitShader, int anyHitShader); + RayTracingPipelineBuilder& Layout(VulkanPipelineLayout* layout); + RayTracingPipelineBuilder& MaxPipelineRayRecursionDepth(int depth); + RayTracingPipelineBuilder& AddShader(VkShaderStageFlagBits stage, VulkanShader* shader); + RayTracingPipelineBuilder& AddRayGenGroup(int rayGenShader); + RayTracingPipelineBuilder& AddMissGroup(int missShader); + RayTracingPipelineBuilder& AddTrianglesHitGroup(int closestHitShader, int anyHitShader = VK_SHADER_UNUSED_KHR); + RayTracingPipelineBuilder& AddProceduralHitGroup(int intersectionShader, int closestHitShader, int anyHitShader); + RayTracingPipelineBuilder& DebugName(const char* name) { debugName = name; return *this; } - std::unique_ptr create(VulkanDevice *device); + std::unique_ptr Create(VulkanDevice* device); private: VkRayTracingPipelineCreateInfoKHR pipelineInfo = {}; std::vector stages; std::vector groups; + const char* debugName = nullptr; }; class ComputePipelineBuilder @@ -155,14 +134,16 @@ class ComputePipelineBuilder public: ComputePipelineBuilder(); - void setLayout(VulkanPipelineLayout *layout); - void setComputeShader(VulkanShader *shader); + ComputePipelineBuilder& Layout(VulkanPipelineLayout *layout); + ComputePipelineBuilder& ComputeShader(VulkanShader *shader); + ComputePipelineBuilder& DebugName(const char* name) { debugName = name; return *this; } - std::unique_ptr create(VulkanDevice *device); + std::unique_ptr Create(VulkanDevice *device); private: VkComputePipelineCreateInfo pipelineInfo = {}; VkPipelineShaderStageCreateInfo stageInfo = {}; + const char* debugName = nullptr; }; class DescriptorSetLayoutBuilder @@ -170,13 +151,15 @@ class DescriptorSetLayoutBuilder public: DescriptorSetLayoutBuilder(); - void addBinding(int binding, VkDescriptorType type, int arrayCount, VkShaderStageFlags stageFlags); + DescriptorSetLayoutBuilder& AddBinding(int binding, VkDescriptorType type, int arrayCount, VkShaderStageFlags stageFlags); + DescriptorSetLayoutBuilder& DebugName(const char* name) { debugName = name; return *this; } - std::unique_ptr create(VulkanDevice *device); + std::unique_ptr Create(VulkanDevice *device); private: VkDescriptorSetLayoutCreateInfo layoutInfo = {}; - FixedSizeVector bindings; + TArray bindings; + const char* debugName = nullptr; }; class DescriptorPoolBuilder @@ -184,14 +167,16 @@ class DescriptorPoolBuilder public: DescriptorPoolBuilder(); - void setMaxSets(int value); - void addPoolSize(VkDescriptorType type, int count); + DescriptorPoolBuilder& MaxSets(int value); + DescriptorPoolBuilder& AddPoolSize(VkDescriptorType type, int count); + DescriptorPoolBuilder& DebugName(const char* name) { debugName = name; return *this; } - std::unique_ptr create(VulkanDevice *device); + std::unique_ptr Create(VulkanDevice *device); private: - FixedSizeVector poolSizes; + std::vector poolSizes; VkDescriptorPoolCreateInfo poolInfo = {}; + const char* debugName = nullptr; }; class QueryPoolBuilder @@ -199,12 +184,14 @@ class QueryPoolBuilder public: QueryPoolBuilder(); - void setQueryType(VkQueryType type, int count, VkQueryPipelineStatisticFlags pipelineStatistics = 0); + QueryPoolBuilder& QueryType(VkQueryType type, int count, VkQueryPipelineStatisticFlags pipelineStatistics = 0); + QueryPoolBuilder& DebugName(const char* name) { debugName = name; return *this; } - std::unique_ptr create(VulkanDevice *device); + std::unique_ptr Create(VulkanDevice *device); private: VkQueryPoolCreateInfo poolInfo = {}; + const char* debugName = nullptr; }; class FramebufferBuilder @@ -212,55 +199,57 @@ class FramebufferBuilder public: FramebufferBuilder(); - void setRenderPass(VulkanRenderPass *renderPass); - void addAttachment(VulkanImageView *view); - void addAttachment(VkImageView view); - void setSize(int width, int height, int layers = 1); + FramebufferBuilder& RenderPass(VulkanRenderPass *renderPass); + FramebufferBuilder& AddAttachment(VulkanImageView *view); + FramebufferBuilder& AddAttachment(VkImageView view); + FramebufferBuilder& Size(int width, int height, int layers = 1); + FramebufferBuilder& DebugName(const char* name) { debugName = name; return *this; } - std::unique_ptr create(VulkanDevice *device); + std::unique_ptr Create(VulkanDevice *device); private: VkFramebufferCreateInfo framebufferInfo = {}; - FixedSizeVector attachments; + std::vector attachments; + const char* debugName = nullptr; }; -union FRenderStyle; - class GraphicsPipelineBuilder { public: GraphicsPipelineBuilder(); - void setSubpass(int subpass); - void setLayout(VulkanPipelineLayout *layout); - void setRenderPass(VulkanRenderPass *renderPass); - void setTopology(VkPrimitiveTopology topology); - void setViewport(float x, float y, float width, float height, float minDepth = 0.0f, float maxDepth = 1.0f); - void setScissor(int x, int y, int width, int height); - void setRasterizationSamples(VkSampleCountFlagBits samples); + GraphicsPipelineBuilder& Subpass(int subpass); + GraphicsPipelineBuilder& Layout(VulkanPipelineLayout *layout); + GraphicsPipelineBuilder& RenderPass(VulkanRenderPass *renderPass); + GraphicsPipelineBuilder& Topology(VkPrimitiveTopology topology); + GraphicsPipelineBuilder& Viewport(float x, float y, float width, float height, float minDepth = 0.0f, float maxDepth = 1.0f); + GraphicsPipelineBuilder& Scissor(int x, int y, int width, int height); + GraphicsPipelineBuilder& RasterizationSamples(VkSampleCountFlagBits samples); - void setCull(VkCullModeFlags cullMode, VkFrontFace frontFace); - void setDepthStencilEnable(bool test, bool write, bool stencil); - void setDepthFunc(VkCompareOp func); - void setDepthClampEnable(bool value); - void setDepthBias(bool enable, float biasConstantFactor, float biasClamp, float biasSlopeFactor); - void setColorWriteMask(VkColorComponentFlags mask); - void setStencil(VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp, uint32_t compareMask, uint32_t writeMask, uint32_t reference); + GraphicsPipelineBuilder& Cull(VkCullModeFlags cullMode, VkFrontFace frontFace); + GraphicsPipelineBuilder& DepthStencilEnable(bool test, bool write, bool stencil); + GraphicsPipelineBuilder& DepthFunc(VkCompareOp func); + GraphicsPipelineBuilder& DepthClampEnable(bool value); + GraphicsPipelineBuilder& DepthBias(bool enable, float biasConstantFactor, float biasClamp, float biasSlopeFactor); + GraphicsPipelineBuilder& ColorWriteMask(VkColorComponentFlags mask); + GraphicsPipelineBuilder& Stencil(VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp, uint32_t compareMask, uint32_t writeMask, uint32_t reference); - void setAdditiveBlendMode(); - void setAlphaBlendMode(); - void setBlendMode(VkBlendOp op, VkBlendFactor src, VkBlendFactor dst); - void setSubpassColorAttachmentCount(int count); + GraphicsPipelineBuilder& AdditiveBlendMode(); + GraphicsPipelineBuilder& AlphaBlendMode(); + GraphicsPipelineBuilder& BlendMode(VkBlendOp op, VkBlendFactor src, VkBlendFactor dst); + GraphicsPipelineBuilder& SubpassColorAttachmentCount(int count); - void addVertexShader(VulkanShader *shader); - void addFragmentShader(VulkanShader *shader); + GraphicsPipelineBuilder& AddVertexShader(VulkanShader *shader); + GraphicsPipelineBuilder& AddFragmentShader(VulkanShader *shader); - void addVertexBufferBinding(int index, size_t stride); - void addVertexAttribute(int location, int binding, VkFormat format, size_t offset); + GraphicsPipelineBuilder& AddVertexBufferBinding(int index, size_t stride); + GraphicsPipelineBuilder& AddVertexAttribute(int location, int binding, VkFormat format, size_t offset); - void addDynamicState(VkDynamicState state); + GraphicsPipelineBuilder& AddDynamicState(VkDynamicState state); - std::unique_ptr create(VulkanDevice *device); + GraphicsPipelineBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); private: VkGraphicsPipelineCreateInfo pipelineInfo = { }; @@ -281,6 +270,8 @@ private: std::vector vertexInputBindings; std::vector vertexInputAttributes; std::vector dynamicStates; + + const char* debugName = nullptr; }; class PipelineLayoutBuilder @@ -288,15 +279,18 @@ class PipelineLayoutBuilder public: PipelineLayoutBuilder(); - void addSetLayout(VulkanDescriptorSetLayout *setLayout); - void addPushConstantRange(VkShaderStageFlags stageFlags, size_t offset, size_t size); + PipelineLayoutBuilder& AddSetLayout(VulkanDescriptorSetLayout *setLayout); + PipelineLayoutBuilder& AddPushConstantRange(VkShaderStageFlags stageFlags, size_t offset, size_t size); - std::unique_ptr create(VulkanDevice *device); + PipelineLayoutBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); private: VkPipelineLayoutCreateInfo pipelineLayoutInfo = {}; std::vector setLayouts; std::vector pushConstantRanges; + const char* debugName = nullptr; }; class RenderPassBuilder @@ -304,50 +298,54 @@ class RenderPassBuilder public: RenderPassBuilder(); - void addAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkImageLayout initialLayout, VkImageLayout finalLayout); - void addDepthStencilAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkAttachmentLoadOp stencilLoad, VkAttachmentStoreOp stencilStore, VkImageLayout initialLayout, VkImageLayout finalLayout); + RenderPassBuilder& AddAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkImageLayout initialLayout, VkImageLayout finalLayout); + RenderPassBuilder& AddDepthStencilAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkAttachmentLoadOp stencilLoad, VkAttachmentStoreOp stencilStore, VkImageLayout initialLayout, VkImageLayout finalLayout); - void addExternalSubpassDependency(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); + RenderPassBuilder& AddExternalSubpassDependency(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); - void addSubpass(); - void addSubpassColorAttachmentRef(uint32_t index, VkImageLayout layout); - void addSubpassDepthStencilAttachmentRef(uint32_t index, VkImageLayout layout); + RenderPassBuilder& AddSubpass(); + RenderPassBuilder& AddSubpassColorAttachmentRef(uint32_t index, VkImageLayout layout); + RenderPassBuilder& AddSubpassDepthStencilAttachmentRef(uint32_t index, VkImageLayout layout); - std::unique_ptr create(VulkanDevice *device); + RenderPassBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice *device); private: VkRenderPassCreateInfo renderPassInfo = { }; - FixedSizeVector attachments; - FixedSizeVector dependencies; - FixedSizeVector subpasses; + std::vector attachments; + std::vector dependencies; + std::vector subpasses; struct SubpassData { - FixedSizeVector colorRefs; + std::vector colorRefs; VkAttachmentReference depthRef = { }; }; - FixedSizeVector, 8> subpassData; + std::vector> subpassData; + + const char* debugName = nullptr; }; class PipelineBarrier { public: - void addMemory(VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); - void addBuffer(VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); - void addBuffer(VulkanBuffer *buffer, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); - void addImage(VulkanImage *image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); - void addImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); - void addQueueTransfer(int srcFamily, int dstFamily, VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); - void addQueueTransfer(int srcFamily, int dstFamily, VulkanImage *image, VkImageLayout layout, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); + PipelineBarrier& AddMemory(VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); + PipelineBarrier& AddBuffer(VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); + PipelineBarrier& AddBuffer(VulkanBuffer *buffer, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); + PipelineBarrier& AddImage(VulkanImage *image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); + PipelineBarrier& AddImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); + PipelineBarrier& AddQueueTransfer(int srcFamily, int dstFamily, VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); + PipelineBarrier& AddQueueTransfer(int srcFamily, int dstFamily, VulkanImage *image, VkImageLayout layout, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); - void execute(VulkanCommandBuffer *commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags = 0); + void Execute(VulkanCommandBuffer *commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags = 0); private: - FixedSizeVector memoryBarriers; - FixedSizeVector bufferMemoryBarriers; - FixedSizeVector imageMemoryBarriers; + std::vector memoryBarriers; + std::vector bufferMemoryBarriers; + std::vector imageMemoryBarriers; }; class QueueSubmit @@ -355,29 +353,28 @@ class QueueSubmit public: QueueSubmit(); - void addCommandBuffer(VulkanCommandBuffer *buffer); - void addWait(VkPipelineStageFlags waitStageMask, VulkanSemaphore *semaphore); - void addSignal(VulkanSemaphore *semaphore); - void execute(VulkanDevice *device, VkQueue queue, VulkanFence *fence = nullptr); + QueueSubmit& AddCommandBuffer(VulkanCommandBuffer *buffer); + QueueSubmit& AddWait(VkPipelineStageFlags waitStageMask, VulkanSemaphore *semaphore); + QueueSubmit& AddSignal(VulkanSemaphore *semaphore); + void Execute(VulkanDevice *device, VkQueue queue, VulkanFence *fence = nullptr); private: VkSubmitInfo submitInfo = {}; - FixedSizeVector waitSemaphores; - FixedSizeVector waitStages; - FixedSizeVector signalSemaphores; - FixedSizeVector commandBuffers; + std::vector waitSemaphores; + std::vector waitStages; + std::vector signalSemaphores; + std::vector commandBuffers; }; class WriteDescriptors { public: - void addBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer); - void addBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer, size_t offset, size_t range); - void addStorageImage(VulkanDescriptorSet *descriptorSet, int binding, VulkanImageView *view, VkImageLayout imageLayout); - void addCombinedImageSampler(VulkanDescriptorSet *descriptorSet, int binding, VulkanImageView *view, VulkanSampler *sampler, VkImageLayout imageLayout); - void addAccelerationStructure(VulkanDescriptorSet *descriptorSet, int binding, VulkanAccelerationStructure *accelStruct); - - void updateSets(VulkanDevice *device); + WriteDescriptors& AddBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer); + WriteDescriptors& AddBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer, size_t offset, size_t range); + WriteDescriptors& AddStorageImage(VulkanDescriptorSet *descriptorSet, int binding, VulkanImageView *view, VkImageLayout imageLayout); + WriteDescriptors& AddCombinedImageSampler(VulkanDescriptorSet *descriptorSet, int binding, VulkanImageView *view, VulkanSampler *sampler, VkImageLayout imageLayout); + WriteDescriptors& AddAccelerationStructure(VulkanDescriptorSet* descriptorSet, int binding, VulkanAccelerationStructure* accelStruct); + void Execute(VulkanDevice *device); private: struct WriteExtra @@ -391,1142 +388,3 @@ private: std::vector writes; std::vector> writeExtras; }; - -///////////////////////////////////////////////////////////////////////////// - -inline ImageBuilder::ImageBuilder() -{ - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.extent.depth = 1; - imageInfo.arrayLayers = 1; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Note: must either be VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_PREINITIALIZED - imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageInfo.flags = 0; -} - -inline void ImageBuilder::setSize(int width, int height, int mipLevels) -{ - imageInfo.extent.width = width; - imageInfo.extent.height = height; - imageInfo.mipLevels = mipLevels; -} - -inline void ImageBuilder::setSamples(VkSampleCountFlagBits samples) -{ - imageInfo.samples = samples; -} - -inline void ImageBuilder::setFormat(VkFormat format) -{ - imageInfo.format = format; -} - -inline void ImageBuilder::setLinearTiling() -{ - imageInfo.tiling = VK_IMAGE_TILING_LINEAR; -} - -inline void ImageBuilder::setUsage(VkImageUsageFlags usage, VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocFlags) -{ - imageInfo.usage = usage; - allocInfo.usage = memoryUsage; - allocInfo.flags = allocFlags; -} - -inline bool ImageBuilder::isFormatSupported(VulkanDevice *device) -{ - VkImageFormatProperties properties = { }; - VkResult result = vkGetPhysicalDeviceImageFormatProperties(device->physicalDevice.device, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &properties); - if (result != VK_SUCCESS) return false; - if (imageInfo.extent.width > properties.maxExtent.width) return false; - if (imageInfo.extent.height > properties.maxExtent.height) return false; - if (imageInfo.extent.depth > properties.maxExtent.depth) return false; - if (imageInfo.mipLevels > properties.maxMipLevels) return false; - if (imageInfo.arrayLayers > properties.maxArrayLayers) return false; - if ((imageInfo.samples & properties.sampleCounts) != imageInfo.samples) return false; - return true; -} - -inline std::unique_ptr ImageBuilder::create(VulkanDevice *device) -{ - VkImage image; - VmaAllocation allocation; - - VkResult result = vmaCreateImage(device->allocator, &imageInfo, &allocInfo, &image, &allocation, nullptr); - if (result != VK_SUCCESS) - throw std::runtime_error("Could not create vulkan image"); - - return std::make_unique(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels); -} - -///////////////////////////////////////////////////////////////////////////// - -inline ImageViewBuilder::ImageViewBuilder() -{ - viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.subresourceRange.baseMipLevel = 0; - viewInfo.subresourceRange.baseArrayLayer = 0; - viewInfo.subresourceRange.layerCount = 1; - viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; -} - -inline void ImageViewBuilder::setImage(VulkanImage *image, VkFormat format, VkImageAspectFlags aspectMask) -{ - viewInfo.image = image->image; - viewInfo.format = format; - viewInfo.subresourceRange.levelCount = image->mipLevels; - viewInfo.subresourceRange.aspectMask = aspectMask; -} - -inline void ImageBuilder::setMemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits) -{ - allocInfo.requiredFlags = requiredFlags; - allocInfo.preferredFlags = preferredFlags; - allocInfo.memoryTypeBits = memoryTypeBits; -} - -inline std::unique_ptr ImageViewBuilder::create(VulkanDevice *device) -{ - VkImageView view; - VkResult result = vkCreateImageView(device->device, &viewInfo, nullptr, &view); - if (result != VK_SUCCESS) - throw std::runtime_error("Could not create texture image view"); - - return std::make_unique(device, view); -} - -///////////////////////////////////////////////////////////////////////////// - -inline SamplerBuilder::SamplerBuilder() -{ - samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.anisotropyEnable = VK_FALSE; - samplerInfo.maxAnisotropy = 1.0f; - samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; - samplerInfo.unnormalizedCoordinates = VK_FALSE; - samplerInfo.compareEnable = VK_FALSE; - samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.mipLodBias = 0.0f; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 100.0f; -} - -inline void SamplerBuilder::setAddressMode(VkSamplerAddressMode addressMode) -{ - samplerInfo.addressModeU = addressMode; - samplerInfo.addressModeV = addressMode; - samplerInfo.addressModeW = addressMode; -} - -inline void SamplerBuilder::setAddressMode(VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w) -{ - samplerInfo.addressModeU = u; - samplerInfo.addressModeV = v; - samplerInfo.addressModeW = w; -} - -inline void SamplerBuilder::setMinFilter(VkFilter minFilter) -{ - samplerInfo.minFilter = minFilter; -} - -inline void SamplerBuilder::setMagFilter(VkFilter magFilter) -{ - samplerInfo.magFilter = magFilter; -} - -inline void SamplerBuilder::setMipmapMode(VkSamplerMipmapMode mode) -{ - samplerInfo.mipmapMode = mode; -} - -inline void SamplerBuilder::setAnisotropy(float maxAnisotropy) -{ - samplerInfo.anisotropyEnable = VK_TRUE; - samplerInfo.maxAnisotropy = maxAnisotropy; -} - -inline void SamplerBuilder::setMaxLod(float value) -{ - samplerInfo.maxLod = value; -} - -inline std::unique_ptr SamplerBuilder::create(VulkanDevice *device) -{ - VkSampler sampler; - VkResult result = vkCreateSampler(device->device, &samplerInfo, nullptr, &sampler); - if (result != VK_SUCCESS) - throw std::runtime_error("Could not create texture sampler"); - return std::make_unique(device, sampler); -} - -///////////////////////////////////////////////////////////////////////////// - -inline BufferBuilder::BufferBuilder() -{ - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; -} - -inline void BufferBuilder::setSize(size_t size) -{ - bufferInfo.size = size; -} - -inline void BufferBuilder::setUsage(VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocFlags) -{ - bufferInfo.usage = bufferUsage; - allocInfo.usage = memoryUsage; - allocInfo.flags = allocFlags; -} - -inline void BufferBuilder::setMemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits) -{ - allocInfo.requiredFlags = requiredFlags; - allocInfo.preferredFlags = preferredFlags; - allocInfo.memoryTypeBits = memoryTypeBits; -} - -inline std::unique_ptr BufferBuilder::create(VulkanDevice *device) -{ - VkBuffer buffer; - VmaAllocation allocation; - - VkResult result = vmaCreateBuffer(device->allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); - if (result != VK_SUCCESS) - throw std::runtime_error("could not allocate memory for vulkan buffer"); - - return std::make_unique(device, buffer, allocation, (size_t)bufferInfo.size); -} - -///////////////////////////////////////////////////////////////////////////// - -inline RayTracingPipelineBuilder::RayTracingPipelineBuilder() -{ - pipelineInfo.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR; -} - -inline void RayTracingPipelineBuilder::setLayout(VulkanPipelineLayout *layout) -{ - pipelineInfo.layout = layout->layout; -} - -inline void RayTracingPipelineBuilder::setMaxPipelineRayRecursionDepth(int depth) -{ - pipelineInfo.maxPipelineRayRecursionDepth = depth; -} - -inline void RayTracingPipelineBuilder::addShader(VkShaderStageFlagBits stage, VulkanShader *shader) -{ - VkPipelineShaderStageCreateInfo stageInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO }; - stageInfo.stage = stage; - stageInfo.module = shader->module; - stageInfo.pName = "main"; - stages.push_back(stageInfo); - - pipelineInfo.pStages = stages.data(); - pipelineInfo.stageCount = (uint32_t)stages.size(); -} - -inline void RayTracingPipelineBuilder::addRayGenGroup(int rayGenShader) -{ - VkRayTracingShaderGroupCreateInfoKHR group = {}; - group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - group.generalShader = rayGenShader; - group.closestHitShader = VK_SHADER_UNUSED_KHR; - group.anyHitShader = VK_SHADER_UNUSED_KHR; - group.intersectionShader = VK_SHADER_UNUSED_KHR; - groups.push_back(group); - - pipelineInfo.pGroups = groups.data(); - pipelineInfo.groupCount = (uint32_t)groups.size(); -} - -inline void RayTracingPipelineBuilder::addMissGroup(int missShader) -{ - VkRayTracingShaderGroupCreateInfoKHR group = {}; - group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - group.generalShader = missShader; - group.closestHitShader = VK_SHADER_UNUSED_KHR; - group.anyHitShader = VK_SHADER_UNUSED_KHR; - group.intersectionShader = VK_SHADER_UNUSED_KHR; - groups.push_back(group); - - pipelineInfo.pGroups = groups.data(); - pipelineInfo.groupCount = (uint32_t)groups.size(); -} - -inline void RayTracingPipelineBuilder::addTrianglesHitGroup(int closestHitShader, int anyHitShader) -{ - VkRayTracingShaderGroupCreateInfoKHR group = {}; - group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; - group.generalShader = VK_SHADER_UNUSED_KHR; - group.closestHitShader = closestHitShader; - group.anyHitShader = anyHitShader; - group.intersectionShader = VK_SHADER_UNUSED_KHR; - groups.push_back(group); - - pipelineInfo.pGroups = groups.data(); - pipelineInfo.groupCount = (uint32_t)groups.size(); -} - -inline void RayTracingPipelineBuilder::addProceduralHitGroup(int intersectionShader, int closestHitShader, int anyHitShader) -{ - VkRayTracingShaderGroupCreateInfoKHR group = {}; - group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; - group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; - group.generalShader = VK_SHADER_UNUSED_KHR; - group.closestHitShader = closestHitShader; - group.anyHitShader = anyHitShader; - group.intersectionShader = intersectionShader; - groups.push_back(group); - - pipelineInfo.pGroups = groups.data(); - pipelineInfo.groupCount = (uint32_t)groups.size(); -} - -inline std::unique_ptr RayTracingPipelineBuilder::create(VulkanDevice *device) -{ - VkPipeline pipeline; - VkResult result = vkCreateRayTracingPipelinesKHR(device->device, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline); - if (result != VK_SUCCESS) - throw std::runtime_error("vkCreateRayTracingPipelinesKHR failed"); - - std::vector shaderGroupHandles(device->physicalDevice.rayTracingProperties.shaderGroupHandleSize * groups.size()); - if (!groups.empty()) - { - result = vkGetRayTracingShaderGroupHandlesKHR(device->device, pipeline, 0, (uint32_t)groups.size(), shaderGroupHandles.size(), shaderGroupHandles.data()); - if (result != VK_SUCCESS) - { - vkDestroyPipeline(device->device, pipeline, nullptr); - throw std::runtime_error("vkGetRayTracingShaderGroupHandlesKHR failed"); - } - } - - return std::make_unique(device, pipeline, shaderGroupHandles); -} - -///////////////////////////////////////////////////////////////////////////// - -inline ComputePipelineBuilder::ComputePipelineBuilder() -{ - pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - stageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; -} - -inline void ComputePipelineBuilder::setLayout(VulkanPipelineLayout *layout) -{ - pipelineInfo.layout = layout->layout; -} - -inline void ComputePipelineBuilder::setComputeShader(VulkanShader *shader) -{ - stageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; - stageInfo.module = shader->module; - stageInfo.pName = "main"; - - pipelineInfo.stage = stageInfo; -} - -inline std::unique_ptr ComputePipelineBuilder::create(VulkanDevice *device) -{ - VkPipeline pipeline; - vkCreateComputePipelines(device->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline); - return std::make_unique(device, pipeline); -} - -///////////////////////////////////////////////////////////////////////////// - -inline DescriptorSetLayoutBuilder::DescriptorSetLayoutBuilder() -{ - layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; -} - -inline void DescriptorSetLayoutBuilder::addBinding(int index, VkDescriptorType type, int arrayCount, VkShaderStageFlags stageFlags) -{ - VkDescriptorSetLayoutBinding binding = { }; - binding.binding = index; - binding.descriptorType = type; - binding.descriptorCount = arrayCount; - binding.stageFlags = stageFlags; - binding.pImmutableSamplers = nullptr; - bindings.push_back(binding); - - layoutInfo.bindingCount = (uint32_t)bindings.size(); - layoutInfo.pBindings = bindings.data(); -} - -inline std::unique_ptr DescriptorSetLayoutBuilder::create(VulkanDevice *device) -{ - VkDescriptorSetLayout layout; - VkResult result = vkCreateDescriptorSetLayout(device->device, &layoutInfo, nullptr, &layout); - if (result != VK_SUCCESS) - throw std::runtime_error("Could not create descriptor set layout"); - return std::make_unique(device, layout); -} - -///////////////////////////////////////////////////////////////////////////// - -inline DescriptorPoolBuilder::DescriptorPoolBuilder() -{ - poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - poolInfo.maxSets = 1; - poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; -} - -inline void DescriptorPoolBuilder::setMaxSets(int value) -{ - poolInfo.maxSets = value; -} - -inline void DescriptorPoolBuilder::addPoolSize(VkDescriptorType type, int count) -{ - VkDescriptorPoolSize size; - size.type = type; - size.descriptorCount = count; - poolSizes.push_back(size); - - poolInfo.poolSizeCount = (uint32_t)poolSizes.size(); - poolInfo.pPoolSizes = poolSizes.data(); -} - -inline std::unique_ptr DescriptorPoolBuilder::create(VulkanDevice *device) -{ - VkDescriptorPool descriptorPool; - VkResult result = vkCreateDescriptorPool(device->device, &poolInfo, nullptr, &descriptorPool); - if (result != VK_SUCCESS) - throw std::runtime_error("Could not create descriptor pool"); - return std::make_unique(device, descriptorPool); -} - -///////////////////////////////////////////////////////////////////////////// - -inline QueryPoolBuilder::QueryPoolBuilder() -{ - poolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; -} - -inline void QueryPoolBuilder::setQueryType(VkQueryType type, int count, VkQueryPipelineStatisticFlags pipelineStatistics) -{ - poolInfo.queryType = type; - poolInfo.queryCount = count; - poolInfo.pipelineStatistics = pipelineStatistics; -} - -inline std::unique_ptr QueryPoolBuilder::create(VulkanDevice *device) -{ - VkQueryPool queryPool; - VkResult result = vkCreateQueryPool(device->device, &poolInfo, nullptr, &queryPool); - if (result != VK_SUCCESS) - throw std::runtime_error("Could not create query pool"); - return std::make_unique(device, queryPool); -} - -///////////////////////////////////////////////////////////////////////////// - -inline FramebufferBuilder::FramebufferBuilder() -{ - framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; -} - -inline void FramebufferBuilder::setRenderPass(VulkanRenderPass *renderPass) -{ - framebufferInfo.renderPass = renderPass->renderPass; -} - -inline void FramebufferBuilder::addAttachment(VulkanImageView *view) -{ - attachments.push_back(view->view); - - framebufferInfo.attachmentCount = (uint32_t)attachments.size(); - framebufferInfo.pAttachments = attachments.data(); -} - -inline void FramebufferBuilder::addAttachment(VkImageView view) -{ - attachments.push_back(view); - - framebufferInfo.attachmentCount = (uint32_t)attachments.size(); - framebufferInfo.pAttachments = attachments.data(); -} - -inline void FramebufferBuilder::setSize(int width, int height, int layers) -{ - framebufferInfo.width = width; - framebufferInfo.height = height; - framebufferInfo.layers = 1; -} - -inline std::unique_ptr FramebufferBuilder::create(VulkanDevice *device) -{ - VkFramebuffer framebuffer = 0; - VkResult result = vkCreateFramebuffer(device->device, &framebufferInfo, nullptr, &framebuffer); - if (result != VK_SUCCESS) - throw std::runtime_error("Failed to create framebuffer"); - return std::make_unique(device, framebuffer); -} - -///////////////////////////////////////////////////////////////////////////// - -inline GraphicsPipelineBuilder::GraphicsPipelineBuilder() -{ - pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.pVertexInputState = &vertexInputInfo; - pipelineInfo.pInputAssemblyState = &inputAssembly; - pipelineInfo.pViewportState = &viewportState; - pipelineInfo.pRasterizationState = &rasterizer; - pipelineInfo.pMultisampleState = &multisampling; - pipelineInfo.pDepthStencilState = nullptr; - pipelineInfo.pColorBlendState = &colorBlending; - pipelineInfo.pDynamicState = &dynamicState; - pipelineInfo.subpass = 0; - pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; - pipelineInfo.basePipelineIndex = -1; - - vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertexInputInfo.vertexBindingDescriptionCount = 0; - vertexInputInfo.pVertexBindingDescriptions = nullptr; - vertexInputInfo.vertexAttributeDescriptionCount = 0; - vertexInputInfo.pVertexAttributeDescriptions = nullptr; - - inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - inputAssembly.primitiveRestartEnable = VK_FALSE; - - viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - - depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; - depthStencil.depthBoundsTestEnable = VK_FALSE; - depthStencil.minDepthBounds = 0.0f; - depthStencil.maxDepthBounds = 1.0f; - depthStencil.stencilTestEnable = VK_FALSE; - depthStencil.front = {}; - depthStencil.back = {}; - - rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizer.depthClampEnable = VK_FALSE; - rasterizer.rasterizerDiscardEnable = VK_FALSE; - rasterizer.polygonMode = VK_POLYGON_MODE_FILL; - rasterizer.lineWidth = 1.0f; - rasterizer.cullMode = VK_CULL_MODE_NONE; - rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; - rasterizer.depthBiasEnable = VK_FALSE; - rasterizer.depthBiasConstantFactor = 0.0f; - rasterizer.depthBiasClamp = 0.0f; - rasterizer.depthBiasSlopeFactor = 0.0f; - - multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampling.sampleShadingEnable = VK_FALSE; - multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisampling.minSampleShading = 1.0f; - multisampling.pSampleMask = nullptr; - multisampling.alphaToCoverageEnable = VK_FALSE; - multisampling.alphaToOneEnable = VK_FALSE; - - colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - colorBlendAttachment.blendEnable = VK_FALSE; - colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; - colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; - colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - - colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - colorBlending.logicOpEnable = VK_FALSE; - colorBlending.logicOp = VK_LOGIC_OP_COPY; - colorBlending.attachmentCount = 1; - colorBlending.pAttachments = &colorBlendAttachment; - colorBlending.blendConstants[0] = 0.0f; - colorBlending.blendConstants[1] = 0.0f; - colorBlending.blendConstants[2] = 0.0f; - colorBlending.blendConstants[3] = 0.0f; - - dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; -} - -inline void GraphicsPipelineBuilder::setRasterizationSamples(VkSampleCountFlagBits samples) -{ - multisampling.rasterizationSamples = samples; -} - -inline void GraphicsPipelineBuilder::setSubpass(int subpass) -{ - pipelineInfo.subpass = subpass; -} - -inline void GraphicsPipelineBuilder::setLayout(VulkanPipelineLayout *layout) -{ - pipelineInfo.layout = layout->layout; -} - -inline void GraphicsPipelineBuilder::setRenderPass(VulkanRenderPass *renderPass) -{ - pipelineInfo.renderPass = renderPass->renderPass; -} - -inline void GraphicsPipelineBuilder::setTopology(VkPrimitiveTopology topology) -{ - inputAssembly.topology = topology; -} - -inline void GraphicsPipelineBuilder::setViewport(float x, float y, float width, float height, float minDepth, float maxDepth) -{ - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = width; - viewport.height = height; - viewport.minDepth = minDepth; - viewport.maxDepth = maxDepth; - - viewportState.viewportCount = 1; - viewportState.pViewports = &viewport; -} - -inline void GraphicsPipelineBuilder::setScissor(int x, int y, int width, int height) -{ - scissor.offset.x = x; - scissor.offset.y = y; - scissor.extent.width = width; - scissor.extent.height = height; - - viewportState.scissorCount = 1; - viewportState.pScissors = &scissor; -} - -inline void GraphicsPipelineBuilder::setCull(VkCullModeFlags cullMode, VkFrontFace frontFace) -{ - rasterizer.cullMode = cullMode; - rasterizer.frontFace = frontFace; -} - -inline void GraphicsPipelineBuilder::setDepthStencilEnable(bool test, bool write, bool stencil) -{ - depthStencil.depthTestEnable = test ? VK_TRUE : VK_FALSE; - depthStencil.depthWriteEnable = write ? VK_TRUE : VK_FALSE; - depthStencil.stencilTestEnable = stencil ? VK_TRUE : VK_FALSE; - - pipelineInfo.pDepthStencilState = (test || write || stencil) ? &depthStencil : nullptr; -} - -inline void GraphicsPipelineBuilder::setStencil(VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp, uint32_t compareMask, uint32_t writeMask, uint32_t reference) -{ - depthStencil.front.failOp = failOp; - depthStencil.front.passOp = passOp; - depthStencil.front.depthFailOp = depthFailOp; - depthStencil.front.compareOp = compareOp; - depthStencil.front.compareMask = compareMask; - depthStencil.front.writeMask = writeMask; - depthStencil.front.reference = reference; - - depthStencil.back.failOp = failOp; - depthStencil.back.passOp = passOp; - depthStencil.back.depthFailOp = depthFailOp; - depthStencil.back.compareOp = compareOp; - depthStencil.back.compareMask = compareMask; - depthStencil.back.writeMask = writeMask; - depthStencil.back.reference = reference; -} - -inline void GraphicsPipelineBuilder::setDepthFunc(VkCompareOp func) -{ - depthStencil.depthCompareOp = func; -} - -inline void GraphicsPipelineBuilder::setDepthClampEnable(bool value) -{ - rasterizer.depthClampEnable = value ? VK_TRUE : VK_FALSE; -} - -inline void GraphicsPipelineBuilder::setDepthBias(bool enable, float biasConstantFactor, float biasClamp, float biasSlopeFactor) -{ - rasterizer.depthBiasEnable = enable ? VK_TRUE : VK_FALSE; - rasterizer.depthBiasConstantFactor = biasConstantFactor; - rasterizer.depthBiasClamp = biasClamp; - rasterizer.depthBiasSlopeFactor = biasSlopeFactor; -} - -inline void GraphicsPipelineBuilder::setColorWriteMask(VkColorComponentFlags mask) -{ - colorBlendAttachment.colorWriteMask = mask; -} - -inline void GraphicsPipelineBuilder::setAdditiveBlendMode() -{ - colorBlendAttachment.blendEnable = VK_TRUE; - colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; - colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; -} - -inline void GraphicsPipelineBuilder::setAlphaBlendMode() -{ - colorBlendAttachment.blendEnable = VK_TRUE; - colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; - colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; -} - -inline void GraphicsPipelineBuilder::setBlendMode(VkBlendOp op, VkBlendFactor src, VkBlendFactor dst) -{ - colorBlendAttachment.blendEnable = VK_TRUE; - colorBlendAttachment.srcColorBlendFactor = src; - colorBlendAttachment.dstColorBlendFactor = dst; - colorBlendAttachment.colorBlendOp = op; - colorBlendAttachment.srcAlphaBlendFactor = src; - colorBlendAttachment.dstAlphaBlendFactor = dst; - colorBlendAttachment.alphaBlendOp = op; -} - -inline void GraphicsPipelineBuilder::setSubpassColorAttachmentCount(int count) -{ - colorBlendAttachments.resize(count, colorBlendAttachment); - colorBlending.pAttachments = colorBlendAttachments.data(); - colorBlending.attachmentCount = (uint32_t)colorBlendAttachments.size(); -} - -inline void GraphicsPipelineBuilder::addVertexShader(VulkanShader *shader) -{ - VkPipelineShaderStageCreateInfo vertShaderStageInfo = {}; - vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; - vertShaderStageInfo.module = shader->module; - vertShaderStageInfo.pName = "main"; - shaderStages.push_back(vertShaderStageInfo); - - pipelineInfo.stageCount = (uint32_t)shaderStages.size(); - pipelineInfo.pStages = shaderStages.data(); -} - -inline void GraphicsPipelineBuilder::addFragmentShader(VulkanShader *shader) -{ - VkPipelineShaderStageCreateInfo fragShaderStageInfo = {}; - fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - fragShaderStageInfo.module = shader->module; - fragShaderStageInfo.pName = "main"; - shaderStages.push_back(fragShaderStageInfo); - - pipelineInfo.stageCount = (uint32_t)shaderStages.size(); - pipelineInfo.pStages = shaderStages.data(); -} - -inline void GraphicsPipelineBuilder::addVertexBufferBinding(int index, size_t stride) -{ - VkVertexInputBindingDescription desc = {}; - desc.binding = index; - desc.stride = (uint32_t)stride; - desc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - vertexInputBindings.push_back(desc); - - vertexInputInfo.vertexBindingDescriptionCount = (uint32_t)vertexInputBindings.size(); - vertexInputInfo.pVertexBindingDescriptions = vertexInputBindings.data(); -} - -inline void GraphicsPipelineBuilder::addVertexAttribute(int location, int binding, VkFormat format, size_t offset) -{ - VkVertexInputAttributeDescription desc = { }; - desc.location = location; - desc.binding = binding; - desc.format = format; - desc.offset = (uint32_t)offset; - vertexInputAttributes.push_back(desc); - - vertexInputInfo.vertexAttributeDescriptionCount = (uint32_t)vertexInputAttributes.size(); - vertexInputInfo.pVertexAttributeDescriptions = vertexInputAttributes.data(); -} - -inline void GraphicsPipelineBuilder::addDynamicState(VkDynamicState state) -{ - dynamicStates.push_back(state); - dynamicState.dynamicStateCount = (uint32_t)dynamicStates.size(); - dynamicState.pDynamicStates = dynamicStates.data(); -} - -inline std::unique_ptr GraphicsPipelineBuilder::create(VulkanDevice *device) -{ - VkPipeline pipeline = 0; - VkResult result = vkCreateGraphicsPipelines(device->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline); - if (result != VK_SUCCESS) - throw std::runtime_error("Could not create graphics pipeline"); - return std::make_unique(device, pipeline); -} - -///////////////////////////////////////////////////////////////////////////// - -inline PipelineLayoutBuilder::PipelineLayoutBuilder() -{ - pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; -} - -inline void PipelineLayoutBuilder::addSetLayout(VulkanDescriptorSetLayout *setLayout) -{ - setLayouts.push_back(setLayout->layout); - pipelineLayoutInfo.setLayoutCount = (uint32_t)setLayouts.size(); - pipelineLayoutInfo.pSetLayouts = setLayouts.data(); -} - -inline void PipelineLayoutBuilder::addPushConstantRange(VkShaderStageFlags stageFlags, size_t offset, size_t size) -{ - VkPushConstantRange range = { }; - range.stageFlags = stageFlags; - range.offset = (uint32_t)offset; - range.size = (uint32_t)size; - pushConstantRanges.push_back(range); - pipelineLayoutInfo.pushConstantRangeCount = (uint32_t)pushConstantRanges.size(); - pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges.data(); -} - -inline std::unique_ptr PipelineLayoutBuilder::create(VulkanDevice *device) -{ - VkPipelineLayout pipelineLayout; - VkResult result = vkCreatePipelineLayout(device->device, &pipelineLayoutInfo, nullptr, &pipelineLayout); - if (result != VK_SUCCESS) - throw std::runtime_error("Could not create pipeline layout"); - return std::make_unique(device, pipelineLayout); -} - -///////////////////////////////////////////////////////////////////////////// - -inline RenderPassBuilder::RenderPassBuilder() -{ - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; -} - -inline void RenderPassBuilder::addAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkImageLayout initialLayout, VkImageLayout finalLayout) -{ - VkAttachmentDescription attachment = {}; - attachment.format = format; - attachment.samples = samples; - attachment.loadOp = load; - attachment.storeOp = store; - attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachment.initialLayout = initialLayout; - attachment.finalLayout = finalLayout; - attachments.push_back(attachment); - renderPassInfo.pAttachments = attachments.data(); - renderPassInfo.attachmentCount = (uint32_t)attachments.size(); -} - -inline void RenderPassBuilder::addDepthStencilAttachment(VkFormat format, VkSampleCountFlagBits samples, VkAttachmentLoadOp load, VkAttachmentStoreOp store, VkAttachmentLoadOp stencilLoad, VkAttachmentStoreOp stencilStore, VkImageLayout initialLayout, VkImageLayout finalLayout) -{ - VkAttachmentDescription attachment = {}; - attachment.format = format; - attachment.samples = samples; - attachment.loadOp = load; - attachment.storeOp = store; - attachment.stencilLoadOp = stencilLoad; - attachment.stencilStoreOp = stencilStore; - attachment.initialLayout = initialLayout; - attachment.finalLayout = finalLayout; - attachments.push_back(attachment); - renderPassInfo.pAttachments = attachments.data(); - renderPassInfo.attachmentCount = (uint32_t)attachments.size(); -} - -inline void RenderPassBuilder::addExternalSubpassDependency(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) -{ - VkSubpassDependency dependency = {}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = srcStageMask; - dependency.srcAccessMask = srcAccessMask; - dependency.dstStageMask = dstStageMask; - dependency.dstAccessMask = dstAccessMask; - - dependencies.push_back(dependency); - renderPassInfo.pDependencies = dependencies.data(); - renderPassInfo.dependencyCount = (uint32_t)dependencies.size(); -} - -inline void RenderPassBuilder::addSubpass() -{ - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - - subpasses.push_back(subpass); - renderPassInfo.pSubpasses = subpasses.data(); - renderPassInfo.subpassCount = (uint32_t)subpasses.size(); - - subpassData.push_back(std::make_unique()); -} - -inline void RenderPassBuilder::addSubpassColorAttachmentRef(uint32_t index, VkImageLayout layout) -{ - VkAttachmentReference colorAttachmentRef = {}; - colorAttachmentRef.attachment = index; - colorAttachmentRef.layout = layout; - - subpassData.back()->colorRefs.push_back(colorAttachmentRef); - subpasses.back().pColorAttachments = subpassData.back()->colorRefs.data(); - subpasses.back().colorAttachmentCount = (uint32_t)subpassData.back()->colorRefs.size(); -} - -inline void RenderPassBuilder::addSubpassDepthStencilAttachmentRef(uint32_t index, VkImageLayout layout) -{ - VkAttachmentReference &depthAttachmentRef = subpassData.back()->depthRef; - depthAttachmentRef.attachment = index; - depthAttachmentRef.layout = layout; - - VkSubpassDescription &subpass = subpasses.back(); - subpass.pDepthStencilAttachment = &depthAttachmentRef; -} - -inline std::unique_ptr RenderPassBuilder::create(VulkanDevice *device) -{ - VkRenderPass renderPass = 0; - VkResult result = vkCreateRenderPass(device->device, &renderPassInfo, nullptr, &renderPass); - if (result != VK_SUCCESS) - throw std::runtime_error("Could not create render pass"); - return std::make_unique(device, renderPass); -} - -///////////////////////////////////////////////////////////////////////////// - -inline void PipelineBarrier::addMemory(VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) -{ - VkMemoryBarrier barrier = { }; - barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; - barrier.srcAccessMask = srcAccessMask; - barrier.dstAccessMask = dstAccessMask; - memoryBarriers.push_back(barrier); -} - -inline void PipelineBarrier::addBuffer(VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) -{ - addBuffer(buffer, 0, buffer->size, srcAccessMask, dstAccessMask); -} - -inline void PipelineBarrier::addBuffer(VulkanBuffer *buffer, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) -{ - VkBufferMemoryBarrier barrier = { }; - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - barrier.srcAccessMask = srcAccessMask; - barrier.dstAccessMask = dstAccessMask; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.buffer = buffer->buffer; - barrier.offset = offset; - barrier.size = size; - bufferMemoryBarriers.push_back(barrier); -} - -inline void PipelineBarrier::addImage(VulkanImage *image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) -{ - addImage(image->image, oldLayout, newLayout, srcAccessMask, dstAccessMask, aspectMask, baseMipLevel, levelCount); -} - -inline void PipelineBarrier::addImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) -{ - VkImageMemoryBarrier barrier = { }; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcAccessMask = srcAccessMask; - barrier.dstAccessMask = dstAccessMask; - barrier.oldLayout = oldLayout; - barrier.newLayout = newLayout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = image; - barrier.subresourceRange.aspectMask = aspectMask; - barrier.subresourceRange.baseMipLevel = baseMipLevel; - barrier.subresourceRange.levelCount = levelCount; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - imageMemoryBarriers.push_back(barrier); -} - -inline void PipelineBarrier::addQueueTransfer(int srcFamily, int dstFamily, VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) -{ - VkBufferMemoryBarrier barrier = { }; - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - barrier.srcAccessMask = srcAccessMask; - barrier.dstAccessMask = dstAccessMask; - barrier.srcQueueFamilyIndex = srcFamily; - barrier.dstQueueFamilyIndex = dstFamily; - barrier.buffer = buffer->buffer; - barrier.offset = 0; - barrier.size = buffer->size; - bufferMemoryBarriers.push_back(barrier); -} - -inline void PipelineBarrier::addQueueTransfer(int srcFamily, int dstFamily, VulkanImage *image, VkImageLayout layout, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) -{ - VkImageMemoryBarrier barrier = { }; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.oldLayout = layout; - barrier.newLayout = layout; - barrier.srcQueueFamilyIndex = srcFamily; - barrier.dstQueueFamilyIndex = dstFamily; - barrier.image = image->image; - barrier.subresourceRange.aspectMask = aspectMask; - barrier.subresourceRange.baseMipLevel = baseMipLevel; - barrier.subresourceRange.levelCount = levelCount; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - imageMemoryBarriers.push_back(barrier); -} - -inline void PipelineBarrier::execute(VulkanCommandBuffer *commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags) -{ - commandBuffer->pipelineBarrier( - srcStageMask, dstStageMask, dependencyFlags, - (uint32_t)memoryBarriers.size(), memoryBarriers.data(), - (uint32_t)bufferMemoryBarriers.size(), bufferMemoryBarriers.data(), - (uint32_t)imageMemoryBarriers.size(), imageMemoryBarriers.data()); -} - -///////////////////////////////////////////////////////////////////////////// - -inline QueueSubmit::QueueSubmit() -{ - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; -} - -inline void QueueSubmit::addCommandBuffer(VulkanCommandBuffer *buffer) -{ - commandBuffers.push_back(buffer->buffer); - submitInfo.pCommandBuffers = commandBuffers.data(); - submitInfo.commandBufferCount = (uint32_t)commandBuffers.size(); -} - -inline void QueueSubmit::addWait(VkPipelineStageFlags waitStageMask, VulkanSemaphore *semaphore) -{ - waitStages.push_back(waitStageMask); - waitSemaphores.push_back(semaphore->semaphore); - - submitInfo.pWaitDstStageMask = waitStages.data(); - submitInfo.pWaitSemaphores = waitSemaphores.data(); - submitInfo.waitSemaphoreCount = (uint32_t)waitSemaphores.size(); -} - -inline void QueueSubmit::addSignal(VulkanSemaphore *semaphore) -{ - signalSemaphores.push_back(semaphore->semaphore); - submitInfo.pSignalSemaphores = signalSemaphores.data(); - submitInfo.signalSemaphoreCount = (uint32_t)signalSemaphores.size(); -} - -inline void QueueSubmit::execute(VulkanDevice *device, VkQueue queue, VulkanFence *fence) -{ - VkResult result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, fence ? fence->fence : VK_NULL_HANDLE); - if (result < VK_SUCCESS) - throw std::runtime_error("Failed to submit command buffer"); -} - -///////////////////////////////////////////////////////////////////////////// - -inline void WriteDescriptors::addBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer) -{ - addBuffer(descriptorSet, binding, type, buffer, 0, buffer->size); -} - -inline void WriteDescriptors::addBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer, size_t offset, size_t range) -{ - VkDescriptorBufferInfo bufferInfo = {}; - bufferInfo.buffer = buffer->buffer; - bufferInfo.offset = offset; - bufferInfo.range = range; - - auto extra = std::make_unique(); - extra->bufferInfo = bufferInfo; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = descriptorSet->set; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = type; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = &extra->bufferInfo; - writes.push_back(descriptorWrite); - writeExtras.push_back(std::move(extra)); -} - -inline void WriteDescriptors::addStorageImage(VulkanDescriptorSet *descriptorSet, int binding, VulkanImageView *view, VkImageLayout imageLayout) -{ - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageView = view->view; - imageInfo.imageLayout = imageLayout; - - auto extra = std::make_unique(); - extra->imageInfo = imageInfo; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = descriptorSet->set; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pImageInfo = &extra->imageInfo; - writes.push_back(descriptorWrite); - writeExtras.push_back(std::move(extra)); -} - -inline void WriteDescriptors::addCombinedImageSampler(VulkanDescriptorSet *descriptorSet, int binding, VulkanImageView *view, VulkanSampler *sampler, VkImageLayout imageLayout) -{ - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageView = view->view; - imageInfo.sampler = sampler->sampler; - imageInfo.imageLayout = imageLayout; - - auto extra = std::make_unique(); - extra->imageInfo = imageInfo; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = descriptorSet->set; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pImageInfo = &extra->imageInfo; - writes.push_back(descriptorWrite); - writeExtras.push_back(std::move(extra)); -} - -inline void WriteDescriptors::addAccelerationStructure(VulkanDescriptorSet *descriptorSet, int binding, VulkanAccelerationStructure *accelStruct) -{ - auto extra = std::make_unique(); - extra->accelStruct = {}; - extra->accelStruct.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; - extra->accelStruct.accelerationStructureCount = 1; - extra->accelStruct.pAccelerationStructures = &accelStruct->accelstruct; - - VkWriteDescriptorSet descriptorWrite = {}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = descriptorSet->set; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pNext = &extra->accelStruct; - writes.push_back(descriptorWrite); - writeExtras.push_back(std::move(extra)); -} - -inline void WriteDescriptors::updateSets(VulkanDevice *device) -{ - vkUpdateDescriptorSets(device->device, (uint32_t)writes.size(), writes.data(), 0, nullptr); -} diff --git a/src/lightmap/vulkandevice.cpp b/src/lightmap/vulkandevice.cpp index 39f1cf0..9a0f0c8 100644 --- a/src/lightmap/vulkandevice.cpp +++ b/src/lightmap/vulkandevice.cpp @@ -167,7 +167,7 @@ bool VulkanDevice::supportsDeviceExtension(const char *ext) const void VulkanDevice::createAllocator() { VmaAllocatorCreateInfo allocinfo = {}; - allocinfo.vulkanApiVersion = VK_API_VERSION_1_2; + allocinfo.vulkanApiVersion = ApiVersion; if (supportsDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) && supportsDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME)) allocinfo.flags = VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; allocinfo.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; @@ -321,7 +321,7 @@ void VulkanDevice::createInstance() appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.pEngineName = "ZDRay"; appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.apiVersion = VK_API_VERSION_1_2; + appInfo.apiVersion = ApiVersion; VkInstanceCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; diff --git a/src/lightmap/vulkandevice.h b/src/lightmap/vulkandevice.h index 9d60c63..f7bfca3 100644 --- a/src/lightmap/vulkandevice.h +++ b/src/lightmap/vulkandevice.h @@ -103,6 +103,8 @@ public: std::vector availableDevices; std::vector supportedDevices; + uint32_t ApiVersion = VK_API_VERSION_1_2; + RENDERDOC_API_1_4_2* renderdoc = nullptr; static void initVolk(); diff --git a/src/lightmap/vulkanobjects.h b/src/lightmap/vulkanobjects.h index 4ba1054..fe2545a 100644 --- a/src/lightmap/vulkanobjects.h +++ b/src/lightmap/vulkanobjects.h @@ -81,7 +81,7 @@ private: class VulkanImage { public: - VulkanImage(VulkanDevice *device, VkImage image, VmaAllocation allocation, int width, int height, int mipLevels); + VulkanImage(VulkanDevice *device, VkImage image, VmaAllocation allocation, int width, int height, int mipLevels, int layerCount); ~VulkanImage(); void SetDebugName(const char *name) { device->setDebugObjectName(name, (uint64_t)image, VK_OBJECT_TYPE_IMAGE); } @@ -90,6 +90,7 @@ public: int width = 0; int height = 0; int mipLevels = 1; + int layerCount = 1; void *Map(size_t offset, size_t size); void Unmap(); @@ -1018,7 +1019,7 @@ inline VulkanFramebuffer::~VulkanFramebuffer() ///////////////////////////////////////////////////////////////////////////// -inline VulkanImage::VulkanImage(VulkanDevice *device, VkImage image, VmaAllocation allocation, int width, int height, int mipLevels) : image(image), width(width), height(height), mipLevels(mipLevels), device(device), allocation(allocation) +inline VulkanImage::VulkanImage(VulkanDevice *device, VkImage image, VmaAllocation allocation, int width, int height, int mipLevels, int layerCount) : image(image), width(width), height(height), mipLevels(mipLevels), layerCount(layerCount), device(device), allocation(allocation) { }