From e1736f573a74b3aff45c4ac04fef2998460ff350 Mon Sep 17 00:00:00 2001 From: mrq Date: Sat, 18 Jul 2020 00:00:00 -0500 Subject: [PATCH] Commit for 2020.07.18.7z --- bin/data/shaders/display.frag.glsl | 6 +- bin/data/shaders/display.vert.glsl | 4 - bin/data/shaders/{ => old}/base.frag.glsl | 0 bin/data/shaders/{ => old}/base.vert.glsl | 0 bin/data/shaders/old/display.frag.glsl | 10 + bin/data/shaders/old/display.vert.glsl | 17 + .../{ => old/dither}/base.dither16.frag.glsl | 0 .../{ => old/dither}/base.dither4.frag.glsl | 0 .../{ => old/dither}/base.dither8.frag.glsl | 0 .../{ => old/dither}/gui.dither16.frag.glsl | 0 .../{ => old/dither}/gui.dither4.frag.glsl | 0 .../{ => old/dither}/gui.dither8.frag.glsl | 0 .../dither}/gui.text.dither16.frag.glsl | 0 .../dither}/gui.text.dither4.frag.glsl | 0 .../dither}/gui.text.dither8.frag.glsl | 0 bin/data/shaders/{ => old}/gui.frag.glsl | 0 .../shaders/{ => old}/gui.gradient.frag.glsl | 0 bin/data/shaders/{ => old}/gui.text.frag.glsl | 0 bin/data/shaders/{ => old}/gui.text.vert.glsl | 0 bin/data/shaders/{ => old}/gui.vert.glsl | 0 .../shaders/{ => old}/raytracing.comp.glsl | 0 .../{ => old/stereo}/base.stereo.vert.glsl | 0 .../{ => old/stereo}/gui.stereo.vert.glsl | 0 .../stereo}/gui.text.stereo.vert.glsl | 0 .../{ => old/stereo}/terrain.stereo.vert.glsl | 0 bin/data/shaders/{ => old}/terrain.frag.glsl | 0 bin/data/shaders/{ => old}/terrain.vert.glsl | 0 bin/data/shaders/{ => old}/texture.frag.glsl | 0 bin/data/shaders/{ => old}/texture.vert.glsl | 0 engine/inc/uf/ext/vulkan/commands/base.h | 3 + engine/inc/uf/ext/vulkan/commands/deferred.h | 24 + engine/inc/uf/ext/vulkan/commands/multiview.h | 3 + .../inc/uf/ext/vulkan/graphics/framebuffer.h | 1 + engine/inc/uf/ext/vulkan/initializers.h | 2 +- engine/inc/uf/ext/vulkan/rendertarget.h | 20 +- engine/src/ext/vulkan/commands/base.cpp | 6 + engine/src/ext/vulkan/commands/deferred.cpp | 217 +++++++++ engine/src/ext/vulkan/commands/multiview.cpp | 11 +- engine/src/ext/vulkan/commands/stereo.cpp.x | 276 ----------- engine/src/ext/vulkan/device.cpp | 14 +- engine/src/ext/vulkan/graphics/base.cpp | 5 +- .../src/ext/vulkan/graphics/framebuffer.cpp | 52 +- engine/src/ext/vulkan/graphics/gui.cpp | 5 +- engine/src/ext/vulkan/graphics/mesh.cpp | 5 +- engine/src/ext/vulkan/rendertarget.cpp | 455 ++++++++---------- engine/src/ext/vulkan/vulkan.cpp | 8 +- 46 files changed, 562 insertions(+), 582 deletions(-) rename bin/data/shaders/{ => old}/base.frag.glsl (100%) rename bin/data/shaders/{ => old}/base.vert.glsl (100%) create mode 100644 bin/data/shaders/old/display.frag.glsl create mode 100644 bin/data/shaders/old/display.vert.glsl rename bin/data/shaders/{ => old/dither}/base.dither16.frag.glsl (100%) rename bin/data/shaders/{ => old/dither}/base.dither4.frag.glsl (100%) rename bin/data/shaders/{ => old/dither}/base.dither8.frag.glsl (100%) rename bin/data/shaders/{ => old/dither}/gui.dither16.frag.glsl (100%) rename bin/data/shaders/{ => old/dither}/gui.dither4.frag.glsl (100%) rename bin/data/shaders/{ => old/dither}/gui.dither8.frag.glsl (100%) rename bin/data/shaders/{ => old/dither}/gui.text.dither16.frag.glsl (100%) rename bin/data/shaders/{ => old/dither}/gui.text.dither4.frag.glsl (100%) rename bin/data/shaders/{ => old/dither}/gui.text.dither8.frag.glsl (100%) rename bin/data/shaders/{ => old}/gui.frag.glsl (100%) rename bin/data/shaders/{ => old}/gui.gradient.frag.glsl (100%) rename bin/data/shaders/{ => old}/gui.text.frag.glsl (100%) rename bin/data/shaders/{ => old}/gui.text.vert.glsl (100%) rename bin/data/shaders/{ => old}/gui.vert.glsl (100%) rename bin/data/shaders/{ => old}/raytracing.comp.glsl (100%) rename bin/data/shaders/{ => old/stereo}/base.stereo.vert.glsl (100%) rename bin/data/shaders/{ => old/stereo}/gui.stereo.vert.glsl (100%) rename bin/data/shaders/{ => old/stereo}/gui.text.stereo.vert.glsl (100%) rename bin/data/shaders/{ => old/stereo}/terrain.stereo.vert.glsl (100%) rename bin/data/shaders/{ => old}/terrain.frag.glsl (100%) rename bin/data/shaders/{ => old}/terrain.vert.glsl (100%) rename bin/data/shaders/{ => old}/texture.frag.glsl (100%) rename bin/data/shaders/{ => old}/texture.vert.glsl (100%) create mode 100644 engine/inc/uf/ext/vulkan/commands/deferred.h create mode 100644 engine/src/ext/vulkan/commands/deferred.cpp delete mode 100644 engine/src/ext/vulkan/commands/stereo.cpp.x diff --git a/bin/data/shaders/display.frag.glsl b/bin/data/shaders/display.frag.glsl index 5edd635c..ea6027b7 100644 --- a/bin/data/shaders/display.frag.glsl +++ b/bin/data/shaders/display.frag.glsl @@ -1,12 +1,10 @@ #version 450 -layout (set = 0, binding = 1) uniform texture2D tex; -layout (set = 0, binding = 2) uniform sampler samp; +layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerAlbedo; layout (location = 0) in vec2 inUv; layout (location = 0) out vec4 outFragColor; void main() { - outFragColor = texture(sampler2D(tex, samp), inUv); -// outFragColor = vec4(inUv, 1.0f, 0.0f); + outFragColor = subpassLoad(samplerAlbedo); } \ No newline at end of file diff --git a/bin/data/shaders/display.vert.glsl b/bin/data/shaders/display.vert.glsl index 9255a247..9d3a6de8 100644 --- a/bin/data/shaders/display.vert.glsl +++ b/bin/data/shaders/display.vert.glsl @@ -3,10 +3,6 @@ layout (location = 0) in vec2 inPos; layout (location = 1) in vec2 inUv; -layout (binding = 0) uniform UBO { - vec2 screenSize; -} ubo; - layout (location = 0) out vec2 outUv; out gl_PerVertex { diff --git a/bin/data/shaders/base.frag.glsl b/bin/data/shaders/old/base.frag.glsl similarity index 100% rename from bin/data/shaders/base.frag.glsl rename to bin/data/shaders/old/base.frag.glsl diff --git a/bin/data/shaders/base.vert.glsl b/bin/data/shaders/old/base.vert.glsl similarity index 100% rename from bin/data/shaders/base.vert.glsl rename to bin/data/shaders/old/base.vert.glsl diff --git a/bin/data/shaders/old/display.frag.glsl b/bin/data/shaders/old/display.frag.glsl new file mode 100644 index 00000000..ea6027b7 --- /dev/null +++ b/bin/data/shaders/old/display.frag.glsl @@ -0,0 +1,10 @@ +#version 450 + +layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerAlbedo; + +layout (location = 0) in vec2 inUv; +layout (location = 0) out vec4 outFragColor; + +void main() { + outFragColor = subpassLoad(samplerAlbedo); +} \ No newline at end of file diff --git a/bin/data/shaders/old/display.vert.glsl b/bin/data/shaders/old/display.vert.glsl new file mode 100644 index 00000000..9d3a6de8 --- /dev/null +++ b/bin/data/shaders/old/display.vert.glsl @@ -0,0 +1,17 @@ +#version 450 + +layout (location = 0) in vec2 inPos; +layout (location = 1) in vec2 inUv; + +layout (location = 0) out vec2 outUv; + +out gl_PerVertex { + vec4 gl_Position; +}; + + +void main() { + outUv = inUv; + + gl_Position = vec4(inPos.xy, 0.0, 1.0); +} \ No newline at end of file diff --git a/bin/data/shaders/base.dither16.frag.glsl b/bin/data/shaders/old/dither/base.dither16.frag.glsl similarity index 100% rename from bin/data/shaders/base.dither16.frag.glsl rename to bin/data/shaders/old/dither/base.dither16.frag.glsl diff --git a/bin/data/shaders/base.dither4.frag.glsl b/bin/data/shaders/old/dither/base.dither4.frag.glsl similarity index 100% rename from bin/data/shaders/base.dither4.frag.glsl rename to bin/data/shaders/old/dither/base.dither4.frag.glsl diff --git a/bin/data/shaders/base.dither8.frag.glsl b/bin/data/shaders/old/dither/base.dither8.frag.glsl similarity index 100% rename from bin/data/shaders/base.dither8.frag.glsl rename to bin/data/shaders/old/dither/base.dither8.frag.glsl diff --git a/bin/data/shaders/gui.dither16.frag.glsl b/bin/data/shaders/old/dither/gui.dither16.frag.glsl similarity index 100% rename from bin/data/shaders/gui.dither16.frag.glsl rename to bin/data/shaders/old/dither/gui.dither16.frag.glsl diff --git a/bin/data/shaders/gui.dither4.frag.glsl b/bin/data/shaders/old/dither/gui.dither4.frag.glsl similarity index 100% rename from bin/data/shaders/gui.dither4.frag.glsl rename to bin/data/shaders/old/dither/gui.dither4.frag.glsl diff --git a/bin/data/shaders/gui.dither8.frag.glsl b/bin/data/shaders/old/dither/gui.dither8.frag.glsl similarity index 100% rename from bin/data/shaders/gui.dither8.frag.glsl rename to bin/data/shaders/old/dither/gui.dither8.frag.glsl diff --git a/bin/data/shaders/gui.text.dither16.frag.glsl b/bin/data/shaders/old/dither/gui.text.dither16.frag.glsl similarity index 100% rename from bin/data/shaders/gui.text.dither16.frag.glsl rename to bin/data/shaders/old/dither/gui.text.dither16.frag.glsl diff --git a/bin/data/shaders/gui.text.dither4.frag.glsl b/bin/data/shaders/old/dither/gui.text.dither4.frag.glsl similarity index 100% rename from bin/data/shaders/gui.text.dither4.frag.glsl rename to bin/data/shaders/old/dither/gui.text.dither4.frag.glsl diff --git a/bin/data/shaders/gui.text.dither8.frag.glsl b/bin/data/shaders/old/dither/gui.text.dither8.frag.glsl similarity index 100% rename from bin/data/shaders/gui.text.dither8.frag.glsl rename to bin/data/shaders/old/dither/gui.text.dither8.frag.glsl diff --git a/bin/data/shaders/gui.frag.glsl b/bin/data/shaders/old/gui.frag.glsl similarity index 100% rename from bin/data/shaders/gui.frag.glsl rename to bin/data/shaders/old/gui.frag.glsl diff --git a/bin/data/shaders/gui.gradient.frag.glsl b/bin/data/shaders/old/gui.gradient.frag.glsl similarity index 100% rename from bin/data/shaders/gui.gradient.frag.glsl rename to bin/data/shaders/old/gui.gradient.frag.glsl diff --git a/bin/data/shaders/gui.text.frag.glsl b/bin/data/shaders/old/gui.text.frag.glsl similarity index 100% rename from bin/data/shaders/gui.text.frag.glsl rename to bin/data/shaders/old/gui.text.frag.glsl diff --git a/bin/data/shaders/gui.text.vert.glsl b/bin/data/shaders/old/gui.text.vert.glsl similarity index 100% rename from bin/data/shaders/gui.text.vert.glsl rename to bin/data/shaders/old/gui.text.vert.glsl diff --git a/bin/data/shaders/gui.vert.glsl b/bin/data/shaders/old/gui.vert.glsl similarity index 100% rename from bin/data/shaders/gui.vert.glsl rename to bin/data/shaders/old/gui.vert.glsl diff --git a/bin/data/shaders/raytracing.comp.glsl b/bin/data/shaders/old/raytracing.comp.glsl similarity index 100% rename from bin/data/shaders/raytracing.comp.glsl rename to bin/data/shaders/old/raytracing.comp.glsl diff --git a/bin/data/shaders/base.stereo.vert.glsl b/bin/data/shaders/old/stereo/base.stereo.vert.glsl similarity index 100% rename from bin/data/shaders/base.stereo.vert.glsl rename to bin/data/shaders/old/stereo/base.stereo.vert.glsl diff --git a/bin/data/shaders/gui.stereo.vert.glsl b/bin/data/shaders/old/stereo/gui.stereo.vert.glsl similarity index 100% rename from bin/data/shaders/gui.stereo.vert.glsl rename to bin/data/shaders/old/stereo/gui.stereo.vert.glsl diff --git a/bin/data/shaders/gui.text.stereo.vert.glsl b/bin/data/shaders/old/stereo/gui.text.stereo.vert.glsl similarity index 100% rename from bin/data/shaders/gui.text.stereo.vert.glsl rename to bin/data/shaders/old/stereo/gui.text.stereo.vert.glsl diff --git a/bin/data/shaders/terrain.stereo.vert.glsl b/bin/data/shaders/old/stereo/terrain.stereo.vert.glsl similarity index 100% rename from bin/data/shaders/terrain.stereo.vert.glsl rename to bin/data/shaders/old/stereo/terrain.stereo.vert.glsl diff --git a/bin/data/shaders/terrain.frag.glsl b/bin/data/shaders/old/terrain.frag.glsl similarity index 100% rename from bin/data/shaders/terrain.frag.glsl rename to bin/data/shaders/old/terrain.frag.glsl diff --git a/bin/data/shaders/terrain.vert.glsl b/bin/data/shaders/old/terrain.vert.glsl similarity index 100% rename from bin/data/shaders/terrain.vert.glsl rename to bin/data/shaders/old/terrain.vert.glsl diff --git a/bin/data/shaders/texture.frag.glsl b/bin/data/shaders/old/texture.frag.glsl similarity index 100% rename from bin/data/shaders/texture.frag.glsl rename to bin/data/shaders/old/texture.frag.glsl diff --git a/bin/data/shaders/texture.vert.glsl b/bin/data/shaders/old/texture.vert.glsl similarity index 100% rename from bin/data/shaders/texture.vert.glsl rename to bin/data/shaders/old/texture.vert.glsl diff --git a/engine/inc/uf/ext/vulkan/commands/base.h b/engine/inc/uf/ext/vulkan/commands/base.h index f81d2d8a..3ce392aa 100644 --- a/engine/inc/uf/ext/vulkan/commands/base.h +++ b/engine/inc/uf/ext/vulkan/commands/base.h @@ -8,11 +8,14 @@ namespace ext { uint32_t width, height; // RAII virtual const std::string& getName() const; + virtual size_t subpasses() const; + virtual void initialize( Device& device ); virtual void createCommandBuffers(); virtual void createCommandBuffers( const std::vector& graphics, const std::vector& passes ); virtual void render(); virtual void destroy(); + virtual VkRenderPass& getRenderPass(); }; } } \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/commands/deferred.h b/engine/inc/uf/ext/vulkan/commands/deferred.h new file mode 100644 index 00000000..0909c30f --- /dev/null +++ b/engine/inc/uf/ext/vulkan/commands/deferred.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include + +namespace ext { + namespace vulkan { + struct UF_API DeferredCommand : public ext::vulkan::Command { + ext::vulkan::RenderTarget framebuffer; + ext::vulkan::FramebufferGraphic blitter; + + // RAII + virtual const std::string& getName() const; + virtual size_t subpasses() const; + + virtual void createCommandBuffers( const std::vector& graphics, const std::vector& passes ); + virtual void render(); + virtual void initialize( Device& device ); + virtual void destroy(); + virtual VkRenderPass& getRenderPass(); + }; + } +} \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/commands/multiview.h b/engine/inc/uf/ext/vulkan/commands/multiview.h index 1de5ad7c..3253c7d5 100644 --- a/engine/inc/uf/ext/vulkan/commands/multiview.h +++ b/engine/inc/uf/ext/vulkan/commands/multiview.h @@ -15,10 +15,13 @@ namespace ext { // RAII virtual const std::string& getName() const; + virtual size_t subpasses() const; + virtual void createCommandBuffers( const std::vector& graphics, const std::vector& passes ); virtual void render(); virtual void initialize( Device& device ); virtual void destroy(); + virtual VkRenderPass& getRenderPass(); }; } } \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/graphics/framebuffer.h b/engine/inc/uf/ext/vulkan/graphics/framebuffer.h index 9d75e451..ae01581a 100644 --- a/engine/inc/uf/ext/vulkan/graphics/framebuffer.h +++ b/engine/inc/uf/ext/vulkan/graphics/framebuffer.h @@ -22,6 +22,7 @@ namespace ext { } uniforms; uint32_t indices = 0; + VkSampler sampler; ext::vulkan::RenderTarget* framebuffer; virtual void createCommandBuffer( VkCommandBuffer ); diff --git a/engine/inc/uf/ext/vulkan/initializers.h b/engine/inc/uf/ext/vulkan/initializers.h index 7cfbfdb4..d80b6faf 100644 --- a/engine/inc/uf/ext/vulkan/initializers.h +++ b/engine/inc/uf/ext/vulkan/initializers.h @@ -283,7 +283,7 @@ namespace ext { return descriptorSetAllocateInfo; } - inline VkDescriptorImageInfo descriptorImageInfo(VkSampler sampler, VkImageView imageView, VkImageLayout imageLayout) + inline VkDescriptorImageInfo descriptorImageInfo(VkImageView imageView, VkImageLayout imageLayout, VkSampler sampler = VK_NULL_HANDLE) { VkDescriptorImageInfo descriptorImageInfo {}; descriptorImageInfo.sampler = sampler; diff --git a/engine/inc/uf/ext/vulkan/rendertarget.h b/engine/inc/uf/ext/vulkan/rendertarget.h index 46680857..d65e0e90 100644 --- a/engine/inc/uf/ext/vulkan/rendertarget.h +++ b/engine/inc/uf/ext/vulkan/rendertarget.h @@ -6,22 +6,34 @@ namespace ext { namespace vulkan { struct UF_API RenderTarget { typedef struct { - VkImage image; + VkFormat format; VkImageLayout layout; + VkImageUsageFlags usage; + VkImage image; VkDeviceMemory mem; VkImageView view; } Attachment; std::vector attachments; + typedef struct { + VkPipelineStageFlags stage; + VkAccessFlags access; + + std::vector colors; + std::vector inputs; + VkAttachmentReference depth; + } Subpass; + std::vector passes; + Device* device = nullptr; - VkSampler sampler; - VkDescriptorImageInfo descriptorImageInfo; VkRenderPass renderPass; - VkFramebuffer framebuffer; + std::vector framebuffers; bool commandBufferSet; // RAII void initialize( Device& device ); void destroy(); + void addPass( VkPipelineStageFlags, VkAccessFlags, const std::vector&, const std::vector&, size_t ); + size_t attach( VkFormat format, VkImageUsageFlags usage, Attachment* attachment = NULL ); }; } } \ No newline at end of file diff --git a/engine/src/ext/vulkan/commands/base.cpp b/engine/src/ext/vulkan/commands/base.cpp index 3531dd33..72b400f5 100644 --- a/engine/src/ext/vulkan/commands/base.cpp +++ b/engine/src/ext/vulkan/commands/base.cpp @@ -8,6 +8,12 @@ const std::string& ext::vulkan::Command::getName() const { return "Base"; } +size_t ext::vulkan::Command::subpasses() const { + return 1; +} +VkRenderPass& ext::vulkan::Command::getRenderPass() { + return swapchain.renderPass; +} void ext::vulkan::Command::createCommandBuffers() { std::vector graphics; diff --git a/engine/src/ext/vulkan/commands/deferred.cpp b/engine/src/ext/vulkan/commands/deferred.cpp new file mode 100644 index 00000000..7ae1a457 --- /dev/null +++ b/engine/src/ext/vulkan/commands/deferred.cpp @@ -0,0 +1,217 @@ +#include +#include +#include +#include +#include + +namespace { + // 0 left 1 right + uint8_t DOMINANT_EYE = 1; +} + +const std::string& ext::vulkan::DeferredCommand::getName() const { + return "Defered"; +} +size_t ext::vulkan::DeferredCommand::subpasses() const { + return framebuffer.passes.size(); +} +VkRenderPass& ext::vulkan::DeferredCommand::getRenderPass() { + return framebuffer.renderPass; +} + +void ext::vulkan::DeferredCommand::initialize( Device& device ) { + { + framebuffer.device = &device; + // attach targets + struct { + size_t albedo, normals, depth, output; + } attachments; + + attachments.albedo = framebuffer.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ); // albedo + attachments.normals = framebuffer.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ); // normals + attachments.depth = framebuffer.attach( swapchain.depthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ); // depth + // Attach swapchain's image as output + { + attachments.output = framebuffer.attachments.size(); + framebuffer.attachments.push_back({ swapchain.colorFormat, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, }); + } + + // First pass: fill the G-Buffer + { + framebuffer.addPass( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + { attachments.albedo, attachments.normals, }, + {}, + attachments.depth + ); + } + // Second pass: write to output + { + framebuffer.addPass( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT, + { attachments.output, }, + { attachments.albedo, attachments.normals }, + attachments.depth + ); + } + } + + framebuffer.initialize( device ); + + blitter.framebuffer = &framebuffer; + blitter.initializeShaders({ + {"./data/shaders/display.vert.spv", VK_SHADER_STAGE_VERTEX_BIT}, + {"./data/shaders/display.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} + }); + blitter.initialize( device, ext::vulkan::swapchain ); +} +void ext::vulkan::DeferredCommand::destroy() { + framebuffer.destroy(); +} +void ext::vulkan::DeferredCommand::createCommandBuffers( const std::vector& graphics, const std::vector& passes ) { + // destroy if exists + if ( swapchain.rebuild ) { + if ( swapchain.commandBufferSet ) { + auto* device = swapchain.device; + bool vsync = swapchain.vsync; + swapchain.destroy(); + swapchain.initialize( *device, 0, 0, vsync ); + } + swapchain.commandBufferSet = true; + + // destroy if exist + if ( framebuffer.commandBufferSet ) { + auto* device = framebuffer.device; + framebuffer.initialize( *device ); + } + framebuffer.commandBufferSet = true; + + // update descriptor set + if ( blitter.initialized ) { + VkDescriptorImageInfo textDescriptorAlbedo = ext::vulkan::initializers::descriptorImageInfo( + framebuffer.attachments[0].view, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + ); + std::vector writeDescriptorSets = { + // Binding 0 : Projection/View matrix uniform buffer + ext::vulkan::initializers::writeDescriptorSet( + blitter.descriptorSet, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + 0, + &(blitter.buffers.at(0).descriptor) + ), + // Binding 1 : Albedo input attachment + ext::vulkan::initializers::writeDescriptorSet( + blitter.descriptorSet, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + 1, + &textDescriptorAlbedo + ), + }; + vkUpdateDescriptorSets( device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr ); + } + } + + float width = this->width > 0 ? this->width : ext::vulkan::width; + float height = this->height > 0 ? this->height : ext::vulkan::height; + blitter.uniforms.screenSize = { width, height }; + + VkCommandBufferBeginInfo cmdBufInfo = {}; + cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + cmdBufInfo.pNext = nullptr; + + for (int32_t i = 0; i < swapchain.drawCommandBuffers.size(); ++i) { + + VK_CHECK_RESULT(vkBeginCommandBuffer(swapchain.drawCommandBuffers[i], &cmdBufInfo)); + // Fill GBuffer + { + std::vector clearValues; clearValues.resize(4); + clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; + clearValues[1].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; + clearValues[2].depthStencil = { 1.0f, 0 }; + clearValues[3].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; + + VkRenderPassBeginInfo renderPassBeginInfo = {}; + renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + renderPassBeginInfo.pNext = nullptr; + renderPassBeginInfo.renderArea.offset.x = 0; + renderPassBeginInfo.renderArea.offset.y = 0; + renderPassBeginInfo.renderArea.extent.width = width; + renderPassBeginInfo.renderArea.extent.height = height; + renderPassBeginInfo.clearValueCount = clearValues.size(); + renderPassBeginInfo.pClearValues = &clearValues[0]; + renderPassBeginInfo.renderPass = framebuffer.renderPass; + renderPassBeginInfo.framebuffer = framebuffer.framebuffers[i]; + + for ( auto& pGraphic : graphics ) { + Graphic& graphic = *((Graphic*) pGraphic); + graphic.createImageMemoryBarrier(swapchain.drawCommandBuffers[i]); + } + + // Update dynamic viewport state + VkViewport viewport = {}; + viewport.width = (float) width; + viewport.height = (float) height; + viewport.minDepth = (float) 0.0f; + viewport.maxDepth = (float) 1.0f; + + // Update dynamic scissor state + VkRect2D scissor = {}; + scissor.extent.width = width; + scissor.extent.height = height; + scissor.offset.x = 0; + scissor.offset.y = 0; + + vkCmdBeginRenderPass(swapchain.drawCommandBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdSetViewport(swapchain.drawCommandBuffers[i], 0, 1, &viewport); + vkCmdSetScissor(swapchain.drawCommandBuffers[i], 0, 1, &scissor); + for ( auto pass : passes ) { + ext::vulkan::currentPass = pass + ";DEFERRED"; + for ( auto& pGraphic : graphics ) { + Graphic& graphic = *((Graphic*) pGraphic); + graphic.createCommandBuffer(swapchain.drawCommandBuffers[i] ); + } + } + vkCmdNextSubpass(swapchain.drawCommandBuffers[i], VK_SUBPASS_CONTENTS_INLINE); + blitter.createCommandBuffer(swapchain.drawCommandBuffers[i]); + vkCmdEndRenderPass(swapchain.drawCommandBuffers[i]); + } + + VK_CHECK_RESULT(vkEndCommandBuffer(swapchain.drawCommandBuffers[i])); + } +} + +void ext::vulkan::DeferredCommand::render() { + //auto& device = ext::vulkan::device; + //auto& swapchain = ext::vulkan::swapchain; + //auto& currentBuffer = ext::vulkan::currentBuffer; + + // Get next image in the swap chain (back/front buffer) + VK_CHECK_RESULT(swapchain.acquireNextImage(¤tBuffer)); + + // Use a fence to wait until the command buffer has finished execution before using it again + VK_CHECK_RESULT(vkWaitForFences(device, 1, &swapchain.waitFences[currentBuffer], VK_TRUE, UINT64_MAX)); + VK_CHECK_RESULT(vkResetFences(device, 1, &swapchain.waitFences[currentBuffer])); + + // Pipeline stage at which the queue submission will wait (via pWaitSemaphores) + VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + // The submit info structure specifices a command buffer queue submission batch + VkSubmitInfo submitInfo = {}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.pWaitDstStageMask = &waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at + submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing + submitInfo.waitSemaphoreCount = 1; // One wait semaphore + submitInfo.pSignalSemaphores = &swapchain.renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed + submitInfo.signalSemaphoreCount = 1; // One signal semaphore + submitInfo.pCommandBuffers = &swapchain.drawCommandBuffers[currentBuffer]; // Command buffers(s) to execute in this batch (submission) + submitInfo.commandBufferCount = 1; + + // Submit to the graphics queue passing a wait fence + VK_CHECK_RESULT(vkQueueSubmit(device.graphicsQueue, 1, &submitInfo, swapchain.waitFences[currentBuffer])); + + // Present the current buffer to the swap chain + // Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation + // This ensures that the image is not presented to the windowing system until all commands have been submitted + VK_CHECK_RESULT(swapchain.queuePresent(device.presentQueue, currentBuffer, swapchain.renderCompleteSemaphore)); + VK_CHECK_RESULT(vkQueueWaitIdle(device.presentQueue)); +} \ No newline at end of file diff --git a/engine/src/ext/vulkan/commands/multiview.cpp b/engine/src/ext/vulkan/commands/multiview.cpp index 80a908f7..b4a31a6f 100644 --- a/engine/src/ext/vulkan/commands/multiview.cpp +++ b/engine/src/ext/vulkan/commands/multiview.cpp @@ -13,6 +13,13 @@ namespace { const std::string& ext::vulkan::MultiviewCommand::getName() const { return "Multiview"; } +size_t ext::vulkan::MultiviewCommand::subpasses() const { + return framebuffers.left.passes.size(); +} +VkRenderPass& ext::vulkan::MultiviewCommand::getRenderPass() { + return framebuffers.left.renderPass; +} + void ext::vulkan::MultiviewCommand::initialize( Device& device ) { framebuffers.left.initialize( device ); framebuffers.right.initialize( device ); @@ -135,7 +142,7 @@ void ext::vulkan::MultiviewCommand::createCommandBuffers( const std::vector -#include -#include -#include -#include - -namespace { - uf::GuiMesh mesh; -} -const std::string& ext::vulkan::MultiviewCommand::getName() const { - return "Multiview"; -} -void ext::vulkan::MultiviewCommand::initialize( Device& device ) { - framebuffers.left.initialize( device ); - framebuffers.right.initialize( device ); -/* - mesh.vertices = { - { {-1.0f, 1.0f}, {0.0f, 0.0f}, }, - { {-1.0f, -1.0f}, {0.0f, 1.0f}, }, - { {1.0f, -1.0f}, {1.0f, 1.0f}, }, - - { {-1.0f, 1.0f}, {0.0f, 0.0f}, }, - { {1.0f, -1.0f}, {1.0f, 1.0f}, }, - { {1.0f, 1.0f}, {1.0f, 0.0f}, } - }; - mesh.initialize(true); -*/ -} -void ext::vulkan::MultiviewCommand::destroy() { - framebuffers.left.destroy(); - framebuffers.right.destroy(); -} -void ext::vulkan::MultiviewCommand::createCommandBuffers( const std::vector& graphics, const std::vector& passes ) { - //auto& device = ext::vulkan::device; - //auto& swapchain = ext::vulkan::swapchain; - //auto& currentBuffer = ext::vulkan::currentBuffer; - - // destroy if exists - if ( swapchain.commandBufferSet ) { - auto* device = swapchain.device; - bool vsync = swapchain.vsync; - swapchain.destroy(); - swapchain.initialize( *device, 0, 0, vsync ); - } - swapchain.commandBufferSet = true; - - // destroy if exist - if ( framebuffers.left.commandBufferSet ) { - auto* device = framebuffers.left.device; - framebuffers.left.initialize( *device ); - } - framebuffers.left.commandBufferSet = true; - // destroy if exist - if ( framebuffers.right.commandBufferSet ) { - auto* device = framebuffers.right.device; - framebuffers.right.initialize( *device ); - } - framebuffers.right.commandBufferSet = true; - - VkCommandBufferBeginInfo cmdBufInfo = {}; - cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cmdBufInfo.pNext = nullptr; - - // Set clear values for all framebuffer attachments with loadOp set to clear - // We use two attachments (color and depth) that are cleared at the start of the subpass and as such we need to set clear values for both - VkClearValue clearValues[2]; - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; - - VkRenderPassBeginInfo renderPassBeginInfo = {}; - renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassBeginInfo.pNext = nullptr; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = height; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - for (int32_t i = 0; i < swapchain.drawCommandBuffers.size(); ++i) { - // Set target frame buffer - - VK_CHECK_RESULT(vkBeginCommandBuffer(swapchain.drawCommandBuffers[i], &cmdBufInfo)); - - for ( auto& pGraphic : graphics ) { - Graphic& graphic = *((Graphic*) pGraphic); - graphic.createImageMemoryBarrier(swapchain.drawCommandBuffers[i]); - } - - // Update dynamic viewport state - VkViewport viewport = {}; - viewport.height = (float)height; - viewport.width = (float)width; - viewport.minDepth = (float) 0.0f; - viewport.maxDepth = (float) 1.0f; - // Update dynamic scissor state - VkRect2D scissor = {}; - scissor.extent.width = width; - scissor.extent.height = height; - scissor.offset.x = 0; - scissor.offset.y = 0; - - VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; - imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imageMemoryBarrier.oldLayout = framebuffers.left.targets[0].layout; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - imageMemoryBarrier.image = framebuffers.left.targets[0].image; - imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageMemoryBarrier.subresourceRange.baseMipLevel = 0; - imageMemoryBarrier.subresourceRange.levelCount = 1; - imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; - imageMemoryBarrier.subresourceRange.layerCount = 1; - imageMemoryBarrier.srcQueueFamilyIndex = ext::vulkan::device.queueFamilyIndices.graphics; - imageMemoryBarrier.dstQueueFamilyIndex = ext::vulkan::device.queueFamilyIndices.graphics; - vkCmdPipelineBarrier( swapchain.drawCommandBuffers[i], VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); - framebuffers.left.targets[0].layout = imageMemoryBarrier.newLayout; - - // Transition the depth buffer to VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL on first use - if ( framebuffers.left.targets[1].layout == VK_IMAGE_LAYOUT_UNDEFINED ) { - imageMemoryBarrier.image = framebuffers.left.targets[1].image; - imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - imageMemoryBarrier.srcAccessMask = 0; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - imageMemoryBarrier.oldLayout = framebuffers.left.targets[1].layout; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - vkCmdPipelineBarrier( swapchain.drawCommandBuffers[i], VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); - framebuffers.left.targets[1].layout = imageMemoryBarrier.newLayout; - } - - // Start the first sub pass specified in our default render pass setup by the base class - // This will clear the color and depth attachment - renderPassBeginInfo.renderPass = framebuffers.left.renderPass; - renderPassBeginInfo.framebuffer = framebuffers.left.framebuffer; - vkCmdBeginRenderPass(swapchain.drawCommandBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(swapchain.drawCommandBuffers[i], 0, 1, &viewport); - vkCmdSetScissor(swapchain.drawCommandBuffers[i], 0, 1, &scissor); - for ( auto pass : passes ) { - ext::vulkan::currentPass = pass + ";STEREO_LEFT"; - for ( auto& pGraphic : graphics ) { - Graphic& graphic = *((Graphic*) pGraphic); - graphic.createCommandBuffer(swapchain.drawCommandBuffers[i] ); - } - } - vkCmdEndRenderPass(swapchain.drawCommandBuffers[i]); - - { - // Transition eye image to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL for display on the companion window - imageMemoryBarrier.image = framebuffers.left.targets[0].image; - imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.oldLayout = framebuffers.left.targets[0].layout; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vkCmdPipelineBarrier( swapchain.drawCommandBuffers[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); - framebuffers.left.targets[0].layout = imageMemoryBarrier.newLayout; - } - - imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imageMemoryBarrier.oldLayout = framebuffers.right.targets[0].layout; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - imageMemoryBarrier.image = framebuffers.right.targets[0].image; - imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageMemoryBarrier.subresourceRange.baseMipLevel = 0; - imageMemoryBarrier.subresourceRange.levelCount = 1; - imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; - imageMemoryBarrier.subresourceRange.layerCount = 1; - imageMemoryBarrier.srcQueueFamilyIndex = ext::vulkan::device.queueFamilyIndices.graphics; - imageMemoryBarrier.dstQueueFamilyIndex = ext::vulkan::device.queueFamilyIndices.graphics; - vkCmdPipelineBarrier( swapchain.drawCommandBuffers[i], VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); - framebuffers.right.targets[0].layout = imageMemoryBarrier.newLayout; - - // Transition the depth buffer to VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL on first use - if ( framebuffers.right.targets[1].layout == VK_IMAGE_LAYOUT_UNDEFINED ) { - imageMemoryBarrier.image = framebuffers.right.targets[1].image; - imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - imageMemoryBarrier.srcAccessMask = 0; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - imageMemoryBarrier.oldLayout = framebuffers.right.targets[1].layout; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - vkCmdPipelineBarrier( swapchain.drawCommandBuffers[i], VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); - framebuffers.right.targets[1].layout = imageMemoryBarrier.newLayout; - } - - renderPassBeginInfo.renderPass = framebuffers.right.renderPass; - renderPassBeginInfo.framebuffer = framebuffers.right.framebuffer; - vkCmdBeginRenderPass(swapchain.drawCommandBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(swapchain.drawCommandBuffers[i], 0, 1, &viewport); - vkCmdSetScissor(swapchain.drawCommandBuffers[i], 0, 1, &scissor); - for ( auto pass : passes ) { - ext::vulkan::currentPass = pass + ";STEREO_RIGHT"; - for ( auto& pGraphic : graphics ) { - Graphic& graphic = *((Graphic*) pGraphic); - // graphic.createCommandBuffer(swapchain.drawCommandBuffers[i] ); - } - } - vkCmdEndRenderPass(swapchain.drawCommandBuffers[i]); - - { - // Transition eye image to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL for display on the companion window - imageMemoryBarrier.image = framebuffers.right.targets[0].image; - imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.oldLayout = framebuffers.right.targets[0].layout; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vkCmdPipelineBarrier( swapchain.drawCommandBuffers[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); - framebuffers.right.targets[0].layout = imageMemoryBarrier.newLayout; - } - - imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - imageMemoryBarrier.image = swapchain.buffers[i].image; - imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageMemoryBarrier.subresourceRange.baseMipLevel = 0; - imageMemoryBarrier.subresourceRange.levelCount = 1; - imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; - imageMemoryBarrier.subresourceRange.layerCount = 1; - imageMemoryBarrier.srcQueueFamilyIndex = ext::vulkan::device.queueFamilyIndices.graphics; - imageMemoryBarrier.dstQueueFamilyIndex = ext::vulkan::device.queueFamilyIndices.graphics; - vkCmdPipelineBarrier( swapchain.drawCommandBuffers[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); - - renderPassBeginInfo.renderPass = swapchain.renderPass; - renderPassBeginInfo.framebuffer = swapchain.frameBuffers[i]; - vkCmdBeginRenderPass(swapchain.drawCommandBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(swapchain.drawCommandBuffers[i], 0, 1, &viewport); - vkCmdSetScissor(swapchain.drawCommandBuffers[i], 0, 1, &scissor); - - // ::mesh.graphic.createCommandBuffer(swapchain.drawCommandBuffers[i]); - - - vkCmdEndRenderPass(swapchain.drawCommandBuffers[i]); - - // Ending the render pass will add an implicit barrier transitioning the frame buffer color attachment to - // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR for presenting it to the windowing system - - VK_CHECK_RESULT(vkEndCommandBuffer(swapchain.drawCommandBuffers[i])); - } -} - -void ext::vulkan::MultiviewCommand::render() { - //auto& device = ext::vulkan::device; - //auto& swapchain = ext::vulkan::swapchain; - //auto& currentBuffer = ext::vulkan::currentBuffer; - - // Get next image in the swap chain (back/front buffer) - VK_CHECK_RESULT(swapchain.acquireNextImage(¤tBuffer)); - - // Use a fence to wait until the command buffer has finished execution before using it again - VK_CHECK_RESULT(vkWaitForFences(device, 1, &swapchain.waitFences[currentBuffer], VK_TRUE, UINT64_MAX)); - VK_CHECK_RESULT(vkResetFences(device, 1, &swapchain.waitFences[currentBuffer])); - - // Pipeline stage at which the queue submission will wait (via pWaitSemaphores) - VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - // The submit info structure specifices a command buffer queue submission batch - VkSubmitInfo submitInfo = {}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.pWaitDstStageMask = &waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at - submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing - submitInfo.waitSemaphoreCount = 1; // One wait semaphore - submitInfo.pSignalSemaphores = &swapchain.renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed - submitInfo.signalSemaphoreCount = 1; // One signal semaphore - submitInfo.pCommandBuffers = &swapchain.drawCommandBuffers[currentBuffer]; // Command buffers(s) to execute in this batch (submission) - submitInfo.commandBufferCount = 1; - - // Submit to the graphics queue passing a wait fence - VK_CHECK_RESULT(vkQueueSubmit(device.graphicsQueue, 1, &submitInfo, swapchain.waitFences[currentBuffer])); - - // Present the current buffer to the swap chain - // Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation - // This ensures that the image is not presented to the windowing system until all commands have been submitted - VK_CHECK_RESULT(swapchain.queuePresent(device.presentQueue, currentBuffer, swapchain.renderCompleteSemaphore)); - VK_CHECK_RESULT(vkQueueWaitIdle(device.presentQueue)); -} \ No newline at end of file diff --git a/engine/src/ext/vulkan/device.cpp b/engine/src/ext/vulkan/device.cpp index ddf15789..6b8de079 100644 --- a/engine/src/ext/vulkan/device.cpp +++ b/engine/src/ext/vulkan/device.cpp @@ -229,7 +229,7 @@ VkResult ext::vulkan::Device::createBuffer( return buffer.bind(); } -void ext::vulkan::Device::initialize() { +void ext::vulkan::Device::initialize() { const std::vector validationLayers = { "VK_LAYER_LUNARG_standard_validation" }; @@ -288,12 +288,11 @@ void ext::vulkan::Device::initialize() { break; } } - // if ( !found ) dprintf( "Vulkan missing requested extension '%s'.\n", extensions[ nExt ] ); + if ( !found ) std::cout << "Vulkan missing requested extension " << extensions[index] << std::endl; } } } - - for ( auto ext : supportedExtensions ) std::cout << "Extension: " << ext << std::endl; + // for ( auto ext : supportedExtensions ) std::cout << "Extension: " << ext << std::endl; // Create instance { @@ -408,13 +407,8 @@ void ext::vulkan::Device::initialize() { deviceExtensions.push_back(extensionProperties[index].extensionName); } } - // if ( !found ) dprintf( "Vulkan missing requested extension '%s'.\n", extensions[ nExt ] ); + if ( !found ) std::cout << "Vulkan missing requested extension " << extensions[index] << std::endl; } - /* - for ( auto ext : deviceExtensions ) { - std::cout << "Device Extension: " << ext << std::endl; - } - */ } } diff --git a/engine/src/ext/vulkan/graphics/base.cpp b/engine/src/ext/vulkan/graphics/base.cpp index 161160c4..e04bd524 100644 --- a/engine/src/ext/vulkan/graphics/base.cpp +++ b/engine/src/ext/vulkan/graphics/base.cpp @@ -201,7 +201,7 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, Swapchain& swapchain VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo( pipelineLayout, - swapchain.renderPass, + ext::vulkan::command ? ext::vulkan::command->getRenderPass() : swapchain.renderPass, 0 ); pipelineCreateInfo.pVertexInputState = &vertexInputState; @@ -214,6 +214,7 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, Swapchain& swapchain pipelineCreateInfo.pDynamicState = &dynamicState; pipelineCreateInfo.stageCount = static_cast(shader.stages.size()); pipelineCreateInfo.pStages = shader.stages.data(); + pipelineCreateInfo.subpass = 0; initializePipeline(pipelineCreateInfo); } @@ -221,7 +222,7 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, Swapchain& swapchain initializeDescriptorPool({ ext::vulkan::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), ext::vulkan::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }, 2); + }, 1); // Set descriptor set initializeDescriptorSet({ // Binding 0 : Projection/View matrix uniform buffer diff --git a/engine/src/ext/vulkan/graphics/framebuffer.cpp b/engine/src/ext/vulkan/graphics/framebuffer.cpp index 0093ed41..cf3d8c45 100644 --- a/engine/src/ext/vulkan/graphics/framebuffer.cpp +++ b/engine/src/ext/vulkan/graphics/framebuffer.cpp @@ -35,6 +35,8 @@ void ext::vulkan::FramebufferGraphic::createCommandBuffer( VkCommandBuffer comma void ext::vulkan::FramebufferGraphic::initialize( Device& device, Swapchain& swapchain ) { this->device = &device; + texture.loadFromFile( "./data/textures/texture.png", ext::vulkan::device, ext::vulkan::device.graphicsQueue ); + std::vector vertices = { { {-1.0f, 1.0f}, {0.0f, 0.0f}, }, @@ -86,16 +88,36 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, Swapchain& swa ), // Fragment shader ext::vulkan::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT, 1 ), + /* ext::vulkan::initializers::descriptorSetLayoutBinding( VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2 ), + */ }); + // Create sampler +/* + { + VkSamplerCreateInfo samplerInfo = {}; + samplerInfo.magFilter = VK_FILTER_NEAREST; + samplerInfo.minFilter = VK_FILTER_NEAREST; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeV = samplerInfo.addressModeU; + samplerInfo.addressModeW = samplerInfo.addressModeU; + samplerInfo.mipLodBias = 0.0f; + samplerInfo.maxAnisotropy = 1.0f; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = 1.0f; + samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + VK_CHECK_RESULT(vkCreateSampler(device, &samplerInfo, nullptr, &sampler)); + } +*/ // Create uniform buffer initializeBuffer( (void*) &uniforms, @@ -188,7 +210,7 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, Swapchain& swa VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo( pipelineLayout, - swapchain.renderPass, + ext::vulkan::command ? ext::vulkan::command->getRenderPass() : swapchain.renderPass, 0 ); pipelineCreateInfo.pVertexInputState = &vertexInputState; @@ -201,23 +223,21 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, Swapchain& swa pipelineCreateInfo.pDynamicState = &dynamicState; pipelineCreateInfo.stageCount = static_cast(shader.stages.size()); pipelineCreateInfo.pStages = shader.stages.data(); + pipelineCreateInfo.subpass = 1; initializePipeline(pipelineCreateInfo); } // Set descriptor pool initializeDescriptorPool({ ext::vulkan::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - ext::vulkan::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1), - ext::vulkan::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_SAMPLER, 1) - }, 3); + ext::vulkan::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1), + }, 1); // Set descriptor set { - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageLayout = framebuffer->attachments[0].layout; - imageInfo.imageView = framebuffer->attachments[0].view; - - VkDescriptorImageInfo samplerInfo = {}; - samplerInfo.sampler = framebuffer->sampler; + VkDescriptorImageInfo textDescriptorAlbedo = ext::vulkan::initializers::descriptorImageInfo( + framebuffer->attachments[0].view, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + ); initializeDescriptorSet({ // Binding 0 : Projection/View matrix uniform buffer @@ -227,6 +247,14 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, Swapchain& swa 0, &(buffers.at(0).descriptor) ), + // Binding 1 : Albedo input attachment + ext::vulkan::initializers::writeDescriptorSet( + descriptorSet, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + 1, + &textDescriptorAlbedo + ), + /* // Binding 1 : Fragment shader texture // Fragment shader: layout (binding = 1) uniform texture2D tex; ext::vulkan::initializers::writeDescriptorSet( @@ -243,6 +271,7 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, Swapchain& swa 2, &samplerInfo ) + */ }); } /* @@ -266,4 +295,5 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, Swapchain& swa } void ext::vulkan::FramebufferGraphic::destroy() { ext::vulkan::Graphic::destroy(); + // vkDestroySampler( *device, sampler, nullptr ); } \ No newline at end of file diff --git a/engine/src/ext/vulkan/graphics/gui.cpp b/engine/src/ext/vulkan/graphics/gui.cpp index 81ba60f4..15f83880 100644 --- a/engine/src/ext/vulkan/graphics/gui.cpp +++ b/engine/src/ext/vulkan/graphics/gui.cpp @@ -161,7 +161,7 @@ void ext::vulkan::GuiGraphic::initialize( Device& device, Swapchain& swapchain ) VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo( pipelineLayout, - swapchain.renderPass, + ext::vulkan::command ? ext::vulkan::command->getRenderPass() : swapchain.renderPass, 0 ); pipelineCreateInfo.pVertexInputState = &vertexInputState; @@ -174,6 +174,7 @@ void ext::vulkan::GuiGraphic::initialize( Device& device, Swapchain& swapchain ) pipelineCreateInfo.pDynamicState = &dynamicState; pipelineCreateInfo.stageCount = static_cast(shader.stages.size()); pipelineCreateInfo.pStages = shader.stages.data(); + pipelineCreateInfo.subpass = 0; initializePipeline(pipelineCreateInfo); } @@ -181,7 +182,7 @@ void ext::vulkan::GuiGraphic::initialize( Device& device, Swapchain& swapchain ) initializeDescriptorPool({ ext::vulkan::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), ext::vulkan::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }, 2); + }, 1); // Set descriptor set initializeDescriptorSet({ // Binding 0 : Projection/View matrix uniform buffer diff --git a/engine/src/ext/vulkan/graphics/mesh.cpp b/engine/src/ext/vulkan/graphics/mesh.cpp index 3719cb99..74443c34 100644 --- a/engine/src/ext/vulkan/graphics/mesh.cpp +++ b/engine/src/ext/vulkan/graphics/mesh.cpp @@ -167,7 +167,7 @@ void ext::vulkan::MeshGraphic::initialize( Device& device, Swapchain& swapchain VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo( pipelineLayout, - swapchain.renderPass, + ext::vulkan::command ? ext::vulkan::command->getRenderPass() : swapchain.renderPass, 0 ); pipelineCreateInfo.pVertexInputState = &vertexInputState; @@ -180,6 +180,7 @@ void ext::vulkan::MeshGraphic::initialize( Device& device, Swapchain& swapchain pipelineCreateInfo.pDynamicState = &dynamicState; pipelineCreateInfo.stageCount = static_cast(shader.stages.size()); pipelineCreateInfo.pStages = shader.stages.data(); + pipelineCreateInfo.subpass = 0; initializePipeline(pipelineCreateInfo); } @@ -187,7 +188,7 @@ void ext::vulkan::MeshGraphic::initialize( Device& device, Swapchain& swapchain initializeDescriptorPool({ ext::vulkan::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), ext::vulkan::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) - }, 2); + }, 1); // Set descriptor set initializeDescriptorSet({ // Binding 0 : Projection/View matrix uniform buffer diff --git a/engine/src/ext/vulkan/rendertarget.cpp b/engine/src/ext/vulkan/rendertarget.cpp index 67a1383a..f025751b 100644 --- a/engine/src/ext/vulkan/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendertarget.cpp @@ -7,299 +7,228 @@ namespace { bool USEVR = false; } +void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFlags access, const std::vector& colors, const std::vector& inputs, size_t depth ) { + Subpass pass; + pass.stage = stage; + pass.access = access; + for ( auto& i : colors ) pass.colors.push_back( { i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } ); + for ( auto& i : inputs ) pass.inputs.push_back( { i, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } ); + pass.depth = { depth, attachments[depth].layout }; + passes.push_back(pass); +} +size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usage, Attachment* attachment ) { + if ( width == 0 ) width = ext::vulkan::width; + if ( height == 0 ) height = ext::vulkan::height; + + if ( !attachment ) { + attachments.resize(attachments.size()+1); + attachment = &attachments.back(); + } else { + vkDestroyImageView(*device, attachment->view, nullptr); + vkDestroyImage(*device, attachment->image, nullptr); + vkFreeMemory(*device, attachment->mem, nullptr); + } + + VkImageAspectFlags aspectMask = 0; + // specialization: depth buffer + if ( usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) { + aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; // | VK_IMAGE_ASPECT_STENCIL_BIT; + attachment->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + } else { + aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + attachment->layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } + attachment->format = format; + attachment->usage = usage; + + VkImageCreateInfo image = {}; + image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image.imageType = VK_IMAGE_TYPE_2D; + image.format = format; + image.extent = { width, height, 1 }; + image.mipLevels = 1; + image.arrayLayers = USEVR ? 2 : 1; + image.samples = VK_SAMPLE_COUNT_1_BIT; + image.tiling = VK_IMAGE_TILING_OPTIMAL; + image.usage = usage | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VK_CHECK_RESULT(vkCreateImage(*device, &image, nullptr, &attachment->image)); + + // Allocate memory for the image (device local) and bind it to our image + VkMemoryAllocateInfo memAlloc = {}; + memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + VkMemoryRequirements memReqs; + vkGetImageMemoryRequirements(*device, attachment->image, &memReqs); + memAlloc.allocationSize = memReqs.size; + memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(*device, &memAlloc, nullptr, &attachment->mem)); + VK_CHECK_RESULT(vkBindImageMemory(*device, attachment->image, attachment->mem, 0)); + + // Create a view for the depth stencil image + // Images aren't directly accessed in Vulkan, but rather through views described by a subresource range + // This allows for multiple views of one image with differing ranges (e.g. for different layers) + VkImageViewCreateInfo imageView = {}; + imageView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + imageView.viewType = VK_IMAGE_VIEW_TYPE_2D; + imageView.format = format; + imageView.subresourceRange = {}; + imageView.subresourceRange.aspectMask = aspectMask; + imageView.subresourceRange.baseMipLevel = 0; + imageView.subresourceRange.levelCount = 1; + imageView.subresourceRange.baseArrayLayer = 0; + imageView.subresourceRange.layerCount = USEVR ? 2 : 1; + imageView.image = attachment->image; + + VK_CHECK_RESULT(vkCreateImageView(*device, &imageView, nullptr, &attachment->view)); + + return attachments.size()-1; +} void ext::vulkan::RenderTarget::initialize( Device& device ) { // Bind { this->device = &device; if ( width == 0 ) width = ext::vulkan::width; if ( height == 0 ) height = ext::vulkan::height; - - attachments.resize(2); } - - // color target - auto& color = attachments[0]; - // depth target - auto& depthStencil = attachments[1]; - - { - // Create an optimal image used as the depth stencil attachment - VkImageCreateInfo image = {}; - image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image.imageType = VK_IMAGE_TYPE_2D; - image.format = ext::vulkan::swapchain.colorFormat; - // Use example's height and width - image.extent = { width, height, 1 }; - image.mipLevels = 1; - image.arrayLayers = USEVR ? 2 : 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &color.image)); - - // Allocate memory for the image (device local) and bind it to our image - VkMemoryAllocateInfo memAlloc = {}; - memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, color.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &color.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, color.image, color.mem, 0)); - - // Create a view for the depth stencil image - // Images aren't directly accessed in Vulkan, but rather through views described by a subresource range - // This allows for multiple views of one image with differing ranges (e.g. for different layers) - VkImageViewCreateInfo imageView = {}; - imageView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - imageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageView.format = ext::vulkan::swapchain.colorFormat; - imageView.subresourceRange = {}; - imageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageView.subresourceRange.baseMipLevel = 0; - imageView.subresourceRange.levelCount = 1; - imageView.subresourceRange.baseArrayLayer = 0; - imageView.subresourceRange.layerCount = USEVR ? 2 : 1; - imageView.image = color.image; - - VK_CHECK_RESULT(vkCreateImageView(device, &imageView, nullptr, &color.view)); - - VkSamplerCreateInfo samplerInfo = {}; - samplerInfo.magFilter = VK_FILTER_NEAREST; - samplerInfo.minFilter = VK_FILTER_NEAREST; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeV = samplerInfo.addressModeU; - samplerInfo.addressModeW = samplerInfo.addressModeU; - samplerInfo.mipLodBias = 0.0f; - samplerInfo.maxAnisotropy = 1.0f; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 1.0f; - samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - VK_CHECK_RESULT(vkCreateSampler(device, &samplerInfo, nullptr, &sampler)); - - // Fill a descriptor for later use in a descriptor set - descriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - descriptorImageInfo.imageView = color.view; - descriptorImageInfo.sampler = sampler; - } - // Create depth/stencil buffer - { - // Create an optimal image used as the depth stencil attachment - VkImageCreateInfo image = {}; - image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image.imageType = VK_IMAGE_TYPE_2D; - image.format = ext::vulkan::swapchain.depthFormat; - // Use example's height and width - image.extent = { width, height, 1 }; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &depthStencil.image)); - - // Allocate memory for the image (device local) and bind it to our image - VkMemoryAllocateInfo memAlloc = {}; - memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, depthStencil.image, &memReqs); - memAlloc.allocationSize = memReqs.size; - memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &depthStencil.mem)); - VK_CHECK_RESULT(vkBindImageMemory(device, depthStencil.image, depthStencil.mem, 0)); - - // Create a view for the depth stencil image - // Images aren't directly accessed in Vulkan, but rather through views described by a subresource range - // This allows for multiple views of one image with differing ranges (e.g. for different layers) - VkImageViewCreateInfo depthStencilView = {}; - depthStencilView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthStencilView.format = ext::vulkan::swapchain.depthFormat; - depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - depthStencilView.subresourceRange.baseMipLevel = 0; - depthStencilView.subresourceRange.levelCount = 1; - depthStencilView.subresourceRange.baseArrayLayer = 0; - depthStencilView.subresourceRange.layerCount = 1; - depthStencilView.image = depthStencil.image; - - VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthStencil.view)); + // resize attachments if necessary + if ( commandBufferSet ) { + for ( auto& attachment: this->attachments ) { + if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue; + attach( attachment.format, attachment.usage, &attachment ); + } } + // ensure attachments are already created + assert( this->attachments.size() > 0 ); // Create render pass - { - // This example will use a single render pass with one subpass + if ( !renderPass ) { + std::vector attachments; attachments.reserve( this->attachments.size() ); + + for ( auto& attachment : this->attachments ) { + VkAttachmentDescription description; + description.format = attachment.format; + description.samples = VK_SAMPLE_COUNT_1_BIT; + description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + description.finalLayout = attachment.layout; - // Descriptors for the attachments used by this renderpass - std::array attachments = {}; - - // Color attachment - attachments[0].format = ext::vulkan::swapchain.colorFormat; // Use the color format selected by the swapchain - attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; // We don't use multi sampling in this example - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear this attachment at the start of the render pass - attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // Keep it's contents after the render pass is finished (for displaying it) - attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // We don't use stencil, so don't care for load - attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // Same for store - attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Layout at render pass start. Initial doesn't matter, so we use undefined - attachments[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // Layout to which the attachment is transitioned when the render pass is finished - // As we want to present the color buffer to the swapchain, we transition to PRESENT_KHR - // Depth attachment - attachments[1].format = ext::vulkan::swapchain.depthFormat; // A proper depth format is selected in the example base - attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear depth at start of first subpass - attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // We don't need depth after render pass has finished (DONT_CARE may result in better performance) - attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // No stencil - attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // No Stencil - attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Layout at render pass start. Initial doesn't matter, so we use undefined - attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Transition to depth/stencil attachment - - // Setup attachment references - VkAttachmentReference colorReference = {}; - colorReference.attachment = 0; // Attachment 0 is color - colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // Attachment layout used as color during the subpass - - VkAttachmentReference depthReference = {}; - depthReference.attachment = 1; // Attachment 1 is color - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Attachment used as depth/stemcil used during the subpass - - VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; // Subpass uses one color attachment - subpassDescription.pColorAttachments = &colorReference; // Reference to the color attachment in slot 0 - subpassDescription.pDepthStencilAttachment = &depthReference; // Reference to the depth attachment in slot 1 - subpassDescription.inputAttachmentCount = 0; // Input attachments can be used to sample from contents of a previous subpass - subpassDescription.pInputAttachments = nullptr; // (Input attachments not used by this example) - subpassDescription.preserveAttachmentCount = 0; // Preserved attachments can be used to loop (and preserve) attachments through subpasses - subpassDescription.pPreserveAttachments = nullptr; // (Preserve attachments not used by this example) - subpassDescription.pResolveAttachments = nullptr; // Resolve attachments are resolved at the end of a sub pass and can be used for e.g. multi sampling - - // Setup subpass dependencies - // These will add the implicit ttachment layout transitionss specified by the attachment descriptions - // The actual usage layout is preserved through the layout specified in the attachment reference - // Each subpass dependency will introduce a memory and execution dependency between the source and dest subpass described by - // srcStageMask, dstStageMask, srcAccessMask, dstAccessMask (and dependencyFlags is set) - // Note: VK_SUBPASS_EXTERNAL is a special constant that refers to all commands executed outside of the actual renderpass) - std::array dependencies; - - // First dependency at the start of the renderpass - // Does the transition from final to initial layout - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; // Producer of the dependency - dependencies[0].dstSubpass = 0; // Consumer is our single subpass that will wait for the execution depdendency - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; //VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Second dependency at the end the renderpass - // Does the transition from the initial to the final layout - dependencies[1].srcSubpass = 0; // Producer of the dependency is our single subpass - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; // Consumer are all commands outside of the renderpass - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; //VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - /* - std::array dependencies; - - // First dependency at the start of the renderpass - // Does the transition from final to initial layout - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; // Producer of the dependency - dependencies[0].dstSubpass = 0; // Consumer is our single subpass that will wait for the execution depdendency - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - // Second dependency at the end the renderpass - // Does the transition from the initial to the final layout - dependencies[1].srcSubpass = 0; // Producer of the dependency is our single subpass - dependencies[1].dstSubpass = 1; // Consumer are all commands outside of the renderpass - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - dependencies[2].srcSubpass = 1; // Producer of the dependency is our single subpass - dependencies[2].dstSubpass = VK_SUBPASS_EXTERNAL; // Consumer are all commands outside of the renderpass - dependencies[2].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dependencies[2].dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; - dependencies[2].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - dependencies[2].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - dependencies[2].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - - */ - - // Create the actual renderpass - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = static_cast(attachments.size()); // Number of attachments used by this render pass - renderPassInfo.pAttachments = attachments.data(); // Descriptions of the attachments used by the render pass - renderPassInfo.subpassCount = 1; // We only use one subpass in this example - renderPassInfo.pSubpasses = &subpassDescription; // Description of that subpass - renderPassInfo.dependencyCount = static_cast(dependencies.size()); // Number of subpass dependencies - renderPassInfo.pDependencies = dependencies.data(); // Subpass dependencies used by the render pass - // renderPassInfo.dependencyCount = 0; // Number of subpass dependencies - // renderPassInfo.pDependencies = nullptr; // Subpass dependencies used by the render pass - - // OpenVR - VkRenderPassMultiviewCreateInfo renderPassMultiviewCI{}; - if ( USEVR ) { - const uint32_t viewMask = 0b00000011; - const uint32_t correlationMask = 0b00000011; - - renderPassMultiviewCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO; - renderPassMultiviewCI.subpassCount = 1; - renderPassMultiviewCI.pViewMasks = &viewMask; - renderPassMultiviewCI.correlationMaskCount = 1; - renderPassMultiviewCI.pCorrelationMasks = &correlationMask; - - renderPassInfo.pNext = &renderPassMultiviewCI; + attachments.push_back(description); } - VK_CHECK_RESULT(vkCreateRenderPass( device, &renderPassInfo, nullptr, &renderPass)); + // ensure that the subpasses are already described + assert( passes.size() > 0 ); + + std::vector descriptions; + std::vector dependencies; + + // dependency: transition from final + VkSubpassDependency dependency; + dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + dependency.dstSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependency.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + size_t i = 0; + for ( auto& pass : passes ) { + VkSubpassDescription description; + + // describe renderpass + description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + description.colorAttachmentCount = pass.colors.size(); + description.pColorAttachments = &pass.colors[0]; + description.pDepthStencilAttachment = &pass.depth; + description.inputAttachmentCount = pass.inputs.size(); + description.pInputAttachments = &pass.inputs[0]; + description.preserveAttachmentCount = 0; + description.pPreserveAttachments = nullptr; + description.pResolveAttachments = nullptr; + descriptions.push_back(description); + + // transition dependency between subpasses + dependency.srcSubpass = dependency.dstSubpass; + dependency.srcStageMask = dependency.dstStageMask; + dependency.srcAccessMask = dependency.dstAccessMask; + dependency.dstSubpass = i++; + dependency.dstStageMask = pass.stage; + dependency.dstAccessMask = pass.access; + dependencies.push_back(dependency); + } + // dependency: transition to final + { + dependency.srcSubpass = dependency.dstSubpass; + dependency.srcStageMask = dependency.dstStageMask; + dependency.srcAccessMask = dependency.dstAccessMask; + dependency.dstSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependency.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies.push_back(dependency); + } + + + std::cout << this << std::endl; + for ( auto& dependency : dependencies ) { + std::cout << "Subpass: " << std::hex << dependency.srcSubpass << " -> " << std::hex << dependency.dstSubpass << std::endl;; + std::cout << "StageMask: " << std::hex << dependency.srcStageMask << " -> " << std::hex << dependency.dstStageMask << std::endl;; + std::cout << "AccessMask: " << std::hex << dependency.srcAccessMask << " -> " << std::hex << dependency.dstAccessMask << std::endl;; + std::cout << std::endl; + } + + + VkRenderPassCreateInfo renderPassInfo = {}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + renderPassInfo.flags = 0; + renderPassInfo.attachmentCount = static_cast(attachments.size()); + renderPassInfo.pAttachments = &attachments[0]; + renderPassInfo.subpassCount = static_cast(descriptions.size()); + renderPassInfo.pSubpasses = &descriptions[0]; + renderPassInfo.dependencyCount = static_cast(dependencies.size()); + renderPassInfo.pDependencies = &dependencies[0]; + + VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass)); } // Create framebuffer { - std::vector attachments; - // attachments[0] = swapchain.buffers[i].view; // Color attachment is the view of the swapchain image - // attachments[1] = depthStencil.view; // Depth/Stencil attachment is the same for all frame buffers - for ( auto attachment : this->attachments ) attachments.push_back(attachment.view); + framebuffers.resize(swapchain.imageCount); + for ( size_t i = 0; i < framebuffers.size(); ++i ) { + std::vector attachments; + for ( auto& attachment : this->attachments ) { + if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) attachments.push_back(swapchain.buffers[i].view); + else attachments.push_back(attachment.view); + } - VkFramebufferCreateInfo frameBufferCreateInfo = {}; - frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - // All frame buffers use the same renderpass setup - frameBufferCreateInfo.renderPass = renderPass; - frameBufferCreateInfo.attachmentCount = static_cast(attachments.size()); - frameBufferCreateInfo.pAttachments = &attachments[0]; - frameBufferCreateInfo.width = width; - frameBufferCreateInfo.height = height; - frameBufferCreateInfo.layers = 1; - // Create the framebuffer - VK_CHECK_RESULT(vkCreateFramebuffer( device, &frameBufferCreateInfo, nullptr, &framebuffer)); + VkFramebufferCreateInfo frameBufferCreateInfo = {}; + frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + // All frame buffers use the same renderpass setup + frameBufferCreateInfo.renderPass = renderPass; + frameBufferCreateInfo.attachmentCount = static_cast(attachments.size()); + frameBufferCreateInfo.pAttachments = &attachments[0]; + frameBufferCreateInfo.width = width; + frameBufferCreateInfo.height = height; + frameBufferCreateInfo.layers = 1; + // Create the framebuffer + VK_CHECK_RESULT(vkCreateFramebuffer( device, &frameBufferCreateInfo, nullptr, &framebuffers[i])); + } } } void ext::vulkan::RenderTarget::destroy() { if ( !device ) return; - vkDestroySampler( *device, sampler, nullptr ); vkDestroyRenderPass( *device, renderPass, nullptr ); - vkDestroyFramebuffer( *device, framebuffer, nullptr ); + for ( auto& framebuffer : framebuffers ) vkDestroyFramebuffer( *device, framebuffer, nullptr ); for ( auto& attachment : attachments ) { + if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue; vkDestroyImageView( *device, attachment.view, nullptr ); + attachment.view = VK_NULL_HANDLE; vkDestroyImage( *device, attachment.image, nullptr ); + attachment.image = VK_NULL_HANDLE; vkFreeMemory( *device, attachment.mem, nullptr ); + attachment.mem = VK_NULL_HANDLE; } renderPass = VK_NULL_HANDLE; - framebuffer = VK_NULL_HANDLE; device = VK_NULL_HANDLE; } \ No newline at end of file diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index 4ca58a2d..dd5846a3 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -157,7 +158,12 @@ void ext::vulkan::initialize( uint8_t stage ) { allocatorInfo.device = device.logicalDevice; vmaCreateAllocator(&allocatorInfo, &allocator); } - if ( !ext::vulkan::command ) ext::vulkan::command = ext::vulkan::openvr ? new ext::vulkan::MultiviewCommand() : new ext::vulkan::Command(); + if ( !ext::vulkan::command ) { + // ext::vulkan::command = ext::vulkan::openvr ? new ext::vulkan::MultiviewCommand() : new ext::vulkan::Command(); + // would ternary but yields "conditional expression between distinct pointer types ‘ext::vulkan::MultiviewCommand*’ and ‘ext::vulkan::DeferredCommand*’ lacks a cast" + if ( ext::vulkan::openvr ) ext::vulkan::command = new ext::vulkan::MultiviewCommand(); + else ext::vulkan::command = new ext::vulkan::DeferredCommand(); + } ext::vulkan::command->initialize(device); ext::vulkan::command->createCommandBuffers();