diff --git a/include/NazaraImgui/NazaraImgui.h b/include/NazaraImgui/NazaraImgui.h index 7b8bb17..e170f5e 100644 --- a/include/NazaraImgui/NazaraImgui.h +++ b/include/NazaraImgui/NazaraImgui.h @@ -66,14 +66,17 @@ namespace Nz { std::shared_ptr Pipeline; std::unordered_map TextureShaderBindings; + Nz::ShaderBindingPtr UboShaderBinding; std::shared_ptr TextureSampler; } m_texturedPipeline; struct { std::shared_ptr Pipeline; + Nz::ShaderBindingPtr UboShaderBinding; } m_untexturedPipeline; + std::shared_ptr m_uboBuffer; std::shared_ptr m_fontTexture; static Imgui* s_instance; diff --git a/src/NazaraImgui/NazaraImgui.cpp b/src/NazaraImgui/NazaraImgui.cpp index 8d00480..cfa3515 100644 --- a/src/NazaraImgui/NazaraImgui.cpp +++ b/src/NazaraImgui/NazaraImgui.cpp @@ -88,6 +88,12 @@ namespace namespace Nz { + struct ImguiUbo + { + float screenWidth; + float screenHeight; + }; + Imgui* Imgui::s_instance = nullptr; Imgui::Imgui(Config config) @@ -100,8 +106,10 @@ namespace Nz Imgui::~Imgui() { + m_untexturedPipeline.UboShaderBinding.reset(); m_untexturedPipeline.Pipeline.reset(); + m_texturedPipeline.UboShaderBinding.reset(); m_texturedPipeline.TextureShaderBindings.clear(); m_texturedPipeline.TextureSampler.reset(); m_texturedPipeline.Pipeline.reset(); @@ -396,6 +404,12 @@ namespace Nz Nz::RenderPipelineLayoutInfo pipelineLayoutInfo; + auto& uboBinding = pipelineLayoutInfo.bindings.emplace_back(); + uboBinding.setIndex = 0; + uboBinding.bindingIndex = 0; + uboBinding.shaderStageFlags = nzsl::ShaderStageType::Vertex; + uboBinding.type = Nz::ShaderBindingType::UniformBuffer; + auto& textureBinding = pipelineLayoutInfo.bindings.emplace_back(); textureBinding.setIndex = 1; textureBinding.bindingIndex = 0; @@ -424,6 +438,19 @@ namespace Nz pipelineVertexBuffer.declaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_Color_UV); m_texturedPipeline.Pipeline = renderDevice->InstantiateRenderPipeline(pipelineInfo); + + m_uboBuffer = renderDevice->InstantiateBuffer(Nz::BufferType::Uniform, sizeof(ImguiUbo), Nz::BufferUsage::DeviceLocal | Nz::BufferUsage::Dynamic); + + m_texturedPipeline.UboShaderBinding = renderPipelineLayout->AllocateShaderBinding(0); + m_texturedPipeline.UboShaderBinding->Update({ + { + 0, + Nz::ShaderBinding::UniformBufferBinding { + m_uboBuffer.get(), 0, sizeof(ImguiUbo) + } + } + }); + return true; } @@ -449,6 +476,13 @@ namespace Nz } Nz::RenderPipelineLayoutInfo pipelineLayoutInfo; + + auto& uboBinding = pipelineLayoutInfo.bindings.emplace_back(); + uboBinding.setIndex = 0; + uboBinding.bindingIndex = 0; + uboBinding.shaderStageFlags = nzsl::ShaderStageType::Vertex; + uboBinding.type = Nz::ShaderBindingType::UniformBuffer; + std::shared_ptr renderPipelineLayout = renderDevice->InstantiateRenderPipelineLayout(std::move(pipelineLayoutInfo)); Nz::RenderPipelineInfo pipelineInfo; @@ -471,6 +505,16 @@ namespace Nz pipelineVertexBuffer.declaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_Color_UV); m_untexturedPipeline.Pipeline = renderDevice->InstantiateRenderPipeline(pipelineInfo); + + m_untexturedPipeline.UboShaderBinding = renderPipelineLayout->AllocateShaderBinding(0); + m_untexturedPipeline.UboShaderBinding->Update({ + { + 0, + Nz::ShaderBinding::UniformBufferBinding { + m_uboBuffer.get(), 0, sizeof(ImguiUbo) + } + } + }); return true; } @@ -489,6 +533,22 @@ namespace Nz if (fb_width == 0 || fb_height == 0) return; + ImguiUbo ubo{ fb_width / 2.f, fb_height / 2.f }; + auto& allocation = frame.GetUploadPool().Allocate(sizeof(ImguiUbo)); + + std::memcpy(allocation.mappedPtr, &ubo, sizeof(ImguiUbo)); + + frame.Execute([&](Nz::CommandBufferBuilder& builder) + { + builder.BeginDebugRegion("UBO Update", Nz::Color::Yellow); + { + builder.PreTransferBarrier(); + builder.CopyBuffer(allocation, m_uboBuffer.get()); + builder.PostTransferBarrier(); + } + builder.EndDebugRegion(); + }, Nz::QueueType::Transfer); + drawData->ScaleClipRects(io.DisplayFramebufferScale); auto renderDevice = Nz::Graphics::Instance()->GetRenderDevice(); @@ -553,11 +613,13 @@ namespace Nz } builder.BindPipeline(*m_texturedPipeline.Pipeline); + builder.BindShaderBinding(0, *m_texturedPipeline.UboShaderBinding); builder.BindShaderBinding(1, *m_texturedPipeline.TextureShaderBindings[texture]); } else { builder.BindPipeline(*m_untexturedPipeline.Pipeline); + builder.BindShaderBinding(0, *m_untexturedPipeline.UboShaderBinding); } builder.SetViewport(Nz::Recti{ 0, 0, fb_width, fb_height }); diff --git a/src/NazaraImgui/Textured.nzsl.h b/src/NazaraImgui/Textured.nzsl.h index bf9b201..2d62b00 100644 --- a/src/NazaraImgui/Textured.nzsl.h +++ b/src/NazaraImgui/Textured.nzsl.h @@ -2,6 +2,19 @@ R"( [nzsl_version("1.0")] module; +[layout(std140)] +struct Data +{ + halfScreenWidth : f32, + halfScreenHeight : f32, +} + +[set(0)] +external +{ + [binding(0)] data: uniform[Data] +} + [set(1)] external { @@ -40,7 +53,7 @@ fn main(fragIn: VertOut) -> FragOut fn main(vertIn: VertIn) -> VertOut { let vertOut: VertOut; - vertOut.position = vec4[f32](vertIn.position, 1.0) / vec4[f32](1280.0 / 2.0, 720.0 / 2.0, 1.0, 1.0) - vec4[f32](1.0,1.0,0.0,0.0); + vertOut.position = vec4[f32](vertIn.position, 1.0) / vec4[f32](data.halfScreenWidth, data.halfScreenHeight, 1.0, 1.0) - vec4[f32](1.0,1.0,0.0,0.0); vertOut.color = vertIn.color; vertOut.uv = vertIn.uv; return vertOut; diff --git a/src/NazaraImgui/Untextured.nzsl.h b/src/NazaraImgui/Untextured.nzsl.h index 74e9ff1..a9aaac3 100644 --- a/src/NazaraImgui/Untextured.nzsl.h +++ b/src/NazaraImgui/Untextured.nzsl.h @@ -2,6 +2,19 @@ R"( [nzsl_version("1.0")] module; +[layout(std140)] +struct Data +{ + halfScreenWidth : f32, + halfScreenHeight : f32, +} + +[set(0)] +external +{ + [binding(0)] data: uniform[Data] +} + struct VertIn { [location(0)] position: vec3[f32], @@ -34,7 +47,7 @@ fn main(fragIn: VertOut) -> FragOut fn main(vertIn: VertIn) -> VertOut { let vertOut: VertOut; - vertOut.position = vec4[f32](vertIn.position, 1.0) / vec4[f32](1280.0 / 2.0, 720.0 / 2.0, 1.0, 1.0) - vec4[f32](1.0,1.0,0.0,0.0); + vertOut.position = vec4[f32](vertIn.position, 1.0) / vec4[f32](data.halfScreenWidth, data.halfScreenHeight, 1.0, 1.0) - vec4[f32](1.0,1.0,0.0,0.0); vertOut.color = vertIn.color; vertOut.uv = vertIn.uv; return vertOut;