Put imgui buffers into render targets
Makes imgui multiviewports work now!
This commit is contained in:
parent
77c9561868
commit
bb00009041
8 changed files with 93 additions and 70 deletions
|
@ -755,6 +755,8 @@ void Engine::render(const int index) {
|
||||||
if(window == nullptr)
|
if(window == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
GFXCommandBuffer* commandbuffer = _gfx->acquire_command_buffer(true);
|
||||||
|
|
||||||
if(index == 0) {
|
if(index == 0) {
|
||||||
if(_current_screen != nullptr && _current_screen->view_changed) {
|
if(_current_screen != nullptr && _current_screen->view_changed) {
|
||||||
_renderer->update_screen();
|
_renderer->update_screen();
|
||||||
|
@ -762,12 +764,10 @@ void Engine::render(const int index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_imgui->render(0);
|
_imgui->render(0);
|
||||||
|
|
||||||
|
_app->render(commandbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
GFXCommandBuffer* commandbuffer = _gfx->acquire_command_buffer(true);
|
|
||||||
|
|
||||||
_app->render(commandbuffer);
|
|
||||||
|
|
||||||
if(_renderer != nullptr)
|
if(_renderer != nullptr)
|
||||||
_renderer->render(commandbuffer, _current_scene, *window->render_target, index);
|
_renderer->render(commandbuffer, _current_scene, *window->render_target, index);
|
||||||
|
|
||||||
|
|
|
@ -14,24 +14,18 @@ struct ImDrawData;
|
||||||
class ImGuiPass : public Pass {
|
class ImGuiPass : public Pass {
|
||||||
public:
|
public:
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
|
|
||||||
void resize(const prism::Extent extent) override;
|
void create_render_target_resources(RenderTarget& target) override;
|
||||||
|
|
||||||
void render_post(GFXCommandBuffer* command_buffer, const int index) override;
|
void render_post(GFXCommandBuffer* command_buffer, RenderTarget& target, const int index) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void load_font(const std::string_view filename);
|
void load_font(const std::string_view filename);
|
||||||
void create_font_texture();
|
void create_font_texture();
|
||||||
void update_buffers(const ImDrawData& draw_data);
|
void update_buffers(RenderTarget& target, const ImDrawData& draw_data);
|
||||||
|
|
||||||
std::unique_ptr<file::File> font_file;
|
std::unique_ptr<file::File> font_file;
|
||||||
|
|
||||||
GFXPipeline* pipeline = nullptr;
|
GFXPipeline* pipeline = nullptr;
|
||||||
GFXTexture* font_texture = nullptr;
|
GFXTexture* font_texture = nullptr;
|
||||||
|
|
||||||
GFXBuffer* vertex_buffer = nullptr;
|
|
||||||
int current_vertex_size = 0;
|
|
||||||
|
|
||||||
GFXBuffer* index_buffer = nullptr;
|
|
||||||
int current_index_size = 0;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,6 +10,7 @@ enum class PassTextureType {
|
||||||
};
|
};
|
||||||
|
|
||||||
class GFXTexture;
|
class GFXTexture;
|
||||||
|
class RenderTarget;
|
||||||
|
|
||||||
class Pass {
|
class Pass {
|
||||||
public:
|
public:
|
||||||
|
@ -17,12 +18,13 @@ public:
|
||||||
|
|
||||||
virtual void initialize() {}
|
virtual void initialize() {}
|
||||||
|
|
||||||
virtual void resize([[maybe_unused]] const prism::Extent extent) {}
|
virtual void create_render_target_resources([[maybe_used]] RenderTarget& target) {}
|
||||||
|
|
||||||
virtual void render_scene([[maybe_unused]] Scene& scene,
|
virtual void render_scene([[maybe_unused]] Scene& scene,
|
||||||
[[maybe_unused]] GFXCommandBuffer* commandBuffer) {}
|
[[maybe_unused]] GFXCommandBuffer* commandBuffer) {}
|
||||||
virtual void render_post([[maybe_unused]] GFXCommandBuffer* commandBuffer,
|
virtual void render_post([[maybe_unused]] GFXCommandBuffer* commandBuffer,
|
||||||
[[maybe_unused]] int index) {}
|
[[maybe_unused]] RenderTarget& target,
|
||||||
|
[[maybe_unused]] int index) {}
|
||||||
|
|
||||||
virtual GFXTexture* get_requested_texture([[maybe_unused]] PassTextureType type) { return nullptr; }
|
virtual GFXTexture* get_requested_texture([[maybe_unused]] PassTextureType type) { return nullptr; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,4 +31,11 @@ public:
|
||||||
|
|
||||||
GFXFramebuffer* edge_framebuffer = nullptr;
|
GFXFramebuffer* edge_framebuffer = nullptr;
|
||||||
GFXFramebuffer* blend_framebuffer = nullptr;
|
GFXFramebuffer* blend_framebuffer = nullptr;
|
||||||
|
|
||||||
|
// imgui
|
||||||
|
GFXBuffer* vertex_buffer = nullptr;
|
||||||
|
int current_vertex_size = 0;
|
||||||
|
|
||||||
|
GFXBuffer* index_buffer = nullptr;
|
||||||
|
int current_index_size = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,56 +19,58 @@ void ImGuiPass::initialize() {
|
||||||
create_font_texture();
|
create_font_texture();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiPass::resize(const prism::Extent extent) {
|
void ImGuiPass::create_render_target_resources(RenderTarget& target) {
|
||||||
GFXGraphicsPipelineCreateInfo createInfo;
|
if(pipeline == nullptr) {
|
||||||
createInfo.label = "ImGui";
|
GFXGraphicsPipelineCreateInfo createInfo;
|
||||||
createInfo.shaders.vertex_src = file::Path("imgui.vert");
|
createInfo.label = "ImGui";
|
||||||
createInfo.shaders.fragment_src = file::Path("imgui.frag");
|
createInfo.shaders.vertex_src = file::Path("imgui.vert");
|
||||||
|
createInfo.shaders.fragment_src = file::Path("imgui.frag");
|
||||||
|
|
||||||
GFXVertexInput vertexInput = {};
|
GFXVertexInput vertexInput = {};
|
||||||
vertexInput.stride = sizeof(ImDrawVert);
|
vertexInput.stride = sizeof(ImDrawVert);
|
||||||
|
|
||||||
createInfo.vertex_input.inputs.push_back(vertexInput);
|
createInfo.vertex_input.inputs.push_back(vertexInput);
|
||||||
|
|
||||||
GFXVertexAttribute positionAttribute = {};
|
GFXVertexAttribute positionAttribute = {};
|
||||||
positionAttribute.format = GFXVertexFormat::FLOAT2;
|
positionAttribute.format = GFXVertexFormat::FLOAT2;
|
||||||
positionAttribute.offset = offsetof(ImDrawVert, pos);
|
positionAttribute.offset = offsetof(ImDrawVert, pos);
|
||||||
|
|
||||||
createInfo.vertex_input.attributes.push_back(positionAttribute);
|
createInfo.vertex_input.attributes.push_back(positionAttribute);
|
||||||
|
|
||||||
GFXVertexAttribute uvAttribute = {};
|
GFXVertexAttribute uvAttribute = {};
|
||||||
uvAttribute.location = 1;
|
uvAttribute.location = 1;
|
||||||
uvAttribute.format = GFXVertexFormat::FLOAT2;
|
uvAttribute.format = GFXVertexFormat::FLOAT2;
|
||||||
uvAttribute.offset = offsetof(ImDrawVert, uv);
|
uvAttribute.offset = offsetof(ImDrawVert, uv);
|
||||||
|
|
||||||
createInfo.vertex_input.attributes.push_back(uvAttribute);
|
createInfo.vertex_input.attributes.push_back(uvAttribute);
|
||||||
|
|
||||||
GFXVertexAttribute colAttribute = {};
|
GFXVertexAttribute colAttribute = {};
|
||||||
colAttribute.location = 2;
|
colAttribute.location = 2;
|
||||||
colAttribute.format = GFXVertexFormat::UNORM4;
|
colAttribute.format = GFXVertexFormat::UNORM4;
|
||||||
colAttribute.offset = offsetof(ImDrawVert, col);
|
colAttribute.offset = offsetof(ImDrawVert, col);
|
||||||
|
|
||||||
createInfo.vertex_input.attributes.push_back(colAttribute);
|
createInfo.vertex_input.attributes.push_back(colAttribute);
|
||||||
|
|
||||||
createInfo.blending.enable_blending = true;
|
createInfo.blending.enable_blending = true;
|
||||||
createInfo.blending.src_rgb = GFXBlendFactor::SrcAlpha;
|
createInfo.blending.src_rgb = GFXBlendFactor::SrcAlpha;
|
||||||
createInfo.blending.src_alpha= GFXBlendFactor::SrcAlpha;
|
createInfo.blending.src_alpha= GFXBlendFactor::SrcAlpha;
|
||||||
createInfo.blending.dst_rgb = GFXBlendFactor::OneMinusSrcAlpha;
|
createInfo.blending.dst_rgb = GFXBlendFactor::OneMinusSrcAlpha;
|
||||||
createInfo.blending.dst_alpha = GFXBlendFactor::OneMinusSrcAlpha;
|
createInfo.blending.dst_alpha = GFXBlendFactor::OneMinusSrcAlpha;
|
||||||
|
|
||||||
createInfo.shader_input.push_constants = {
|
createInfo.shader_input.push_constants = {
|
||||||
{sizeof(Matrix4x4), 0}
|
{sizeof(Matrix4x4), 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
createInfo.shader_input.bindings = {
|
createInfo.shader_input.bindings = {
|
||||||
{1, GFXBindingType::PushConstant},
|
{1, GFXBindingType::PushConstant},
|
||||||
{2, GFXBindingType::Texture}
|
{2, GFXBindingType::Texture}
|
||||||
};
|
};
|
||||||
|
|
||||||
pipeline = engine->get_gfx()->create_graphics_pipeline(createInfo);
|
pipeline = engine->get_gfx()->create_graphics_pipeline(createInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, const int index) {
|
void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, RenderTarget& target, const int index) {
|
||||||
ImDrawData* draw_data = nullptr;
|
ImDrawData* draw_data = nullptr;
|
||||||
if(index == 0) {
|
if(index == 0) {
|
||||||
draw_data = ImGui::GetDrawData();
|
draw_data = ImGui::GetDrawData();
|
||||||
|
@ -95,12 +97,12 @@ void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, const int index) {
|
||||||
Expects(framebuffer_width > 0);
|
Expects(framebuffer_width > 0);
|
||||||
Expects(framebuffer_height > 0);
|
Expects(framebuffer_height > 0);
|
||||||
|
|
||||||
update_buffers(*draw_data);
|
update_buffers(target, *draw_data);
|
||||||
|
|
||||||
command_buffer->set_graphics_pipeline(pipeline);
|
command_buffer->set_graphics_pipeline(pipeline);
|
||||||
|
|
||||||
command_buffer->set_vertex_buffer(vertex_buffer, 0, 0);
|
command_buffer->set_vertex_buffer(target.vertex_buffer, 0, 0);
|
||||||
command_buffer->set_index_buffer(index_buffer, IndexType::UINT16);
|
command_buffer->set_index_buffer(target.index_buffer, IndexType::UINT16);
|
||||||
|
|
||||||
const Matrix4x4 projection = transform::orthographic(draw_data->DisplayPos.x,
|
const Matrix4x4 projection = transform::orthographic(draw_data->DisplayPos.x,
|
||||||
draw_data->DisplayPos.x + draw_data->DisplaySize.x,
|
draw_data->DisplayPos.x + draw_data->DisplaySize.x,
|
||||||
|
@ -187,21 +189,21 @@ void ImGuiPass::create_font_texture() {
|
||||||
io.Fonts->TexID = reinterpret_cast<void*>(font_texture);
|
io.Fonts->TexID = reinterpret_cast<void*>(font_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiPass::update_buffers(const ImDrawData& draw_data) {
|
void ImGuiPass::update_buffers(RenderTarget& target, const ImDrawData& draw_data) {
|
||||||
const int new_vertex_size = draw_data.TotalVtxCount * sizeof(ImDrawVert);
|
const int new_vertex_size = draw_data.TotalVtxCount * sizeof(ImDrawVert);
|
||||||
const int new_index_size = draw_data.TotalIdxCount * sizeof(ImDrawIdx);
|
const int new_index_size = draw_data.TotalIdxCount * sizeof(ImDrawIdx);
|
||||||
|
|
||||||
Expects(new_vertex_size > 0);
|
Expects(new_vertex_size > 0);
|
||||||
Expects(new_index_size > 0);
|
Expects(new_index_size > 0);
|
||||||
|
|
||||||
if(vertex_buffer == nullptr || current_vertex_size < new_vertex_size) {
|
if(target.vertex_buffer == nullptr || target.current_vertex_size < new_vertex_size) {
|
||||||
vertex_buffer = engine->get_gfx()->create_buffer(nullptr, new_vertex_size, true, GFXBufferUsage::Vertex);
|
target.vertex_buffer = engine->get_gfx()->create_buffer(nullptr, new_vertex_size, true, GFXBufferUsage::Vertex);
|
||||||
current_vertex_size = new_vertex_size;
|
target.current_vertex_size = new_vertex_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index_buffer == nullptr || current_index_size < new_index_size) {
|
if(target.index_buffer == nullptr || target.current_index_size < new_index_size) {
|
||||||
index_buffer = engine->get_gfx()->create_buffer(nullptr, new_index_size, true, GFXBufferUsage::Index);
|
target.index_buffer = engine->get_gfx()->create_buffer(nullptr, new_index_size, true, GFXBufferUsage::Index);
|
||||||
current_index_size = new_index_size;
|
target.current_index_size = new_index_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vertex_offset = 0;
|
int vertex_offset = 0;
|
||||||
|
@ -209,8 +211,8 @@ void ImGuiPass::update_buffers(const ImDrawData& draw_data) {
|
||||||
for(int i = 0; i < draw_data.CmdListsCount; i++) {
|
for(int i = 0; i < draw_data.CmdListsCount; i++) {
|
||||||
const ImDrawList* cmd_list = draw_data.CmdLists[i];
|
const ImDrawList* cmd_list = draw_data.CmdLists[i];
|
||||||
|
|
||||||
engine->get_gfx()->copy_buffer(vertex_buffer, cmd_list->VtxBuffer.Data, vertex_offset, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
engine->get_gfx()->copy_buffer(target.vertex_buffer, cmd_list->VtxBuffer.Data, vertex_offset, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||||
engine->get_gfx()->copy_buffer(index_buffer, cmd_list->IdxBuffer.Data, index_offset, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
engine->get_gfx()->copy_buffer(target.index_buffer, cmd_list->IdxBuffer.Data, index_offset, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||||
|
|
||||||
vertex_offset += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
|
vertex_offset += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
|
||||||
index_offset += cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx);
|
index_offset += cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx);
|
||||||
|
|
|
@ -172,7 +172,7 @@ void Renderer::resize_render_target(RenderTarget& target, const prism::Extent ex
|
||||||
createUIPipeline();
|
createUIPipeline();
|
||||||
|
|
||||||
for(auto& pass : passes)
|
for(auto& pass : passes)
|
||||||
pass->resize(extent);
|
pass->create_render_target_resources(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::recreate_all_render_targets() {
|
void Renderer::recreate_all_render_targets() {
|
||||||
|
@ -224,6 +224,24 @@ void Renderer::update_screen() {
|
||||||
void Renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarget& target, int index) {
|
void Renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarget& target, int index) {
|
||||||
const auto extent = target.extent;
|
const auto extent = target.extent;
|
||||||
const auto render_extent = target.get_render_extent();
|
const auto render_extent = target.get_render_extent();
|
||||||
|
|
||||||
|
if(index > 0) {
|
||||||
|
GFXRenderPassBeginInfo beginInfo = {};
|
||||||
|
beginInfo.render_area.extent = render_extent;
|
||||||
|
|
||||||
|
commandbuffer->set_render_pass(beginInfo);
|
||||||
|
|
||||||
|
Viewport viewport = {};
|
||||||
|
viewport.width = render_extent.width;
|
||||||
|
viewport.height = render_extent.height;
|
||||||
|
|
||||||
|
commandbuffer->set_viewport(viewport);
|
||||||
|
|
||||||
|
for(auto& pass : passes)
|
||||||
|
pass->render_post(commandbuffer, target, index);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
commandbuffer->push_group("Scene Rendering");
|
commandbuffer->push_group("Scene Rendering");
|
||||||
|
|
||||||
|
@ -368,7 +386,7 @@ void Renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
||||||
commandbuffer->push_group("Extra Passes");
|
commandbuffer->push_group("Extra Passes");
|
||||||
|
|
||||||
for(auto& pass : passes)
|
for(auto& pass : passes)
|
||||||
pass->render_post(commandbuffer, index);
|
pass->render_post(commandbuffer, target, index);
|
||||||
|
|
||||||
commandbuffer->pop_group();
|
commandbuffer->pop_group();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,8 @@ class DebugPass : public Pass {
|
||||||
public:
|
public:
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
|
|
||||||
void resize(const prism::Extent extent) override;
|
void create_render_target_resources(RenderTarget& target) override;
|
||||||
|
|
||||||
void render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) override;
|
void render_scene(Scene& scene, GFXCommandBuffer* commandBuffer) override;
|
||||||
|
|
||||||
void get_selected_object(int x, int y, std::function<void(SelectableObject)> callback);
|
void get_selected_object(int x, int y, std::function<void(SelectableObject)> callback);
|
||||||
|
|
|
@ -170,8 +170,8 @@ void DebugPass::initialize() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugPass::resize(const prism::Extent extent) {
|
void DebugPass::create_render_target_resources(RenderTarget& target) {
|
||||||
this->extent = extent;
|
this->extent = target.extent;
|
||||||
|
|
||||||
createOffscreenResources();
|
createOffscreenResources();
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue