diff --git a/client/client/ext.cpp b/client/client/ext.cpp index 6b62d40e..512ad883 100644 --- a/client/client/ext.cpp +++ b/client/client/ext.cpp @@ -126,7 +126,7 @@ void client::initialize() { ext::vulkan::width = size.x; ext::vulkan::height = size.y; - ext::vulkan::swapchain.rebuild = true; + ext::vulkan::rebuild = true; return "true"; } ); } else if ( client::config["engine"]["hook"]["mode"] == "Both" || client::config["engine"]["hook"]["mode"] == "Optimal" ) { diff --git a/engine/inc/uf/ext/vulkan/buffer.h b/engine/inc/uf/ext/vulkan/buffer.h index ba82d36c..b1795956 100644 --- a/engine/inc/uf/ext/vulkan/buffer.h +++ b/engine/inc/uf/ext/vulkan/buffer.h @@ -14,8 +14,8 @@ namespace ext { void* mapped = nullptr; VkBufferUsageFlags usageFlags; - VkMemoryPropertyFlags memoryPropertyFlags; + VkMemoryAllocateInfo memAlloc; VkMemoryRequirements memReqs; diff --git a/engine/inc/uf/ext/vulkan/graphics/framebuffer.h b/engine/inc/uf/ext/vulkan/graphics/framebuffer.h index 3b915910..076cc25a 100644 --- a/engine/inc/uf/ext/vulkan/graphics/framebuffer.h +++ b/engine/inc/uf/ext/vulkan/graphics/framebuffer.h @@ -23,7 +23,7 @@ namespace ext { uint32_t indices = 0; VkSampler sampler; - ext::vulkan::RenderTarget* framebuffer; + ext::vulkan::RenderTarget* renderTarget; virtual void createCommandBuffer( VkCommandBuffer ); virtual bool autoAssignable() const; diff --git a/engine/inc/uf/ext/vulkan/graphics/rendertarget.h b/engine/inc/uf/ext/vulkan/graphics/rendertarget.h index 6d5dc338..bf20cc6e 100644 --- a/engine/inc/uf/ext/vulkan/graphics/rendertarget.h +++ b/engine/inc/uf/ext/vulkan/graphics/rendertarget.h @@ -23,7 +23,7 @@ namespace ext { uint32_t indices = 0; VkSampler sampler; - ext::vulkan::RenderTarget* framebuffer; + ext::vulkan::RenderTarget* renderTarget; virtual void createCommandBuffer( VkCommandBuffer ); virtual bool autoAssignable() const; diff --git a/engine/inc/uf/ext/vulkan/rendermode.h b/engine/inc/uf/ext/vulkan/rendermode.h new file mode 100644 index 00000000..60d66989 --- /dev/null +++ b/engine/inc/uf/ext/vulkan/rendermode.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace ext { + namespace vulkan { + struct Graphic; + struct UF_API RenderMode { + uint32_t width = 0, height = 0; + std::string name = ""; + + Device* device = VK_NULL_HANDLE; + ext::vulkan::RenderTarget renderTarget; + + std::vector fences; + std::vector commands; + + // virtual ~RenderMode(); + // RAII + virtual std::string getType() const; + 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(); + }; + } +} \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/rendermodes/base.h b/engine/inc/uf/ext/vulkan/rendermodes/base.h index 938c9f8e..0939d5d8 100644 --- a/engine/inc/uf/ext/vulkan/rendermodes/base.h +++ b/engine/inc/uf/ext/vulkan/rendermodes/base.h @@ -1,15 +1,11 @@ #pragma once -#include +#include namespace ext { namespace vulkan { struct Graphic; - struct UF_API RenderMode { - uint32_t width = 0, height = 0; - std::string name = ""; - - Device* device = VK_NULL_HANDLE; + struct UF_API BaseRenderMode : RenderMode { // virtual ~RenderMode(); // RAII virtual std::string getType() const; @@ -17,13 +13,9 @@ namespace ext { 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(); - virtual ext::vulkan::RenderTarget& getRenderTarget(); }; } } \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/rendermodes/deferred.h b/engine/inc/uf/ext/vulkan/rendermodes/deferred.h index a59f631c..287dd7ce 100644 --- a/engine/inc/uf/ext/vulkan/rendermodes/deferred.h +++ b/engine/inc/uf/ext/vulkan/rendermodes/deferred.h @@ -1,13 +1,11 @@ #pragma once -#include -#include +#include #include namespace ext { namespace vulkan { struct UF_API DeferredRenderMode : public ext::vulkan::RenderMode { - ext::vulkan::RenderTarget renderTarget; ext::vulkan::FramebufferGraphic blitter; // RAII @@ -17,9 +15,6 @@ namespace ext { virtual void createCommandBuffers( const std::vector& graphics, const std::vector& passes ); virtual void initialize( Device& device ); virtual void destroy(); - - virtual VkRenderPass& getRenderPass(); - virtual ext::vulkan::RenderTarget& getRenderTarget(); }; } } \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/rendermodes/multiview.h b/engine/inc/uf/ext/vulkan/rendermodes/multiview.h index 22d975ac..9bcc3585 100644 --- a/engine/inc/uf/ext/vulkan/rendermodes/multiview.h +++ b/engine/inc/uf/ext/vulkan/rendermodes/multiview.h @@ -1,18 +1,18 @@ #pragma once -#include -#include +#include #include namespace ext { namespace vulkan { struct UF_API MultiviewRenderMode : public ext::vulkan::RenderMode { struct { - ext::vulkan::RenderTarget left; + ext::vulkan::RenderTarget& left; ext::vulkan::RenderTarget right; } renderTargets; ext::vulkan::FramebufferGraphic blitter; + MultiviewRenderMode(); // RAII virtual std::string getType() const; virtual size_t subpasses() const; @@ -20,9 +20,6 @@ namespace ext { virtual void createCommandBuffers( const std::vector& graphics, const std::vector& passes ); virtual void initialize( Device& device ); virtual void destroy(); - - virtual VkRenderPass& getRenderPass(); - virtual ext::vulkan::RenderTarget& getRenderTarget(); }; } } \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/rendermodes/rendertarget.h b/engine/inc/uf/ext/vulkan/rendermodes/rendertarget.h index 75edeefe..859126e3 100644 --- a/engine/inc/uf/ext/vulkan/rendermodes/rendertarget.h +++ b/engine/inc/uf/ext/vulkan/rendermodes/rendertarget.h @@ -1,14 +1,13 @@ #pragma once -#include -#include +#include #include namespace ext { namespace vulkan { struct UF_API RenderTargetRenderMode : public ext::vulkan::RenderMode { - ext::vulkan::RenderTarget renderTarget; ext::vulkan::RenderTargetGraphic blitter; + VkFence fence; VkCommandBuffer commandBuffer; @@ -20,9 +19,6 @@ namespace ext { virtual void initialize( Device& device ); virtual void destroy(); virtual void render(); - - virtual VkRenderPass& getRenderPass(); - virtual ext::vulkan::RenderTarget& getRenderTarget(); }; } } \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/rendertarget.h b/engine/inc/uf/ext/vulkan/rendertarget.h index cce22136..71492681 100644 --- a/engine/inc/uf/ext/vulkan/rendertarget.h +++ b/engine/inc/uf/ext/vulkan/rendertarget.h @@ -9,6 +9,8 @@ namespace ext { VkFormat format; VkImageLayout layout; VkImageUsageFlags usage; + bool aliased = false; + VkImage image; VkDeviceMemory mem; VkImageView view; @@ -33,7 +35,7 @@ namespace ext { 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 ); + size_t attach( VkFormat format, VkImageUsageFlags usage, VkImageLayout layout, Attachment* attachment = NULL ); }; } } \ No newline at end of file diff --git a/engine/inc/uf/ext/vulkan/swapchain.h b/engine/inc/uf/ext/vulkan/swapchain.h index a3255671..d7169468 100644 --- a/engine/inc/uf/ext/vulkan/swapchain.h +++ b/engine/inc/uf/ext/vulkan/swapchain.h @@ -9,24 +9,20 @@ namespace ext { Device* device = nullptr; VkSurfaceKHR surface; VkSwapchainKHR swapChain = VK_NULL_HANDLE; - - - VkSemaphore presentCompleteSemaphore; - VkSemaphore renderCompleteSemaphore; - std::vector waitFences; - - bool commandBufferSet = false; - std::vector drawCommandBuffers; + bool initialized = false; bool vsync = true; uint32_t buffers; + VkSemaphore presentCompleteSemaphore; + VkSemaphore renderCompleteSemaphore; + // helpers - VkResult acquireNextImage( uint32_t *imageIndex ); + VkResult acquireNextImage( uint32_t* imageIndex, VkSemaphore ); VkResult queuePresent( VkQueue queue, uint32_t imageIndex, VkSemaphore waitSemaphore = VK_NULL_HANDLE ); // RAII - void initialize( Device& device, size_t width = 0, size_t height = 0, bool vsync = true ); + void initialize( Device& device ); void destroy(); }; } diff --git a/engine/inc/uf/ext/vulkan/vulkan.h b/engine/inc/uf/ext/vulkan/vulkan.h index d6421df2..4e751318 100644 --- a/engine/inc/uf/ext/vulkan/vulkan.h +++ b/engine/inc/uf/ext/vulkan/vulkan.h @@ -46,7 +46,7 @@ namespace ext { extern UF_API Swapchain swapchain; extern UF_API std::mutex mutex; - extern UF_API bool resizedFramebuffer; + extern UF_API bool rebuild; extern UF_API uint32_t currentBuffer; extern UF_API std::string currentPass; @@ -56,7 +56,7 @@ namespace ext { extern UF_API std::vector scenes; RenderMode& UF_API addRenderMode( RenderMode*, const std::string& = "" ); - RenderMode& UF_API getRenderMode( const std::string& ); + RenderMode& UF_API getRenderMode( const std::string&, bool = true ); void UF_API initialize( uint8_t = 0 ); void UF_API tick(); diff --git a/engine/src/engine/scene/scene.cpp b/engine/src/engine/scene/scene.cpp index 9df0a596..0ee79bd8 100644 --- a/engine/src/engine/scene/scene.cpp +++ b/engine/src/engine/scene/scene.cpp @@ -6,7 +6,7 @@ void uf::Scene::initialize() { // this->m_graphics = new std::vector(); // ext::vulkan::graphics = (std::vector*) this->m_graphics; ext::vulkan::scenes.push_back(this); - ext::vulkan::swapchain.rebuild = true; + ext::vulkan::rebuild = true; uf::Object::initialize(); } void uf::Scene::tick() { @@ -32,7 +32,7 @@ void uf::Scene::destroy() { ext::vulkan::scenes.end() ); */ - ext::vulkan::swapchain.rebuild = true; + ext::vulkan::rebuild = true; /* std::vector* graphics = (std::vector*) this->m_graphics; for ( auto* graphic : *graphics ) { diff --git a/engine/src/ext/openvr/openvr.cpp b/engine/src/ext/openvr/openvr.cpp index e7c2fea5..1776870e 100644 --- a/engine/src/ext/openvr/openvr.cpp +++ b/engine/src/ext/openvr/openvr.cpp @@ -216,7 +216,8 @@ void ext::openvr::tick() { } void ext::openvr::submit() { - ext::vulkan::MultiviewRenderMode* renderMode = (ext::vulkan::MultiviewRenderMode*) ext::vulkan::renderModes[0]; +/* +// ext::vulkan::MultiviewRenderMode* renderMode = (ext::vulkan::MultiviewRenderMode*) ext::vulkan::renderModes[0]; float width = renderMode->width > 0 ? renderMode->width : ext::vulkan::width; float height = renderMode->height > 0 ? renderMode->height : ext::vulkan::height; // Submit to SteamVR @@ -248,6 +249,7 @@ void ext::openvr::submit() { vr::VRCompositor()->Submit( vr::Eye_Right, &texture, &bounds ); vr::VRCompositor()->PostPresentHandoff(); +*/ } void ext::openvr::recommendedResolution( uint32_t& width, uint32_t& height ) { diff --git a/engine/src/ext/vulkan/buffer.cpp b/engine/src/ext/vulkan/buffer.cpp index f815beed..420e6c50 100644 --- a/engine/src/ext/vulkan/buffer.cpp +++ b/engine/src/ext/vulkan/buffer.cpp @@ -103,12 +103,12 @@ VkResult ext::vulkan::Buffer::invalidate( VkDeviceSize size, VkDeviceSize offset } void ext::vulkan::Buffer::allocate( VkBufferCreateInfo bufferCreateInfo ) { - VK_CHECK_RESULT(vkCreateBuffer( device, &bufferCreateInfo, nullptr, &buffer)); - +// VK_CHECK_RESULT(vkCreateBuffer( device, &bufferCreateInfo, nullptr, &buffer)); VmaAllocationCreateInfo allocCreateInfo = {}; + allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; allocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - if ( bufferCreateInfo.usage | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT ) { + if ( bufferCreateInfo.usage & (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT) ) { allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; } diff --git a/engine/src/ext/vulkan/device.cpp b/engine/src/ext/vulkan/device.cpp index cd73d11e..8c45312e 100644 --- a/engine/src/ext/vulkan/device.cpp +++ b/engine/src/ext/vulkan/device.cpp @@ -156,6 +156,8 @@ VkResult ext::vulkan::Device::createBuffer( VkBufferUsageFlags usageFlags, VkMem memAlloc.allocationSize = memReqs.size; // Find a memory type index that fits the properties of the buffer memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags); + + std::cout << "Allocating Memory: " << memory << std::endl; VK_CHECK_RESULT( vkAllocateMemory(logicalDevice, &memAlloc, nullptr, memory)); // If a pointer to the buffer data has been passed, map the buffer and copy over the data @@ -189,10 +191,13 @@ VkResult ext::vulkan::Device::createBuffer( void *data ) { buffer.device = logicalDevice; + buffer.usageFlags = usageFlags; + buffer.memoryPropertyFlags = memoryPropertyFlags; // Create the buffer handle VkBufferCreateInfo bufferCreateInfo = ext::vulkan::initializers::bufferCreateInfo(usageFlags, size); buffer.allocate( bufferCreateInfo ); + /* // VK_CHECK_RESULT(vkCreateBuffer(logicalDevice, &bufferCreateInfo, nullptr, &buffer.buffer)); // Create the memory backing up the buffer handle @@ -538,16 +543,16 @@ void ext::vulkan::Device::initialize() { // If the surface format list only includes one entry with VK_FORMAT_UNDEFINED, // there is no preferered format, so we assume VK_FORMAT_B8G8R8A8_UNORM if ( (formatCount == 1) && (formats[0].format == VK_FORMAT_UNDEFINED) ) { - formats.color = VK_FORMAT_B8G8R8A8_UNORM; - formats.space = formats[0].colorSpace; + this->formats.color = VK_FORMAT_B8G8R8A8_UNORM; + this->formats.space = formats[0].colorSpace; } else { // iterate over the list of available surface format and // check for the presence of VK_FORMAT_B8G8R8A8_UNORM bool found_B8G8R8A8_UNORM = false; for ( auto&& surfaceFormat : formats ) { if ( surfaceFormat.format == VK_FORMAT_B8G8R8A8_UNORM ) { - formats.color = surfaceFormat.format; - formats.space = surfaceFormat.colorSpace; + this->formats.color = surfaceFormat.format; + this->formats.space = surfaceFormat.colorSpace; found_B8G8R8A8_UNORM = true; break; } @@ -555,8 +560,8 @@ void ext::vulkan::Device::initialize() { // in case VK_FORMAT_B8G8R8A8_UNORM is not available // select the first available color format if ( !found_B8G8R8A8_UNORM ) { - formats.color = formats[0].format; - formats.space = formats[0].colorSpace; + this->formats.color = formats[0].format; + this->formats.space = formats[0].colorSpace; } } } @@ -577,7 +582,7 @@ void ext::vulkan::Device::initialize() { vkGetPhysicalDeviceFormatProperties( this->physicalDevice, format, &formatProps ); // Format must support depth stencil attachment for optimal tiling if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { - formats.depth = format; + this->formats.depth = format; } } } diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index 9485914e..da701fa4 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -161,7 +161,7 @@ bool ext::vulkan::Graphic::autoAssignable() const { } void ext::vulkan::Graphic::autoAssign() { if ( !autoAssigned ) { - swapchain.rebuild = true; + ext::vulkan::rebuild = true; /* ext::vulkan::graphics->push_back(this); */ @@ -196,7 +196,7 @@ void ext::vulkan::Graphic::destroy() { ); */ autoAssigned = false; - swapchain.rebuild = true; + ext::vulkan::rebuild = true; } initialized = false; if ( !device || device == VK_NULL_HANDLE ) return; diff --git a/engine/src/ext/vulkan/graphics/base.cpp b/engine/src/ext/vulkan/graphics/base.cpp index b7210012..9368bfbd 100644 --- a/engine/src/ext/vulkan/graphics/base.cpp +++ b/engine/src/ext/vulkan/graphics/base.cpp @@ -98,13 +98,31 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, RenderMode& renderMod VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, false ); - // Swap buffers + // Move uniform buffer to the front + { + for ( auto it = buffers.begin(); it != buffers.end(); ++it ) { + Buffer& buffer = *it; + if ( !(buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue; + Buffer uniformBuffer = std::move(buffer); + buffers.erase(it); + buffers.insert( buffers.begin(), std::move(uniformBuffer) ); + break; + } + } +/* buffers = { std::move(buffers.at(2)), std::move(buffers.at(0)), std::move(buffers.at(1)), }; - +*/ +/* + std::cout << "Buffers for " << this << "(" << this->name() << ")" << std::endl; + for ( std::size_t i = 0; i < buffers.size(); ++i ) { + auto& buffer = buffers[i]; + std::cout << i << ": " << buffer.buffer << ": " << std::hex << buffer.usageFlags << std::endl; + } +*/ // set pipeline { VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = ext::vulkan::initializers::pipelineInputAssemblyStateCreateInfo( @@ -119,13 +137,6 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, RenderMode& renderMod VK_FRONT_FACE_CLOCKWISE, 0 ); - - /* - VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( - 0xf, - VK_FALSE - ); - */ /* VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, @@ -138,21 +149,44 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, RenderMode& renderMod blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; + VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo( + 1, + &blendAttachmentState + ); */ + /* + VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( + 0xf, + VK_FALSE + ); + VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo( + 1, + &blendAttachmentState + ); + */ + std::vector blendAttachmentStates; - for ( auto& attachment : renderMode.getFramebuffer().attachments ) { - if ( attachment.layout == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) { - blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( + for ( auto& attachment : renderMode.renderTarget.attachments ) { + if ( attachment.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) { + VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( 0xf, - VK_FALSE + VK_TRUE ); + blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; + blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; + blendAttachmentStates.push_back(blendAttachmentState); } } VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo( - blendAttachmentStates.size(), + renderMode.getType() == "Swapchain" ? 1 : blendAttachmentStates.size(), blendAttachmentStates.data() ); + /* colorBlendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; colorBlendState.logicOpEnable = VK_FALSE; colorBlendState.logicOp = VK_LOGIC_OP_COPY; @@ -160,6 +194,7 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, RenderMode& renderMod colorBlendState.blendConstants[1] = 0.0f; colorBlendState.blendConstants[2] = 0.0f; colorBlendState.blendConstants[3] = 0.0f; + */ VkPipelineDepthStencilStateCreateInfo depthStencilState = ext::vulkan::initializers::pipelineDepthStencilStateCreateInfo( VK_TRUE, VK_TRUE, @@ -211,7 +246,7 @@ void ext::vulkan::BaseGraphic::initialize( Device& device, RenderMode& renderMod VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo( pipelineLayout, - renderMode.getRenderPass(), + renderMode.renderTarget.renderPass, 0 ); diff --git a/engine/src/ext/vulkan/graphics/compute.cpp b/engine/src/ext/vulkan/graphics/compute.cpp index 3fb40433..cdc68e46 100644 --- a/engine/src/ext/vulkan/graphics/compute.cpp +++ b/engine/src/ext/vulkan/graphics/compute.cpp @@ -356,7 +356,7 @@ void ext::vulkan::RTGraphic::initialize( Device& device, RenderMode& renderMode VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo( pipelineLayout, - renderMode.getRenderPass(), + renderMode.renderTarget.renderPass, 0 ); VkPipelineVertexInputStateCreateInfo emptyInputState = {}; diff --git a/engine/src/ext/vulkan/graphics/framebuffer.cpp b/engine/src/ext/vulkan/graphics/framebuffer.cpp index bad42585..2909bec9 100644 --- a/engine/src/ext/vulkan/graphics/framebuffer.cpp +++ b/engine/src/ext/vulkan/graphics/framebuffer.cpp @@ -126,12 +126,25 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, RenderMode& re VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, false ); - // Swap buffers + // Move uniform buffer to the front + { + for ( auto it = buffers.begin(); it != buffers.end(); ++it ) { + Buffer& buffer = *it; + if ( !(buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue; + Buffer uniformBuffer = std::move(buffer); + buffers.erase(it); + buffers.insert( buffers.begin(), std::move(uniformBuffer) ); + break; + } + + } +/* buffers = { std::move(buffers.at(2)), std::move(buffers.at(0)), std::move(buffers.at(1)), }; +*/ // set pipeline { VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = ext::vulkan::initializers::pipelineInputAssemblyStateCreateInfo( @@ -145,6 +158,21 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, RenderMode& re VK_FRONT_FACE_COUNTER_CLOCKWISE, 0 ); + std::vector blendAttachmentStates; + for ( auto& attachment : renderMode.renderTarget.attachments ) { + if ( attachment.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) { + VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( + 0xf, + VK_FALSE + ); + blendAttachmentStates.push_back(blendAttachmentState); + } + } + VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo( + blendAttachmentStates.size(), + blendAttachmentStates.data() + ); + /* VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( 0xf, VK_FALSE @@ -153,6 +181,7 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, RenderMode& re 1, &blendAttachmentState ); + */ VkPipelineDepthStencilStateCreateInfo depthStencilState = ext::vulkan::initializers::pipelineDepthStencilStateCreateInfo( VK_TRUE, VK_TRUE, @@ -210,7 +239,7 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, RenderMode& re VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo( pipelineLayout, - renderMode.getRenderPass(), + renderMode.renderTarget.renderPass, 0 ); pipelineCreateInfo.pVertexInputState = &vertexInputState; @@ -235,7 +264,7 @@ void ext::vulkan::FramebufferGraphic::initialize( Device& device, RenderMode& re // Set descriptor set { VkDescriptorImageInfo textDescriptorAlbedo = ext::vulkan::initializers::descriptorImageInfo( - framebuffer->attachments[0].view, + renderTarget->attachments[0].view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ); diff --git a/engine/src/ext/vulkan/graphics/gui.cpp b/engine/src/ext/vulkan/graphics/gui.cpp index 9fada5c1..a498b9ad 100644 --- a/engine/src/ext/vulkan/graphics/gui.cpp +++ b/engine/src/ext/vulkan/graphics/gui.cpp @@ -62,11 +62,25 @@ void ext::vulkan::GuiGraphic::initialize( Device& device, RenderMode& renderMode false ); // Swap buffers + // Move uniform buffer to the front + { + for ( auto it = buffers.begin(); it != buffers.end(); ++it ) { + Buffer& buffer = *it; + if ( !(buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue; + Buffer uniformBuffer = std::move(buffer); + buffers.erase(it); + buffers.insert( buffers.begin(), std::move(uniformBuffer) ); + break; + } + + } +/* buffers = { std::move(buffers.at(2)), std::move(buffers.at(0)), std::move(buffers.at(1)), }; +*/ // check // set pipeline @@ -163,7 +177,7 @@ void ext::vulkan::GuiGraphic::initialize( Device& device, RenderMode& renderMode VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo( pipelineLayout, - renderMode.getRenderPass(), + renderMode.renderTarget.renderPass, 0 ); pipelineCreateInfo.pVertexInputState = &vertexInputState; diff --git a/engine/src/ext/vulkan/graphics/mesh.cpp b/engine/src/ext/vulkan/graphics/mesh.cpp index fe3cdcbd..8b84dd6a 100644 --- a/engine/src/ext/vulkan/graphics/mesh.cpp +++ b/engine/src/ext/vulkan/graphics/mesh.cpp @@ -58,12 +58,25 @@ void ext::vulkan::MeshGraphic::initialize( Device& device, RenderMode& renderMod VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, false ); - // Swap buffers + // Move uniform buffer to the front + { + for ( auto it = buffers.begin(); it != buffers.end(); ++it ) { + Buffer& buffer = *it; + if ( !(buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue; + Buffer uniformBuffer = std::move(buffer); + buffers.erase(it); + buffers.insert( buffers.begin(), std::move(uniformBuffer) ); + break; + } + + } +/* buffers = { std::move(buffers.at(2)), std::move(buffers.at(0)), std::move(buffers.at(1)), }; +*/ // check /* @@ -169,7 +182,7 @@ void ext::vulkan::MeshGraphic::initialize( Device& device, RenderMode& renderMod VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo( pipelineLayout, - renderMode.getRenderPass(), + renderMode.renderTarget.renderPass, 0 ); pipelineCreateInfo.pVertexInputState = &vertexInputState; diff --git a/engine/src/ext/vulkan/graphics/rendertarget.cpp b/engine/src/ext/vulkan/graphics/rendertarget.cpp index 31c4edb1..7729d9df 100644 --- a/engine/src/ext/vulkan/graphics/rendertarget.cpp +++ b/engine/src/ext/vulkan/graphics/rendertarget.cpp @@ -118,11 +118,25 @@ void ext::vulkan::RenderTargetGraphic::initialize( Device& device, RenderMode& r false ); // Swap buffers + // Move uniform buffer to the front + { + for ( auto it = buffers.begin(); it != buffers.end(); ++it ) { + Buffer& buffer = *it; + if ( !(buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue; + Buffer uniformBuffer = std::move(buffer); + buffers.erase(it); + buffers.insert( buffers.begin(), std::move(uniformBuffer) ); + break; + } + + } +/* buffers = { std::move(buffers.at(2)), std::move(buffers.at(0)), std::move(buffers.at(1)), }; +*/ // set pipeline { VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = ext::vulkan::initializers::pipelineInputAssemblyStateCreateInfo( @@ -136,11 +150,30 @@ void ext::vulkan::RenderTargetGraphic::initialize( Device& device, RenderMode& r VK_FRONT_FACE_COUNTER_CLOCKWISE, 0 ); - + std::vector blendAttachmentStates; + for ( auto& attachment : renderMode.renderTarget.attachments ) { + if ( attachment.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) { + VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( + 0xf, + VK_FALSE + ); + blendAttachmentStates.push_back(blendAttachmentState); + } + } + VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo( + blendAttachmentStates.size(), + blendAttachmentStates.data() + ); + /* VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( 0xf, VK_FALSE ); + VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo( + 1, + &blendAttachmentState + ); + */ /* VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( // VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, @@ -159,10 +192,11 @@ void ext::vulkan::RenderTargetGraphic::initialize( Device& device, RenderMode& r &blendAttachmentState ); */ + /* std::vector blendAttachmentStates; - for ( auto& attachment : renderMode.framebuffer->attachments ) { + for ( auto& attachment : renderMode.renderTarget.attachments ) { if ( attachment.layout == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) { - blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( + VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState( 0xf, VK_FALSE ); @@ -180,7 +214,7 @@ void ext::vulkan::RenderTargetGraphic::initialize( Device& device, RenderMode& r colorBlendState.blendConstants[1] = 0.0f; colorBlendState.blendConstants[2] = 0.0f; colorBlendState.blendConstants[3] = 0.0f; - + */ VkPipelineDepthStencilStateCreateInfo depthStencilState = ext::vulkan::initializers::pipelineDepthStencilStateCreateInfo( VK_TRUE, VK_TRUE, @@ -238,7 +272,7 @@ void ext::vulkan::RenderTargetGraphic::initialize( Device& device, RenderMode& r VkGraphicsPipelineCreateInfo pipelineCreateInfo = ext::vulkan::initializers::pipelineCreateInfo( pipelineLayout, - renderMode.getRenderPass(), + renderMode.renderTarget.renderPass, 0 ); pipelineCreateInfo.pVertexInputState = &vertexInputState; @@ -263,7 +297,7 @@ void ext::vulkan::RenderTargetGraphic::initialize( Device& device, RenderMode& r // Set descriptor set { VkDescriptorImageInfo renderTargetDescriptor = ext::vulkan::initializers::descriptorImageInfo( - framebuffer->attachments[0].view, + renderTarget->attachments[0].view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, sampler ); diff --git a/engine/src/ext/vulkan/rendermode.cpp b/engine/src/ext/vulkan/rendermode.cpp index b8a0f467..040f3fab 100644 --- a/engine/src/ext/vulkan/rendermode.cpp +++ b/engine/src/ext/vulkan/rendermode.cpp @@ -20,9 +20,6 @@ const std::string& ext::vulkan::RenderMode::getName() const { size_t ext::vulkan::RenderMode::subpasses() const { return 1; } -VkRenderPass& ext::vulkan::RenderMode::getRenderPass() { - return swapchain.renderPass; -} void ext::vulkan::RenderMode::createCommandBuffers() { std::vector graphics; @@ -43,87 +40,15 @@ void ext::vulkan::RenderMode::createCommandBuffers() { createCommandBuffers( graphics, ext::vulkan::passes ); } void ext::vulkan::RenderMode::createCommandBuffers( const std::vector& graphics, const std::vector& passes ) { - // destroy if exists - if ( swapchain.initialized ) { - auto* device = swapchain.device; - bool vsync = swapchain.vsync; - swapchain.destroy(); - swapchain.initialize( *device ); - } - - float width = width > 0 ? this->width : ext::vulkan::width; - float height = height > 0 ? this->height : ext::vulkan::height; - - VkCommandBufferBeginInfo commandBufferInfo = {}; - commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - commandBufferInfo.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.renderPass = renderTarget.renderPass; - renderPassBeginInfo.renderArea.offset.x = 0; - renderPassBeginInfo.renderArea.offset.y = 0; - renderPassBeginInfo.renderArea.extent.width = width; - renderPassBeginInfo.renderArea.extent.height = width; - renderPassBeginInfo.clearValueCount = 2; - renderPassBeginInfo.pClearValues = clearValues; - for (size_t i = 0; i < commands.size(); ++i) { - // Set target frame buffer - renderPassBeginInfo.framebuffer = renderTarget.framebuffers[i]; - - VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &commandBufferInfo)); - - for ( auto graphic : graphics ) { - graphic->createImageMemoryBarrier(commands[i]); - } - - // Start the first sub pass specified in our default render pass setup by the base class - // This will clear the color and depth attachment - vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - // Update dynamic viewport state - VkViewport viewport = {}; - viewport.height = (float) height; - viewport.width = (float) width; - viewport.minDepth = (float) 0.0f; - viewport.maxDepth = (float) 1.0f; - vkCmdSetViewport(commands[i], 0, 1, &viewport); - // Update dynamic scissor state - VkRect2D scissor = {}; - scissor.extent.width = width; - scissor.extent.height = height; - scissor.offset.x = 0; - scissor.offset.y = 0; - vkCmdSetScissor(commands[i], 0, 1, &scissor); - - for ( auto pass : passes ) { - ext::vulkan::currentPass = pass; - for ( auto graphic : graphics ) { - graphic->createCommandBuffer(commands[i] ); - } - } - vkCmdEndRenderPass(commands[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(commands[i])); - } } void ext::vulkan::RenderMode::render() { // Get next image in the swap chain (back/front buffer) - VK_CHECK_RESULT(swapchain.acquireNextImage(¤tBuffer)); + VK_CHECK_RESULT(swapchain.acquireNextImage(¤tBuffer, swapchain.presentCompleteSemaphore)); // Use a fence to wait until the command buffer has finished execution before using it again - VK_CHECK_RESULT(vkWaitForFences(*device, 1, &waitFences[currentBuffer], VK_TRUE, UINT64_MAX)); - VK_CHECK_RESULT(vkResetFences(*device, 1, &waitFences[currentBuffer])); + VK_CHECK_RESULT(vkWaitForFences(*device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX)); + VK_CHECK_RESULT(vkResetFences(*device, 1, &fences[currentBuffer])); // Pipeline stage at which the queue submission will wait (via pWaitSemaphores) VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; @@ -131,20 +56,20 @@ void ext::vulkan::RenderMode::render() { 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 = &presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing + submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing submitInfo.waitSemaphoreCount = 1; // One wait semaphore - submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed + submitInfo.pSignalSemaphores = &swapchain.renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed submitInfo.signalSemaphoreCount = 1; // One signal semaphore submitInfo.pCommandBuffers = &commands[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, waitFences[currentBuffer])); + VK_CHECK_RESULT(vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, fences[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, renderCompleteSemaphore)); + VK_CHECK_RESULT(swapchain.queuePresent(device->presentQueue, currentBuffer, swapchain.renderCompleteSemaphore)); VK_CHECK_RESULT(vkQueueWaitIdle(device->presentQueue)); } @@ -156,36 +81,25 @@ void ext::vulkan::RenderMode::initialize( Device& device ) { // Create command buffers { - drawCommandBuffers.resize( buffers ); + commands.resize( swapchain.buffers ); VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo( device.commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, - static_cast(drawCommandBuffers.size()) + static_cast(commands.size()) ); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, drawCommandBuffers.data())); + VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, commands.data())); } // Set sync objects { - // Semaphores (Used for correct command ordering) - VkSemaphoreCreateInfo semaphoreCreateInfo = {}; - semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - semaphoreCreateInfo.pNext = nullptr; - - // Semaphore used to ensures that image presentation is complete before starting to submit again - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &presentCompleteSemaphore)); - - // Semaphore used to ensures that all commands submitted have been finished before submitting the image to the queue - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderCompleteSemaphore)); - // Fences (Used to check draw command buffer completion) VkFenceCreateInfo fenceCreateInfo = {}; fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; // Create in signaled state so we don't wait on first render of each command buffer fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - waitFences.resize( buffers ); - for ( auto& fence : waitFences ) { + fences.resize( commands.size() ); + for ( auto& fence : fences ) { VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); } @@ -194,13 +108,14 @@ void ext::vulkan::RenderMode::initialize( Device& device ) { } void ext::vulkan::RenderMode::destroy() { + renderTarget.destroy(); + if ( commands.size() > 0 ) { vkFreeCommandBuffers( *device, device->commandPool, static_cast(commands.size()), commands.data()); } - if ( presentCompleteSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( *device, presentCompleteSemaphore, nullptr); - } - if ( renderCompleteSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( *device, renderCompleteSemaphore, nullptr); + + for ( auto& fence : fences ) { + vkDestroyFence( *device, fence, nullptr); + fence = VK_NULL_HANDLE; } } \ No newline at end of file diff --git a/engine/src/ext/vulkan/rendermodes/base.cpp b/engine/src/ext/vulkan/rendermodes/base.cpp index bbfd0339..0e07ad0a 100644 --- a/engine/src/ext/vulkan/rendermodes/base.cpp +++ b/engine/src/ext/vulkan/rendermodes/base.cpp @@ -6,13 +6,17 @@ #include #include +namespace { + std::vector images; +} + /* ext::vulkan::BaseRenderMode::~BaseRenderMode() { this->destroy(); } */ std::string ext::vulkan::BaseRenderMode::getType() const { - return "Base"; + return "Swapchain"; } const std::string& ext::vulkan::BaseRenderMode::getName() const { return this->name; @@ -20,36 +24,14 @@ const std::string& ext::vulkan::BaseRenderMode::getName() const { size_t ext::vulkan::BaseRenderMode::subpasses() const { return 1; } -VkRenderPass& ext::vulkan::BaseRenderMode::getRenderPass() { - return swapchain.renderPass; -} - -void ext::vulkan::BaseRenderMode::createCommandBuffers() { - std::vector graphics; - std::function filter = [&]( uf::Entity* entity ) { - if ( !entity->hasComponent() ) return; - uf::MeshBase& mesh = entity->getComponent(); - if ( !mesh.generated ) return; - ext::vulkan::Graphic& graphic = mesh.graphic; - if ( !graphic.initialized ) return; - if ( !graphic.renderMode ) return; - graphics.push_back(&graphic); - }; - for ( uf::Scene* scene : ext::vulkan::scenes ) { - if ( !scene ) continue; - scene->process(filter); - } - - createCommandBuffers( graphics, ext::vulkan::passes ); -} void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector& graphics, const std::vector& passes ) { // destroy if exists - if ( swapchain.initialized ) { - auto* device = swapchain.device; - bool vsync = swapchain.vsync; - swapchain.destroy(); - swapchain.initialize( *device ); + if ( ext::vulkan::rebuild ) { + this->destroy(); + this->initialize( *this->device ); } + renderTarget.initialized = true; + if ( ext::vulkan::renderModes.size() > 1 ) return; float width = width > 0 ? this->width : ext::vulkan::width; float height = height > 0 ? this->height : ext::vulkan::height; @@ -71,7 +53,7 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vectorgraphicsQueue, 1, &submitInfo, 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, renderCompleteSemaphore)); - VK_CHECK_RESULT(vkQueueWaitIdle(device->presentQueue)); + if ( ext::vulkan::renderModes.size() > 1 ) return; + ext::vulkan::RenderMode::render(); } void ext::vulkan::BaseRenderMode::initialize( Device& device ) { - this->device = &device; + this->name = "Swapchain"; + ext::vulkan::RenderMode::initialize( device ); + // manual initialization + // recreate swapchain + // destroy any existing imageviews + // attachments marked as aliased are actually from the swapchain - this->width = ext::vulkan::width; - this->height = ext::vulkan::height; + swapchain.destroy(); + swapchain.initialize( device ); + // bind swapchain images + images.resize( ext::vulkan::swapchain.buffers ); + VK_CHECK_RESULT(vkGetSwapchainImagesKHR( device, swapchain.swapChain, &swapchain.buffers, images.data())); + // create image views for swapchain images + renderTarget.attachments.clear(); + renderTarget.attachments.resize( ext::vulkan::swapchain.buffers + 1 ); + for ( size_t i = 0; i < images.size(); ++i ) { + VkImageViewCreateInfo colorAttachmentView = {}; + colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + colorAttachmentView.pNext = NULL; + colorAttachmentView.format = device.formats.color; + colorAttachmentView.components = { + VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A + }; + colorAttachmentView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + colorAttachmentView.subresourceRange.baseMipLevel = 0; + colorAttachmentView.subresourceRange.levelCount = 1; + colorAttachmentView.subresourceRange.baseArrayLayer = 0; + colorAttachmentView.subresourceRange.layerCount = 1; + colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D; + colorAttachmentView.flags = 0; + colorAttachmentView.image = images[i]; + VK_CHECK_RESULT(vkCreateImageView( device, &colorAttachmentView, nullptr, &renderTarget.attachments[i].view)); + + renderTarget.attachments[i].image = images[i]; + renderTarget.attachments[i].format = device.formats.color; + renderTarget.attachments[i].layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + renderTarget.attachments[i].usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + renderTarget.attachments[i].aliased = true; + renderTarget.attachments[i].mem = VK_NULL_HANDLE; + } + // Create depth + auto& depthAttachment = renderTarget.attachments.back(); + { + // 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 = device.formats.depth; + // 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, &depthAttachment.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, depthAttachment.image, &memReqs); + memAlloc.allocationSize = memReqs.size; + memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &depthAttachment.mem)); + VK_CHECK_RESULT(vkBindImageMemory(device, depthAttachment.image, depthAttachment.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 = device.formats.depth; + 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 = depthAttachment.image; + + VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthAttachment.view)); + + } + // Create renderpass + if ( !renderTarget.renderPass ) {// Create render pass + // This example will use a single render pass with one subpass + + // Descriptors for the attachments used by this renderpass + std::array attachments = {}; + + // Color attachment + attachments[0].format = device.formats.color; // 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_PRESENT_SRC_KHR; // 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 = device.formats.depth; // 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 + + // Setup a single subpass reference + 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; + dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | 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; + dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[1].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 + + VK_CHECK_RESULT(vkCreateRenderPass( device, &renderPassInfo, nullptr, &renderTarget.renderPass)); + } + // Create framebuffer + { + // Create a frame buffer for every image in the swapchain + renderTarget.framebuffers.resize(images.size()); + for (size_t i = 0; i < renderTarget.framebuffers.size(); i++) + { + std::array attachments; + attachments[0] = renderTarget.attachments[i].view; // Color attachment is the view of the swapchain image + attachments[1] = depthAttachment.view; // Depth/Stencil attachment is the same for all frame buffers + + VkFramebufferCreateInfo frameBufferCreateInfo = {}; + frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + // All frame buffers use the same renderpass setup + frameBufferCreateInfo.renderPass = renderTarget.renderPass; + frameBufferCreateInfo.attachmentCount = static_cast(attachments.size()); + frameBufferCreateInfo.pAttachments = attachments.data(); + frameBufferCreateInfo.width = width; + frameBufferCreateInfo.height = height; + frameBufferCreateInfo.layers = 1; + // Create the framebuffer + VK_CHECK_RESULT(vkCreateFramebuffer( device, &frameBufferCreateInfo, nullptr, &renderTarget.framebuffers[i])); + } + + } +/* { renderTarget.device = &device; // attach targets @@ -161,8 +315,10 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) { size_t color, depth; } attachments; - attachments.color = renderTarget.attach( device.formats.color, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ); // color - attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ); // depth + attachments.color = 0; { + + } + attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ); // depth // First pass: fill the G-Buffer { @@ -175,19 +331,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) { } } renderTarget.initialize( device ); - - // Create command buffers - { - commands.resize( buffers ); - - VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo( - device.commandPool, - VK_COMMAND_BUFFER_LEVEL_PRIMARY, - static_cast(commands.size()) - ); - - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, commands.data())); - } +*/ // Set sync objects { // Semaphores (Used for correct command ordering) @@ -196,33 +340,47 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) { semaphoreCreateInfo.pNext = nullptr; // Semaphore used to ensures that image presentation is complete before starting to submit again - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &presentCompleteSemaphore)); + VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &swapchain.presentCompleteSemaphore)); // Semaphore used to ensures that all commands submitted have been finished before submitting the image to the queue - VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderCompleteSemaphore)); - - // Fences (Used to check draw command buffer completion) - VkFenceCreateInfo fenceCreateInfo = {}; - fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - // Create in signaled state so we don't wait on first render of each command buffer - fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - waitFences.resize( buffers ); - for ( auto& fence : waitFences ) { - VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); - } - - VkPipelineStageFlags submitPipelineStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &swapchain.renderCompleteSemaphore)); } } void ext::vulkan::BaseRenderMode::destroy() { - if ( commands.size() > 0 ) { - vkFreeCommandBuffers( *device, device->commandPool, static_cast(commands.size()), commands.data()); + ext::vulkan::RenderMode::destroy(); + + if ( renderTarget.renderPass != VK_NULL_HANDLE ) { + vkDestroyRenderPass( *device, renderTarget.renderPass, nullptr ); + renderTarget.renderPass = VK_NULL_HANDLE; } - if ( presentCompleteSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( *device, presentCompleteSemaphore, nullptr); + + for ( uint32_t i = 0; i < renderTarget.framebuffers.size(); i++ ) { + if ( renderTarget.framebuffers[i] != VK_NULL_HANDLE ) { + vkDestroyFramebuffer( *device, renderTarget.framebuffers[i], nullptr ); + renderTarget.framebuffers[i] = VK_NULL_HANDLE; + } } - if ( renderCompleteSemaphore != VK_NULL_HANDLE ) { - vkDestroySemaphore( *device, renderCompleteSemaphore, nullptr); + for ( auto& attachment : renderTarget.attachments ) { + if ( attachment.view != VK_NULL_HANDLE ) { + vkDestroyImageView( *device, attachment.view, nullptr); + attachment.view = VK_NULL_HANDLE; + } + if ( attachment.aliased ) continue; + if ( attachment.image != VK_NULL_HANDLE ) { + vkDestroyImage( *device, attachment.image, nullptr ); + attachment.image = VK_NULL_HANDLE; + } + if ( attachment.mem != VK_NULL_HANDLE ) { + vkFreeMemory( *device, attachment.mem, nullptr ); + attachment.mem = VK_NULL_HANDLE; + } + } + + if ( swapchain.presentCompleteSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( *device, swapchain.presentCompleteSemaphore, nullptr); + } + if ( swapchain.renderCompleteSemaphore != VK_NULL_HANDLE ) { + vkDestroySemaphore( *device, swapchain.renderCompleteSemaphore, nullptr); } } \ No newline at end of file diff --git a/engine/src/ext/vulkan/rendermodes/deferred.cpp b/engine/src/ext/vulkan/rendermodes/deferred.cpp index 83b96b27..27937675 100644 --- a/engine/src/ext/vulkan/rendermodes/deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/deferred.cpp @@ -16,9 +16,6 @@ std::string ext::vulkan::DeferredRenderMode::getType() const { size_t ext::vulkan::DeferredRenderMode::subpasses() const { return renderTarget.passes.size(); } -VkRenderPass& ext::vulkan::DeferredRenderMode::getRenderPass() { - return renderTarget.renderPass; -} void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { ext::vulkan::RenderMode::initialize( device ); @@ -29,13 +26,18 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { size_t albedo, normals, depth, output; } attachments; - attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ); // albedo - attachments.normals = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ); // normals - attachments.depth = renderTarget.attach( swapchain.depthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ); // depth + attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo + attachments.normals = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // normals + attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ); // depth // Attach swapchain's image as output { attachments.output = renderTarget.attachments.size(); - renderTarget.attachments.push_back({ device.formats.color, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, }); + RenderTarget::Attachment swapchainAttachment; + swapchainAttachment.format = device.formats.color; + swapchainAttachment.usage = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + swapchainAttachment.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + swapchainAttachment.aliased = true; + renderTarget.attachments.push_back(swapchainAttachment); } // First pass: fill the G-Buffer @@ -43,6 +45,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { renderTarget.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.albedo }, {}, attachments.depth ); @@ -53,13 +56,14 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT, { attachments.output, }, { attachments.albedo, attachments.normals }, + // { attachments.albedo }, attachments.depth ); } } renderTarget.initialize( device ); - blitter.framebuffer = &framebuffer; + blitter.renderTarget = &renderTarget; blitter.initializeShaders({ {"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT}, {"./data/shaders/display.subpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} @@ -67,25 +71,18 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { blitter.initialize( device, *this ); } void ext::vulkan::DeferredRenderMode::destroy() { - renderTarget.destroy(); + ext::vulkan::RenderMode::destroy(); + blitter.destroy(); } void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector& graphics, const std::vector& passes ) { // destroy if exists // ext::vulkan::RenderMode& swapchain = if ( ext::vulkan::rebuild ) { - if ( swapchain.initialized ) { - auto* device = swapchain.device; - swapchain.destroy(); - swapchain.initialize( *device ); - } - swapchain.initialized = true; - // destroy if exist - if ( renderTarget.initialized ) { + { auto* device = renderTarget.device; renderTarget.initialize( *device ); } - renderTarget.initialized = true; // update descriptor set if ( blitter.initialized ) { @@ -109,7 +106,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr ); + blitter.initializeDescriptorSet( writeDescriptorSets ); } } @@ -121,8 +118,8 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector clearValues; clearValues.resize(4); @@ -144,7 +141,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vectorcreateImageMemoryBarrier(swapchain.commands[i]); + graphic->createImageMemoryBarrier(commands[i]); } // Update dynamic viewport state @@ -161,30 +158,30 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vectorrenderMode->getName() != this->getName() ) continue; - graphic->createCommandBuffer(swapchain.commands[i] ); + graphic->createCommandBuffer(commands[i] ); } } - vkCmdNextSubpass(swapchain.commands[i], VK_SUBPASS_CONTENTS_INLINE); - blitter.createCommandBuffer(swapchain.commands[i]); + vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); + blitter.createCommandBuffer(commands[i]); // render gui layer { RenderMode* layer = &ext::vulkan::getRenderMode("Gui"); if ( layer->getName() == "Gui" ) { RenderTargetRenderMode* guiLayer = (RenderTargetRenderMode*) layer; - guiLayer->blitter.createCommandBuffer(swapchain.commands[i]); + guiLayer->blitter.createCommandBuffer(commands[i]); } } - vkCmdEndRenderPass(swapchain.commands[i]); + vkCmdEndRenderPass(commands[i]); } - VK_CHECK_RESULT(vkEndCommandBuffer(swapchain.commands[i])); + VK_CHECK_RESULT(vkEndCommandBuffer(commands[i])); } } \ No newline at end of file diff --git a/engine/src/ext/vulkan/rendermodes/multiview.cpp b/engine/src/ext/vulkan/rendermodes/multiview.cpp.x similarity index 96% rename from engine/src/ext/vulkan/rendermodes/multiview.cpp rename to engine/src/ext/vulkan/rendermodes/multiview.cpp.x index 14a0c371..b61566c7 100644 --- a/engine/src/ext/vulkan/rendermodes/multiview.cpp +++ b/engine/src/ext/vulkan/rendermodes/multiview.cpp.x @@ -10,15 +10,16 @@ namespace { uint8_t DOMINANT_EYE = 1; } +ext::vulkan::MultiviewRenderMode::MultiviewRenderMode() : rendertargets.left( rendertarget ) { + +} + std::string ext::vulkan::MultiviewRenderMode::getType() const { return "Multiview"; } size_t ext::vulkan::MultiviewRenderMode::subpasses() const { return rendertargets.left.passes.size(); } -VkRenderPass& ext::vulkan::MultiviewRenderMode::getRenderPass() { - return rendertargets.left.renderPass; -} void ext::vulkan::MultiviewRenderMode::initialize( Device& device ) { rendertargets.left.initialize( device ); diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index 72059ea9..0845ec4d 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -10,9 +10,6 @@ std::string ext::vulkan::RenderTargetRenderMode::getType() const { size_t ext::vulkan::RenderTargetRenderMode::subpasses() const { return renderTarget.passes.size(); } -VkRenderPass& ext::vulkan::RenderTargetRenderMode::getRenderPass() { - return renderTarget.renderPass; -} void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { ext::vulkan::RenderMode::initialize( device ); @@ -23,8 +20,8 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { size_t color, depth; } attachments; - attachments.color = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ); // albedo - attachments.depth = renderTarget.attach( swapchain.depthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ); // depth + attachments.color = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo + attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ); // depth // First pass: write to target { @@ -38,58 +35,38 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { } renderTarget.initialize( device ); - blitter.framebuffer = &framebuffer; + blitter.renderTarget = &renderTarget; blitter.initializeShaders({ {"./data/shaders/display.rendertarget.vert.spv", VK_SHADER_STAGE_VERTEX_BIT}, {"./data/shaders/display.rendertarget.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT} }); blitter.initialize(); - - // Create command buffers - { - VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo( - device.commandPool, - VK_COMMAND_BUFFER_LEVEL_PRIMARY, - 1 - ); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &commandBuffer)); - } - // Set sync objects - { - // Fence for syncs - VkFenceCreateInfo fenceCreateInfo = ext::vulkan::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT); - VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); - } } void ext::vulkan::RenderTargetRenderMode::destroy() { - renderTarget.destroy(); - - if ( fence != VK_NULL_HANDLE ) { - vkDestroyFence(*device, fence, nullptr); - fence = VK_NULL_HANDLE; - } + ext::vulkan::RenderMode::destroy(); + blitter.destroy(); } void ext::vulkan::RenderTargetRenderMode::render() { // Submit commands // Use a fence to ensure that command buffer has finished executing before using it again - vkWaitForFences( *device, 1, &fence, VK_TRUE, UINT64_MAX ); - vkResetFences( *device, 1, &fence ); + vkWaitForFences( *device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX ); + vkResetFences( *device, 1, &fences[currentBuffer] ); VkSubmitInfo renderSubmitInfo = ext::vulkan::initializers::submitInfo(); renderSubmitInfo.commandBufferCount = 1; - renderSubmitInfo.pCommandBuffers = &commandBuffer; + renderSubmitInfo.pCommandBuffers = &commands[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(device->graphicsQueue, 1, &renderSubmitInfo, fence)); + VK_CHECK_RESULT(vkQueueSubmit(device->graphicsQueue, 1, &renderSubmitInfo, fences[currentBuffer])); } void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vector& graphics, const std::vector& passes ) { // destroy if exists - if ( swapchain.rebuild ) { + if ( ext::vulkan::rebuild ) { // destroy if exist - if ( renderTarget.commandBufferSet ) { + if ( renderTarget.initialized ) { auto* device = renderTarget.device; renderTarget.initialize( *device ); } - renderTarget.commandBufferSet = true; + renderTarget.initialized = true; // update descriptor set if ( blitter.initialized ) { @@ -125,54 +102,56 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmdBufInfo.pNext = nullptr; - VK_CHECK_RESULT(vkBeginCommandBuffer(commandBuffer, &cmdBufInfo)); - { - std::vector clearValues; clearValues.resize(2); - clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - clearValues[1].depthStencil = { 1.0f, 0 }; + for (size_t i = 0; i < commands.size(); ++i) { + VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo)); + { + std::vector clearValues; clearValues.resize(2); + clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 0.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 = clearValues.size(); - renderPassBeginInfo.pClearValues = &clearValues[0]; - renderPassBeginInfo.renderPass = renderTarget.renderPass; - renderPassBeginInfo.framebuffer = renderTarget.framebuffers[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 = clearValues.size(); + renderPassBeginInfo.pClearValues = &clearValues[0]; + renderPassBeginInfo.renderPass = renderTarget.renderPass; + renderPassBeginInfo.framebuffer = renderTarget.framebuffers[i]; - for ( auto graphic : graphics ) { - graphic.createImageMemoryBarrier(commandBuffer); + for ( auto graphic : graphics ) { + graphic->createImageMemoryBarrier(commands[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(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdSetViewport(commands[i], 0, 1, &viewport); + vkCmdSetScissor(commands[i], 0, 1, &scissor); + for ( auto pass : passes ) { + ext::vulkan::currentPass = pass + ";TOTEXTURE"; + for ( auto graphic : graphics ) { + if ( graphic->renderMode && graphic->renderMode->getName() != this->getName() ) continue; + graphic->createCommandBuffer(commands[i] ); + } + } + vkCmdEndRenderPass(commands[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(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdSetViewport(commandBuffer, 0, 1, &viewport); - vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - for ( auto pass : passes ) { - ext::vulkan::currentPass = pass + ";TOTEXTURE"; - for ( auto graphic : graphics ) { - if ( graphic->renderMode && graphic->renderMode->getName() != this->getName() ) continue; - graphic->createCommandBuffer(commandBuffer ); - } - } - vkCmdEndRenderPass(commandBuffer); + VK_CHECK_RESULT(vkEndCommandBuffer(commands[i])); } - - VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer)); } \ No newline at end of file diff --git a/engine/src/ext/vulkan/rendertarget.cpp b/engine/src/ext/vulkan/rendertarget.cpp index 5640a1a5..8d48d97c 100644 --- a/engine/src/ext/vulkan/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendertarget.cpp @@ -16,7 +16,7 @@ void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFla if ( depth < attachments.size() ) pass.depth = { depth, attachments[depth].layout }; passes.push_back(pass); } -size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usage, Attachment* attachment ) { +size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usage, VkImageLayout layout, Attachment* attachment ) { if ( width == 0 ) width = ext::vulkan::width; if ( height == 0 ) height = ext::vulkan::height; @@ -24,20 +24,29 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa attachments.resize(attachments.size()+1); attachment = &attachments.back(); } else { - vkDestroyImageView(*device, attachment->view, nullptr); - vkDestroyImage(*device, attachment->image, nullptr); - vkFreeMemory(*device, attachment->mem, nullptr); + if ( attachment->view ) { + vkDestroyImageView(*device, attachment->view, nullptr); + attachment->view = VK_NULL_HANDLE; + } + if ( attachment->image ) { + vkDestroyImage(*device, attachment->image, nullptr); + attachment->image = VK_NULL_HANDLE; + } + if ( attachment->mem ) { + vkFreeMemory(*device, attachment->mem, nullptr); + attachment->mem = VK_NULL_HANDLE; + } } 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->layout = layout; attachment->format = format; attachment->usage = usage; @@ -50,7 +59,7 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa 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.usage = usage; image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; VK_CHECK_RESULT(vkCreateImage(*device, &image, nullptr, &attachment->image)); @@ -93,8 +102,8 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) { // resize attachments if necessary if ( initialized ) { for ( auto& attachment: this->attachments ) { - if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue; - attach( attachment.format, attachment.usage, &attachment ); + if ( attachment.aliased ) continue; + attach( attachment.format, attachment.usage, attachment.layout, &attachment ); } } // ensure attachments are already created @@ -168,16 +177,6 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) { 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; @@ -191,18 +190,18 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) { VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass)); } - // Create framebuffer - bool boundToSwapchain = false; - for ( auto& attachment : this->attachments ) { - if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) boundToSwapchain = true; - } { - framebuffers.resize(boundToSwapchain ? swapchain.imageCount : 1); + // destroy previous framebuffers + for ( auto& framebuffer : framebuffers ) vkDestroyFramebuffer( device, framebuffer, nullptr ); + + RenderMode& base = ext::vulkan::getRenderMode( "Swapchain", false ); + framebuffers.resize(ext::vulkan::swapchain.buffers); 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); + if ( attachment.aliased && attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) { + attachments.push_back(base.renderTarget.attachments[i].view); + } else attachments.push_back(attachment.view); } VkFramebufferCreateInfo frameBufferCreateInfo = {}; @@ -218,6 +217,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) { VK_CHECK_RESULT(vkCreateFramebuffer( device, &frameBufferCreateInfo, nullptr, &framebuffers[i])); } } + initialized = true; } void ext::vulkan::RenderTarget::destroy() { @@ -226,7 +226,7 @@ void ext::vulkan::RenderTarget::destroy() { for ( auto& framebuffer : framebuffers ) vkDestroyFramebuffer( *device, framebuffer, nullptr ); for ( auto& attachment : attachments ) { - if ( attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue; + if ( attachment.aliased ) continue; vkDestroyImageView( *device, attachment.view, nullptr ); attachment.view = VK_NULL_HANDLE; vkDestroyImage( *device, attachment.image, nullptr ); diff --git a/engine/src/ext/vulkan/swapchain.cpp b/engine/src/ext/vulkan/swapchain.cpp index a4652ba8..a8745476 100644 --- a/engine/src/ext/vulkan/swapchain.cpp +++ b/engine/src/ext/vulkan/swapchain.cpp @@ -3,7 +3,7 @@ #include #include -VkResult ext::vulkan::Swapchain::acquireNextImage( uint32_t *imageIndex ) { +VkResult ext::vulkan::Swapchain::acquireNextImage( uint32_t* imageIndex, VkSemaphore presentCompleteSemaphore ) { // By setting timeout to UINT64_MAX we will always wait until the next image has been acquired or an actual error is thrown // With that we don't have to handle VK_NOT_READY return vkAcquireNextImageKHR( *device, swapChain, UINT64_MAX, presentCompleteSemaphore, (VkFence) nullptr, imageIndex ); @@ -121,8 +121,8 @@ void ext::vulkan::Swapchain::initialize( Device& device ) { swapchainCI.pNext = NULL; swapchainCI.surface = device.surface; swapchainCI.minImageCount = desiredNumberOfSwapchainImages; - swapchainCI.imageFormat = device->formats.color; - swapchainCI.imageColorSpace = device->formats.space; + swapchainCI.imageFormat = device.formats.color; + swapchainCI.imageColorSpace = device.formats.space; swapchainCI.imageExtent = { swapchainExtent.width, swapchainExtent.height }; swapchainCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; swapchainCI.preTransform = (VkSurfaceTransformFlagBitsKHR)preTransform; @@ -150,7 +150,7 @@ void ext::vulkan::Swapchain::initialize( Device& device ) { // If an existing swap chain is re-created, destroy the old swap chain // This also cleans up all the presentable images - if (oldSwapchain != VK_NULL_HANDLE) vkDestroySwapchainKHR( device.logicalDevice, oldSwapchain, nullptr); + if (oldSwapchain != VK_NULL_HANDLE) vkDestroySwapchainKHR( device.logicalDevice, oldSwapchain, nullptr); VK_CHECK_RESULT(vkGetSwapchainImagesKHR( device.logicalDevice, swapChain, &buffers, NULL)); } } @@ -162,13 +162,6 @@ void ext::vulkan::Swapchain::destroy() { vkDestroySwapchainKHR( *device, swapChain, nullptr); } - for ( auto& fence : waitFences ) { - vkDestroyFence( *device, fence, nullptr); - fence = VK_NULL_HANDLE; - } - - presentCompleteSemaphore = VK_NULL_HANDLE; - renderCompleteSemaphore = VK_NULL_HANDLE; swapChain = 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 f898b14a..1624f349 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -8,8 +8,8 @@ #include #include -uint32_t ext::vulkan::width = 800; -uint32_t ext::vulkan::height = 600; +uint32_t ext::vulkan::width = 1280; +uint32_t ext::vulkan::height = 720; bool ext::vulkan::validation = true; ext::vulkan::Device ext::vulkan::device; @@ -17,15 +17,15 @@ ext::vulkan::Allocator ext::vulkan::allocator; ext::vulkan::Swapchain ext::vulkan::swapchain; std::mutex ext::vulkan::mutex; -bool ext::vulkan::resizedFramebuffer = false; -uint32_t ext::vulkan::currentBuffer = 600; -// std::vector ext::vulkan::graphics; +bool ext::vulkan::rebuild = false; +uint32_t ext::vulkan::currentBuffer = 0; std::vector ext::vulkan::passes = { "BASE" }; -//std::vector* ext::vulkan::graphics = NULL; std::vector ext::vulkan::scenes; std::string ext::vulkan::currentPass = "BASE"; -std::vector ext::vulkan::renderModes; +std::vector ext::vulkan::renderModes = { + new ext::vulkan::BaseRenderMode, +}; VkResult ext::vulkan::CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) { auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); @@ -44,7 +44,8 @@ VKAPI_ATTR VkBool32 VKAPI_CALL ext::vulkan::debugCallback( const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData ) { - std::cerr << "[Validation Layer] " << pCallbackData->pMessage << std::endl; + if ( messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT ) return VK_FALSE; + uf::iostream << "[Validation Layer] " << pCallbackData->pMessage << "\n"; return VK_FALSE; } @@ -52,7 +53,7 @@ VkShaderModule ext::vulkan::loadShader(const char *filename, VkDevice device) { std::ifstream is(filename, std::ios::binary | std::ios::in | std::ios::ate); if ( !is.is_open() ) { - std::cerr << "Error: Could not open shader file \"" << filename << "\"" << std::endl; + uf::iostream << "Error: Could not open shader file \"" << filename << "\"" << "\n"; return VK_NULL_HANDLE; } size_t size = is.tellg(); @@ -155,12 +156,20 @@ ext::vulkan::RenderMode& ext::vulkan::addRenderMode( ext::vulkan::RenderMode* mo renderModes.push_back(mode); return *mode; } -ext::vulkan::RenderMode& ext::vulkan::getRenderMode( const std::string& name ) { - RenderMode* target = renderModes[ renderModes.size()-1 ]; +ext::vulkan::RenderMode& ext::vulkan::getRenderMode( const std::string& name, bool isName ) { + RenderMode* target = renderModes[0]; for ( auto& renderMode: renderModes ) { - if ( renderMode->getName() == name ) { - target = renderMode; - break; + if ( isName ) { + if ( renderMode->getName() == "" ) target = renderMode; + if ( renderMode->getName() == name ) { + target = renderMode; + break; + } + } else { + if ( renderMode->getType() == name ) { + target = renderMode; + break; + } } } return *target; @@ -180,6 +189,7 @@ void ext::vulkan::initialize( uint8_t stage ) { for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; renderMode->initialize(device); + std::cout << "Initialized render mode `" << renderMode->name << "` (" << renderMode->getType() << ")" << std::endl; } /* resort */ { /* @@ -222,7 +232,7 @@ void ext::vulkan::initialize( uint8_t stage ) { if ( !mesh.generated ) return; if ( graphic.initialized ) return; graphic.initialize(); - swapchain.rebuild = true; + ext::vulkan::rebuild = true; }; for ( uf::Scene* scene : ext::vulkan::scenes ) { if ( !scene ) continue; @@ -252,7 +262,7 @@ void ext::vulkan::tick() { auto& graphics = *ext::vulkan::graphics; for ( Graphic* graphic : graphics ) { if ( !graphic->initialized ) { - swapchain.rebuild = true; + ext::vulkan::rebuild = true; graphic->initialize(); } } @@ -265,19 +275,19 @@ void ext::vulkan::tick() { // if ( !graphic->process ) return; if ( !mesh.generated ) return; if ( graphic.initialized ) return; - swapchain.rebuild = true; + ext::vulkan::rebuild = true; graphic.initialize(); }; for ( uf::Scene* scene : ext::vulkan::scenes ) { if ( !scene ) continue; scene->process(filter); } - if ( swapchain.rebuild ) { + if ( ext::vulkan::rebuild ) { for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; renderMode->createCommandBuffers(); } - swapchain.rebuild = false; + ext::vulkan::rebuild = false; } // ext::vulkan::mutex.unlock(); } @@ -311,7 +321,7 @@ void ext::vulkan::render() { } // Handle resizes - if ( resizedFramebuffer ) resizedFramebuffer = false; + if ( ext::vulkan::rebuild ) ext::vulkan::rebuild = false; } void ext::vulkan::destroy() { vkDeviceWaitIdle( device ); @@ -320,21 +330,13 @@ void ext::vulkan::destroy() { if ( !entity->hasComponent() ) return; uf::MeshBase& mesh = entity->getComponent(); ext::vulkan::Graphic& graphic = mesh.graphic; - if ( !graphic.initialized ) return; graphic.destroy(); }; for ( uf::Scene* scene : ext::vulkan::scenes ) { if ( !scene ) continue; scene->process(filter); } -/* - if ( ext::vulkan::graphics ) { - auto& graphics = *ext::vulkan::graphics; - for ( Graphic* graphic : graphics ) { - graphic->destroy(); - } - } -*/ + for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; renderMode->destroy(); @@ -343,6 +345,7 @@ void ext::vulkan::destroy() { } vmaDestroyAllocator( allocator ); + swapchain.destroy(); device.destroy(); } diff --git a/ext/main.cpp b/ext/main.cpp index 35f26fb9..3431ef86 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -110,8 +110,10 @@ void EXT_API ext::initialize() { ext::vulkan::height = ::config["window"]["size"]["y"].asInt(); // setup render mode - ext::vulkan::addRenderMode( new ext::vulkan::DeferredRenderMode, "" ); - // ext::vulkan::addRenderMode( new ext::vulkan::RenderTargetRenderMode, "Gui" ); + if ( ::config["engine"]["render modes"]["deferred"].asBool() ) + ext::vulkan::addRenderMode( new ext::vulkan::DeferredRenderMode, "" ); + if ( ::config["engine"]["render modes"]["gui"].asBool() ) + ext::vulkan::addRenderMode( new ext::vulkan::RenderTargetRenderMode, "Gui" ); ext::vulkan::initialize(); } /* */ { diff --git a/ext/scenes/world/housamo/sprite.cpp b/ext/scenes/world/housamo/sprite.cpp index 7e176db0..46705cdf 100644 --- a/ext/scenes/world/housamo/sprite.cpp +++ b/ext/scenes/world/housamo/sprite.cpp @@ -54,9 +54,9 @@ void ext::HousamoSprite::initialize() { uf::Asset& assetLoader = world.getComponent(); this->addHook( "graphics:Assign.%UID%", [&](const std::string& event)->std::string{ - uf::Mesh& mesh = this->getComponent(); - mesh.graphic.initialize(); - mesh.graphic.autoAssign(); + // uf::Mesh& mesh = this->getComponent(); + // mesh.graphic.initialize(); + // mesh.graphic.autoAssign(); metadata["system"]["control"] = true; metadata["system"]["loaded"] = true; return "true"; @@ -76,15 +76,17 @@ void ext::HousamoSprite::initialize() { uf::Image image = *imagePointer; uf::Mesh& mesh = this->getComponent(); - float scalex = 1.0f; //(640.0f / 1024.0f); - float scaley = 1.0f; //(904.0f / 1024.0f); + float scalex = 1.0f; + float scaley = 1.0f; + // float scaley = ((float) image.getDimensions().x / (float) image.getDimensions().y); + // float scalex = (640.0f / 1024.0f); + // float scaley = (904.0f / 1024.0f); // float scalex = (image.getDimensions().x / 1024.0f); // float scaley = (image.getDimensions().y / 1024.0f); if ( metadata["orientation"] == "landscape" ) { scalex = (904.0f / 1024.0f); scaley = (640.0f / 1024.0f); } - // std::cout << this->m_name ": " << metadata["orientation"] << std::endl; mesh.vertices = { {{-1*-0.5f, 0.0f, 0.0f}, {scalex*1.0f, scaley*0.0f}, { 0.0f, 0.0f, -1.0f } }, {{-1*0.5f, 0.0f, 0.0f}, {scalex*0.0f, scaley*0.0f}, { 0.0f, 0.0f, -1.0f } }, diff --git a/ext/scenes/world/terrain/generator.cpp b/ext/scenes/world/terrain/generator.cpp index 00b8bbfc..fba3943d 100644 --- a/ext/scenes/world/terrain/generator.cpp +++ b/ext/scenes/world/terrain/generator.cpp @@ -17,7 +17,7 @@ namespace { bool SWIZZLE_OPTIMIZATION = false; - ext::TerrainVoxel::light_t AMBIENT_LIGHT = 0x1111; //{std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; + ext::TerrainVoxel::light_t AMBIENT_LIGHT = 0x6666; //{std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; struct COLOR { uint r : 4; uint g : 4; @@ -204,6 +204,7 @@ void ext::TerrainGenerator::generate( ext::Region& region ){ // if ( (x) % (this->m_size.x / partitions) == 0 ) voxel = atlas.wall; // if ( (z) % (this->m_size.z / partitions) == 0 ) voxel = atlas.wall; + /* if ( (x + 1) % (this->m_size.x / partitions) == 0 ) voxel = atlas.wall; if ( (z + 1) % (this->m_size.z / partitions) == 0 ) voxel = atlas.wall; @@ -211,8 +212,8 @@ void ext::TerrainGenerator::generate( ext::Region& region ){ if ( x % (this->m_size.x / partitions) >= 3 && x % (this->m_size.x / partitions) <= partitions - 4 ) voxel = 0; if ( z % (this->m_size.z / partitions) >= 3 && z % (this->m_size.z / partitions) <= partitions - 4 ) voxel = 0; } + */ if ( y <= 1 ) voxel = atlas.floor; if ( y == this->m_size.y - 1 ) voxel = atlas.ceiling; - if ( uf::vector::sum(location) != 0 ) { if ( e < 0.5 ) voxel = y == 0 ? atlas.lava : 0; // if ( raw_noise[x][1][z] / maxValue < 0.2 || raw_noise[x][2][z] / maxValue > 0.8 ) voxel = atlas.stair; @@ -227,8 +228,8 @@ void ext::TerrainGenerator::generate( ext::Region& region ){ if ( LABYRINTH & ext::Maze::WEST ) if ( x == this->m_size.x - 1 ) voxel = atlas.wall; if ( LABYRINTH & ext::Maze::NORTH ) if ( z == 0 ) voxel = atlas.wall; if ( LABYRINTH & ext::Maze::SOUTH ) if ( z == this->m_size.z - 1 ) voxel = atlas.wall; - if ( LABYRINTH & ext::Maze::FLOOR ) if ( y == 0 ) voxel = atlas.floor; - if ( LABYRINTH & ext::Maze::CEIL ) if ( y == this->m_size.y - 1 ) voxel = atlas.ceiling; + // if ( LABYRINTH & ext::Maze::FLOOR ) if ( y == 0 ) voxel = atlas.floor; + // if ( LABYRINTH & ext::Maze::CEIL ) if ( y == this->m_size.y - 1 ) voxel = atlas.ceiling; if ( light < AMBIENT_LIGHT ) light = AMBIENT_LIGHT; @@ -355,14 +356,14 @@ ext::TerrainVoxel::uid_t ext::TerrainGenerator::getVoxel( int x, int y, int z ) // if ( this->m_voxels.id.raw ) return this->m_voxels.id.raw[x][y][z]; if ( !this->m_voxels.id.raw.empty() ) { - std::size_t i = this->wrapPosition( x, y, z ); + std::size_t i = this->wrapPosition( x, y, z, this->m_voxels.id.swizzle ); return this->m_voxels.id.raw[i]; } std::size_t i = 0; for ( auto& _ : this->m_voxels.id.rle ) { for ( std::size_t __ = 0; __ < _.length; ++__ ) { - auto v = this->unwrapIndex( i++ ); + auto v = this->unwrapIndex( i++, this->m_voxels.id.swizzle ); if ( v.x == x && v.y == y && v.z == z ) return _.value; } } @@ -440,14 +441,14 @@ ext::TerrainVoxel::light_t ext::TerrainGenerator::getLight( int x, int y, int z /* if ( !this->m_voxels.lighting.raw.empty() ) { - std::size_t i = this->wrapPosition( x, y, z ); + std::size_t i = this->wrapPosition( x, y, z, this->m_voxels.lighting.swizzle ); return this->m_voxels.lighting.raw[i]; } */ std::size_t i = 0; for ( auto& _ : this->m_voxels.lighting.rle ) { for ( std::size_t __ = 0; __ < _.length; ++__ ) { - auto v = this->unwrapIndex( i++ ); + auto v = this->unwrapIndex( i++, this->m_voxels.lighting.swizzle ); if ( v.x == x && v.y == y && v.z == z ) { return _.value; } @@ -474,9 +475,9 @@ pod::Vector3ui ext::TerrainGenerator::unwrapIndex( std::size_t i, Swizzle swizzl this->m_size.y, }; return { - i % this->m_size.x, - i / ( this->m_size.x * this->m_size.y ), - ( i / this->m_size.x ) % this->m_size.y, + i % size.x, + i / ( size.x * size.y ), + ( i / size.x ) % size.y, }; break; case Swizzle::ZXY: @@ -486,9 +487,9 @@ pod::Vector3ui ext::TerrainGenerator::unwrapIndex( std::size_t i, Swizzle swizzl this->m_size.z, }; return { - ( i / this->m_size.x ) % this->m_size.y, - i % this->m_size.x, - i / ( this->m_size.x * this->m_size.y ), + ( i / size.x ) % size.y, + i % size.x, + i / ( size.x * size.y ), }; break; case Swizzle::XYZ: @@ -499,9 +500,9 @@ pod::Vector3ui ext::TerrainGenerator::unwrapIndex( std::size_t i, Swizzle swizzl this->m_size.x, }; return { - ( i / this->m_size.x ) % this->m_size.y, - i / ( this->m_size.x * this->m_size.y ), - i % this->m_size.x, + ( i / size.x ) % size.y, + i / ( size.x * size.y ), + i % size.x, }; break; } @@ -565,7 +566,7 @@ void ext::TerrainGenerator::wrapVoxel() { if ( this->m_voxels.id.raw.empty() ) r this->m_voxels.id.swizzle = ext::TerrainGenerator::DEFAULT_SWIZZLE; for ( std::size_t i = 0; i < this->m_size.x * this->m_size.y * this->m_size.z; ++i ) { - auto position = this->unwrapIndex( i ); + auto position = this->unwrapIndex( i, this->m_voxels.id.swizzle ); raw_id[position.x][position.y][position.z] = this->m_voxels.id.raw[i]; } @@ -622,7 +623,6 @@ void ext::TerrainGenerator::wrapVoxel() { if ( this->m_voxels.id.raw.empty() ) r for ( uint x = 0; x < this->m_size.x; x++ ) buffer.push_back( raw_id[x][y][z] ); this->m_voxels.id.swizzle = Swizzle::YZX; - this->m_voxels.id.rle = uf::rle::encode( buffer ); } } @@ -633,7 +633,7 @@ void ext::TerrainGenerator::wrapLight() { if ( this->m_voxels.lighting.raw.empty this->m_voxels.lighting.swizzle = ext::TerrainGenerator::DEFAULT_SWIZZLE; for ( std::size_t i = 0; i < this->m_size.x * this->m_size.y * this->m_size.z; ++i ) { - auto position = this->unwrapIndex( i ); + auto position = this->unwrapIndex( i, this->m_voxels.lighting.swizzle ); raw_lighting[position.x][position.y][position.z] = this->m_voxels.lighting.raw[i]; } @@ -800,7 +800,7 @@ void ext::TerrainGenerator::setVoxel( int x, int y, int z, const ext::TerrainVox if ( region ) region->getComponent()["region"]["modified"] = true; } - std::size_t i = this->wrapPosition(x, y, z); + std::size_t i = this->wrapPosition(x, y, z, this->m_voxels.id.swizzle); this->m_voxels.id.raw[i] = voxel; this->wrapVoxel(); @@ -880,7 +880,7 @@ void ext::TerrainGenerator::setLight( int x, int y, int z, const ext::TerrainVox if ( region ) region->getComponent()["region"]["modified"] = true; } - std::size_t i = this->wrapPosition(x, y, z); + std::size_t i = this->wrapPosition(x, y, z, this->m_voxels.lighting.swizzle); // std::cout << "Set Voxel( " << x << ", " << y << ", " << z << ") ("<< i <<") to level " << light << std::endl; this->m_voxels.lighting.raw[i] = light; this->wrapLight(); @@ -1211,8 +1211,7 @@ void ext::TerrainGenerator::light( const pod::Vector3i& location, const ext::Ter void ext::TerrainGenerator::updateLight(){ // this->unwrapLight(); // set lights to original values - return; - +/* std::size_t i = 0; std::cout << "Updating lights for " << this->m_location.x << ", " << this->m_location.y << ", " << this->m_location.z << std::endl; for ( auto& _ : this->m_voxels.id.rle ) { @@ -1224,10 +1223,10 @@ void ext::TerrainGenerator::updateLight(){ } } //this->wrapLight(); - +*/ // set lights -/* - i = 0; + + std::size_t i = 0; for ( auto& _ : this->m_voxels.id.rle ) { for ( std::size_t __ = 0; __ < _.length; ++__ ) { ext::TerrainVoxel voxel = ext::TerrainVoxel::atlas( _.value ); @@ -1236,7 +1235,6 @@ void ext::TerrainGenerator::updateLight(){ this->light(v.x, v.y, v.z, voxel.light() ); } } -*/ // this->wrapLight(); // this->writeToFile(); } diff --git a/ext/scenes/world/terrain/region.cpp b/ext/scenes/world/terrain/region.cpp index 72d9b4ab..9a3d1160 100644 --- a/ext/scenes/world/terrain/region.cpp +++ b/ext/scenes/world/terrain/region.cpp @@ -126,7 +126,7 @@ void ext::Region::initialize() { if ( first ) { // shiro - { + if ( metadata["region"][""]["NPCs"].asBool() ) { uf::Object* = new ext::HousamoSprite; this->addChild(*); uf::Serializer& pMetadata = ->getComponent(); @@ -137,7 +137,7 @@ void ext::Region::initialize() { pTransform.position += transform.position + pod::Vector3f{ 2, 0, 0 }; } // pong - { + if ( metadata["region"][""]["NPCs"].asBool() ) { uf::Object* = new ext::HousamoSprite; this->addChild(*); uf::Serializer& pMetadata = ->getComponent(); @@ -194,7 +194,9 @@ void ext::Region::destroy() { this->getComponent().destroy(); } if ( this->hasComponent() ) { - this->getComponent().destroy(); + auto& mesh = this->getComponent(); + mesh.graphic.destroy(); + mesh.destroy(); } uf::Object::destroy(); } diff --git a/ext/scenes/world/terrain/terrain.cpp b/ext/scenes/world/terrain/terrain.cpp index 614e4813..5a80ede9 100644 --- a/ext/scenes/world/terrain/terrain.cpp +++ b/ext/scenes/world/terrain/terrain.cpp @@ -45,7 +45,9 @@ void ext::Terrain::destroy() { this->getComponent().destroy(); } if ( this->hasComponent() ) { - this->getComponent().destroy(); + auto& mesh = this->getComponent(); + mesh.graphic.destroy(); + mesh.destroy(); } uf::Object::destroy(); } @@ -296,6 +298,10 @@ void ext::Terrain::tick() { break; } } + { + uf::Serializer& rMetadata = kv->getComponent(); + if ( !rMetadata["region"]["rasterized"].asBool() ) degenerate = false; + } if ( degenerate ) locations.push_back(location); } @@ -495,6 +501,10 @@ void ext::Terrain::tick() { break; } } + { + uf::Serializer& rMetadata = kv->getComponent(); + if ( !rMetadata["region"]["rasterized"].asBool() ) degenerate = false; + } if ( degenerate ) locations.push_back(location); }