Compare commits

..

2 Commits

Author SHA1 Message Date
Attila Uygun 874fec434a Implement ImguiBackend::Render()
Create geometry in Render() before calling Draw()
2023-10-29 23:21:54 +01:00
Attila Uygun e4f020d359 Add support for set/reset viewport 2023-10-29 23:13:17 +01:00
8 changed files with 79 additions and 48 deletions

View File

@ -70,12 +70,9 @@ void Engine::Run() {
Initialize(); Initialize();
DeltaTimer timer; DeltaTimer timer;
float accumulator = 0.0; float accumulator = 0.0f;
float frame_frac = 0.0f;
for (;;) { for (;;) {
TaskRunner::GetThreadLocalTaskRunner()->RunTasks();
platform_->Update(); platform_->Update();
if (platform_->should_exit()) if (platform_->should_exit())
return; return;
@ -83,8 +80,6 @@ void Engine::Run() {
if (!renderer_->IsInitialzed()) if (!renderer_->IsInitialzed())
continue; continue;
Draw(frame_frac);
// Accumulate time. // Accumulate time.
accumulator += timer.Delta(); accumulator += timer.Delta();
@ -94,8 +89,11 @@ void Engine::Run() {
accumulator -= time_step_; accumulator -= time_step_;
}; };
TaskRunner::GetThreadLocalTaskRunner()->RunTasks();
// Calculate frame fraction from remainder of the frame time. // Calculate frame fraction from remainder of the frame time.
frame_frac = accumulator / time_step_; float frame_frac = accumulator / time_step_;
Draw(frame_frac);
} }
} }
@ -145,6 +143,8 @@ void Engine::Update(float delta_time) {
if (stats_visible_) if (stats_visible_)
ShowStats(); ShowStats();
imgui_backend_.Render();
} }
void Engine::Draw(float frame_frac) { void Engine::Draw(float frame_frac) {

View File

@ -65,8 +65,6 @@ void ImguiBackend::Initialize() {
Engine::Get().RefreshImage("imgui_atlas"); Engine::Get().RefreshImage("imgui_atlas");
ImGui::GetIO().Fonts->SetTexID( ImGui::GetIO().Fonts->SetTexID(
(ImTextureID)(intptr_t)Engine::Get().AcquireTexture("imgui_atlas")); (ImTextureID)(intptr_t)Engine::Get().AcquireTexture("imgui_atlas"));
NewFrame(0);
} }
void ImguiBackend::Shutdown() { void ImguiBackend::Shutdown() {
@ -117,9 +115,9 @@ std::unique_ptr<InputEvent> ImguiBackend::OnInputEvent(
} }
void ImguiBackend::NewFrame(float delta_time) { void ImguiBackend::NewFrame(float delta_time) {
if (is_new_frame_) for (auto& id : geometries_)
ImGui::EndFrame(); renderer_->DestroyGeometry(id);
is_new_frame_ = true; geometries_.clear();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.DisplaySize = ImVec2((float)renderer_->GetScreenWidth(), io.DisplaySize = ImVec2((float)renderer_->GetScreenWidth(),
@ -128,13 +126,28 @@ void ImguiBackend::NewFrame(float delta_time) {
ImGui::NewFrame(); ImGui::NewFrame();
} }
void ImguiBackend::Draw() { void ImguiBackend::Render() {
is_new_frame_ = false;
ImGui::Render(); ImGui::Render();
ImDrawData* draw_data = ImGui::GetDrawData(); ImDrawData* draw_data = ImGui::GetDrawData();
if (draw_data->CmdListsCount <= 0) geometries_.resize(draw_data->CmdListsCount);
for (int n = 0; n < draw_data->CmdListsCount; n++) {
const ImDrawList* cmd_list = draw_data->CmdLists[n];
auto mesh = std::make_unique<Mesh>();
mesh->Create(kPrimitive_Triangles, vertex_description,
cmd_list->VtxBuffer.Size, cmd_list->VtxBuffer.Data,
kDataType_UShort, cmd_list->IdxBuffer.Size,
cmd_list->IdxBuffer.Data);
geometries_[n] = renderer_->CreateGeometry(std::move(mesh));
}
}
void ImguiBackend::Draw() {
ImDrawData* draw_data = ImGui::GetDrawData();
if (!draw_data || draw_data->CmdListsCount <= 0)
return; return;
renderer_->SetViewport(0, 0, draw_data->DisplaySize.x, draw_data->DisplaySize.y);
base::Matrix4f ortho_projection; base::Matrix4f ortho_projection;
ortho_projection.CreateOrthoProjection( ortho_projection.CreateOrthoProjection(
draw_data->DisplayPos.x, draw_data->DisplayPos.x,
@ -147,28 +160,20 @@ void ImguiBackend::Draw() {
for (int n = 0; n < draw_data->CmdListsCount; n++) { for (int n = 0; n < draw_data->CmdListsCount; n++) {
const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n];
auto mesh = std::make_unique<Mesh>();
mesh->Create(kPrimitive_Triangles, vertex_description,
cmd_list->VtxBuffer.Size, cmd_list->VtxBuffer.Data,
kDataType_UShort, cmd_list->IdxBuffer.Size,
cmd_list->IdxBuffer.Data);
auto geometry_id = renderer_->CreateGeometry(std::move(mesh));
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) {
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->ClipRect.z <= pcmd->ClipRect.x || if (pcmd->ClipRect.z <= pcmd->ClipRect.x ||
pcmd->ClipRect.w <= pcmd->ClipRect.y) pcmd->ClipRect.w <= pcmd->ClipRect.y)
continue; continue;
reinterpret_cast<Texture*>(pcmd->GetTexID())->Activate(0); reinterpret_cast<Texture*>(pcmd->GetTexID())->Activate(0);
renderer_->SetScissor(int(pcmd->ClipRect.x), int(pcmd->ClipRect.y), renderer_->SetScissor(int(pcmd->ClipRect.x), int(pcmd->ClipRect.y),
int(pcmd->ClipRect.z - pcmd->ClipRect.x), int(pcmd->ClipRect.z - pcmd->ClipRect.x),
int(pcmd->ClipRect.w - pcmd->ClipRect.y)); int(pcmd->ClipRect.w - pcmd->ClipRect.y));
renderer_->Draw(geometry_id, pcmd->ElemCount, pcmd->IdxOffset); renderer_->Draw(geometries_[n], pcmd->ElemCount, pcmd->IdxOffset);
} }
renderer_->DestroyGeometry(geometry_id);
} }
renderer_->ResetScissor(); renderer_->ResetScissor();
renderer_->ResetViewport();
} }
} // namespace eng } // namespace eng

View File

@ -2,6 +2,7 @@
#define ENGINE_IMGUI_BACKEND_H #define ENGINE_IMGUI_BACKEND_H
#include <memory> #include <memory>
#include <vector>
namespace eng { namespace eng {
@ -22,12 +23,13 @@ class ImguiBackend {
std::unique_ptr<InputEvent> OnInputEvent(std::unique_ptr<InputEvent> event); std::unique_ptr<InputEvent> OnInputEvent(std::unique_ptr<InputEvent> event);
void NewFrame(float delta_time); void NewFrame(float delta_time);
void Render();
void Draw(); void Draw();
private: private:
std::vector<uint64_t> geometries_;
std::unique_ptr<Shader> shader_; std::unique_ptr<Shader> shader_;
Renderer* renderer_ = nullptr; Renderer* renderer_ = nullptr;
bool is_new_frame_ = false;
}; };
} // namespace eng } // namespace eng

View File

@ -47,7 +47,6 @@ RendererOpenGL::~RendererOpenGL() {
void RendererOpenGL::OnWindowResized(int width, int height) { void RendererOpenGL::OnWindowResized(int width, int height) {
screen_width_ = width; screen_width_ = width;
screen_height_ = height; screen_height_ = height;
glViewport(0, 0, screen_width_, screen_height_);
} }
int RendererOpenGL::GetScreenWidth() const { int RendererOpenGL::GetScreenWidth() const {
@ -58,6 +57,14 @@ int RendererOpenGL::GetScreenHeight() const {
return screen_height_; return screen_height_;
} }
void RendererOpenGL::SetViewport(int x, int y, int width, int height) {
glViewport(0, 0, width, height);
}
void RendererOpenGL::ResetViewport() {
glViewport(0, 0, screen_width_, screen_height_);
}
void RendererOpenGL::SetScissor(int x, int y, int width, int height) { void RendererOpenGL::SetScissor(int x, int y, int width, int height) {
glScissor(x, screen_height_ - y - height, width, height); glScissor(x, screen_height_ - y - height, width, height);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
@ -436,6 +443,7 @@ void RendererOpenGL::SetUniform(uint64_t resource_id,
} }
void RendererOpenGL::PrepareForDrawing() { void RendererOpenGL::PrepareForDrawing() {
glViewport(0, 0, screen_width_, screen_height_);
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
} }

View File

@ -32,6 +32,9 @@ class RendererOpenGL final : public Renderer {
int GetScreenWidth() const final; int GetScreenWidth() const final;
int GetScreenHeight() const final; int GetScreenHeight() const final;
void SetViewport(int x, int y, int width, int height) final;
void ResetViewport() final;
void SetScissor(int x, int y, int width, int height) final; void SetScissor(int x, int y, int width, int height) final;
void ResetScissor() final; void ResetScissor() final;

View File

@ -39,6 +39,9 @@ class Renderer {
virtual int GetScreenWidth() const = 0; virtual int GetScreenWidth() const = 0;
virtual int GetScreenHeight() const = 0; virtual int GetScreenHeight() const = 0;
virtual void SetViewport(int x, int y, int width, int height) = 0;
virtual void ResetViewport() = 0;
virtual void SetScissor(int x, int y, int width, int height) = 0; virtual void SetScissor(int x, int y, int width, int height) = 0;
virtual void ResetScissor() = 0; virtual void ResetScissor() = 0;

View File

@ -390,6 +390,30 @@ int RendererVulkan::GetScreenHeight() const {
return context_.GetWindowHeight(); return context_.GetWindowHeight();
} }
void RendererVulkan::SetViewport(int x, int y, int width, int height) {
VkViewport viewport;
viewport.x = 0;
viewport.y = (float)height;
viewport.width = (float)width;
viewport.height = -(float)height;
viewport.minDepth = 0;
viewport.maxDepth = 1.0;
vkCmdSetViewport(frames_[current_frame_].draw_command_buffer, 0, 1,
&viewport);
}
void RendererVulkan::ResetViewport() {
VkViewport viewport;
viewport.x = 0;
viewport.y = (float)context_.GetWindowHeight();
viewport.width = (float)context_.GetWindowWidth();
viewport.height = -(float)context_.GetWindowHeight();
viewport.minDepth = 0;
viewport.maxDepth = 1.0;
vkCmdSetViewport(frames_[current_frame_].draw_command_buffer, 0, 1,
&viewport);
}
void RendererVulkan::SetScissor(int x, int y, int width, int height) { void RendererVulkan::SetScissor(int x, int y, int width, int height) {
if (x < 0) if (x < 0)
x = 0; x = 0;
@ -1990,8 +2014,6 @@ bool RendererVulkan::CreatePipelineLayout(
} }
void RendererVulkan::DrawListBegin() { void RendererVulkan::DrawListBegin() {
VkCommandBuffer command_buffer = frames_[current_frame_].draw_command_buffer;
VkRenderPassBeginInfo render_pass_begin; VkRenderPassBeginInfo render_pass_begin;
render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
render_pass_begin.pNext = nullptr; render_pass_begin.pNext = nullptr;
@ -2010,26 +2032,11 @@ void RendererVulkan::DrawListBegin() {
render_pass_begin.clearValueCount = clear_values.size(); render_pass_begin.clearValueCount = clear_values.size();
render_pass_begin.pClearValues = clear_values.data(); render_pass_begin.pClearValues = clear_values.data();
vkCmdBeginRenderPass(command_buffer, &render_pass_begin, vkCmdBeginRenderPass(frames_[current_frame_].draw_command_buffer,
VK_SUBPASS_CONTENTS_INLINE); &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
VkViewport viewport; ResetViewport();
viewport.x = 0; ResetScissor();
viewport.y = (float)context_.GetWindowHeight();
viewport.width = (float)context_.GetWindowWidth();
viewport.height = -(float)context_.GetWindowHeight();
viewport.minDepth = 0;
viewport.maxDepth = 1.0;
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
VkRect2D scissor;
scissor.offset.x = 0;
scissor.offset.y = 0;
scissor.extent.width = context_.GetWindowWidth();
scissor.extent.height = context_.GetWindowHeight();
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
} }
void RendererVulkan::DrawListEnd() { void RendererVulkan::DrawListEnd() {

View File

@ -33,6 +33,9 @@ class RendererVulkan final : public Renderer {
int GetScreenWidth() const final; int GetScreenWidth() const final;
int GetScreenHeight() const final; int GetScreenHeight() const final;
void SetViewport(int x, int y, int width, int height) final;
void ResetViewport() final;
void SetScissor(int x, int y, int width, int height) final; void SetScissor(int x, int y, int width, int height) final;
void ResetScissor() final; void ResetScissor() final;