diff --git a/engine/gfx/vulkan/src/gfx_vulkan.cpp b/engine/gfx/vulkan/src/gfx_vulkan.cpp index 75eb414..c8ffd2d 100755 --- a/engine/gfx/vulkan/src/gfx_vulkan.cpp +++ b/engine/gfx/vulkan/src/gfx_vulkan.cpp @@ -455,12 +455,19 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) { texture->format = imageFormat; texture->aspect = imageAspect; - if (check_flag(info.usage, GFXTextureUsage::Attachment) && - !check_flag(info.usage, GFXTextureUsage::Sampled)) { - if (info.format == GFXPixelFormat::DEPTH_32F) { - texture->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + if (check_flag(info.usage, GFXTextureUsage::Attachment)) { + if(check_flag(info.usage, GFXTextureUsage::Sampled)) { + if (info.format == GFXPixelFormat::DEPTH_32F) { + texture->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + } else { + texture->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } } else { - texture->layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + if (info.format == GFXPixelFormat::DEPTH_32F) { + texture->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + } else { + texture->layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } } } else if (check_flag(info.usage, GFXTextureUsage::Storage) && check_flag(info.usage, GFXTextureUsage::ShaderWrite)) { @@ -679,19 +686,6 @@ GFXVulkan::create_framebuffer(const GFXFramebufferCreateInfo& info) { for (auto& attachment : info.attachments) { auto 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; - - VkImageSubresourceRange range = {}; - range.baseMipLevel = 0; - range.levelCount = 1; - range.baseArrayLayer = 0; - range.layerCount = 1; - - transitionImageLayout(texture->handle, texture->format, texture->aspect, - range, texture->layout, expectedLayout); } VkFramebufferCreateInfo framebufferInfo = {}; @@ -724,6 +718,9 @@ GFXVulkan::create_render_pass(const GFXRenderPassCreateInfo& info) { std::vector descriptions; std::vector references; + std::vector dependencies; + + bool hasDepthAttachment = false; VkAttachmentDescription depthAttachment; @@ -778,6 +775,52 @@ GFXVulkan::create_render_pass(const GFXRenderPassCreateInfo& info) { descriptions.push_back(attachment); references.push_back(attachmentRef); } + + if(isDepthAttachment) { + VkSubpassDependency implicitBeginDependency; + implicitBeginDependency.srcSubpass = VK_SUBPASS_EXTERNAL; + implicitBeginDependency.dstSubpass = 0; + implicitBeginDependency.srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + implicitBeginDependency.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + implicitBeginDependency.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + implicitBeginDependency.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + implicitBeginDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + dependencies.push_back(implicitBeginDependency); + + VkSubpassDependency implicitEndDependency; + implicitEndDependency.srcSubpass = 0; + implicitEndDependency.dstSubpass = VK_SUBPASS_EXTERNAL; + implicitEndDependency.srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + implicitEndDependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + implicitEndDependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + implicitEndDependency.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + implicitEndDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + dependencies.push_back(implicitEndDependency); + } else { + VkSubpassDependency implicitBeginDependency; + implicitBeginDependency.srcSubpass = VK_SUBPASS_EXTERNAL; + implicitBeginDependency.dstSubpass = 0; + implicitBeginDependency.srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + implicitBeginDependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + implicitBeginDependency.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + implicitBeginDependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + implicitBeginDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + dependencies.push_back(implicitBeginDependency); + + VkSubpassDependency implicitEndDependency; + implicitEndDependency.srcSubpass = 0; + implicitEndDependency.dstSubpass = VK_SUBPASS_EXTERNAL; + implicitEndDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + implicitEndDependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + implicitEndDependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + implicitEndDependency.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + implicitEndDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + dependencies.push_back(implicitEndDependency); + } } VkSubpassDescription subpass = {}; @@ -799,6 +842,8 @@ GFXVulkan::create_render_pass(const GFXRenderPassCreateInfo& info) { renderPassInfo.pAttachments = descriptions.data(); renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subpass; + renderPassInfo.pDependencies = dependencies.data(); + renderPassInfo.dependencyCount = dependencies.size(); vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass->handle); @@ -1856,6 +1901,20 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, texture->layout); } } break; + case GFXCommandType::MemoryBarrier: + { + vkCmdPipelineBarrier(cmd, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + 0, + 0, + nullptr, + 0, + 0, + 0, + nullptr); + } + break; default: prism::log("Unhandled GFX Command Type {}", utility::enum_to_string(command.type)); diff --git a/engine/renderer/src/renderer.cpp b/engine/renderer/src/renderer.cpp index 35da550..aee5108 100755 --- a/engine/renderer/src/renderer.cpp +++ b/engine/renderer/src/renderer.cpp @@ -120,27 +120,27 @@ void renderer::recreate_all_render_targets() { void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarget& target, platform::window_ptr index) { const auto extent = target.extent; const auto render_extent = target.get_render_extent(); - - if(index != nullptr && !platform::is_main_window(index)) { + + if (index != nullptr && !platform::is_main_window(index)) { GFXRenderPassBeginInfo beginInfo = {}; beginInfo.render_area.extent = render_extent; commandbuffer->set_render_pass(beginInfo); - + Viewport viewport = {}; viewport.width = static_cast(render_extent.width); viewport.height = static_cast(render_extent.height); - + commandbuffer->set_viewport(viewport); - - for(auto& pass : passes) + + for (auto &pass: passes) pass->render_post(commandbuffer, target, index); - + return; } commandbuffer->push_group("Scene Rendering"); - + GFXRenderPassBeginInfo beginInfo = {}; beginInfo.framebuffer = target.offscreenFramebuffer; beginInfo.render_pass = offscreen_render_pass; @@ -148,43 +148,45 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge controller_continuity continuity; - if(scene != nullptr) { + if (scene != nullptr) { commandbuffer->push_group("Shadow Rendering"); - + shadow_pass->render(commandbuffer, *scene); - + commandbuffer->pop_group(); - - if(render_options.enable_ibl) { + + if (render_options.enable_ibl) { commandbuffer->push_group("Scene Capture"); scene_capture->render(commandbuffer, scene); commandbuffer->pop_group(); } - + commandbuffer->set_render_pass(beginInfo); - - const auto& cameras = scene->get_all(); - for(auto& [obj, camera] : cameras) { + + const auto &cameras = scene->get_all(); + for (auto&[obj, camera]: cameras) { const bool requires_limited_perspective = render_options.enable_depth_of_field; - if(requires_limited_perspective) { + if (requires_limited_perspective) { camera.perspective = prism::perspective(radians(camera.fov), - static_cast(render_extent.width) / static_cast(render_extent.height), + static_cast(render_extent.width) / + static_cast(render_extent.height), camera.near, 100.0f); } else { camera.perspective = prism::infinite_perspective(radians(camera.fov), - static_cast(render_extent.width) / static_cast(render_extent.height), + static_cast(render_extent.width) / + static_cast(render_extent.height), camera.near); } - + camera.view = inverse(scene->get(obj).model); - + Viewport viewport = {}; viewport.width = static_cast(render_extent.width); viewport.height = static_cast(render_extent.height); commandbuffer->set_viewport(viewport); - + commandbuffer->push_group("render camera"); render_camera(commandbuffer, *scene, obj, camera, render_extent, target, continuity); @@ -192,10 +194,10 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge commandbuffer->pop_group(); } } - + commandbuffer->pop_group(); - if(render_options.enable_aa) { + if (render_options.enable_aa) { commandbuffer->push_group("SMAA"); smaa_pass->render(commandbuffer, target); @@ -203,7 +205,7 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge commandbuffer->pop_group(); } - if(render_options.enable_depth_of_field && dof_pass != nullptr) + if (render_options.enable_depth_of_field && dof_pass != nullptr) dof_pass->render(commandbuffer, *scene); commandbuffer->push_group("Post Processing"); @@ -211,37 +213,37 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge commandbuffer->end_render_pass(); // begin auto exposure - + commandbuffer->set_compute_pipeline(histogram_pipeline); - + commandbuffer->bind_texture(target.offscreenColorTexture, 0); commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1, sizeof(uint32_t) * 256); - + const float lum_range = render_options.max_luminance - render_options.min_luminance; prism::float4 params = prism::float4(render_options.min_luminance, - 1.0f / lum_range, - static_cast(render_extent.width), - static_cast(render_extent.height)); - + 1.0f / lum_range, + static_cast(render_extent.width), + static_cast(render_extent.height)); + commandbuffer->set_push_constant(¶ms, sizeof(prism::float4)); - + commandbuffer->dispatch(static_cast(std::ceil(static_cast(render_extent.width) / 16.0f)), static_cast(std::ceil(static_cast(render_extent.height) / 16.0f)), 1); - + commandbuffer->set_compute_pipeline(histogram_average_pipeline); commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1, sizeof(uint32_t) * 256); params = prism::float4(render_options.min_luminance, - lum_range, - std::clamp(1.0f - std::exp(-(1.0f / 60.0f) * 1.1f), 0.0f, 1.0f), - static_cast(render_extent.width * render_extent.height)); - + lum_range, + std::clamp(1.0f - std::exp(-(1.0f / 60.0f) * 1.1f), 0.0f, 1.0f), + static_cast(render_extent.width * render_extent.height)); + commandbuffer->set_push_constant(¶ms, sizeof(prism::float4)); - + commandbuffer->bind_texture(average_luminance_texture, 0); - + commandbuffer->dispatch(1, 1, 1); // continue post processing @@ -257,13 +259,17 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge commandbuffer->set_viewport(viewport); commandbuffer->set_graphics_pipeline(post_pipeline); - - if(render_options.enable_depth_of_field) + + if (render_options.enable_depth_of_field) commandbuffer->bind_texture(dof_pass->normal_field, 1); else commandbuffer->bind_texture(target.offscreenColorTexture, 1); - - commandbuffer->bind_texture(target.blend_texture, 3); + + if (render_options.enable_aa) { + commandbuffer->bind_texture(target.blend_texture, 3); + } else { + commandbuffer->bind_texture(dummy_texture, 3); + } if(auto texture = get_requested_texture(PassTextureType::SelectionSobel)) commandbuffer->bind_texture(texture, 5); diff --git a/engine/renderer/src/shadowpass.cpp b/engine/renderer/src/shadowpass.cpp index be6606a..d26caa2 100755 --- a/engine/renderer/src/shadowpass.cpp +++ b/engine/renderer/src/shadowpass.cpp @@ -62,7 +62,7 @@ void ShadowPass::create_scene_resources(Scene& scene) { cubeTextureInfo.width = render_options.shadow_resolution; cubeTextureInfo.height = render_options.shadow_resolution; cubeTextureInfo.format = GFXPixelFormat::R_32F; - cubeTextureInfo.usage = GFXTextureUsage::Sampled; + cubeTextureInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst; cubeTextureInfo.array_length = max_point_shadows; cubeTextureInfo.samplingMode = SamplingMode::ClampToBorder; cubeTextureInfo.border_color = GFXBorderColor::OpaqueWhite; @@ -78,7 +78,7 @@ void ShadowPass::create_scene_resources(Scene& scene) { spotTextureInfo.width = render_options.shadow_resolution; spotTextureInfo.height = render_options.shadow_resolution; spotTextureInfo.format = GFXPixelFormat::DEPTH_32F; - spotTextureInfo.usage = GFXTextureUsage::Sampled; + spotTextureInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst; spotTextureInfo.array_length = max_spot_shadows; spotTextureInfo.samplingMode = SamplingMode::ClampToBorder; spotTextureInfo.border_color = GFXBorderColor::OpaqueWhite; @@ -215,6 +215,8 @@ void ShadowPass::render_sun(GFXCommandBuffer* command_buffer, Scene& scene, pris render_meshes(command_buffer, scene, realMVP, Matrix4x4(), lightPos, Light::Type::Sun, frustum, 0); scene.sun_light_dirty = false; + + command_buffer->end_render_pass(); } } @@ -250,6 +252,7 @@ void ShadowPass::render_spot(GFXCommandBuffer* command_buffer, Scene& scene, pri render_meshes(command_buffer, scene, realMVP, Matrix4x4(), scene.get(light_object).get_world_position(), Light::Type::Spot, frustum, 0); command_buffer->end_render_pass(); + command_buffer->copy_texture(offscreen_depth, render_options.shadow_resolution, render_options.shadow_resolution, scene.spotLightArray, 0, last_spot_light, 0); scene.spot_light_dirty[last_spot_light] = false; @@ -295,6 +298,7 @@ void ShadowPass::render_point(GFXCommandBuffer* command_buffer, Scene& scene, pr render_meshes(command_buffer, scene, projection * shadowTransforms[face], model, lightPos, Light::Type::Point, frustum, last_point_light); command_buffer->end_render_pass(); + command_buffer->copy_texture(offscreen_color_texture, render_options.shadow_resolution, render_options.shadow_resolution, scene.pointLightArray, face, last_point_light, 0); } @@ -390,7 +394,7 @@ void ShadowPass::create_offscreen_resources() { textureInfo.width = render_options.shadow_resolution; textureInfo.height = render_options.shadow_resolution; textureInfo.format = GFXPixelFormat::R_32F; - textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled; + textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled | GFXTextureUsage::TransferSrc; textureInfo.samplingMode = SamplingMode::ClampToEdge; offscreen_color_texture = gfx->create_texture(textureInfo); diff --git a/engine/renderer/src/smaapass.cpp b/engine/renderer/src/smaapass.cpp index 26170cc..50eba2d 100755 --- a/engine/renderer/src/smaapass.cpp +++ b/engine/renderer/src/smaapass.cpp @@ -73,6 +73,8 @@ void SMAAPass::render(GFXCommandBuffer* command_buffer, RenderTarget& target) { command_buffer->bind_texture(target.offscreenDepthTexture, 1); // depth command_buffer->draw(0, 3, 0, 1); + + command_buffer->end_render_pass(); } // blend @@ -88,6 +90,8 @@ void SMAAPass::render(GFXCommandBuffer* command_buffer, RenderTarget& target) { command_buffer->bind_texture(search_image, 3); command_buffer->draw(0, 3, 0, 1); + + command_buffer->end_render_pass(); } }