diff --git a/engine/gfx/vulkan/include/gfx_vulkan.hpp b/engine/gfx/vulkan/include/gfx_vulkan.hpp index 21e0988..3973dee 100755 --- a/engine/gfx/vulkan/include/gfx_vulkan.hpp +++ b/engine/gfx/vulkan/include/gfx_vulkan.hpp @@ -75,6 +75,7 @@ private: uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); void transitionImageLayout(VkImage image, VkFormat format, VkImageAspectFlags aspect, VkImageLayout oldLayout, VkImageLayout newLayout); + void inlineTransitionImageLayout(VkCommandBuffer command_buffer, VkImage image, VkFormat format, VkImageAspectFlags aspect, VkImageLayout oldLayout, VkImageLayout newLayout); VkShaderModule createShaderModule(const uint32_t* code, const int length); VkCommandBuffer beginSingleTimeCommands(); void endSingleTimeCommands(VkCommandBuffer commandBuffer); diff --git a/engine/gfx/vulkan/src/gfx_vulkan.cpp b/engine/gfx/vulkan/src/gfx_vulkan.cpp index acbc864..4fd20cd 100755 --- a/engine/gfx/vulkan/src/gfx_vulkan.cpp +++ b/engine/gfx/vulkan/src/gfx_vulkan.cpp @@ -266,26 +266,7 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) { imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; } - VkImageLayout imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - if ((info.usage & GFXTextureUsage::Attachment) == GFXTextureUsage::Attachment) { - if (info.format == GFXPixelFormat::DEPTH_32F) { - if((info.usage & GFXTextureUsage::Sampled) == GFXTextureUsage::Sampled) - imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - else - imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - } - else { - if((info.usage & GFXTextureUsage::Sampled) == GFXTextureUsage::Sampled) - imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - else - imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } - } - else { - imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - - VkImageAspectFlags imageAspect; + VkImageAspectFlagBits imageAspect; if (info.format == GFXPixelFormat::DEPTH_32F) imageAspect = VK_IMAGE_ASPECT_DEPTH_BIT; else @@ -318,10 +299,11 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) { vkCreateImage(device, &imageInfo, nullptr, &texture->handle); - texture->layout = imageLayout; texture->width = info.width; texture->height = info.height; texture->format = imageFormat; + texture->aspect = imageAspect; + texture->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // allocate memory VkMemoryRequirements memRequirements; @@ -336,8 +318,6 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) { vkBindImageMemory(device, texture->handle, texture->memory, 0); - transitionImageLayout(texture->handle, imageFormat, imageAspect, VK_IMAGE_LAYOUT_UNDEFINED, imageLayout); - // create image view VkImageViewCreateInfo viewInfo = {}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; @@ -426,12 +406,12 @@ void GFXVulkan::copy_texture(GFXTexture* texture, void* data, GFXSize size) { vkUnmapMemory(device, stagingBufferMemory); // copy staging buffer to image - transitionImageLayout(vulkanTexture->handle, vulkanTexture->format, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); + inlineTransitionImageLayout(commandBuffer, vulkanTexture->handle, vulkanTexture->format, vulkanTexture->aspect, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + VkBufferImageCopy region = {}; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.aspectMask = vulkanTexture->aspect; region.imageSubresource.mipLevel = 0; region.imageSubresource.baseArrayLayer = 0; region.imageSubresource.layerCount = 1; @@ -443,9 +423,9 @@ void GFXVulkan::copy_texture(GFXTexture* texture, void* data, GFXSize size) { vkCmdCopyBufferToImage(commandBuffer, stagingBuffer, vulkanTexture->handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - endSingleTimeCommands(commandBuffer); + inlineTransitionImageLayout(commandBuffer, vulkanTexture->handle, vulkanTexture->format, vulkanTexture->aspect, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - transitionImageLayout(vulkanTexture->handle, vulkanTexture->format, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + endSingleTimeCommands(commandBuffer); } void GFXVulkan::copy_texture(GFXTexture* from, GFXTexture* to) { @@ -453,7 +433,25 @@ void GFXVulkan::copy_texture(GFXTexture* from, GFXTexture* to) { } void GFXVulkan::copy_texture(GFXTexture* from, GFXBuffer* to) { - console::error(System::GFX, "Copy Texture->Buffer unimplemented!"); + GFXVulkanTexture* vulkanTexture = (GFXVulkanTexture*)from; + GFXVulkanBuffer* vulkanBuffer = (GFXVulkanBuffer*)to; + + VkCommandBuffer commandBuffer = beginSingleTimeCommands(); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = vulkanTexture->aspect; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + region.imageExtent = { + (uint32_t)vulkanTexture->width, + (uint32_t)vulkanTexture->height, + 1 + }; + + vkCmdCopyImageToBuffer(commandBuffer, vulkanTexture->handle, vulkanTexture->layout, vulkanBuffer->get(0).handle, 1, ®ion); + + endSingleTimeCommands(commandBuffer); } GFXSampler* GFXVulkan::create_sampler(const GFXSamplerCreateInfo& info) { @@ -492,6 +490,12 @@ GFXFramebuffer* GFXVulkan::create_framebuffer(const GFXFramebufferCreateInfo& in for (auto& attachment : info.attachments) { GFXVulkanTexture* texture = (GFXVulkanTexture*)attachment; attachments.push_back(texture->view); + + VkImageLayout expectedLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + if (texture->aspect & VK_IMAGE_ASPECT_DEPTH_BIT) + expectedLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + transitionImageLayout(texture->handle, texture->format, texture->aspect, texture->layout, expectedLayout); } VkFramebufferCreateInfo framebufferInfo = {}; @@ -530,10 +534,6 @@ GFXRenderPass* GFXVulkan::create_render_pass(const GFXRenderPassCreateInfo& info if (info.attachments[i] == GFXPixelFormat::DEPTH_32F) isDepthAttachment = true; - VkImageLayout imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - if (isDepthAttachment) - imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - VkAttachmentDescription attachment = {}; attachment.format = toVkFormat(info.attachments[i]); attachment.samples = VK_SAMPLE_COUNT_1_BIT; @@ -542,17 +542,19 @@ GFXRenderPass* GFXVulkan::create_render_pass(const GFXRenderPassCreateInfo& info attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachment.finalLayout = imageLayout; - if (imageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) - attachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - if (imageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + if (isDepthAttachment) attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + else + attachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; VkAttachmentReference attachmentRef = {}; attachmentRef.attachment = i; - attachmentRef.layout = imageLayout; + + if (isDepthAttachment) + attachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + else + attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; if (isDepthAttachment) { hasDepthAttachment = true; @@ -1021,6 +1023,10 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) { if (!currentPipeline->cachedDescriptorSets.count(getDescriptorHash(currentPipeline))) cacheDescriptorState(currentPipeline, currentPipeline->descriptorLayout); + for (auto [texture, trans] : currentPipeline->expectedTransisitions) { + inlineTransitionImageLayout(commandBuffers[imageIndex], texture->handle, texture->format, texture->aspect, trans.oldLayout, trans.newLayout); + } + vkCmdBindDescriptorSets(commandBuffers[imageIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->layout, 0, 1, ¤tPipeline->cachedDescriptorSets[getDescriptorHash(currentPipeline)], 0, nullptr); lastDescriptorHash = getDescriptorHash(currentPipeline); @@ -1035,6 +1041,10 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) { if (!currentPipeline->cachedDescriptorSets.count(getDescriptorHash(currentPipeline))) cacheDescriptorState(currentPipeline, currentPipeline->descriptorLayout); + for (auto [texture, trans] : currentPipeline->expectedTransisitions) { + inlineTransitionImageLayout(commandBuffers[imageIndex], texture->handle, texture->format, texture->aspect, trans.oldLayout, trans.newLayout); + } + vkCmdBindDescriptorSets(commandBuffers[imageIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->layout, 0, 1, ¤tPipeline->cachedDescriptorSets[getDescriptorHash(currentPipeline)], 0, nullptr); lastDescriptorHash = getDescriptorHash(currentPipeline); @@ -1114,8 +1124,8 @@ void GFXVulkan::createInstance(std::vector layers, std::vectorlayout; // color attachments are not the right layout - //if (imageInfo.imageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) - // imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + if (imageInfo.imageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; imageInfo.imageView = vulkanTexture->view; imageInfo.sampler = vulkanTexture->sampler; + //if (imageInfo.imageLayout != vulkanTexture->layout) { + GFXVulkanPipeline::ExpectedTransisition trans; + trans.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + trans.newLayout = imageInfo.imageLayout; + + pipeline->expectedTransisitions[vulkanTexture] = trans; + //} + VkWriteDescriptorSet descriptorWrite = {}; descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorWrite.dstSet = descriptorSet; @@ -1595,7 +1613,13 @@ uint32_t GFXVulkan::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags pr void GFXVulkan::transitionImageLayout(VkImage image, VkFormat format, VkImageAspectFlags aspect, VkImageLayout oldLayout, VkImageLayout newLayout) { VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - VkImageMemoryBarrier barrier = {}; + inlineTransitionImageLayout(commandBuffer, image, format, aspect, oldLayout, newLayout); + + endSingleTimeCommands(commandBuffer); +} + +void GFXVulkan::inlineTransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkFormat format, VkImageAspectFlags aspect, VkImageLayout oldLayout, VkImageLayout newLayout) { + VkImageMemoryBarrier barrier{}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.oldLayout = oldLayout; barrier.newLayout = newLayout; @@ -1607,19 +1631,40 @@ void GFXVulkan::transitionImageLayout(VkImage image, VkFormat format, VkImageAsp barrier.subresourceRange.levelCount = 1; barrier.subresourceRange.baseArrayLayer = 0; barrier.subresourceRange.layerCount = 1; - barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; // TODO - barrier.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; // TODO + + VkPipelineStageFlags sourceStage; + VkPipelineStageFlags destinationStage; + + if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + + sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + } + else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } + else { + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + } vkCmdPipelineBarrier( commandBuffer, - VK_PIPELINE_STAGE_HOST_BIT /* TODO */, VK_PIPELINE_STAGE_HOST_BIT /* TODO */, + sourceStage, destinationStage, 0, 0, nullptr, 0, nullptr, 1, &barrier ); - - endSingleTimeCommands(commandBuffer); } VkShaderModule GFXVulkan::createShaderModule(const uint32_t* code, const int length) { diff --git a/engine/gfx/vulkan/src/gfx_vulkan_pipeline.hpp b/engine/gfx/vulkan/src/gfx_vulkan_pipeline.hpp index c0c73d7..209d052 100755 --- a/engine/gfx/vulkan/src/gfx_vulkan_pipeline.hpp +++ b/engine/gfx/vulkan/src/gfx_vulkan_pipeline.hpp @@ -4,6 +4,8 @@ #include "gfx_pipeline.hpp" +class GFXVulkanTexture; + class GFXVulkanPipeline : public GFXPipeline { public: std::string label; @@ -18,4 +20,11 @@ public: // dynamic descriptor sets std::map cachedDescriptorSets; + + struct ExpectedTransisition { + VkImageLayout oldLayout; + VkImageLayout newLayout; + }; + + std::map expectedTransisitions; }; diff --git a/engine/gfx/vulkan/src/gfx_vulkan_texture.hpp b/engine/gfx/vulkan/src/gfx_vulkan_texture.hpp index cb193f6..6aaca85 100755 --- a/engine/gfx/vulkan/src/gfx_vulkan_texture.hpp +++ b/engine/gfx/vulkan/src/gfx_vulkan_texture.hpp @@ -14,5 +14,6 @@ public: int width, height; VkFormat format; - VkImageLayout layout; + VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED; + VkImageAspectFlagBits aspect; }; diff --git a/engine/renderer/src/renderer.cpp b/engine/renderer/src/renderer.cpp index 71349c5..28fcefc 100755 --- a/engine/renderer/src/renderer.cpp +++ b/engine/renderer/src/renderer.cpp @@ -81,6 +81,12 @@ struct UIPushConstant { Matrix4x4 mvp; }; +struct SkyPushConstant { + Matrix4x4 view; + Vector4 sun_position_fov; + float aspect; +}; + Renderer::Renderer(GFX* gfx, const bool enable_imgui) : gfx(gfx) { Expects(gfx != nullptr); @@ -534,12 +540,7 @@ void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj render_screen(command_buffer, screen.screen, continuity, options); } - struct SkyPushConstant { - Matrix4x4 view; - Vector4 sun_position_fov; - float aspect; - } pc; - + SkyPushConstant pc; pc.view = matrix_from_quat(scene.get(camera_object).rotation); pc.aspect = static_cast(extent.width) / static_cast(extent.height); @@ -956,7 +957,7 @@ void Renderer::createSkyPipeline() { }; pipelineInfo.shader_input.push_constants = { - {sizeof(Matrix4x4) + sizeof(Vector4) + sizeof(float), 0} + {sizeof(SkyPushConstant), 0} }; pipelineInfo.depth.depth_mode = GFXDepthMode::LessOrEqual; diff --git a/shaders/sky.vert.glsl b/shaders/sky.vert.glsl index d317fe5..cef4fd1 100755 --- a/shaders/sky.vert.glsl +++ b/shaders/sky.vert.glsl @@ -1,5 +1,11 @@ layout (location = 0) out vec2 out_uv; +layout(push_constant, binding = 1) uniform PushConstant{ + mat4 view; + vec4 sun_position_fov; + float aspect; +}; + void main() { out_uv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); gl_Position = vec4(out_uv * 2.0f + -1.0f, 1.0f, 1.0f);