From 4ca8ce653defd358a18d33aab93d180f6acf6a02 Mon Sep 17 00:00:00 2001 From: Jean Philippe Date: Tue, 5 May 2026 15:07:58 +0900 Subject: [PATCH 1/2] feat: added SetCull method --- Resources/Shaders/skybox.frag | 4 +- Resources/Shaders/skybox.vert | 4 +- ZEngine/ZEngine/Hardwares/VulkanDevice.cpp | 4 +- .../Rendering/Renderers/GraphicRenderer.cpp | 2 - .../Renderers/Pipelines/RendererPipeline.cpp | 2 +- .../Renderers/RenderPasses/RenderPass.cpp | 6 + .../Renderers/RenderPasses/RenderPass.h | 1 + .../Rendering/Renderers/RendererPasses.cpp | 118 +----------------- .../Rendering/Renderers/RendererPasses.h | 10 -- .../GraphicRendererPipelineSpecification.h | 3 +- 10 files changed, 17 insertions(+), 137 deletions(-) diff --git a/Resources/Shaders/skybox.frag b/Resources/Shaders/skybox.frag index 05386bcb..2a6f6968 100644 --- a/Resources/Shaders/skybox.frag +++ b/Resources/Shaders/skybox.frag @@ -7,5 +7,5 @@ layout(set = 1, binding = 1) uniform sampler LinearWrapSampler; void main() { - outColor = texture(samplerCube(EnvMap, LinearWrapSampler), dir); -} \ No newline at end of file + outColor = texture(samplerCube(EnvMap, LinearWrapSampler), normalize(dir)); +} diff --git a/Resources/Shaders/skybox.vert b/Resources/Shaders/skybox.vert index 772c862c..8f5118dd 100644 --- a/Resources/Shaders/skybox.vert +++ b/Resources/Shaders/skybox.vert @@ -12,8 +12,8 @@ Camera; void main() { - dir = normalize(vec3(pos.x, -pos.y, pos.z)); + dir = pos; // normalize(vec3(pos.x, -pos.y, pos.z)); mat4 rotScaleView = mat4(mat3(Camera.View)); vec4 position = Camera.Projection * rotScaleView * vec4(pos, 1.0f); - gl_Position = position.xyww; + gl_Position = vec4(position.xy, position.w, position.w); // position.xyww; } diff --git a/ZEngine/ZEngine/Hardwares/VulkanDevice.cpp b/ZEngine/ZEngine/Hardwares/VulkanDevice.cpp index a0deb584..4165733b 100644 --- a/ZEngine/ZEngine/Hardwares/VulkanDevice.cpp +++ b/ZEngine/ZEngine/Hardwares/VulkanDevice.cpp @@ -1747,8 +1747,8 @@ namespace ZEngine::Hardwares VkViewport viewport = {}; viewport.x = x; viewport.y = y; - viewport.width = w; - viewport.height = h; + viewport.width = (float)w; + viewport.height = (float)h; viewport.minDepth = min_depth; viewport.maxDepth = max_depth; vkCmdSetViewport(m_command_buffer, 0, 1, &viewport); diff --git a/ZEngine/ZEngine/Rendering/Renderers/GraphicRenderer.cpp b/ZEngine/ZEngine/Rendering/Renderers/GraphicRenderer.cpp index 395a252b..fe2bb8ff 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/GraphicRenderer.cpp +++ b/ZEngine/ZEngine/Rendering/Renderers/GraphicRenderer.cpp @@ -58,7 +58,6 @@ namespace ZEngine::Rendering::Renderers * Renderer Passes */ auto upload_pass = ZPushStructCtor(Device->Arena, UploadPass); - auto initial_pass = ZPushStructCtor(Device->Arena, InitialPass); auto scene_depth_prepass = ZPushStructCtor(Device->Arena, DepthPrePass); auto skybox_pass = ZPushStructCtor(Device->Arena, SkyboxPass); auto grid_pass = ZPushStructCtor(Device->Arena, GridPass); @@ -82,7 +81,6 @@ namespace ZEngine::Rendering::Renderers RenderGraph->ResourceBuilder->CreateBufferSet("g_scene_spot_light_buffer"); RenderGraph->AddCallbackPass("Upload Pass", upload_pass); - // RenderGraph->AddCallbackPass("Initial Pass", initial_pass); RenderGraph->AddCallbackPass("Depth Pre-Pass", scene_depth_prepass); RenderGraph->AddCallbackPass("Skybox Pass", skybox_pass); RenderGraph->AddCallbackPass("Grid Pass", grid_pass); diff --git a/ZEngine/ZEngine/Rendering/Renderers/Pipelines/RendererPipeline.cpp b/ZEngine/ZEngine/Rendering/Renderers/Pipelines/RendererPipeline.cpp index f4ecae51..a937bd2a 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/Pipelines/RendererPipeline.cpp +++ b/ZEngine/ZEngine/Rendering/Renderers/Pipelines/RendererPipeline.cpp @@ -84,7 +84,7 @@ namespace ZEngine::Rendering::Renderers::Pipelines rasterization_create_info.rasterizerDiscardEnable = VK_FALSE; rasterization_create_info.polygonMode = VK_POLYGON_MODE_FILL; rasterization_create_info.lineWidth = 1.0f; - rasterization_create_info.cullMode = VK_CULL_MODE_NONE; + rasterization_create_info.cullMode = (VkCullModeFlagBits) Specification.CullMode; rasterization_create_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; rasterization_create_info.depthBiasEnable = VK_FALSE; rasterization_create_info.depthBiasConstantFactor = 0.0f; // Optional diff --git a/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.cpp b/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.cpp index 724ca679..660cc7b1 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.cpp +++ b/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.cpp @@ -430,6 +430,12 @@ namespace ZEngine::Rendering::Renderers::RenderPasses return *this; } + RenderPassBuilder& RenderPassBuilder::SetCullMode(uint32_t mode) + { + m_spec.PipelineSpecification.CullMode = mode; + return *this; + } + RenderPassBuilder& RenderPassBuilder::SetInputBindingCount(uint32_t count) { m_spec.PipelineSpecification.VertexInputBindingSpecifications.init(Arena, count, count); diff --git a/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.h b/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.h index 643d152c..6cdb4f66 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.h +++ b/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.h @@ -72,6 +72,7 @@ namespace ZEngine::Rendering::Renderers::RenderPasses RenderPassBuilder& PipelineDepthCompareOp(uint32_t value); RenderPassBuilder& SetShaderOverloadMaxSet(uint32_t count); RenderPassBuilder& SetOverloadPoolSize(uint32_t count); + RenderPassBuilder& SetCullMode(uint32_t); RenderPassBuilder& SetInputBindingCount(uint32_t count); RenderPassBuilder& SetStride(uint32_t input_binding_index, uint32_t value); diff --git a/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.cpp b/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.cpp index df55817e..5b4fd5e8 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.cpp +++ b/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.cpp @@ -104,77 +104,6 @@ namespace ZEngine::Rendering::Renderers WriteOnceControl[device->SwapchainPtr->CurrentFrame->Index] = 1; } - void InitialPass::Setup(Hardwares::VulkanDevicePtr const device, cstring name, RenderGraphResourceBuilderPtr const res_builder, RenderGraphResourceInspectorPtr res_inspector) - { - // VertexData.init(device->Arena, 3, make_initializer_list(device->Arena, 0.0f, 0.0f, 0.0f)); - - // auto& vb_res = res_builder->CreateBufferSet("initial_vertex_buffer", BufferSetCreationType::VERTEX); - // VBHandle = vb_res.ResourceInfo.VertexBufferSetHandle; - - // auto vb_view = ArrayView{VertexData}; - - // auto buffer_set = device->VertexBufferSetManager.Access(VBHandle); - // for (unsigned i = 0; i < device->SwapchainPtr->BufferredFrameCount; ++i) - //{ - // auto buffer = buffer_set->At(i); - // buffer->Allocate(vb_view.size_bytes(), "initial_vertex_buffer"); - // buffer->Write(i, 0, vb_view); - // } - - RenderGraphRenderPassCreation pass_node = {.Name = name}; - - pass_node.Inputs.init(device->Arena, 2); - pass_node.Outputs.init(device->Arena, 1); - pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameDepthRenderTargetName}); - pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameColorRenderTargetName}); - - res_builder->CreateRenderPassNode(pass_node); - } - - void InitialPass::Compile(Hardwares::VulkanDevicePtr const device, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPassBuilder* pass_builder, RenderGraphResourceInspectorPtr res_inspector, RenderPasses::RenderPass** const output_pass) - { - if (output_pass && !(*output_pass)) - { - auto pass_spec = pass_builder->SetPipelineName("Initial-Pipeline") - .SetInputBindingCount(1) - .SetStride(0, sizeof(float) * 3) - .SetRate(0, VK_VERTEX_INPUT_RATE_VERTEX) - .SetInputAttributeCount(1) - .SetLocation(0, 0) - - .SetBinding(0, 0) - .SetFormat(0, Specifications::ImageFormat::R32G32B32_SFLOAT) - .SetOffset(0, 0) - - .EnablePipelineDepthTest(true) - .UseShader("initial") - .Detach(); - // clang-format off - *output_pass = device->CreateRenderPass(pass_spec); - // clang-format on - (*output_pass)->Bake(); - } - } - - void InitialPass::Execute(Hardwares::VulkanDevicePtr const device, RenderGraphResourceInspectorPtr res_inspector, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPass* const pass, Buffers::FramebufferVNext* const framebuffer, Hardwares::CommandBufferPtr const command_buffer) - { - auto buffer_set = device->VertexBufferSetManager.Access(VBHandle); - auto vertex_buffer = buffer_set->At(device->SwapchainPtr->CurrentFrame->Index); - - command_buffer->BeginRenderPass(pass, framebuffer->Handle, false); - { - uint32_t w = pass->GetRenderAreaWidth(); - uint32_t h = pass->GetRenderAreaHeight(); - command_buffer->SetViewport(w, h); - command_buffer->SetScissor(w, h); - } - command_buffer->BindPipeline(Specifications::PipelineBindPoint::GRAPHIC, pass->Pipeline); - command_buffer->BindVertexBuffer(*vertex_buffer); - command_buffer->BindDescriptorSets(device->SwapchainPtr->CurrentFrame->Index); - command_buffer->Draw(1, 1, 0, 0); - command_buffer->EndRenderPass(); - } - void DepthPrePass::Setup(Hardwares::VulkanDevicePtr const device, cstring name, RenderGraphResourceBuilderPtr const res_builder, RenderGraphResourceInspectorPtr res_inspector) { RenderGraphRenderPassCreation pass_node = {.Name = name}; @@ -240,27 +169,6 @@ namespace ZEngine::Rendering::Renderers auto env_map_res = res_builder->CreateTexture("skybox_env_map", "Settings/EnvironmentMaps/bergen_4k.hdr"); m_env_map = env_map_res.ResourceInfo.TextureHandle; - // m_vb_handle = device->CreateVertexBufferSet(); - // m_ib_handle = device->CreateIndexBufferSet(); - - // auto count = device->SwapchainPtr->BufferredFrameCount; - // auto vtx_buffer_set = device->VertexBufferSetManager.Access(m_vb_handle); - // auto idx_buffer_set = device->IndexBufferSetManager.Access(m_ib_handle); - - // auto vtx_buf_view = ArrayView{m_vertex_data}; - // auto idx_buf_view = ArrayView{m_index_data}; - - // for (int i = 0; i < count; ++i) - //{ - // auto vertex_buffer = vtx_buffer_set->At(i); - // auto index_buffer = idx_buffer_set->At(i); - - // vertex_buffer->Allocate(vtx_buf_view.size_bytes(), "SkyboxPassVtx"); - // index_buffer->Allocate(idx_buf_view.size_bytes(), "SkyboxPassIdx"); - - // vertex_buffer->Write(i, 0, vtx_buf_view); - // index_buffer->Write(i, 0, idx_buf_view); - //} auto& output_skybox = res_builder->CreateRenderTarget("skybox_render_target", {.Width = 1280, .Height = 780, .Format = ImageFormat::R8G8B8A8_UNORM}); RenderGraphRenderPassCreation pass_node = {.Name = name}; @@ -293,6 +201,7 @@ namespace ZEngine::Rendering::Renderers .SetOffset(0, 0) .EnablePipelineDepthTest(true) .EnablePipelineDepthWrite(false) + .SetCullMode(0) .UseShader("skybox") .Detach(); @@ -339,31 +248,6 @@ namespace ZEngine::Rendering::Renderers { auto arena = device->Arena; - // m_index_data.init(arena, 6, make_initializer_list(arena, 0, 1, 2, 2, 3, 0)); - // m_vertex_data.init(arena, 12, make_initializer_list(arena, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f)); - - // m_vb_handle = device->CreateVertexBufferSet(); - // m_ib_handle = device->CreateIndexBufferSet(); - - // auto count = device->SwapchainPtr->BufferredFrameCount; - // auto vtx_buffer_set = device->VertexBufferSetManager.Access(m_vb_handle); - // auto idx_buffer_set = device->IndexBufferSetManager.Access(m_ib_handle); - - // auto vtx_buf_view = ArrayView{m_vertex_data}; - // auto idx_buf_view = ArrayView{m_index_data}; - - // for (int i = 0; i < count; ++i) - //{ - // auto vertex_buffer = vtx_buffer_set->At(i); - // auto index_buffer = idx_buffer_set->At(i); - - // vertex_buffer->Allocate(vtx_buf_view.size_bytes(), "GridPassVtx"); - // index_buffer->Allocate(idx_buf_view.size_bytes(), "GridPassIdx"); - - // vertex_buffer->Write(i, 0, vtx_buf_view); - // index_buffer->Write(i, 0, idx_buf_view); - //} - auto& output_grid = res_builder->CreateRenderTarget("grid_render_target", {.Width = 1280, .Height = 780, .Format = ImageFormat::R8G8B8A8_UNORM}); RenderGraphRenderPassCreation pass_node = {.Name = name}; diff --git a/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.h b/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.h index 3438674c..32118c4a 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.h +++ b/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.h @@ -33,16 +33,6 @@ namespace ZEngine::Rendering::Renderers virtual void Execute(Hardwares::VulkanDevicePtr const device, RenderGraphResourceInspectorPtr res_inspector, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPass* const pass, Buffers::FramebufferVNext* const framebuffer, Hardwares::CommandBufferPtr const command_buffer) override; }; - struct InitialPass : public IRenderGraphCallbackPass - { - Core::Containers::Array VertexData = {}; - Hardwares::VertexBufferSetHandle VBHandle = {}; - - virtual void Setup(Hardwares::VulkanDevicePtr const device, cstring name, RenderGraphResourceBuilderPtr const res_builder, RenderGraphResourceInspectorPtr res_inspector) override; - virtual void Compile(Hardwares::VulkanDevicePtr const device, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPassBuilder* pass_builder, RenderGraphResourceInspectorPtr res_inspector, RenderPasses::RenderPass** const output_pass) override; - virtual void Execute(Hardwares::VulkanDevicePtr const device, RenderGraphResourceInspectorPtr res_inspector, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPass* const pass, Buffers::FramebufferVNext* const framebuffer, Hardwares::CommandBufferPtr const command_buffer) override; - }; - struct DepthPrePass : public IRenderGraphCallbackPass { virtual void Setup(Hardwares::VulkanDevicePtr const device, cstring name, RenderGraphResourceBuilderPtr const res_builder, RenderGraphResourceInspectorPtr res_inspector) override; diff --git a/ZEngine/ZEngine/Rendering/Specifications/GraphicRendererPipelineSpecification.h b/ZEngine/ZEngine/Rendering/Specifications/GraphicRendererPipelineSpecification.h index 6a81d431..639d8d39 100644 --- a/ZEngine/ZEngine/Rendering/Specifications/GraphicRendererPipelineSpecification.h +++ b/ZEngine/ZEngine/Rendering/Specifications/GraphicRendererPipelineSpecification.h @@ -26,9 +26,10 @@ namespace ZEngine::Rendering::Specifications bool EnableBlending = false; bool EnableDepthTest = false; bool EnableDepthWrite = true; - uint32_t DepthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; bool EnableStencilTest = false; const char* DebugName = {}; + uint32_t DepthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; + uint32_t CullMode = 0; ShaderSpecification ShaderSpecificationValue = {}; Rendering::Buffers::FramebufferVNext* TargetFrameBuffer = {}; Renderers::RenderPasses::Attachment* Attachment = {}; From 5b5b1fd022009c282710231859e0a916ad3945b6 Mon Sep 17 00:00:00 2001 From: Jean Philippe Date: Sun, 10 May 2026 13:52:19 +0900 Subject: [PATCH 2/2] feat: make vb/ib buffers as output of renderpass --- Resources/Shaders/{initial.frag => base.frag} | 0 Resources/Shaders/base.vert | 6 + Resources/Shaders/composite.frag | 14 ++ Resources/Shaders/composite.vert | 9 + Resources/Shaders/infinite_grid.frag | 32 ++- Resources/Shaders/infinite_grid.vert | 10 +- Resources/Shaders/initial.vert | 16 -- Resources/Shaders/skybox.frag | 4 +- Resources/Shaders/skybox.vert | 6 +- Tetragrama/Editor.cpp | 2 +- .../Controllers/PerspectiveCameraController.h | 2 +- ZEngine/ZEngine/Core/Memory/Allocator.cpp | 10 +- ZEngine/ZEngine/Hardwares/VulkanDevice.cpp | 89 +++++--- ZEngine/ZEngine/Hardwares/VulkanDevice.h | 2 + .../Rendering/Cameras/PerspectiveCamera.cpp | 24 +-- .../Rendering/Renderers/GraphicRenderer.cpp | 6 + .../Rendering/Renderers/GraphicRenderer.h | 15 +- .../ZEngine/Rendering/Renderers/IRenderer.h | 7 +- .../Renderers/Pipelines/RendererPipeline.cpp | 36 +++- .../Rendering/Renderers/RenderGraph.cpp | 195 +++++++++++------- .../ZEngine/Rendering/Renderers/RenderGraph.h | 13 +- .../Renderers/RenderPasses/RenderPass.cpp | 17 +- .../Renderers/RenderPasses/RenderPass.h | 2 + .../Rendering/Renderers/RendererPasses.cpp | 179 +++++++++++++--- .../Rendering/Renderers/RendererPasses.h | 14 ++ ZEngine/ZEngine/Rendering/Shaders/Shader.cpp | 2 +- .../Specifications/RenderPassSpecification.h | 8 + 27 files changed, 498 insertions(+), 222 deletions(-) rename Resources/Shaders/{initial.frag => base.frag} (100%) create mode 100644 Resources/Shaders/base.vert create mode 100644 Resources/Shaders/composite.frag create mode 100644 Resources/Shaders/composite.vert delete mode 100644 Resources/Shaders/initial.vert diff --git a/Resources/Shaders/initial.frag b/Resources/Shaders/base.frag similarity index 100% rename from Resources/Shaders/initial.frag rename to Resources/Shaders/base.frag diff --git a/Resources/Shaders/base.vert b/Resources/Shaders/base.vert new file mode 100644 index 00000000..594985b5 --- /dev/null +++ b/Resources/Shaders/base.vert @@ -0,0 +1,6 @@ +#version 460 + +void main() +{ + gl_Position = vec4(vec3(0), 0.0f); +} diff --git a/Resources/Shaders/composite.frag b/Resources/Shaders/composite.frag new file mode 100644 index 00000000..d9425d3f --- /dev/null +++ b/Resources/Shaders/composite.frag @@ -0,0 +1,14 @@ +#version 460 + +layout(location = 0) in vec2 outUV; + +layout(set = 0, binding = 0) uniform texture2D sharedRTAsTex; +layout(set = 1, binding = 1) uniform sampler LinearWrapSampler; + +layout(location = 0) out vec4 outColor; + +void main() +{ + vec4 color = texture(sampler2D(sharedRTAsTex, LinearWrapSampler), outUV); + outColor = color; +} diff --git a/Resources/Shaders/composite.vert b/Resources/Shaders/composite.vert new file mode 100644 index 00000000..f6f16976 --- /dev/null +++ b/Resources/Shaders/composite.vert @@ -0,0 +1,9 @@ +#version 460 + +layout(location = 0) out vec2 outUV; + +void main() +{ + outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); + gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); +} diff --git a/Resources/Shaders/infinite_grid.frag b/Resources/Shaders/infinite_grid.frag index 14fceda8..ffa9bea4 100644 --- a/Resources/Shaders/infinite_grid.frag +++ b/Resources/Shaders/infinite_grid.frag @@ -8,21 +8,24 @@ layout(location = 1) in float scaleFactor; layout(location = 0) out vec4 outColor; float gridCellSize = 0.025; - vec4 gridColorThin = vec4(1.0, 1.0, 1.0, 1.0); vec4 gridColorThick = vec4(0.5, 0.5, 0.5, 1.0); const float gridMinPixelsBetweenCells = 2.0; void main() { - vec2 dudv = vec2(length(vec2(dFdx(uv.x), dFdy(uv.x))), length(vec2(dFdx(uv.y), dFdy(uv.y)))); + vec2 dudv = vec2(length(vec2(dFdx(uv.x), dFdy(uv.x))), length(vec2(dFdx(uv.y), dFdy(uv.y)))); + dudv = max(dudv, vec2(0.0001)); float lodLevel = max(0.0, log_10((length(dudv) * gridMinPixelsBetweenCells) / gridCellSize) + 1.0); - float lodFade = fract(lodLevel); + lodLevel = min(lodLevel, 2.0); + + // Smooth fade between LOD levels to kill flickering + float lodFade = smoothstep(0.0, 1.0, fract(lodLevel)); - float lod0 = gridCellSize * pow(10.0, floor(lodLevel + 0)); - float lod1 = gridCellSize * pow(10.0, floor(lodLevel + 1)); - float lod2 = gridCellSize * pow(10.0, floor(lodLevel + 2)); + float lod0 = gridCellSize * pow(10.0, floor(lodLevel)); + float lod1 = gridCellSize * pow(10.0, floor(lodLevel + 1.0)); + float lod2 = gridCellSize * pow(10.0, floor(lodLevel + 2.0)); dudv *= 4.0; @@ -31,8 +34,17 @@ void main() float lod2a = max2(vec2(1.0) - abs(satv(mod(uv, lod2) / dudv) * 2.0 - vec2(1.0))); vec4 c = lod2a > 0.0 ? gridColorThick : lod1a > 0.0 ? mix(gridColorThick, gridColorThin, lodFade) : gridColorThin; - float opacityFalloff = (1.0 - satf(length(uv) / scaleFactor)); - c.a *= lod2a > 0.0 ? lod2a : lod1a > 0.0 ? lod1a : (lod0a * (1.0 - lodFade)); + + // Fade based on distance from camera, using actual world-space diagonal + float maxDist = scaleFactor * 1.5; // covers the quad diagonal + float opacityFalloff = pow(1.0 - satf(length(uv) / maxDist), 0.5); + + c.a = lod2a > 0.0 ? lod2a : lod1a > 0.0 ? lod1a : (lod0a * (1.0 - lodFade)); c.a *= opacityFalloff; - outColor = c; -} \ No newline at end of file + + // Discard fully transparent fragments to avoid depth artifacts + if (c.a < 0.001) + discard; + + outColor = c; +} diff --git a/Resources/Shaders/infinite_grid.vert b/Resources/Shaders/infinite_grid.vert index 8b267caa..56e60571 100644 --- a/Resources/Shaders/infinite_grid.vert +++ b/Resources/Shaders/infinite_grid.vert @@ -13,9 +13,9 @@ Camera; void main() { - scaleFactor = 50.0; + scaleFactor = 1000.0f; + vec3 worldPos = pos + vec3(Camera.Position.x, 0.0, Camera.Position.z); - vec3 posScale = pos * scaleFactor; - uv = posScale.xz; - gl_Position = Camera.Projection * Camera.View * vec4(posScale, 1.0); -} \ No newline at end of file + uv = worldPos.xz; + gl_Position = Camera.Projection * Camera.View * vec4(worldPos, 1.0); +} diff --git a/Resources/Shaders/initial.vert b/Resources/Shaders/initial.vert deleted file mode 100644 index d7c27ac1..00000000 --- a/Resources/Shaders/initial.vert +++ /dev/null @@ -1,16 +0,0 @@ -#version 460 - -layout(location = 0) in vec3 pos; - -layout(set = 0, binding = 0) uniform UBCamera -{ - mat4 View; - mat4 Projection; - vec4 Position; -} -Camera; - -void main() -{ - gl_Position = vec4(pos, 1.0f); -} \ No newline at end of file diff --git a/Resources/Shaders/skybox.frag b/Resources/Shaders/skybox.frag index 2a6f6968..949763eb 100644 --- a/Resources/Shaders/skybox.frag +++ b/Resources/Shaders/skybox.frag @@ -3,9 +3,9 @@ layout(location = 0) in vec3 dir; layout(location = 0) out vec4 outColor; layout(set = 0, binding = 1) uniform textureCube EnvMap; -layout(set = 1, binding = 1) uniform sampler LinearWrapSampler; +layout(set = 0, binding = 2) uniform sampler LinearClampToEdgeSampler; void main() { - outColor = texture(samplerCube(EnvMap, LinearWrapSampler), normalize(dir)); + outColor = texture(samplerCube(EnvMap, LinearClampToEdgeSampler), normalize(dir)); } diff --git a/Resources/Shaders/skybox.vert b/Resources/Shaders/skybox.vert index 8f5118dd..d9851947 100644 --- a/Resources/Shaders/skybox.vert +++ b/Resources/Shaders/skybox.vert @@ -14,6 +14,8 @@ void main() { dir = pos; // normalize(vec3(pos.x, -pos.y, pos.z)); mat4 rotScaleView = mat4(mat3(Camera.View)); - vec4 position = Camera.Projection * rotScaleView * vec4(pos, 1.0f); - gl_Position = vec4(position.xy, position.w, position.w); // position.xyww; + + vec4 position = Camera.Projection * rotScaleView * vec4(pos * 10.0f, 1.0f); + + gl_Position = position.xyww; } diff --git a/Tetragrama/Editor.cpp b/Tetragrama/Editor.cpp index 22dbf84f..87b5640a 100644 --- a/Tetragrama/Editor.cpp +++ b/Tetragrama/Editor.cpp @@ -47,7 +47,7 @@ namespace Tetragrama UILayer = ZPushStructCtor(Arena, ImguiLayer); UILayer->Initialize(Arena, this); - editor_cam_controller->Initialize(Arena, CurrentWindow, 150.0, 0.f, 45.f); + editor_cam_controller->Initialize(Arena, CurrentWindow, 10.0, 0.f, 15.f); editor_scene->Initialize(Arena, Configuration->ActiveSceneName.c_str()); CameraController = editor_cam_controller; diff --git a/ZEngine/ZEngine/Controllers/PerspectiveCameraController.h b/ZEngine/ZEngine/Controllers/PerspectiveCameraController.h index b7632b6a..5542a284 100644 --- a/ZEngine/ZEngine/Controllers/PerspectiveCameraController.h +++ b/ZEngine/ZEngine/Controllers/PerspectiveCameraController.h @@ -59,7 +59,7 @@ namespace ZEngine::Controllers protected: float m_camera_fov = 90.0f; - float m_camera_near = 1.f; + float m_camera_near = 0.1f; float m_camera_far = 1000.0f; bool m_process_event = true; Core::Maths::Vec3f m_camera_target = {0.0f, 0.0f, 0.0f}; diff --git a/ZEngine/ZEngine/Core/Memory/Allocator.cpp b/ZEngine/ZEngine/Core/Memory/Allocator.cpp index 127fcbdd..d2b7ef3b 100644 --- a/ZEngine/ZEngine/Core/Memory/Allocator.cpp +++ b/ZEngine/ZEngine/Core/Memory/Allocator.cpp @@ -84,12 +84,12 @@ namespace ZEngine::Core::Memory void ArenaAllocator::CreateSubArena(size_t size, ArenaAllocator* out_arena) { out_arena->m_memory = reinterpret_cast(Allocate(size)); - out_arena->m_initial_previous_offset = m_previous_offset; - out_arena->m_initial_current_offset = m_previous_offset; + out_arena->m_initial_previous_offset = 0; + out_arena->m_initial_current_offset = 0; - out_arena->m_previous_offset = out_arena->m_initial_previous_offset; - out_arena->m_current_offset = out_arena->m_initial_current_offset; - out_arena->m_total_size = m_previous_offset + size; + out_arena->m_previous_offset = 0; + out_arena->m_current_offset = 0; + out_arena->m_total_size = size; } ArenaTemp BeginTempArena(ArenaAllocator* arena) diff --git a/ZEngine/ZEngine/Hardwares/VulkanDevice.cpp b/ZEngine/ZEngine/Hardwares/VulkanDevice.cpp index 4165733b..a0266e65 100644 --- a/ZEngine/ZEngine/Hardwares/VulkanDevice.cpp +++ b/ZEngine/ZEngine/Hardwares/VulkanDevice.cpp @@ -435,27 +435,46 @@ namespace ZEngine::Hardwares /* * Creating Global Descriptor Pool for : Textures, Samplers */ - VkSamplerCreateInfo sampler_create_info = {}; - sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - sampler_create_info.minFilter = VK_FILTER_LINEAR; - sampler_create_info.magFilter = VK_FILTER_LINEAR; - sampler_create_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_create_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_create_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_create_info.anisotropyEnable = PhysicalDeviceFeature.features.samplerAnisotropy; - sampler_create_info.maxAnisotropy = PhysicalDeviceFeature.features.samplerAnisotropy ? PhysicalDeviceProperties.properties.limits.maxSamplerAnisotropy : 1.0f; - sampler_create_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; - sampler_create_info.unnormalizedCoordinates = VK_FALSE; - sampler_create_info.compareEnable = VK_FALSE; - sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler_create_info.mipLodBias = 0.0f; - sampler_create_info.minLod = 0.0f; - sampler_create_info.maxLod = VK_LOD_CLAMP_NONE; - - ZENGINE_VALIDATE_ASSERT(vkCreateSampler(LogicalDevice, &sampler_create_info, nullptr, &GlobalLinearWrapSampler) == VK_SUCCESS, "Failed to create Texture Sampler") - - GlobalLinearWrapSamplerImageInfo = VkDescriptorImageInfo{.sampler = GlobalLinearWrapSampler, .imageView = VK_NULL_HANDLE, .imageLayout = VK_IMAGE_LAYOUT_UNDEFINED}; - MaxGlobalTexture = std::min(MaxGlobalTexture, PhysicalDeviceVulkan12Properties.maxPerStageDescriptorUpdateAfterBindSampledImages - 1); + VkSamplerCreateInfo linear_sampler_create_info = {}; + linear_sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + linear_sampler_create_info.minFilter = VK_FILTER_LINEAR; + linear_sampler_create_info.magFilter = VK_FILTER_LINEAR; + linear_sampler_create_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + linear_sampler_create_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + linear_sampler_create_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + linear_sampler_create_info.anisotropyEnable = PhysicalDeviceFeature.features.samplerAnisotropy; + linear_sampler_create_info.maxAnisotropy = PhysicalDeviceFeature.features.samplerAnisotropy ? PhysicalDeviceProperties.properties.limits.maxSamplerAnisotropy : 1.0f; + linear_sampler_create_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; + linear_sampler_create_info.unnormalizedCoordinates = VK_FALSE; + linear_sampler_create_info.compareEnable = VK_FALSE; + linear_sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + linear_sampler_create_info.mipLodBias = 0.0f; + linear_sampler_create_info.minLod = 0.0f; + linear_sampler_create_info.maxLod = VK_LOD_CLAMP_NONE; + + VkSamplerCreateInfo linear_sampler_clamp_to_edge_create_info = {}; + linear_sampler_clamp_to_edge_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + linear_sampler_clamp_to_edge_create_info.minFilter = VK_FILTER_LINEAR; + linear_sampler_clamp_to_edge_create_info.magFilter = VK_FILTER_LINEAR; + linear_sampler_clamp_to_edge_create_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + linear_sampler_clamp_to_edge_create_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + linear_sampler_clamp_to_edge_create_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + linear_sampler_clamp_to_edge_create_info.anisotropyEnable = VK_FALSE; + linear_sampler_clamp_to_edge_create_info.maxAnisotropy = 1.0f; + linear_sampler_clamp_to_edge_create_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; + linear_sampler_clamp_to_edge_create_info.unnormalizedCoordinates = VK_FALSE; + linear_sampler_clamp_to_edge_create_info.compareEnable = VK_FALSE; + linear_sampler_clamp_to_edge_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + linear_sampler_clamp_to_edge_create_info.mipLodBias = 0.0f; + linear_sampler_clamp_to_edge_create_info.minLod = 0.0f; + linear_sampler_clamp_to_edge_create_info.maxLod = VK_LOD_CLAMP_NONE; + + ZENGINE_VALIDATE_ASSERT(vkCreateSampler(LogicalDevice, &linear_sampler_create_info, nullptr, &GlobalLinearWrapSampler) == VK_SUCCESS, "Failed to create Texture Sampler") + ZENGINE_VALIDATE_ASSERT(vkCreateSampler(LogicalDevice, &linear_sampler_clamp_to_edge_create_info, nullptr, &GlobalLinearClampToEdgeSampler) == VK_SUCCESS, "Failed to create Texture Sampler") + + GlobalLinearWrapSamplerImageInfo = VkDescriptorImageInfo{.sampler = GlobalLinearWrapSampler, .imageView = VK_NULL_HANDLE, .imageLayout = VK_IMAGE_LAYOUT_UNDEFINED}; + GlobalLinearClampToEdgeSamplerImageInfo = VkDescriptorImageInfo{.sampler = GlobalLinearClampToEdgeSampler, .imageView = VK_NULL_HANDLE, .imageLayout = VK_IMAGE_LAYOUT_UNDEFINED}; + MaxGlobalTexture = std::min(MaxGlobalTexture, PhysicalDeviceVulkan12Properties.maxPerStageDescriptorUpdateAfterBindSampledImages - 1); GlobalTextures.Initialize(Arena, MaxGlobalTexture); Image2DBufferManager.Initialize(Arena, MaxGlobalTexture); @@ -618,12 +637,14 @@ namespace ZEngine::Hardwares __createDebugMessengerPtr = nullptr; } vkDestroySampler(LogicalDevice, GlobalLinearWrapSampler, nullptr); + vkDestroySampler(LogicalDevice, GlobalLinearClampToEdgeSampler, nullptr); vkDestroyDevice(LogicalDevice, nullptr); vkDestroyInstance(Instance, nullptr); - GlobalLinearWrapSampler = VK_NULL_HANDLE; - LogicalDevice = VK_NULL_HANDLE; - Instance = VK_NULL_HANDLE; + GlobalLinearWrapSampler = VK_NULL_HANDLE; + GlobalLinearClampToEdgeSampler = VK_NULL_HANDLE; + LogicalDevice = VK_NULL_HANDLE; + Instance = VK_NULL_HANDLE; } void VulkanDevice::QueueSubmit(CommandBuffer* const command_buffer, Rendering::Primitives::Semaphore* const signal_semaphore, uint32_t wait_flag, uint64_t signal_value, uint64_t wait_value, Rendering::Primitives::Semaphore* const wait_semaphore) @@ -1366,12 +1387,18 @@ namespace ZEngine::Hardwares if (std::filesystem::exists(vertex_file)) { - spec.VertexFilename = vertex_file.c_str(); + auto name_c_size = (vertex_file.size() + 1u); + auto name_c_str = ZPushString(Arena, name_c_size); + Helpers::secure_strcpy(name_c_str, name_c_size, vertex_file.c_str()); + spec.VertexFilename = name_c_str; } if (std::filesystem::exists(fragment_file)) { - spec.FragmentFilename = fragment_file.c_str(); + auto name_c_size = (fragment_file.size() + 1u); + auto name_c_str = ZPushString(Arena, name_c_size); + Helpers::secure_strcpy(name_c_str, name_c_size, fragment_file.c_str()); + spec.FragmentFilename = name_c_str; } shader->Initialize(this, spec); @@ -1618,10 +1645,16 @@ namespace ZEngine::Hardwares // We're safe to use index as Set for (uint32_t i = 0; i < set_layout.size(); ++i) { - frame_sets.push(descriptor_set_map.at(i)[frame_index]); + if (descriptor_set_map.contains(i)) + { + frame_sets.push(descriptor_set_map.at(i)[frame_index]); + } } - vkCmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, frame_sets.size(), frame_sets.data(), 0, nullptr); + if(!frame_sets.empty()) + { + vkCmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, frame_sets.size(), frame_sets.data(), 0, nullptr); + } ZReleaseScratch(scratch); } } diff --git a/ZEngine/ZEngine/Hardwares/VulkanDevice.h b/ZEngine/ZEngine/Hardwares/VulkanDevice.h index d88eda40..5c0e7033 100644 --- a/ZEngine/ZEngine/Hardwares/VulkanDevice.h +++ b/ZEngine/ZEngine/Hardwares/VulkanDevice.h @@ -609,9 +609,11 @@ namespace ZEngine::Hardwares VkPhysicalDeviceFeatures2 PhysicalDeviceFeature = {}; VkPhysicalDeviceMemoryProperties PhysicalDeviceMemoryProperties = {}; VkSampler GlobalLinearWrapSampler = VK_NULL_HANDLE; + VkSampler GlobalLinearClampToEdgeSampler = VK_NULL_HANDLE; VkDescriptorPool GlobalDescriptorPoolHandle = VK_NULL_HANDLE; VmaAllocator VmaAllocatorValue = nullptr; VkDescriptorImageInfo GlobalLinearWrapSamplerImageInfo = {}; + VkDescriptorImageInfo GlobalLinearClampToEdgeSamplerImageInfo = {}; CommandBufferManagerPtr CommandBufferMgr = {}; DeviceSwapchainPtr SwapchainPtr = {}; Core::Containers::Array DefaultDepthFormats = {}; diff --git a/ZEngine/ZEngine/Rendering/Cameras/PerspectiveCamera.cpp b/ZEngine/ZEngine/Rendering/Cameras/PerspectiveCamera.cpp index dab22236..376f0ea3 100644 --- a/ZEngine/ZEngine/Rendering/Cameras/PerspectiveCamera.cpp +++ b/ZEngine/ZEngine/Rendering/Cameras/PerspectiveCamera.cpp @@ -102,25 +102,25 @@ namespace ZEngine::Rendering::Cameras ZEngine::Core::Maths::Mat4f PerspectiveCamera::GetPerspectiveMatrix() const { /* - * Ref : https://johannesugb.github.io/gpu-programming/why-do-opengl-proj-matrices-fail-in-vulkan/ - * Unlike the article, for our implementation we decided to use have the y-axis Up. * For future Gfx API we may want to revisit/adapt it. */ - ZEngine::Core::Maths::Mat4f I = ZEngine::Core::Maths::Identity(); - I[2][2] = -1; - - float inv_a = m_viewport_height / m_viewport_width; - float tan_half_fov = ZEngine::Core::Maths::tan(Fov / 2); + float a = m_viewport_width / m_viewport_height; + float tan_half_fov = ZEngine::Core::Maths::tan(Fov / 2.0f); float far_minus_near = ClipFar - ClipNear; - ZEngine::Core::Maths::Mat4f P(ZEngine::Core::Maths::Identity()); - P[0][0] = (inv_a / tan_half_fov); - P[1][1] = (1.0f / tan_half_fov); + ZEngine::Core::Maths::Mat4f P{}; + P[0][0] = 1.0f / (a * tan_half_fov); + + // Y scale (Vulkan Y is Down, so we use a negative here to keep Y-Up in world space) + P[1][1] = (-1.0f / tan_half_fov); + P[2][2] = (ClipFar / far_minus_near); - P[2][3] = 1; + + P[2][3] = 1.0f; + P[3][2] = (-(ClipFar * ClipNear) / far_minus_near); - return P * I; + return P; } ZEngine::Core::Maths::Vec3f PerspectiveCamera::GetPosition() const diff --git a/ZEngine/ZEngine/Rendering/Renderers/GraphicRenderer.cpp b/ZEngine/ZEngine/Rendering/Renderers/GraphicRenderer.cpp index fe2bb8ff..2ac4df85 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/GraphicRenderer.cpp +++ b/ZEngine/ZEngine/Rendering/Renderers/GraphicRenderer.cpp @@ -57,13 +57,16 @@ namespace ZEngine::Rendering::Renderers /* * Renderer Passes */ + auto base_pass = ZPushStructCtor(Device->Arena, BasePass); auto upload_pass = ZPushStructCtor(Device->Arena, UploadPass); auto scene_depth_prepass = ZPushStructCtor(Device->Arena, DepthPrePass); auto skybox_pass = ZPushStructCtor(Device->Arena, SkyboxPass); auto grid_pass = ZPushStructCtor(Device->Arena, GridPass); auto gbuffer_pass = ZPushStructCtor(Device->Arena, GbufferPass); auto lighting_pass = ZPushStructCtor(Device->Arena, LightingPass); + auto composite_pass = ZPushStructCtor(Device->Arena, CompositePass); + // FrameSharedRenderTarget = Device->CreateTexture({.PerformTransition = false, .Width = 1280, .Height = 780, .Format = ImageFormat::R8G8B8A8_UNORM}); FrameColorRenderTarget = Device->CreateTexture({.PerformTransition = false, .Width = 1280, .Height = 780, .Format = ImageFormat::R8G8B8A8_UNORM}); FrameDepthRenderTarget = Device->CreateTexture({.PerformTransition = false, .Width = 1280, .Height = 780, .Format = ImageFormat::DEPTH_STENCIL_FROM_DEVICE}); @@ -73,6 +76,7 @@ namespace ZEngine::Rendering::Renderers */ RenderGraph->Initialize(Device, RenderSceneData); + // RenderGraph->ResourceBuilder->AttachRenderTarget(RendererResourceName::FrameSharedRenderTargetName, FrameSharedRenderTarget); RenderGraph->ResourceBuilder->AttachRenderTarget(RendererResourceName::FrameDepthRenderTargetName, FrameDepthRenderTarget); RenderGraph->ResourceBuilder->AttachRenderTarget(RendererResourceName::FrameColorRenderTargetName, FrameColorRenderTarget); @@ -81,11 +85,13 @@ namespace ZEngine::Rendering::Renderers RenderGraph->ResourceBuilder->CreateBufferSet("g_scene_spot_light_buffer"); RenderGraph->AddCallbackPass("Upload Pass", upload_pass); + RenderGraph->AddCallbackPass("Base Pass", base_pass); RenderGraph->AddCallbackPass("Depth Pre-Pass", scene_depth_prepass); RenderGraph->AddCallbackPass("Skybox Pass", skybox_pass); RenderGraph->AddCallbackPass("Grid Pass", grid_pass); // RenderGraph->AddCallbackPass("G-Buffer Pass", gbuffer_pass); // RenderGraph->AddCallbackPass("Lighting Pass", lighting_pass); + // RenderGraph->AddCallbackPass("Composite Pass", composite_pass); RenderGraph->Setup(); RenderGraph->Compile(); diff --git a/ZEngine/ZEngine/Rendering/Renderers/GraphicRenderer.h b/ZEngine/ZEngine/Rendering/Renderers/GraphicRenderer.h index 9361b9a1..97655b73 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/GraphicRenderer.h +++ b/ZEngine/ZEngine/Rendering/Renderers/GraphicRenderer.h @@ -10,14 +10,15 @@ namespace ZEngine::Rendering::Renderers GraphicRenderer(); ~GraphicRenderer(); - cstring VertexBufferName = "VertexStorageBuffer"; - cstring IndexBufferName = "IndexStorageBuffer"; - cstring TransformBufferName = "TransformStorageBuffer"; - cstring RenderDataBufferName = "RenderDataStorageBuffer"; - cstring MaterialBufferName = "MaterialStorageBuffer"; + cstring VertexBufferName = "VertexStorageBuffer"; + cstring IndexBufferName = "IndexStorageBuffer"; + cstring TransformBufferName = "TransformStorageBuffer"; + cstring RenderDataBufferName = "RenderDataStorageBuffer"; + cstring MaterialBufferName = "MaterialStorageBuffer"; - Textures::TextureHandle FrameColorRenderTarget = {}; - Textures::TextureHandle FrameDepthRenderTarget = {}; + Textures::TextureHandle FrameSharedRenderTarget = {}; + Textures::TextureHandle FrameColorRenderTarget = {}; + Textures::TextureHandle FrameDepthRenderTarget = {}; void Initialize(Hardwares::VulkanDevicePtr device) override; void Deinitialize() override; diff --git a/ZEngine/ZEngine/Rendering/Renderers/IRenderer.h b/ZEngine/ZEngine/Rendering/Renderers/IRenderer.h index 9cdd365b..e2bf000a 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/IRenderer.h +++ b/ZEngine/ZEngine/Rendering/Renderers/IRenderer.h @@ -48,10 +48,11 @@ namespace ZEngine::Rendering::Renderers struct RendererResourceName { - inline static cstring FrameDepthRenderTargetName = "g_frame_depth_render_target"; - inline static cstring FrameColorRenderTargetName = "g_frame_color_render_target"; + inline static cstring FrameDepthRenderTargetName = "g_frame_depth_render_target"; + inline static cstring FrameSharedRenderTargetName = "g_frame_shared_render_target"; + inline static cstring FrameColorRenderTargetName = "g_frame_color_render_target"; - inline static cstring SceneCameraBufferName = "SceneCamera"; + inline static cstring SceneCameraBufferName = "SceneCamera"; }; struct IRenderer diff --git a/ZEngine/ZEngine/Rendering/Renderers/Pipelines/RendererPipeline.cpp b/ZEngine/ZEngine/Rendering/Renderers/Pipelines/RendererPipeline.cpp index a937bd2a..a275dd79 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/Pipelines/RendererPipeline.cpp +++ b/ZEngine/ZEngine/Rendering/Renderers/Pipelines/RendererPipeline.cpp @@ -123,14 +123,34 @@ namespace ZEngine::Rendering::Renderers::Pipelines color_blend_attachment_states.init(scratch.Arena, attachment_count, attachment_count); for (uint32_t i = 0; i < attachment_count; ++i) { - color_blend_attachment_states[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - color_blend_attachment_states[i].blendEnable = Specification.EnableBlending ? VK_TRUE : VK_FALSE; - color_blend_attachment_states[i].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - color_blend_attachment_states[i].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - color_blend_attachment_states[i].colorBlendOp = VK_BLEND_OP_ADD; - color_blend_attachment_states[i].srcAlphaBlendFactor = Specification.EnableBlending ? VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA : VK_BLEND_FACTOR_ONE; - color_blend_attachment_states[i].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - color_blend_attachment_states[i].alphaBlendOp = VK_BLEND_OP_ADD; + color_blend_attachment_states[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + if (Specification.EnableBlending) + { + color_blend_attachment_states[i].blendEnable = VK_TRUE; + + // todo (jpkernel): those config should be expose at the pass builder level + // Color: Standard Alpha Blending + color_blend_attachment_states[i].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_blend_attachment_states[i].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_blend_attachment_states[i].colorBlendOp = VK_BLEND_OP_ADD; + + // Alpha: Accumulate opaqueness + color_blend_attachment_states[i].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + color_blend_attachment_states[i].dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_blend_attachment_states[i].alphaBlendOp = VK_BLEND_OP_ADD; + } + else + { + color_blend_attachment_states[i].blendEnable = VK_FALSE; + // Standard "Opaque" settings + color_blend_attachment_states[i].srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + color_blend_attachment_states[i].dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + color_blend_attachment_states[i].colorBlendOp = VK_BLEND_OP_ADD; + color_blend_attachment_states[i].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + color_blend_attachment_states[i].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_blend_attachment_states[i].alphaBlendOp = VK_BLEND_OP_ADD; + } } VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = {}; diff --git a/ZEngine/ZEngine/Rendering/Renderers/RenderGraph.cpp b/ZEngine/ZEngine/Rendering/Renderers/RenderGraph.cpp index d7d8aec5..4b17b7cb 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/RenderGraph.cpp +++ b/ZEngine/ZEngine/Rendering/Renderers/RenderGraph.cpp @@ -33,7 +33,7 @@ namespace ZEngine::Rendering::Renderers { for (auto [name, _] : NodeMap) // Todo UnorderedHashMap needs to support for (auto& [key, val]) {....} { - NodeMap[name].EdgeNodes.init(Device->Arena, 5); + NodeMap[name].EdgeNodes.init(Device->Arena); NodeMap[name].CallbackPass->Setup(Device, name, ResourceBuilder, ResourceInspector); } } @@ -50,7 +50,7 @@ namespace ZEngine::Rendering::Renderers if (NodeMap.contains(resource.ProducerNodeName)) { RenderGraphNode& producer_node = NodeMap[resource.ProducerNodeName]; - producer_node.EdgeNodes.push(pass.first); + producer_node.EdgeNodes.insert(pass.first); } } } @@ -61,48 +61,54 @@ namespace ZEngine::Rendering::Renderers /* * Topological Sorting */ - auto scratch = ZGetScratch(Device->Arena); + auto scratch = ZGetScratch(Device->Arena); - Array sorted_nodes = {}; - UnorderedHashMap visited_nodes = {}; - Array stack = {}; + Array sorted_nodes = {}; + UnorderedHashSet processed_nodes = {}; + UnorderedHashSet visited_nodes = {}; + std::stack stack = {}; - sorted_nodes.init(scratch.Arena, 6); - stack.init(scratch.Arena, 6); + sorted_nodes.init(scratch.Arena, NodeMap.size()); visited_nodes.init(scratch.Arena); + processed_nodes.init(scratch.Arena); - for (auto node : NodeMap) + for (const auto& [name, _] : NodeMap) { - stack.push(node.first); + if (processed_nodes.contains(name)) + { + continue; + } + + stack.push(name); + while (!stack.empty()) { - auto& node_name = stack.back(); - if (visited_nodes[node_name] == 2) - { - stack.pop(); - continue; - } + const auto& top = stack.top(); - if (visited_nodes[node_name] == 1) + if (!visited_nodes.contains(top)) { - visited_nodes[node_name] = 2; - sorted_nodes.push(node_name); - stack.pop(); - continue; - } + visited_nodes.insert(top); - visited_nodes[node_name] = 1; - auto& graph_node = NodeMap[node_name]; - if (graph_node.EdgeNodes.empty()) - { - continue; + auto& graph_node = NodeMap[top]; + if (!graph_node.EdgeNodes.empty()) + { + for (auto edge : graph_node.EdgeNodes) + { + if (!visited_nodes.contains(edge)) + { + stack.push(edge); + } + } + } } - - for (auto edge : graph_node.EdgeNodes) + else { - if (!visited_nodes.contains(edge)) + stack.pop(); + + if (!processed_nodes.contains(top)) { - stack.push(edge); + sorted_nodes.push(top); + processed_nodes.insert(top); } } } @@ -144,6 +150,11 @@ namespace ZEngine::Rendering::Renderers RenderPassBuilder->UseRenderTarget(resource.ResourceInfo.TextureHandle); } + + else if (output.Type == RenderGraphResourceType::REFERENCE) + { + RenderPassBuilder->UseRenderTarget(resource.ResourceInfo.TextureHandle); + } } for (auto& input : node.Creation.Inputs) @@ -165,9 +176,19 @@ namespace ZEngine::Rendering::Renderers for (cstring name : SortedNodesMap) { - auto& node = NodeMap[name]; - Specifications::FrameBufferSpecificationVNext framebuffer_spec = {.Width = node.Handle->RenderAreaWidth, .Height = node.Handle->RenderAreaHeight, .RenderTargets = node.Handle->RenderTargets, .Attachment = node.Handle->Attachment}; - node.Framebuffer = ZPushStructCtorArgs(Device->Arena, Buffers::FramebufferVNext, Device, framebuffer_spec); + auto& node = NodeMap[name]; + if (node.Handle && (node.Handle->Specification.Type != Specifications::RenderPassType::GRAPHIC)) + { + continue; + } + + Specifications::FrameBufferSpecificationVNext framebuffer_spec = { + .Width = node.Handle->RenderAreaWidth, + .Height = node.Handle->RenderAreaHeight, + .RenderTargets = node.Handle->RenderTargets, + .Attachment = node.Handle->Attachment, + }; + node.Framebuffer = ZPushStructCtorArgs(Device->Arena, Buffers::FramebufferVNext, Device, framebuffer_spec); } } @@ -175,7 +196,7 @@ namespace ZEngine::Rendering::Renderers { ZENGINE_VALIDATE_ASSERT(command_buffer, "Command Buffer can't be null") - command_buffer->ClearColor(0.1f, 0.1f, 0.1f, 1.0f); + command_buffer->ClearColor(0.5f, 0.5f, 0.5f, 1.0f); command_buffer->ClearDepth(1.0f, 0); for (auto& node_name : SortedNodesMap) @@ -227,47 +248,49 @@ namespace ZEngine::Rendering::Renderers } auto& resource = ResourceMap[output.Name]; - ZENGINE_VALIDATE_ASSERT(resource.Type == RenderGraphResourceType::ATTACHMENT, "RenderPass Output should be an Attachment") - - auto texture = Device->GlobalTextures.Access(resource.ResourceInfo.TextureHandle); - auto img_buf = Device->Image2DBufferManager.Access(texture->BufferHandle); - auto& buffer = img_buf->GetBuffer(); - - Specifications::ImageMemoryBarrierSpecification barrier_spec = {}; - if (texture->IsDepthTexture) - { - barrier_spec.ImageHandle = buffer.Handle; - barrier_spec.OldLayout = img_buf->Layout; - barrier_spec.NewLayout = Specifications::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - barrier_spec.ImageAspectMask = VkImageAspectFlagBits(VK_IMAGE_ASPECT_DEPTH_BIT /*| VK_IMAGE_ASPECT_STENCIL_BIT*/); // Todo : To consider Stencil - // buffer, we want to extend - // Texture spec to introduce - // HasStencil bit - barrier_spec.SourceAccessMask = 0; - barrier_spec.DestinationAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; - barrier_spec.SourceStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - barrier_spec.DestinationStageMask = VkPipelineStageFlagBits(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); - barrier_spec.LayerCount = 1; - Primitives::ImageMemoryBarrier barrier{barrier_spec}; - command_buffer->TransitionImageLayout(barrier); - img_buf->Layout = barrier_spec.NewLayout; - } - else + if (resource.Type == RenderGraphResourceType::ATTACHMENT) { - barrier_spec.ImageHandle = buffer.Handle; - barrier_spec.OldLayout = img_buf->Layout; - barrier_spec.NewLayout = Specifications::ImageLayout::COLOR_ATTACHMENT_OPTIMAL; - barrier_spec.ImageAspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier_spec.SourceAccessMask = 0; - barrier_spec.DestinationAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - barrier_spec.SourceStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - barrier_spec.DestinationStageMask = VkPipelineStageFlagBits(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - barrier_spec.LayerCount = 1; + auto texture = Device->GlobalTextures.Access(resource.ResourceInfo.TextureHandle); + auto img_buf = Device->Image2DBufferManager.Access(texture->BufferHandle); + auto& buffer = img_buf->GetBuffer(); - Primitives::ImageMemoryBarrier barrier{barrier_spec}; - command_buffer->TransitionImageLayout(barrier); - img_buf->Layout = barrier_spec.NewLayout; + Specifications::ImageMemoryBarrierSpecification barrier_spec = {}; + if (texture->IsDepthTexture) + { + barrier_spec.ImageHandle = buffer.Handle; + barrier_spec.OldLayout = img_buf->Layout; + barrier_spec.NewLayout = Specifications::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + barrier_spec.ImageAspectMask = VkImageAspectFlagBits(VK_IMAGE_ASPECT_DEPTH_BIT /*| VK_IMAGE_ASPECT_STENCIL_BIT*/); // Todo : To consider Stencil + // buffer, we want to extend + // Texture spec to introduce + // HasStencil bit + barrier_spec.SourceAccessMask = 0; + barrier_spec.DestinationAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + barrier_spec.SourceStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + barrier_spec.DestinationStageMask = VkPipelineStageFlagBits(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); + barrier_spec.LayerCount = 1; + + Primitives::ImageMemoryBarrier barrier{barrier_spec}; + command_buffer->TransitionImageLayout(barrier); + img_buf->Layout = barrier_spec.NewLayout; + } + else + { + barrier_spec.ImageHandle = buffer.Handle; + barrier_spec.OldLayout = img_buf->Layout; + barrier_spec.NewLayout = Specifications::ImageLayout::COLOR_ATTACHMENT_OPTIMAL; + barrier_spec.ImageAspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier_spec.SourceAccessMask = 0; + barrier_spec.DestinationAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + barrier_spec.SourceStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + barrier_spec.DestinationStageMask = VkPipelineStageFlagBits(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + barrier_spec.LayerCount = 1; + + Primitives::ImageMemoryBarrier barrier{barrier_spec}; + command_buffer->TransitionImageLayout(barrier); + img_buf->Layout = barrier_spec.NewLayout; + } } } @@ -283,6 +306,11 @@ namespace ZEngine::Rendering::Renderers auto& pass_spec = node.Handle->Specification; + if ((pass_spec.Type != Specifications::RenderPassType::GRAPHIC) && (pass_spec.Type != Specifications::RenderPassType::COMPUTE)) + { + continue; + } + pass_spec.ExternalOutputs.clear(); pass_spec.Inputs.clear(); pass_spec.InputTextures.clear(); @@ -293,6 +321,7 @@ namespace ZEngine::Rendering::Renderers if (output.Type == RenderGraphResourceType::REFERENCE) { + pass_spec.ExternalOutputs.push(resource.ResourceInfo.TextureHandle); continue; } @@ -335,8 +364,13 @@ namespace ZEngine::Rendering::Renderers node.Handle->UpdateRenderTargets(); node.Handle->UpdateInputBinding(); - Specifications::FrameBufferSpecificationVNext framebuffer_spec = {.Width = node.Handle->RenderAreaWidth, .Height = node.Handle->RenderAreaHeight, .RenderTargets = node.Handle->RenderTargets, .Attachment = node.Handle->Attachment}; - node.Framebuffer = ZPushStructCtorArgs(Device->Arena, Buffers::FramebufferVNext, Device, framebuffer_spec); + Specifications::FrameBufferSpecificationVNext framebuffer_spec = { + .Width = node.Handle->RenderAreaWidth, + .Height = node.Handle->RenderAreaHeight, + .RenderTargets = node.Handle->RenderTargets, + .Attachment = node.Handle->Attachment, + }; + node.Framebuffer = ZPushStructCtorArgs(Device->Arena, Buffers::FramebufferVNext, Device, framebuffer_spec); } } @@ -346,10 +380,13 @@ namespace ZEngine::Rendering::Renderers { auto& node = NodeMap[node_name]; node.Handle->Dispose(); - node.Framebuffer->Dispose(); + if (node.Handle->Specification.Type == Specifications::RenderPassType::GRAPHIC) + { + node.Framebuffer->Dispose(); + } } - for (auto resource : ResourceMap) + for (const auto& resource : ResourceMap) { auto& value = ResourceMap[resource.first]; if (value.ResourceInfo.External) @@ -445,9 +482,9 @@ namespace ZEngine::Rendering::Renderers void RenderGraphResourceBuilder::CreateRenderPassNode(const RenderGraphRenderPassCreation& creation) { Graph->NodeMap[creation.Name].Creation = creation; - for (const auto& output : Graph->NodeMap.at(creation.Name).Creation.Outputs) + for (const auto& output : creation.Outputs) { - if (output.Type == RenderGraphResourceType::ATTACHMENT) + if ((output.Type == RenderGraphResourceType::ATTACHMENT) || (output.Type == RenderGraphResourceType::BUFFER_SET)) { RenderGraphResource& resource = Graph->ResourceMap[output.Name]; resource.ProducerNodeName = creation.Name; diff --git a/ZEngine/ZEngine/Rendering/Renderers/RenderGraph.h b/ZEngine/ZEngine/Rendering/Renderers/RenderGraph.h index 1e784b78..4467bbba 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/RenderGraph.h +++ b/ZEngine/ZEngine/Rendering/Renderers/RenderGraph.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -88,12 +89,12 @@ namespace ZEngine::Rendering::Renderers struct RenderGraphNode { - bool Enabled = true; - RenderGraphRenderPassCreation Creation = {}; - Core::Containers::Array EdgeNodes = {}; - ZRawPtr(RenderPasses::RenderPass) Handle = nullptr; - ZRawPtr(Buffers::FramebufferVNext) Framebuffer = nullptr; - IRenderGraphCallbackPassPtr CallbackPass = nullptr; + bool Enabled = true; + RenderGraphRenderPassCreation Creation = {}; + Core::Containers::UnorderedHashSet EdgeNodes = {}; + RenderPasses::RenderPassPtr Handle = nullptr; + ZRawPtr(Buffers::FramebufferVNext) Framebuffer = nullptr; + IRenderGraphCallbackPassPtr CallbackPass = nullptr; }; struct RenderGraph diff --git a/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.cpp b/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.cpp index 660cc7b1..b8815a90 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.cpp +++ b/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.cpp @@ -18,6 +18,12 @@ namespace ZEngine::Rendering::Renderers::RenderPasses { m_device = device; Specification = specification; + + if ((specification.Type != Specifications::RenderPassType::GRAPHIC) && (specification.Type != Specifications::RenderPassType::COMPUTE)) + { + return; + } + RenderTargets.init(device->Arena, 4); if (Specification.SwapchainAsRenderTarget) @@ -95,7 +101,10 @@ namespace ZEngine::Rendering::Renderers::RenderPasses m_device->GlobalTextures.Remove(handle); } - Pipeline->Dispose(); + if (Pipeline) + { + Pipeline->Dispose(); + } if (!(Specification.SwapchainAsRenderTarget) && Attachment) { @@ -105,6 +114,10 @@ namespace ZEngine::Rendering::Renderers::RenderPasses void RenderPass::Bake() { + if ((Specification.Type != Specifications::RenderPassType::GRAPHIC) && (Specification.Type != Specifications::RenderPassType::COMPUTE)) + { + return; + } Pipeline->Bake(); } @@ -128,7 +141,7 @@ namespace ZEngine::Rendering::Renderers::RenderPasses auto end = missing_names.end(); std::string unset_inputs = std::accumulate(std::next(start), end, *start, [](std::string_view a, std::string_view b) { return fmt::format("{}, {}", a.data(), b.data()); }); - ZENGINE_CORE_WARN("Shader '{}': {} unset input(s): {}", Specification.PipelineSpecification.DebugName, missing_names.size(), unset_inputs.c_str()); + ZENGINE_CORE_WARN("Pipeline '{}': {} unset input(s): {}", Specification.PipelineSpecification.DebugName, missing_names.size(), unset_inputs.c_str()); verify = false; } diff --git a/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.h b/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.h index 6cdb4f66..8b5949db 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.h +++ b/ZEngine/ZEngine/Rendering/Renderers/RenderPasses/RenderPass.h @@ -28,6 +28,7 @@ namespace ZEngine::Rendering::Renderers::RenderPasses uint32_t RenderAreaWidth = 0; uint32_t RenderAreaHeight = 0; + Specifications::RenderPassSpecification Specification = {}; std::set Inputs = {}; Core::Containers::Array RenderTargets = {}; @@ -57,6 +58,7 @@ namespace ZEngine::Rendering::Renderers::RenderPasses bool m_perform_update{false}; Hardwares::VulkanDevice* m_device; }; + ZDEFINE_PTR(RenderPass); struct RenderPassBuilder { diff --git a/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.cpp b/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.cpp index 5b4fd5e8..ec7f77be 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.cpp +++ b/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.cpp @@ -13,7 +13,7 @@ namespace ZEngine::Rendering::Renderers SkyboxVertexData.init(device->Arena, 24, make_initializer_list(device->Arena, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f)); SkyboxIndexData.init(device->Arena, 36, make_initializer_list(device->Arena, 0, 1, 2, 2, 3, 0, 1, 5, 6, 6, 2, 1, 5, 4, 7, 7, 6, 5, 4, 0, 3, 3, 7, 4, 3, 2, 6, 6, 7, 3, 4, 5, 1, 1, 0, 4)); - GridVertexData.init(device->Arena, 12, make_initializer_list(device->Arena, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f)); + GridVertexData.init(device->Arena, 12, make_initializer_list(device->Arena, -1000.0f, 0.01f, -1000.0f, 1000.0f, 0.01f, -1000.0f, 1000.0f, 0.01f, 1000.0f, -1000.0f, 0.01f, 1000.0f)); GridIndexData.init(device->Arena, 6, make_initializer_list(device->Arena, 0, 1, 2, 2, 3, 0)); const auto& skybox_res_vb_info = res_builder->CreateBufferSet("SkyboxVbSet", BufferSetCreationType::VERTEX); @@ -49,36 +49,25 @@ namespace ZEngine::Rendering::Renderers RenderGraphRenderPassCreation pass_node = {.Name = name}; pass_node.Inputs.init(device->Arena, 1); - pass_node.Outputs.init(device->Arena, 2); - pass_node.Outputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameDepthRenderTargetName}); - pass_node.Outputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameColorRenderTargetName}); + pass_node.Outputs.init(device->Arena, 4); + + pass_node.Outputs.push(RenderGraphRenderPassInputOutputInfo{.Name = skybox_res_vb_info.Name, .Type = RenderGraphResourceType::BUFFER_SET}); + pass_node.Outputs.push(RenderGraphRenderPassInputOutputInfo{.Name = skybox_res_ib_info.Name, .Type = RenderGraphResourceType::BUFFER_SET}); + pass_node.Outputs.push(RenderGraphRenderPassInputOutputInfo{.Name = grid_res_vb_info.Name, .Type = RenderGraphResourceType::BUFFER_SET}); + pass_node.Outputs.push(RenderGraphRenderPassInputOutputInfo{.Name = grid_res_ib_info.Name, .Type = RenderGraphResourceType::BUFFER_SET}); res_builder->CreateRenderPassNode(pass_node); } void UploadPass::Compile(Hardwares::VulkanDevicePtr const device, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPassBuilder* pass_builder, RenderGraphResourceInspectorPtr res_inspector, RenderPasses::RenderPass** const output_pass) { - // this compile action is purely fake, as this pass is only used to upload data to the buffers, - // and doesn't actually need a render pass. However, we need to create a dummy render pass to be able to execute this pass in the render graph. + CHECK_AND_ESCAPE_NULL(output_pass) + if (output_pass && !(*output_pass)) { - auto pass_spec = pass_builder->SetPipelineName("Initial-Pipeline") - .SetInputBindingCount(1) - .SetStride(0, sizeof(float) * 3) - .SetRate(0, VK_VERTEX_INPUT_RATE_VERTEX) - .SetInputAttributeCount(1) - .SetLocation(0, 0) - - .SetBinding(0, 0) - .SetFormat(0, Specifications::ImageFormat::R32G32B32_SFLOAT) - .SetOffset(0, 0) - - .EnablePipelineDepthTest(true) - .UseShader("initial") - .Detach(); - // clang-format off - *output_pass = device->CreateRenderPass(pass_spec); - // clang-format on + auto pass_spec = pass_builder->Detach(); + pass_spec.Type = Specifications::RenderPassType::TRANSFER; + *output_pass = device->CreateRenderPass(pass_spec); (*output_pass)->Bake(); } } @@ -104,12 +93,61 @@ namespace ZEngine::Rendering::Renderers WriteOnceControl[device->SwapchainPtr->CurrentFrame->Index] = 1; } - void DepthPrePass::Setup(Hardwares::VulkanDevicePtr const device, cstring name, RenderGraphResourceBuilderPtr const res_builder, RenderGraphResourceInspectorPtr res_inspector) + void BasePass::Setup(Hardwares::VulkanDevicePtr const device, cstring name, RenderGraphResourceBuilderPtr const res_builder, RenderGraphResourceInspectorPtr res_inspector) { RenderGraphRenderPassCreation pass_node = {.Name = name}; pass_node.Inputs.init(device->Arena, 1); + pass_node.Outputs.init(device->Arena, 1); + pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameDepthRenderTargetName}); + pass_node.Outputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameColorRenderTargetName}); + + res_builder->CreateRenderPassNode(pass_node); + } + + void BasePass::Compile(Hardwares::VulkanDevicePtr const device, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPassBuilder* pass_builder, RenderGraphResourceInspectorPtr res_inspector, RenderPasses::RenderPass** const output_pass) + { + CHECK_AND_ESCAPE_NULL(output_pass) + + if (output_pass && !(*output_pass)) + { + auto pass_spec = pass_builder->SetPipelineName("Base-Pipeline") + .SetInputBindingCount(0) + .EnablePipelineDepthTest(true) + + .UseShader("base") + .Detach(); + // clang-format off + *output_pass = device->CreateRenderPass(pass_spec); + // clang-format on + (*output_pass)->Bake(); + } + (*output_pass)->Verify(); + } + + void BasePass::Execute(Hardwares::VulkanDevicePtr const device, RenderGraphResourceInspectorPtr res_inspector, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPass* const pass, Buffers::FramebufferVNext* const framebuffer, Hardwares::CommandBufferPtr const command_buffer) + { + command_buffer->BeginRenderPass(pass, framebuffer->Handle, false); + { + uint32_t w = pass->GetRenderAreaWidth(); + uint32_t h = pass->GetRenderAreaHeight(); + command_buffer->SetViewport(w, h); + command_buffer->SetScissor(w, h); + } + command_buffer->BindPipeline(Specifications::PipelineBindPoint::GRAPHIC, pass->Pipeline); + command_buffer->BindDescriptorSets(device->SwapchainPtr->CurrentFrame->Index); + command_buffer->Draw(3, 1, 0, 0); + command_buffer->EndRenderPass(); + } + + void DepthPrePass::Setup(Hardwares::VulkanDevicePtr const device, cstring name, RenderGraphResourceBuilderPtr const res_builder, RenderGraphResourceInspectorPtr res_inspector) + { + RenderGraphRenderPassCreation pass_node = {.Name = name}; + + pass_node.Inputs.init(device->Arena, 1); + pass_node.Outputs.init(device->Arena, 1); + pass_node.Outputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameDepthRenderTargetName}); res_builder->CreateRenderPassNode(pass_node); } @@ -170,15 +208,18 @@ namespace ZEngine::Rendering::Renderers m_env_map = env_map_res.ResourceInfo.TextureHandle; - auto& output_skybox = res_builder->CreateRenderTarget("skybox_render_target", {.Width = 1280, .Height = 780, .Format = ImageFormat::R8G8B8A8_UNORM}); + const auto& skybox_vb_set = res_inspector->GetResource("SkyboxVbSet"); + const auto& skybox_ib_set = res_inspector->GetResource("SkyboxIbSet"); + RenderGraphRenderPassCreation pass_node = {.Name = name}; - pass_node.Inputs.init(device->Arena, 2); + pass_node.Inputs.init(device->Arena, 4); pass_node.Outputs.init(device->Arena, 1); + pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = skybox_vb_set.Name, .Type = skybox_vb_set.Type}); + pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = skybox_ib_set.Name, .Type = skybox_ib_set.Type}); pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameDepthRenderTargetName}); pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameColorRenderTargetName}); - pass_node.Outputs.push(RenderGraphRenderPassInputOutputInfo{.Name = output_skybox.Name}); res_builder->CreateRenderPassNode(pass_node); } @@ -201,8 +242,11 @@ namespace ZEngine::Rendering::Renderers .SetOffset(0, 0) .EnablePipelineDepthTest(true) .EnablePipelineDepthWrite(false) - .SetCullMode(0) + .PipelineDepthCompareOp(2) + + .EnablePipelineBlending(false) + .SetCullMode(0) .UseShader("skybox") .Detach(); // clang-format off @@ -215,7 +259,7 @@ namespace ZEngine::Rendering::Renderers { (*output_pass)->SetInput("UBCamera", scene->SceneCameraBufferHandle); (*output_pass)->SetInput("EnvMap", m_env_map); - (*output_pass)->SetInput("LinearWrapSampler", device->GlobalLinearWrapSamplerImageInfo); + (*output_pass)->SetInput("LinearClampToEdgeSampler", device->GlobalLinearClampToEdgeSamplerImageInfo); } (*output_pass)->Verify(); @@ -248,15 +292,18 @@ namespace ZEngine::Rendering::Renderers { auto arena = device->Arena; - auto& output_grid = res_builder->CreateRenderTarget("grid_render_target", {.Width = 1280, .Height = 780, .Format = ImageFormat::R8G8B8A8_UNORM}); + const auto& grid_vb_set = res_inspector->GetResource("GridVbSet"); + const auto& grid_ib_set = res_inspector->GetResource("GridIbSet"); + RenderGraphRenderPassCreation pass_node = {.Name = name}; - pass_node.Inputs.init(arena, 2); + pass_node.Inputs.init(arena, 4); pass_node.Outputs.init(arena, 1); + pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = grid_vb_set.Name, .Type = grid_vb_set.Type}); + pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = grid_ib_set.Name, .Type = grid_ib_set.Type}); pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameDepthRenderTargetName}); pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameColorRenderTargetName}); - pass_node.Outputs.push(RenderGraphRenderPassInputOutputInfo{.Name = output_grid.Name}); res_builder->CreateRenderPassNode(pass_node); } @@ -279,6 +326,12 @@ namespace ZEngine::Rendering::Renderers .SetOffset(0, 0) .EnablePipelineDepthTest(true) + .EnablePipelineDepthWrite(false) + .PipelineDepthCompareOp(3) + + .EnablePipelineBlending(true) + + .SetCullMode(0) .UseShader("infinite_grid") .Detach(); // clang-format off @@ -290,8 +343,8 @@ namespace ZEngine::Rendering::Renderers if (scene) { (*output_pass)->SetInput("UBCamera", scene->SceneCameraBufferHandle); - (*output_pass)->Verify(); } + (*output_pass)->Verify(); } void GridPass::Execute(Hardwares::VulkanDevicePtr const device, RenderGraphResourceInspectorPtr res_inspector, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPass* const pass, Buffers::FramebufferVNext* const framebuffer, Hardwares::CommandBufferPtr const command_buffer) @@ -339,7 +392,6 @@ namespace ZEngine::Rendering::Renderers pass_node.Outputs.init(device->Arena, 4); pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameDepthRenderTargetName}); - pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameColorRenderTargetName}); pass_node.Outputs.push({.Name = gbuffer_albedo.Name}); pass_node.Outputs.push({.Name = gbuffer_specular.Name}); @@ -484,4 +536,63 @@ namespace ZEngine::Rendering::Renderers // command_buffer->DrawIndirect(*indirect_buffer->At(scene->FrameIndex)); // command_buffer->EndRenderPass(); } + + void CompositePass::Setup(Hardwares::VulkanDevicePtr const device, cstring name, RenderGraphResourceBuilderPtr const res_builder, RenderGraphResourceInspectorPtr res_inspector) + { + auto arena = device->Arena; + + // auto& gbuffer_albedo = res_inspector->GetResource("gbuffer_albedo_render_target"); + // auto& gbuffer_specular = res_inspector->GetResource("gbuffer_specular_render_target"); + // auto& gbuffer_normals = res_inspector->GetResource("gbuffer_normals_render_target"); + // auto& gbuffer_position = res_inspector->GetResource("gbuffer_position_render_target"); + + RenderGraphRenderPassCreation pass_node = {.Name = name}; + + const auto& shared_rt = res_inspector->GetResource(RendererResourceName::FrameSharedRenderTargetName); + + pass_node.Inputs.init(arena, 3); + pass_node.Outputs.init(arena, 1); + + pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameDepthRenderTargetName}); + pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = shared_rt.Name, .BindingInputKeyName = "sharedRTAsTex", .Type = RenderGraphResourceType::TEXTURE}); + + // pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = gbuffer_albedo.Name}); + // pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = gbuffer_specular.Name}); + // pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = gbuffer_normals.Name}); + // pass_node.Inputs.push(RenderGraphRenderPassInputOutputInfo{.Name = gbuffer_position.Name}); + + pass_node.Outputs.push(RenderGraphRenderPassInputOutputInfo{.Name = RendererResourceName::FrameColorRenderTargetName}); + + res_builder->CreateRenderPassNode(pass_node); + } + + void CompositePass::Compile(Hardwares::VulkanDevicePtr const device, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPassBuilder* pass_builder, RenderGraphResourceInspectorPtr res_inspector, RenderPasses::RenderPass** const output_pass) + { + CHECK_AND_ESCAPE_NULL(output_pass) + + if (output_pass && !(*output_pass)) + { + auto pass_spec = pass_builder->SetPipelineName("Composite-Pipeline").SetInputBindingCount(0).EnablePipelineDepthTest(true).UseShader("composite").Detach(); + *output_pass = device->CreateRenderPass(pass_spec); + (*output_pass)->Bake(); + } + + (*output_pass)->SetInput("LinearWrapSampler", device->GlobalLinearWrapSamplerImageInfo); + (*output_pass)->Verify(); + } + + void CompositePass::Execute(Hardwares::VulkanDevicePtr const device, RenderGraphResourceInspectorPtr res_inspector, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPass* const pass, Buffers::FramebufferVNext* const framebuffer, Hardwares::CommandBufferPtr const command_buffer) + { + command_buffer->BeginRenderPass(pass, framebuffer->Handle, false); + { + uint32_t w = pass->GetRenderAreaWidth(); + uint32_t h = pass->GetRenderAreaHeight(); + command_buffer->SetViewport(w, h); + command_buffer->SetScissor(w, h); + } + command_buffer->BindPipeline(Specifications::PipelineBindPoint::GRAPHIC, pass->Pipeline); + command_buffer->BindDescriptorSets(device->SwapchainPtr->CurrentFrame->Index); + command_buffer->Draw(3, 1, 0, 0); + command_buffer->EndRenderPass(); + } } // namespace ZEngine::Rendering::Renderers diff --git a/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.h b/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.h index 32118c4a..c65809bb 100644 --- a/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.h +++ b/ZEngine/ZEngine/Rendering/Renderers/RendererPasses.h @@ -33,6 +33,13 @@ namespace ZEngine::Rendering::Renderers virtual void Execute(Hardwares::VulkanDevicePtr const device, RenderGraphResourceInspectorPtr res_inspector, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPass* const pass, Buffers::FramebufferVNext* const framebuffer, Hardwares::CommandBufferPtr const command_buffer) override; }; + struct BasePass : public IRenderGraphCallbackPass + { + virtual void Setup(Hardwares::VulkanDevicePtr const device, cstring name, RenderGraphResourceBuilderPtr const res_builder, RenderGraphResourceInspectorPtr res_inspector) override; + virtual void Compile(Hardwares::VulkanDevicePtr const device, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPassBuilder* pass_builder, RenderGraphResourceInspectorPtr res_inspector, RenderPasses::RenderPass** const output_pass) override; + virtual void Execute(Hardwares::VulkanDevicePtr const device, RenderGraphResourceInspectorPtr res_inspector, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPass* const pass, Buffers::FramebufferVNext* const framebuffer, Hardwares::CommandBufferPtr const command_buffer) override; + }; + struct DepthPrePass : public IRenderGraphCallbackPass { virtual void Setup(Hardwares::VulkanDevicePtr const device, cstring name, RenderGraphResourceBuilderPtr const res_builder, RenderGraphResourceInspectorPtr res_inspector) override; @@ -71,4 +78,11 @@ namespace ZEngine::Rendering::Renderers virtual void Execute(Hardwares::VulkanDevicePtr const device, RenderGraphResourceInspectorPtr res_inspector, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPass* const pass, Buffers::FramebufferVNext* const framebuffer, Hardwares::CommandBufferPtr const command_buffer) override; }; + struct CompositePass : public IRenderGraphCallbackPass + { + virtual void Setup(Hardwares::VulkanDevicePtr const device, cstring name, RenderGraphResourceBuilderPtr const res_builder, RenderGraphResourceInspectorPtr res_inspector) override; + virtual void Compile(Hardwares::VulkanDevicePtr const device, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPassBuilder* pass_builder, RenderGraphResourceInspectorPtr res_inspector, RenderPasses::RenderPass** const output_pass) override; + virtual void Execute(Hardwares::VulkanDevicePtr const device, RenderGraphResourceInspectorPtr res_inspector, Rendering::Scenes::SceneDataPtr const scene, RenderPasses::RenderPass* const pass, Buffers::FramebufferVNext* const framebuffer, Hardwares::CommandBufferPtr const command_buffer) override; + }; + } // namespace ZEngine::Rendering::Renderers \ No newline at end of file diff --git a/ZEngine/ZEngine/Rendering/Shaders/Shader.cpp b/ZEngine/ZEngine/Rendering/Shaders/Shader.cpp index eeb9de38..8f722359 100644 --- a/ZEngine/ZEngine/Rendering/Shaders/Shader.cpp +++ b/ZEngine/ZEngine/Rendering/Shaders/Shader.cpp @@ -518,7 +518,7 @@ namespace ZEngine::Rendering::Shaders */ if (pool_size_collection.empty()) { - ZENGINE_CORE_WARN("Shader: - The pool size is empty!") + ZENGINE_CORE_WARN("Shader '{0}': - The pool size is empty!", m_specification.Name) ZReleaseScratch(scratch); return; } diff --git a/ZEngine/ZEngine/Rendering/Specifications/RenderPassSpecification.h b/ZEngine/ZEngine/Rendering/Specifications/RenderPassSpecification.h index cdf823ba..13327935 100644 --- a/ZEngine/ZEngine/Rendering/Specifications/RenderPassSpecification.h +++ b/ZEngine/ZEngine/Rendering/Specifications/RenderPassSpecification.h @@ -7,10 +7,18 @@ namespace ZEngine::Rendering::Specifications { + enum class RenderPassType + { + GRAPHIC, + COMPUTE, + TRANSFER + }; + struct RenderPassSpecification { const char* DebugName = {}; bool SwapchainAsRenderTarget = false; + RenderPassType Type = {RenderPassType::GRAPHIC}; Specifications::GraphicRendererPipelineSpecification PipelineSpecification = {}; Core::Containers::Array Inputs = {}; Core::Containers::UnorderedHashMap InputTextures = {};