diff --git a/core/application/application.cpp b/core/application/application.cpp index 15f61fa..2db0332 100644 --- a/core/application/application.cpp +++ b/core/application/application.cpp @@ -172,7 +172,7 @@ void application::init(window_params in_window_params, int argc, char** argv) SDL_ShowWindow(window_); renderer_->init(window_); - renderer_->init_slang(R"(E:\Projects\AronaStudio\Arona\shaders\)"); + renderer_->init_slang(get_shader_path()); renderer_->resize(in_window_params.width, in_window_params.height); g_is_running = true; } @@ -251,3 +251,8 @@ std::shared_ptr application::create_render_target(const int width { return renderer_->create_render_target(width, height, format); } + +std::shared_ptr application::create_pixel_shader_drawer() const +{ + return renderer_->create_pixel_shader_drawer(); +} diff --git a/core/application/application.h b/core/application/application.h index 813cab7..0bb5470 100644 --- a/core/application/application.h +++ b/core/application/application.h @@ -5,6 +5,7 @@ #include "slang-com-ptr.h" #include "slang.h" +class pixel_shader_drawer; class render_target; class renderer; class texture; @@ -48,10 +49,12 @@ public: virtual int run(); virtual void shutdown(); virtual void draw_gui() = 0; + virtual const char* get_shader_path() = 0; virtual void init_imgui(ImGuiContext* in_context) = 0; std::shared_ptr load_texture(const std::string& path) const; std::shared_ptr create_texture(const unsigned char* data, const int width, const int height) const; std::shared_ptr create_render_target(const int width, const int height, texture_format format) const; + std::shared_ptr create_pixel_shader_drawer() const; virtual const char* get_entry_model() const = 0; virtual const char* get_draw_ps_vertex_shader_entry() const = 0; // Vertex Shader used for drawing ps diff --git a/core/rhi/opengl/pixel_shader_drawer_opengl.cpp b/core/rhi/opengl/pixel_shader_drawer_opengl.cpp new file mode 100644 index 0000000..d5e4f57 --- /dev/null +++ b/core/rhi/opengl/pixel_shader_drawer_opengl.cpp @@ -0,0 +1,140 @@ +#include "pixel_shader_drawer_opengl.h" + +#include "application/application.h" +#include "rhi/renderer.h" +#include "shader/shader_ps_opengl.h" +#include "shader/shader_vs_opengl.h" + +void ps_opengl_compute_callback(const ImDrawList* parent_list, const ImDrawCmd* cmd) +{ + const auto data = static_cast(cmd->UserCallbackData); + const std::shared_ptr& rt = data->rt; + const auto program = data->program; + program->use_program(); + + // do on callback + float x = 0; + float width = rt->get_width(); + float y = 0; + float height = rt->get_height(); + + const float ortho_projection[4][4] = + { + { 2.0f/(width-x), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(y-height), 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { (width+x)/(x-width), (y+height)/(height-y), 0.0f, 1.0f }, + }; + // glUseProgram(bd->ShaderHandle); + // glUniform1i(bd->AttribLocationTex, 0); + // glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + program->set_uniform("viewMatrix", ortho_projection); + + // ImVec2 clip_min(x, y); + // ImVec2 clip_max(width, height); + glViewport(0, 0, width, height); + + // Apply scissor/clipping rectangle (Y is inverted in OpenGL) + glScissor(0, 0, width, height); + // glScissor((int)clip_min.x, (int)(0 - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y)); + + ImDrawVert& vert1 = data->vtx_buffer[0]; + ImDrawVert& vert2 = data->vtx_buffer[1]; + ImDrawVert& vert3 = data->vtx_buffer[2]; + ImDrawVert& vert4 = data->vtx_buffer[3]; + vert1.pos = ImVec2(0, 0); + vert2.pos = ImVec2(width, 0); + vert3.pos = ImVec2(width, height); + vert4.pos = ImVec2(0, height); + vert1.uv = ImVec2(0, 0); + vert2.uv = ImVec2(1, 0); + vert3.uv = ImVec2(1, 1); + vert4.uv = ImVec2(0, 1); + vert1.col = 0xFFFFFFFF; + vert2.col = 0xFFFFFFFF; + vert3.col = 0xFFFFFFFF; + vert4.col = 0xFFFFFFFF; + + + const size_t vtx_size = data->vtx_buffer.size() * sizeof(ImDrawVert); + const size_t idx_size = data->idx_buffer.size() * sizeof(ImDrawIdx); + glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_size, data->vtx_buffer.data()); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_size, data->idx_buffer.data()); + + glBindBuffer(GL_ARRAY_BUFFER, data->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data->ibo); + + glBindFramebuffer(GL_FRAMEBUFFER, rt->get_fbo()); + + glDrawElementsBaseVertex(GL_TRIANGLES, 6, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, 0, 0); + // glDrawElements(GL_TRIANGLES, 6, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, 0); + + program->unuse_program(); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + + +pixel_shader_drawer_opengl::~pixel_shader_drawer_opengl() +{ + if (vbo) + glDeleteBuffers(1, &vbo); + if (ibo) + glDeleteBuffers(1, &ibo); +} + +void pixel_shader_drawer_opengl::init(int width, int height, std::shared_ptr in_pixel_shader, std::shared_ptr in_vertex_shader) +{ + if (!in_vertex_shader) + { + in_vertex_shader = application::get()->get_renderer()->get_pixel_shader_render_default_vs(); + } + + const auto gl_ps = std::static_pointer_cast(in_pixel_shader); + const auto gl_vs = std::static_pointer_cast(in_vertex_shader); + vertex_shader = gl_vs; + pixel_shader = gl_ps; + rt = std::static_pointer_cast(application::get()->create_render_target(width, height, texture_format::RGBA32_FLOAT)); + program = std::make_shared(); + program->create_program(gl_ps, gl_vs); + + idx_buffer = {0, 1, 2, 0, 2, 3}; + vtx_buffer.resize(4); + + glGenBuffers(1, &vbo); + glGenBuffers(1, &ibo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + const size_t vtx_size = vtx_buffer.size() * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, vtx_size, vtx_buffer.data(), GL_STREAM_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); + const size_t idx_size = idx_buffer.size() * sizeof(ImDrawIdx); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_size, idx_buffer.data(), GL_STREAM_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + +void pixel_shader_drawer_opengl::resize(int width, int height) +{ + rt->resize(width, height); +} + +void pixel_shader_drawer_opengl::draw() +{ +#if _DEBUG + assert(!(pixel_shader.expired() || vertex_shader.expired())); +#endif + ImGui::GetWindowDrawList()->AddCallback(ps_opengl_compute_callback, this); + ImGui::GetWindowDrawList()->AddCallback(ImDrawCallback_ResetRenderState, nullptr); + rt->draw(); +} + +void pixel_shader_drawer_opengl::set_vertex_shader(std::shared_ptr in_vertex_shader) +{ +#if _DEBUG + assert(!(pixel_shader.expired() || vertex_shader.expired())); +#endif + program->create_program(pixel_shader.lock(), vertex_shader.lock()); +} diff --git a/core/rhi/opengl/pixel_shader_drawer_opengl.h b/core/rhi/opengl/pixel_shader_drawer_opengl.h new file mode 100644 index 0000000..537c742 --- /dev/null +++ b/core/rhi/opengl/pixel_shader_drawer_opengl.h @@ -0,0 +1,28 @@ +#pragma once +#include "render_target_opengl.h" +#include "rhi/pixel_shader_drawer.h" +#include "shader/shader_program_opengl.h" + +class shader_ps_opengl; +class shader_vs_opengl; + +class pixel_shader_drawer_opengl : public pixel_shader_drawer +{ +public: + pixel_shader_drawer_opengl() = default; + ~pixel_shader_drawer_opengl() override; + void init(int width, int height, std::shared_ptr in_pixel_shader, std::shared_ptr in_vertex_shader) override; + void resize(int width, int height) override; + void draw() override; + void set_vertex_shader(std::shared_ptr in_vertex_shader) override; + + std::shared_ptr rt; + std::shared_ptr program; + std::vector vtx_buffer; + std::vector idx_buffer; + GLuint vbo = 0; + GLuint ibo = 0; + + std::weak_ptr vertex_shader; + std::weak_ptr pixel_shader; +}; diff --git a/core/rhi/opengl/renderer_opengl.cpp b/core/rhi/opengl/renderer_opengl.cpp index 771c0de..948d2d7 100644 --- a/core/rhi/opengl/renderer_opengl.cpp +++ b/core/rhi/opengl/renderer_opengl.cpp @@ -4,6 +4,7 @@ #include "imgui_impl_opengl3.h" #include "imgui_impl_sdl3.h" +#include "pixel_shader_drawer_opengl.h" #include "render_target_opengl.h" #include "texture_opengl.h" #include "application/application.h" @@ -129,6 +130,11 @@ std::shared_ptr renderer_opengl::load_shader(const std::string& entry_na return out; } +std::shared_ptr renderer_opengl::create_pixel_shader_drawer() +{ + return std::make_shared(); +} + void renderer_opengl::new_frame(SDL_Window* window_handle) { ImGui_ImplOpenGL3_NewFrame(); diff --git a/core/rhi/opengl/renderer_opengl.h b/core/rhi/opengl/renderer_opengl.h index f2aeaa1..13aa822 100644 --- a/core/rhi/opengl/renderer_opengl.h +++ b/core/rhi/opengl/renderer_opengl.h @@ -12,6 +12,7 @@ public: void create_slang_session(const std::string& shader_path, slang::ISession** out_session) override; std::shared_ptr load_shader(const std::string& entry_name) override; + std::shared_ptr create_pixel_shader_drawer() override; void new_frame(SDL_Window* window_handle) override; void end_frame(SDL_Window* window_handle) override; diff --git a/core/rhi/opengl/shader/shader_ps_opengl.cpp b/core/rhi/opengl/shader/shader_ps_opengl.cpp index 55da2b7..6b33561 100644 --- a/core/rhi/opengl/shader/shader_ps_opengl.cpp +++ b/core/rhi/opengl/shader/shader_ps_opengl.cpp @@ -1,133 +1 @@ #include "shader_ps_opengl.h" - -#include "shader_program_opengl.h" -#include "shader_vs_opengl.h" -#include "application/application.h" -#include "misc/likely.h" -#include "rhi/renderer.h" - -void ps_opengl_compute_callback(const ImDrawList* parent_list, const ImDrawCmd* cmd) -{ - const auto data = (shader_ps_opengl::ps_data*)cmd->UserCallbackData; - std::shared_ptr& rt = data->rt; - const auto program = data->program; - program->use_program(); - - // do on callback - float x = 0; - float width = rt->get_width(); - float y = 0; - float height = rt->get_height(); - - const float ortho_projection[4][4] = - { - { 2.0f/(width-x), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/(y-height), 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { (width+x)/(x-width), (y+height)/(height-y), 0.0f, 1.0f }, - }; - // glUseProgram(bd->ShaderHandle); - // glUniform1i(bd->AttribLocationTex, 0); - // glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - program->set_uniform("viewMatrix", ortho_projection); - - ImVec2 clip_min(x, y); - ImVec2 clip_max(width, height); - glViewport(0, 0, width, height); - - // Apply scissor/clipping rectangle (Y is inverted in OpenGL) - glScissor(0, 0, width, height); - // glScissor((int)clip_min.x, (int)(0 - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y)); - - ImDrawVert& vert1 = data->vtx_buffer[0]; - ImDrawVert& vert2 = data->vtx_buffer[1]; - ImDrawVert& vert3 = data->vtx_buffer[2]; - ImDrawVert& vert4 = data->vtx_buffer[3]; - vert1.pos = ImVec2(0, 0); - vert2.pos = ImVec2(width, 0); - vert3.pos = ImVec2(width, height); - vert4.pos = ImVec2(0, height); - vert1.uv = ImVec2(0, 0); - vert2.uv = ImVec2(1, 0); - vert3.uv = ImVec2(1, 1); - vert4.uv = ImVec2(0, 1); - vert1.col = 0xFFFFFFFF; - vert2.col = 0xFFFFFFFF; - vert3.col = 0xFFFFFFFF; - vert4.col = 0xFFFFFFFF; - - - const size_t vtx_size = data->vtx_buffer.size() * sizeof(ImDrawVert); - const size_t idx_size = data->idx_buffer.size() * sizeof(ImDrawIdx); - glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_size, data->vtx_buffer.data()); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_size, data->idx_buffer.data()); - - glBindBuffer(GL_ARRAY_BUFFER, data->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data->ibo); - - glBindFramebuffer(GL_FRAMEBUFFER, rt->get_fbo()); - - glDrawElementsBaseVertex(GL_TRIANGLES, 6, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, 0, 0); - // glDrawElements(GL_TRIANGLES, 6, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, 0); - - program->unuse_program(); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -} - -void shader_ps_opengl::draw(int width, int height, std::shared_ptr in_vertex_shader) -{ - const bool is_default_vtx_shader = in_vertex_shader == nullptr; - if (is_default_vtx_shader) - { - in_vertex_shader = application::get()->get_renderer()->get_pixel_shader_render_default_vs(); - } - const std::shared_ptr vs = std::static_pointer_cast(in_vertex_shader); - const std::shared_ptr ps = std::static_pointer_cast(shared_from_this()); - - if (draw_data.fragment_shader_id != get_shader_id() || draw_data.vertex_shader_id != vs->get_shader_id()) - { - if (!draw_data.program) - draw_data.program = std::make_shared(); - - draw_data.program->create_program(ps, vs); - draw_data.fragment_shader_id = get_shader_id(); - draw_data.vertex_shader_id = vs->get_shader_id(); - } - - if (UNLIKELY(!draw_data.rt)) - { - draw_data.rt = std::static_pointer_cast(application::get()->create_render_target(width, height, texture_format::RGBA8)); - } - - draw_data.rt->resize(width, height); - - if (draw_data.vbo == 0) - { - glGenBuffers(1, &draw_data.vbo); - glGenBuffers(1, &draw_data.ibo); - glBindBuffer(GL_ARRAY_BUFFER, draw_data.vbo); - const size_t vtx_size = draw_data.vtx_buffer.size() * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, vtx_size, draw_data.vtx_buffer.data(), GL_STREAM_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, draw_data.ibo); - const size_t idx_size = draw_data.idx_buffer.size() * sizeof(ImDrawIdx); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_size, draw_data.idx_buffer.data(), GL_STREAM_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - - ImGui::GetWindowDrawList()->AddCallback(ps_opengl_compute_callback, &draw_data); - ImGui::GetWindowDrawList()->AddCallback(ImDrawCallback_ResetRenderState, nullptr); - draw_data.rt->draw(); -} - -shader_ps_opengl::ps_data::~ps_data() -{ - if (vbo) - glDeleteBuffers(1, &vbo); - if (ibo) - glDeleteBuffers(1, &ibo); -} diff --git a/core/rhi/opengl/shader/shader_ps_opengl.h b/core/rhi/opengl/shader/shader_ps_opengl.h index 97d51d3..a79d683 100644 --- a/core/rhi/opengl/shader/shader_ps_opengl.h +++ b/core/rhi/opengl/shader/shader_ps_opengl.h @@ -7,27 +7,10 @@ class shader_vs_opengl; class shader_ps_opengl : public shader_opengl { public: - explicit shader_ps_opengl(const std::shared_ptr& handle) : shader_opengl(handle), draw_data({}) + explicit shader_ps_opengl(const std::shared_ptr& handle) : shader_opengl(handle) { - draw_data.idx_buffer = {0, 1, 2, 0, 2, 3}; - draw_data.vtx_buffer.resize(4); + } [[nodiscard]] GLenum get_shader_type() const override { return GL_FRAGMENT_SHADER; } - - void draw(int width, int height, std::shared_ptr in_vertex_shader) override; - - struct ps_data - { - ~ps_data(); - std::shared_ptr rt; - std::shared_ptr program; - std::vector vtx_buffer; - std::vector idx_buffer; - GLuint vbo = 0; - GLuint ibo = 0; - - GLuint vertex_shader_id; - GLuint fragment_shader_id; - } draw_data; }; diff --git a/core/rhi/pixel_shader_drawer.cpp b/core/rhi/pixel_shader_drawer.cpp new file mode 100644 index 0000000..6061dd7 --- /dev/null +++ b/core/rhi/pixel_shader_drawer.cpp @@ -0,0 +1,2 @@ +#include "E:/Projects/Arona/build/AronaCore/core/CMakeFiles/core.dir/Debug/cmake_pch.hxx" +#include "pixel_shader_drawer.h" diff --git a/core/rhi/pixel_shader_drawer.h b/core/rhi/pixel_shader_drawer.h new file mode 100644 index 0000000..ea8a66a --- /dev/null +++ b/core/rhi/pixel_shader_drawer.h @@ -0,0 +1,16 @@ +#pragma once + +class shader; +class render_target; + +class pixel_shader_drawer +{ +public: + virtual ~pixel_shader_drawer() = default; + virtual void init(int width, int height, std::shared_ptr in_pixel_shader, std::shared_ptr in_vertex_shader = nullptr) = 0; + virtual void resize(int width, int height) = 0; + virtual void draw() = 0; + virtual void set_vertex_shader(std::shared_ptr in_vertex_shader) {} +protected: + std::shared_ptr rt_; +}; diff --git a/core/rhi/renderer.h b/core/rhi/renderer.h index ac074ce..8f3681c 100644 --- a/core/rhi/renderer.h +++ b/core/rhi/renderer.h @@ -4,6 +4,7 @@ #include "imgui.h" #include "slang_handle.h" +class pixel_shader_drawer; class shader; class render_target; class texture; @@ -24,6 +25,7 @@ public: virtual Slang::ComPtr get_slang_session() { return session_; } virtual std::shared_ptr load_shader(const std::string& entry_name) = 0; virtual std::shared_ptr get_pixel_shader_render_default_vs(); + virtual std::shared_ptr create_pixel_shader_drawer() = 0; virtual void new_frame(SDL_Window* window_handle) = 0; virtual void end_frame(SDL_Window* window_handle) = 0; diff --git a/core/rhi/shader.h b/core/rhi/shader.h index d829a1e..b6221e3 100644 --- a/core/rhi/shader.h +++ b/core/rhi/shader.h @@ -4,6 +4,12 @@ class render_target; class texture; class slang_handle; +struct shader_draw_data +{ + int width; + int height; +}; + class shader : public std::enable_shared_from_this { public: @@ -18,7 +24,6 @@ public: virtual void bind() = 0; virtual void unbind() = 0; virtual void compute(int x, int y, int z) {} - virtual void draw(int width, int height, std::shared_ptr in_vertex_shader = nullptr) {} // param setters virtual void set_cbuffer(const char* name, void* buffer, int size) = 0; @@ -47,6 +52,9 @@ public: { set_uav_buffer(name, (void*)buffer.data(), buffer.size(), sizeof(T)); } + + void begin_draw(const shader_draw_data& in_data) { if (on_begin_draw) on_begin_draw(in_data, *this); } + std::function on_begin_draw; protected: std::shared_ptr handle_; }; diff --git a/core/rhi/windows/dx11/pixel_shader_drawer_dx11.cpp b/core/rhi/windows/dx11/pixel_shader_drawer_dx11.cpp new file mode 100644 index 0000000..497b8c8 --- /dev/null +++ b/core/rhi/windows/dx11/pixel_shader_drawer_dx11.cpp @@ -0,0 +1,156 @@ +#include "pixel_shader_drawer_dx11.h" + +#include "renderer_dx11.h" +#include "render_target_dx11.h" +#include "application/application.h" +#include "shader/shader_ps_dx11.h" + +void ps_dx11_compute_callback(const ImDrawList* parent_list, const ImDrawCmd* cmd) +{ + pixel_shader_drawer_dx11* data = static_cast(cmd->UserCallbackData); + auto& ps = data->pixel_shader; + const auto& vertex_buffer = data->vertex_buffer; + const auto& render_target = data->render_target; + const auto& index_buffer = data->index_buffer; + const auto vertex_shader = data->vertex_shader.lock(); + const int width = render_target->get_width(); + const int height = render_target->get_height(); + + D3D11_MAPPED_SUBRESOURCE vtx_resource; + ID3D11Buffer* vb = vertex_buffer; + if (g_d3d11_device_context->Map(vb, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + return; + ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; + vtx_dst[0].pos = ImVec2(0, 0); + vtx_dst[0].uv = ImVec2(0, 0); + vtx_dst[0].col = 0xffffffff; + + vtx_dst[1].pos = ImVec2(width, 0); + vtx_dst[1].uv = ImVec2(1, 0); + vtx_dst[1].col = 0xffffffff; + + vtx_dst[2].pos = ImVec2(width, height); + vtx_dst[2].uv = ImVec2(1, 1); + vtx_dst[2].col = 0xffffffff; + + vtx_dst[3].pos = ImVec2(0, height); + vtx_dst[3].uv = ImVec2(0, 1); + vtx_dst[3].col = 0xffffffff; + g_d3d11_device_context->Unmap(vb, 0); + + const auto target_rtv = render_target->get_render_target_view().get_reference(); + g_d3d11_device_context->OMSetRenderTargets(1, &target_rtv, nullptr); + + g_d3d11_device_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + D3D11_VIEWPORT vp = {}; + vp.Width = width; + vp.Height = height; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + g_d3d11_device_context->RSSetViewports(1, &vp); + + vertex_shader->bind(); + + const unsigned int stride = sizeof(ImDrawVert); + const unsigned int offset = 0; + g_d3d11_device_context->IASetVertexBuffers(0, 1, &vb, &stride, &offset); + g_d3d11_device_context->IASetIndexBuffer(index_buffer, DXGI_FORMAT_R16_UINT, 0); + + // setup new scissors + D3D11_RECT new_scissors; + new_scissors.left = 0; + new_scissors.right = width; + new_scissors.top = 0; + new_scissors.bottom = height; + g_d3d11_device_context->RSSetScissorRects(1, &new_scissors); + + ps.lock()->bind(); + g_d3d11_device_context->DrawIndexed(6, 0, 0); + vertex_shader->unbind(); + ps.lock()->unbind(); + + ID3D11RenderTargetView* main_render_target = g_main_render_target_view.get_reference(); + g_d3d11_device_context->OMSetRenderTargets(1, &main_render_target, nullptr); +} + +void pixel_shader_drawer_dx11::init(int width, int height, std::shared_ptr in_pixel_shader, + std::shared_ptr in_vertex_shader) +{ + if (!in_vertex_shader) + { + in_vertex_shader = application::get()->get_renderer()->get_pixel_shader_render_default_vs(); + } + vertex_shader = in_vertex_shader; + pixel_shader = in_pixel_shader; + + render_target = std::static_pointer_cast(application::get()->create_render_target(width, height, texture_format::RGBA8)); + + { + D3D11_BUFFER_DESC desc = {}; + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = sizeof(ImDrawVert) * 4; + desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + g_d3d11_device->CreateBuffer(&desc, nullptr, vertex_buffer.get_init_reference()); + } + { + D3D11_BUFFER_DESC desc = {}; + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = sizeof(ImDrawIdx) * 6; + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + g_d3d11_device->CreateBuffer(&desc, nullptr, index_buffer.get_init_reference()); + + // init index buffer + const ImDrawIdx indices[] = { 0, 1, 2, 0, 2, 3 }; + D3D11_MAPPED_SUBRESOURCE index_resource; + g_d3d11_device_context->Map(index_buffer.get_reference(), 0, D3D11_MAP_WRITE_DISCARD, 0, &index_resource); + memcpy(index_resource.pData, indices, sizeof(indices)); + g_d3d11_device_context->Unmap(index_buffer.get_reference(), 0); + } + + update_view_matrix(width, height); +} + +void pixel_shader_drawer_dx11::set_vertex_shader(std::shared_ptr in_vertex_shader) +{ + vertex_shader = in_vertex_shader; +} + +void pixel_shader_drawer_dx11::draw() +{ +#if _DEBUG + assert(!(vertex_shader.expired() || pixel_shader.expired())); +#endif + ImGui::GetWindowDrawList()->AddCallback(ps_dx11_compute_callback, this); + ImGui::GetWindowDrawList()->AddCallback(ImDrawCallback_ResetRenderState, nullptr); + render_target->draw(); +} + +void pixel_shader_drawer_dx11::resize(int width, int height) +{ + render_target->resize(width, height); + update_view_matrix(width, height); +} + +void pixel_shader_drawer_dx11::update_view_matrix(int width, int height) const +{ +#if _DEBUG + assert(!(vertex_shader.expired())); +#endif + const float L = 0; + const float R = width; + const float T = 0; + const float B = height; + + float mvp[4][4] = + { + { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, + }; + vertex_shader.lock()->set_cbuffer("viewMatrix", mvp, sizeof(mvp)); +} diff --git a/core/rhi/windows/dx11/pixel_shader_drawer_dx11.h b/core/rhi/windows/dx11/pixel_shader_drawer_dx11.h new file mode 100644 index 0000000..47dc4d1 --- /dev/null +++ b/core/rhi/windows/dx11/pixel_shader_drawer_dx11.h @@ -0,0 +1,23 @@ +#pragma once +#include "misc/ref_counting.h" +#include "rhi/pixel_shader_drawer.h" +#include + +class render_target_dx11; + +class pixel_shader_drawer_dx11 : public pixel_shader_drawer +{ +public: + void init(int width, int height, std::shared_ptr in_pixel_shader, std::shared_ptr in_vertex_shader) override; + void set_vertex_shader(std::shared_ptr in_vertex_shader) override; + void draw() override; + void resize(int width, int height) override; + + std::weak_ptr pixel_shader; + std::weak_ptr vertex_shader; + std::shared_ptr render_target; + ref_count_ptr vertex_buffer; + ref_count_ptr index_buffer; +protected: + void update_view_matrix(int width, int height) const; +}; diff --git a/core/rhi/windows/dx11/renderer_dx11.cpp b/core/rhi/windows/dx11/renderer_dx11.cpp index 025db35..63e05f2 100644 --- a/core/rhi/windows/dx11/renderer_dx11.cpp +++ b/core/rhi/windows/dx11/renderer_dx11.cpp @@ -6,6 +6,7 @@ #include "imgui.h" #include "imgui_impl_dx11.h" #include "imgui_impl_sdl3.h" +#include "pixel_shader_drawer_dx11.h" #include "render_target_dx11.h" #include "texture_dx11.h" #include "application/application.h" @@ -123,6 +124,11 @@ std::shared_ptr renderer_dx11::load_shader(const std::string& entry_name return out; } +std::shared_ptr renderer_dx11::create_pixel_shader_drawer() +{ + return std::make_shared(); +} + void renderer_dx11::new_frame(SDL_Window* window_handle) { ImGui_ImplDX11_NewFrame(); diff --git a/core/rhi/windows/dx11/renderer_dx11.h b/core/rhi/windows/dx11/renderer_dx11.h index c9bd2f2..ef78cde 100644 --- a/core/rhi/windows/dx11/renderer_dx11.h +++ b/core/rhi/windows/dx11/renderer_dx11.h @@ -22,6 +22,7 @@ public: void create_slang_session(const std::string& shader_path, slang::ISession** out_session) override; std::shared_ptr load_shader(const std::string& entry_name) override; + std::shared_ptr create_pixel_shader_drawer() override; void new_frame(SDL_Window* window_handle) override; void end_frame(SDL_Window* window_handle) override; diff --git a/core/rhi/windows/dx11/shader/shader_ps_dx11.cpp b/core/rhi/windows/dx11/shader/shader_ps_dx11.cpp index e664704..c3f111e 100644 --- a/core/rhi/windows/dx11/shader/shader_ps_dx11.cpp +++ b/core/rhi/windows/dx11/shader/shader_ps_dx11.cpp @@ -57,138 +57,3 @@ HRESULT shader_ps_dx11::create_shader(ID3DBlob* blob, ID3D11Device* device) { return device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, pixel_shader_.writeRef()); } - -void ps_dx11_compute_callback(const ImDrawList* parent_list, const ImDrawCmd* cmd) -{ - shader_ps_dx11::ps_data* data = (shader_ps_dx11::ps_data*)cmd->UserCallbackData; - auto& ps = data->ps; - auto& vertex_buffer = data->vertex_buffer; - auto& render_target = data->render_target; - auto& index_buffer = data->index_buffer; - auto vertex_shader = data->vertex_shader.lock(); - const int width = render_target->get_width(); - const int height = render_target->get_height(); - - D3D11_MAPPED_SUBRESOURCE vtx_resource; - ID3D11Buffer* vb = vertex_buffer; - if (g_d3d11_device_context->Map(vb, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) - return; - ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; - vtx_dst[0].pos = ImVec2(0, 0); - vtx_dst[0].uv = ImVec2(0, 0); - vtx_dst[0].col = 0xffffffff; - - vtx_dst[1].pos = ImVec2(width, 0); - vtx_dst[1].uv = ImVec2(1, 0); - vtx_dst[1].col = 0xffffffff; - - vtx_dst[2].pos = ImVec2(width, height); - vtx_dst[2].uv = ImVec2(1, 1); - vtx_dst[2].col = 0xffffffff; - - vtx_dst[3].pos = ImVec2(0, height); - vtx_dst[3].uv = ImVec2(0, 1); - vtx_dst[3].col = 0xffffffff; - g_d3d11_device_context->Unmap(vb, 0); - - const auto target_rtv = render_target->get_render_target_view().get_reference(); - g_d3d11_device_context->OMSetRenderTargets(1, &target_rtv, nullptr); - - g_d3d11_device_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - - D3D11_VIEWPORT vp = {}; - vp.Width = width; - vp.Height = height; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = vp.TopLeftY = 0; - g_d3d11_device_context->RSSetViewports(1, &vp); - - vertex_shader->bind(); - - const unsigned int stride = sizeof(ImDrawVert); - const unsigned int offset = 0; - g_d3d11_device_context->IASetVertexBuffers(0, 1, &vb, &stride, &offset); - g_d3d11_device_context->IASetIndexBuffer(index_buffer, DXGI_FORMAT_R16_UINT, 0); - - // setup new scissors - D3D11_RECT new_scissors; - new_scissors.left = 0; - new_scissors.right = width; - new_scissors.top = 0; - new_scissors.bottom = height; - g_d3d11_device_context->RSSetScissorRects(1, &new_scissors); - - ps->bind(); - g_d3d11_device_context->DrawIndexed(6, 0, 0); - vertex_shader->unbind(); - ps->unbind(); - - ID3D11RenderTargetView* main_render_target = g_main_render_target_view.get_reference(); - g_d3d11_device_context->OMSetRenderTargets(1, &main_render_target, nullptr); -} - -void shader_ps_dx11::draw(int width, int height, std::shared_ptr in_vertex_shader) -{ - if (!draw_data.initialized) - { - draw_data.ps = this; - { - draw_data.render_target = std::static_pointer_cast(application::get()->create_render_target(width, height, texture_format::RGBA8)); - } - { - D3D11_BUFFER_DESC desc = {}; - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.ByteWidth = sizeof(ImDrawVert) * 4; - desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - g_d3d11_device->CreateBuffer(&desc, nullptr, draw_data.vertex_buffer.get_init_reference()); - } - { - D3D11_BUFFER_DESC desc = {}; - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.ByteWidth = sizeof(ImDrawIdx) * 6; - desc.BindFlags = D3D11_BIND_INDEX_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - g_d3d11_device->CreateBuffer(&desc, nullptr, draw_data.index_buffer.get_init_reference()); - - // init index buffer - const ImDrawIdx indices[] = { 0, 1, 2, 0, 2, 3 }; - D3D11_MAPPED_SUBRESOURCE index_resource; - g_d3d11_device_context->Map(draw_data.index_buffer.get_reference(), 0, D3D11_MAP_WRITE_DISCARD, 0, &index_resource); - memcpy(index_resource.pData, indices, sizeof(indices)); - g_d3d11_device_context->Unmap(draw_data.index_buffer.get_reference(), 0); - } - draw_data.initialized = true; - } - if (!in_vertex_shader) - { - in_vertex_shader = application::get()->get_renderer()->get_pixel_shader_render_default_vs(); - const float L = 0; - const float R = width; - const float T = 0; - const float B = height; - // float mvp[4][4] = - // { - // { 2.0f/(R-L), 0.0f, 0.0f, (R+L)/(L-R) }, - // { 0.0f, 2.0f/(T-B), 0.0f, (T+B)/(B-T) }, - // { 0.0f, 0.0f, 0.5f, 0.5f }, - // { 0.0f, 0.0f, 0.0f, 1.0f }, - // }; - - float mvp[4][4] = - { - { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, - }; - in_vertex_shader->set_cbuffer("viewMatrix", mvp, sizeof(mvp)); - } - draw_data.vertex_shader = in_vertex_shader; - - draw_data.render_target->resize(width, height); - ImGui::GetWindowDrawList()->AddCallback(ps_dx11_compute_callback, &draw_data); - ImGui::GetWindowDrawList()->AddCallback(ImDrawCallback_ResetRenderState, nullptr); - draw_data.render_target->draw(); -} diff --git a/core/rhi/windows/dx11/shader/shader_ps_dx11.h b/core/rhi/windows/dx11/shader/shader_ps_dx11.h index c1262e7..b4cad70 100644 --- a/core/rhi/windows/dx11/shader/shader_ps_dx11.h +++ b/core/rhi/windows/dx11/shader/shader_ps_dx11.h @@ -1,7 +1,6 @@ #pragma once #include "shader_dx11.h" #include "slang-com-ptr.h" -#include "misc/ref_counting.h" class shader_ps_dx11 : public shader_dx11 { @@ -19,19 +18,6 @@ public: [[nodiscard]] ID3D11DeviceChild* get_shader() override { return pixel_shader_; } [[nodiscard]] const char* get_shader_model() const override { return "ps_5_0"; } [[nodiscard]] bool is_initialized() const override { return pixel_shader_ != nullptr; } - - void draw(int width, int height, std::shared_ptr in_vertex_shader = nullptr) override; - - struct ps_data - { - shader_ps_dx11* ps; - std::shared_ptr render_target; - ref_count_ptr vertex_buffer; - ref_count_ptr index_buffer; - std::weak_ptr vertex_shader; - - bool initialized = false; - } draw_data; private: Slang::ComPtr pixel_shader_;