diff --git a/src/f_wipe.cpp b/src/f_wipe.cpp index f553aafa6..6f75cb45f 100644 --- a/src/f_wipe.cpp +++ b/src/f_wipe.cpp @@ -319,7 +319,7 @@ static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) { #endif -static void refresh_wipe_screen_texture(rhi::Rhi& rhi, rhi::Handle ctx, rhi::Handle& tex) +static void refresh_wipe_screen_texture(rhi::Rhi& rhi, rhi::Handle& tex) { bool recreate = false; if (!tex) @@ -371,24 +371,17 @@ void F_WipeStartScreen(void) return; } - rhi::Handle ctx = srb2::sys::main_graphics_context(); - - if (!ctx) - { - return; - } - hwr2::HardwareState* hw_state = srb2::sys::main_hardware_state(); - refresh_wipe_screen_texture(*rhi, ctx, hw_state->wipe_frames.start); + refresh_wipe_screen_texture(*rhi, hw_state->wipe_frames.start); - hw_state->twodee_renderer->flush(*rhi, ctx, g_2d); + hw_state->twodee_renderer->flush(*rhi, g_2d); rhi::Rect dst_region = {0, 0, static_cast(vid.width), static_cast(vid.height)}; rhi::TextureDetails backbuf_deets = rhi->get_texture_details(hw_state->backbuffer->color()); dst_region.w = std::min(dst_region.w, backbuf_deets.width); dst_region.h = std::min(dst_region.h, backbuf_deets.height); - rhi->copy_framebuffer_to_texture(ctx, hw_state->wipe_frames.start, dst_region, dst_region); + rhi->copy_framebuffer_to_texture(hw_state->wipe_frames.start, dst_region, dst_region); I_FinishUpdate(); #endif @@ -414,29 +407,22 @@ void F_WipeEndScreen(void) return; } - rhi::Handle ctx = srb2::sys::main_graphics_context(); - - if (!ctx) - { - return; - } - hwr2::HardwareState* hw_state = srb2::sys::main_hardware_state(); - refresh_wipe_screen_texture(*rhi, ctx, hw_state->wipe_frames.end); + refresh_wipe_screen_texture(*rhi, hw_state->wipe_frames.end); - hw_state->twodee_renderer->flush(*rhi, ctx, g_2d); + hw_state->twodee_renderer->flush(*rhi, g_2d); rhi::Rect dst_region = {0, 0, static_cast(vid.width), static_cast(vid.height)}; rhi::TextureDetails backbuf_deets = rhi->get_texture_details(hw_state->backbuffer->color()); dst_region.w = std::min(dst_region.w, backbuf_deets.width); dst_region.h = std::min(dst_region.h, backbuf_deets.height); - rhi->copy_framebuffer_to_texture(ctx, hw_state->wipe_frames.end, dst_region, dst_region); + rhi->copy_framebuffer_to_texture(hw_state->wipe_frames.end, dst_region, dst_region); hw_state->blit_rect->set_output(0, 0, dst_region.w, dst_region.h, false, true); rhi::TextureDetails start_deets = rhi->get_texture_details(hw_state->wipe_frames.start); hw_state->blit_rect->set_texture(hw_state->wipe_frames.start, start_deets.width, start_deets.height); - hw_state->blit_rect->draw(*rhi, ctx); + hw_state->blit_rect->draw(*rhi); I_FinishUpdate(); #endif @@ -535,7 +521,6 @@ void F_RunWipe(UINT8 wipemode, UINT8 wipetype, boolean drawMenu, const char *col g_wipeencorewiggle = 0; } rhi::Rhi* rhi = srb2::sys::get_rhi(srb2::sys::g_current_rhi); - rhi::Handle ctx = srb2::sys::main_graphics_context(); hwr2::HardwareState* hw_state = srb2::sys::main_hardware_state(); if (reverse) @@ -550,7 +535,7 @@ void F_RunWipe(UINT8 wipemode, UINT8 wipetype, boolean drawMenu, const char *col } hw_state->wipe->set_target_size(static_cast(vid.width), static_cast(vid.height)); - hw_state->wipe->draw(*rhi, ctx); + hw_state->wipe->draw(*rhi); } I_OsPolling(); diff --git a/src/hwr2/CMakeLists.txt b/src/hwr2/CMakeLists.txt index fa068990f..879f4e669 100644 --- a/src/hwr2/CMakeLists.txt +++ b/src/hwr2/CMakeLists.txt @@ -5,14 +5,10 @@ target_sources(SRB2SDL2 PRIVATE blit_rect.cpp blit_rect.hpp hardware_state.hpp - pass_imgui.cpp - pass_imgui.hpp - pass_manager.cpp - pass_manager.hpp + imgui_renderer.cpp + imgui_renderer.hpp pass_resource_managers.cpp pass_resource_managers.hpp - pass.cpp - pass.hpp patch_atlas.cpp patch_atlas.hpp postprocess_wipe.cpp diff --git a/src/hwr2/blit_postimg_screens.cpp b/src/hwr2/blit_postimg_screens.cpp index 13a9e8213..64f508f5c 100644 --- a/src/hwr2/blit_postimg_screens.cpp +++ b/src/hwr2/blit_postimg_screens.cpp @@ -10,11 +10,14 @@ #include "blit_postimg_screens.hpp" +#include + #include #include #include #include #include +#include #include "../p_tick.h" #include "../i_time.h" @@ -36,34 +39,6 @@ struct BlitVertex }; } // namespace -static const PipelineDesc kPostimgPipelineDesc = -{ - PipelineProgram::kPostimg, - {{{sizeof(BlitVertex)}}, {{VertexAttributeName::kPosition, 0, 0}, {VertexAttributeName::kTexCoord0, 0, 12}}}, - {{{{UniformName::kTime, UniformName::kProjection, UniformName::kModelView, UniformName::kTexCoord0Transform, UniformName::kTexCoord0Min, UniformName::kTexCoord0Max, UniformName::kPostimgWater, UniformName::kPostimgHeat}}}}, - {{SamplerName::kSampler0}}, - std::nullopt, - {std::nullopt, {true, true, true, true}}, - PrimitiveType::kTriangles, - CullMode::kNone, - FaceWinding::kCounterClockwise, - {0.0, 0.0, 0.0, 1.0} -}; - -static const PipelineDesc kPostimgIndexedPipelineDesc = -{ - PipelineProgram::kPostimg, - {{{sizeof(BlitVertex)}}, {{VertexAttributeName::kPosition, 0, 0}, {VertexAttributeName::kTexCoord0, 0, 12}}}, - {{{{UniformName::kTime, UniformName::kProjection, UniformName::kModelView, UniformName::kTexCoord0Transform, UniformName::kTexCoord0Min, UniformName::kTexCoord0Max, UniformName::kPostimgWater, UniformName::kPostimgHeat}}}}, - {{SamplerName::kSampler0, SamplerName::kSampler1}}, - std::nullopt, - {std::nullopt, {true, true, true, true}}, - PrimitiveType::kTriangles, - CullMode::kNone, - FaceWinding::kCounterClockwise, - {0.0, 0.0, 0.0, 1.0} -}; - static const BlitVertex kVerts[] = {{-.5f, -.5f, 0.f, 0.f, 0.f}, {.5f, -.5f, 0.f, 1.f, 0.f}, {-.5f, .5f, 0.f, 0.f, 1.f}, {.5f, .5f, 0.f, 1.f, 1.f}}; @@ -99,105 +74,15 @@ BlitPostimgScreens::BlitPostimgScreens(PaletteManager* palette_mgr) { } -void BlitPostimgScreens::draw(Rhi& rhi, Handle ctx) +void BlitPostimgScreens::draw(Rhi& rhi) { prepass(rhi); - transfer(rhi, ctx); - - for (uint32_t i = 0; i < screens_; i++) - { - BlitPostimgScreens::ScreenData& data = screen_data_[i]; - - rhi.bind_pipeline(ctx, data.pipeline); - rhi.set_viewport(ctx, get_screen_viewport(i, screens_, target_width_, target_height_)); - rhi.bind_uniform_set(ctx, 0, data.uniform_set); - rhi.bind_binding_set(ctx, data.binding_set); - rhi.bind_index_buffer(ctx, quad_ibo_); - rhi.draw_indexed(ctx, 6, 0); - } -} - -void BlitPostimgScreens::prepass(Rhi& rhi) -{ - if (!renderpass_) - { - renderpass_ = rhi.create_render_pass( - { - false, - AttachmentLoadOp::kClear, - AttachmentStoreOp::kStore, - AttachmentLoadOp::kDontCare, - AttachmentStoreOp::kDontCare, - AttachmentLoadOp::kDontCare, - AttachmentStoreOp::kDontCare - } - ); - } - - if (!pipeline_) - { - pipeline_ = rhi.create_pipeline(kPostimgPipelineDesc); - } - - if (!indexed_pipeline_) - { - indexed_pipeline_ = rhi.create_pipeline(kPostimgIndexedPipelineDesc); - } - - if (!quad_vbo_) - { - quad_vbo_ = rhi.create_buffer({sizeof(kVerts), BufferType::kVertexBuffer, BufferUsage::kImmutable}); - upload_quad_buffer_ = true; - } - - if (!quad_ibo_) - { - quad_ibo_ = rhi.create_buffer({sizeof(kIndices), BufferType::kIndexBuffer, BufferUsage::kImmutable}); - upload_quad_buffer_ = true; - } - - screen_data_.clear(); -} - -void BlitPostimgScreens::transfer(Rhi& rhi, Handle ctx) -{ - // Upload needed buffers - if (upload_quad_buffer_) - { - rhi.update_buffer(ctx, quad_vbo_, 0, tcb::as_bytes(tcb::span(kVerts))); - rhi.update_buffer(ctx, quad_ibo_, 0, tcb::as_bytes(tcb::span(kIndices))); - upload_quad_buffer_ = false; - } + transfer(rhi); for (uint32_t i = 0; i < screens_; i++) { BlitPostimgScreens::ScreenConfig& screen_config = screen_configs_[i]; - BlitPostimgScreens::ScreenData data {}; - - if (screen_config.indexed) - { - data.pipeline = indexed_pipeline_; - } - else - { - data.pipeline = pipeline_; - } - - VertexAttributeBufferBinding vertex_bindings[] = {{0, quad_vbo_}}; - TextureBinding sampler_bindings[] = - { - {SamplerName::kSampler0, screen_config.source}, - {SamplerName::kSampler1, palette_mgr_->palette()} - }; - - data.binding_set = rhi.create_binding_set( - ctx, - data.pipeline, - { - vertex_bindings, - tcb::span(sampler_bindings, screen_config.indexed ? 2 : 1) - } - ); + BlitPostimgScreens::ScreenData& data = screen_data_[i]; glm::mat4 projection = glm::scale(glm::identity(), glm::vec3(2.f, -2.f, 1.f)); glm::mat4 modelview = glm::identity(); @@ -222,19 +107,95 @@ void BlitPostimgScreens::transfer(Rhi& rhi, Handle ctx) glm::vec2 texcoord_min = screen_config.uv_offset; glm::vec2 texcoord_max = screen_config.uv_offset + screen_config.uv_size; - UniformVariant uniforms[] = - { - static_cast(leveltime), - projection, - modelview, - texcoord_transform, - texcoord_min, - texcoord_max, - screen_config.post.water, - screen_config.post.heat - }; + RasterizerStateDesc r_state {}; + r_state.cull = CullMode::kNone; - data.uniform_set = rhi.create_uniform_set(ctx, {uniforms}); + rhi.bind_program(data.program); + rhi.set_rasterizer_state(r_state); + rhi.set_viewport(get_screen_viewport(i, screens_, target_width_, target_height_)); + rhi.bind_vertex_attrib("a_position", quad_vbo_, rhi::VertexAttributeFormat::kFloat3, offsetof(BlitVertex, x), sizeof(BlitVertex)); + rhi.bind_vertex_attrib("a_texcoord0", quad_vbo_, rhi::VertexAttributeFormat::kFloat2, offsetof(BlitVertex, u), sizeof(BlitVertex)); + rhi.bind_index_buffer(quad_ibo_); + rhi.set_uniform("u_time", static_cast(leveltime)); + rhi.set_uniform("u_projection", projection); + rhi.set_uniform("u_modelview", modelview); + rhi.set_uniform("u_texcoord0_transform", texcoord_transform); + rhi.set_uniform("u_texcoord0_min", texcoord_min); + rhi.set_uniform("u_texcoord0_max", texcoord_max); + rhi.set_uniform("u_postimg_water", screen_config.post.water); + rhi.set_uniform("u_postimg_heat", screen_config.post.heat); + rhi.set_sampler("s_sampler0", 0, screen_config.source); + if (screen_config.indexed) + { + rhi.set_sampler("s_sampler1", 1, palette_mgr_->palette()); + } + rhi.draw_indexed(6, 0); + } +} + +void BlitPostimgScreens::prepass(Rhi& rhi) +{ + if (!program_) + { + static const char* defines[1] = { + "ENABLE_S_SAMPLER0" + }; + ProgramDesc desc {}; + desc.name = "postimg"; + desc.defines = tcb::make_span(defines); + program_ = rhi.create_program(desc); + } + + if (!indexed_program_) + { + static const char* defines[2] = { + "ENABLE_S_SAMPLER0", + "ENABLE_S_SAMPLER1" + }; + ProgramDesc desc {}; + desc.name = "postimg"; + desc.defines = tcb::make_span(defines); + program_ = rhi.create_program(desc); + } + + if (!quad_vbo_) + { + quad_vbo_ = rhi.create_buffer({sizeof(kVerts), BufferType::kVertexBuffer, BufferUsage::kImmutable}); + upload_quad_buffer_ = true; + } + + if (!quad_ibo_) + { + quad_ibo_ = rhi.create_buffer({sizeof(kIndices), BufferType::kIndexBuffer, BufferUsage::kImmutable}); + upload_quad_buffer_ = true; + } + + screen_data_.clear(); +} + +void BlitPostimgScreens::transfer(Rhi& rhi) +{ + // Upload needed buffers + if (upload_quad_buffer_) + { + rhi.update_buffer(quad_vbo_, 0, tcb::as_bytes(tcb::span(kVerts))); + rhi.update_buffer(quad_ibo_, 0, tcb::as_bytes(tcb::span(kIndices))); + upload_quad_buffer_ = false; + } + + for (uint32_t i = 0; i < screens_; i++) + { + BlitPostimgScreens::ScreenConfig& screen_config = screen_configs_[i]; + BlitPostimgScreens::ScreenData data {}; + + if (screen_config.indexed) + { + data.program = program_; + } + else + { + data.program = indexed_program_; + } screen_data_[i] = std::move(data); } diff --git a/src/hwr2/blit_postimg_screens.hpp b/src/hwr2/blit_postimg_screens.hpp index c91b65ca9..1a7c60eed 100644 --- a/src/hwr2/blit_postimg_screens.hpp +++ b/src/hwr2/blit_postimg_screens.hpp @@ -46,14 +46,11 @@ public: private: struct ScreenData { - rhi::Handle pipeline; - rhi::Handle binding_set; - rhi::Handle uniform_set; + rhi::Handle program; }; - rhi::Handle pipeline_; - rhi::Handle indexed_pipeline_; - rhi::Handle renderpass_; + rhi::Handle program_; + rhi::Handle indexed_program_; rhi::Handle quad_vbo_; rhi::Handle quad_ibo_; bool upload_quad_buffer_; @@ -67,12 +64,12 @@ private: PaletteManager* palette_mgr_; void prepass(rhi::Rhi& rhi); - void transfer(rhi::Rhi& rhi, rhi::Handle ctx); + void transfer(rhi::Rhi& rhi); public: explicit BlitPostimgScreens(PaletteManager* palette_mgr); - void draw(rhi::Rhi& rhi, rhi::Handle ctx); + void draw(rhi::Rhi& rhi); void set_num_screens(uint32_t screens) noexcept { diff --git a/src/hwr2/blit_rect.cpp b/src/hwr2/blit_rect.cpp index 1e6edec2f..a1d3e8c23 100644 --- a/src/hwr2/blit_rect.cpp +++ b/src/hwr2/blit_rect.cpp @@ -11,6 +11,7 @@ #include "blit_rect.hpp" #include +#include #include #include @@ -38,95 +39,42 @@ static const BlitVertex kVerts[] = static const uint16_t kIndices[] = {0, 1, 2, 1, 3, 2}; -/// @brief Pipeline used for non-paletted source textures. -static const PipelineDesc kUnshadedPipelineDescription = { - PipelineProgram::kUnshaded, - {{{sizeof(BlitVertex)}}, {{VertexAttributeName::kPosition, 0, 0}, {VertexAttributeName::kTexCoord0, 0, 12}}}, - {{{UniformName::kProjection}, {{UniformName::kModelView, UniformName::kTexCoord0Transform}}}}, - {{// RGB/A texture - SamplerName::kSampler0}}, - std::nullopt, - {std::nullopt, {true, true, true, true}}, - PrimitiveType::kTriangles, - CullMode::kNone, - FaceWinding::kCounterClockwise, - {0.f, 0.f, 0.f, 1.f}}; - -/// @brief Pipeline used for sharp bilinear special blit. -static const PipelineDesc kSharpBilinearPipelineDescription = { - PipelineProgram::kSharpBilinear, - {{{sizeof(BlitVertex)}}, {{VertexAttributeName::kPosition, 0, 0}, {VertexAttributeName::kTexCoord0, 0, 12}}}, - {{{UniformName::kProjection}, {{UniformName::kModelView, UniformName::kTexCoord0Transform, UniformName::kSampler0Size}}}}, - {{// RGB/A texture - SamplerName::kSampler0}}, - std::nullopt, - {std::nullopt, {true, true, true, true}}, - PrimitiveType::kTriangles, - CullMode::kNone, - FaceWinding::kCounterClockwise, - {0.f, 0.f, 0.f, 1.f}}; - -/// @brief Pipeline used for CRT special blit -static const PipelineDesc kCrtPipelineDescription = { - PipelineProgram::kCrt, - {{{sizeof(BlitVertex)}}, {{VertexAttributeName::kPosition, 0, 0}, {VertexAttributeName::kTexCoord0, 0, 12}}}, - {{{UniformName::kProjection}, {{UniformName::kModelView, UniformName::kTexCoord0Transform, UniformName::kSampler0Size}}}}, - {{// RGB/A texture - SamplerName::kSampler0, SamplerName::kSampler1}}, - std::nullopt, - {std::nullopt, {true, true, true, true}}, - PrimitiveType::kTriangles, - CullMode::kNone, - FaceWinding::kCounterClockwise, - {0.f, 0.f, 0.f, 1.f}}; - -/// @brief Pipeline used for CRT special blit (sharp) -static const PipelineDesc kCrtSharpPipelineDescription = { - PipelineProgram::kCrtSharp, - {{{sizeof(BlitVertex)}}, {{VertexAttributeName::kPosition, 0, 0}, {VertexAttributeName::kTexCoord0, 0, 12}}}, - {{{UniformName::kProjection}, {{UniformName::kModelView, UniformName::kTexCoord0Transform, UniformName::kSampler0Size}}}}, - {{// RGB/A texture - SamplerName::kSampler0, SamplerName::kSampler1}}, - std::nullopt, - {std::nullopt, {true, true, true, true}}, - PrimitiveType::kTriangles, - CullMode::kNone, - FaceWinding::kCounterClockwise, - {0.f, 0.f, 0.f, 1.f}}; - BlitRectPass::BlitRectPass() : BlitRectPass(BlitRectPass::BlitMode::kNearest) {} BlitRectPass::BlitRectPass(BlitRectPass::BlitMode blit_mode) : blit_mode_(blit_mode) {} BlitRectPass::~BlitRectPass() = default; -void BlitRectPass::draw(Rhi& rhi, Handle ctx) +void BlitRectPass::draw(Rhi& rhi) { prepass(rhi); - transfer(rhi, ctx); - graphics(rhi, ctx); + transfer(rhi); + graphics(rhi); } void BlitRectPass::prepass(Rhi& rhi) { - if (!pipeline_) + if (!program_) { + ProgramDesc desc {}; + const char* defines[1] = {"ENABLE_VA_TEXCOORD0"}; + desc.defines = tcb::make_span(defines); switch (blit_mode_) { - case BlitRectPass::BlitMode::kNearest: - pipeline_ = rhi.create_pipeline(kUnshadedPipelineDescription); - break; - case BlitRectPass::BlitMode::kSharpBilinear: - pipeline_ = rhi.create_pipeline(kSharpBilinearPipelineDescription); - break; - case BlitRectPass::BlitMode::kCrt: - pipeline_ = rhi.create_pipeline(kCrtPipelineDescription); - break; - case BlitRectPass::BlitMode::kCrtSharp: - pipeline_ = rhi.create_pipeline(kCrtSharpPipelineDescription); - break; - default: - std::terminate(); + case BlitRectPass::BlitMode::kNearest: + desc.name = "unshaded"; + break; + case BlitRectPass::BlitMode::kSharpBilinear: + desc.name = "sharpbilinear"; + break; + case BlitRectPass::BlitMode::kCrt: + desc.name = "crt"; + break; + case BlitRectPass::BlitMode::kCrtSharp: + desc.name = "crtsharp"; + break; + default: + std::terminate(); } - + program_ = rhi.create_program(desc); } if (!quad_vbo_) @@ -156,17 +104,17 @@ void BlitRectPass::prepass(Rhi& rhi) } } -void BlitRectPass::transfer(Rhi& rhi, Handle ctx) +void BlitRectPass::transfer(Rhi& rhi) { if (quad_vbo_needs_upload_ && quad_vbo_) { - rhi.update_buffer(ctx, quad_vbo_, 0, tcb::as_bytes(tcb::span(kVerts))); + rhi.update_buffer(quad_vbo_, 0, tcb::as_bytes(tcb::span(kVerts))); quad_vbo_needs_upload_ = false; } if (quad_ibo_needs_upload_ && quad_ibo_) { - rhi.update_buffer(ctx, quad_ibo_, 0, tcb::as_bytes(tcb::span(kIndices))); + rhi.update_buffer(quad_ibo_, 0, tcb::as_bytes(tcb::span(kIndices))); quad_ibo_needs_upload_ = false; } @@ -227,9 +175,21 @@ void BlitRectPass::transfer(Rhi& rhi, Handle ctx) 0, 0, 255, 255, 0, 0, 0, 255, }; - rhi.update_texture(ctx, dot_pattern_, {0, 0, 12, 4}, PixelFormat::kRGBA8, tcb::as_bytes(tcb::span(kDotPattern))); + rhi.update_texture(dot_pattern_, {0, 0, 12, 4}, PixelFormat::kRGBA8, tcb::as_bytes(tcb::span(kDotPattern))); dot_pattern_needs_upload_ = false; } +} + +void BlitRectPass::graphics(Rhi& rhi) +{ + rhi.bind_program(program_); + + RasterizerStateDesc rs {}; + rs.cull = CullMode::kNone; + + rhi.set_rasterizer_state(rs); + rhi.bind_vertex_attrib("a_position", quad_vbo_, VertexAttributeFormat::kFloat3, offsetof(BlitVertex, x), sizeof(BlitVertex)); + rhi.bind_vertex_attrib("a_texcoord0", quad_vbo_, VertexAttributeFormat::kFloat2, offsetof(BlitVertex, u), sizeof(BlitVertex)); float aspect = 1.0; float output_aspect = 1.0; @@ -242,122 +202,46 @@ void BlitRectPass::transfer(Rhi& rhi, Handle ctx) rhi::TextureDetails texture_details = rhi.get_texture_details(texture_); - std::array g1_uniforms = {{ - // Projection - glm::scale( - glm::identity(), - glm::vec3(taller ? 1.f : 1.f / output_aspect, taller ? -1.f / (1.f / output_aspect) : -1.f, 1.f) - ) - }}; + glm::mat4 projection = glm::scale( + glm::identity(), + glm::vec3(taller ? 1.f : 1.f / output_aspect, taller ? -1.f / (1.f / output_aspect) : -1.f, 1.f) + ); + glm::mat4 modelview = glm::scale( + glm::identity(), + glm::vec3(taller ? 2.f : 2.f * aspect, taller ? 2.f * (1.f / aspect) : 2.f, 1.f) + );; + glm::mat3 texcoord0_transform = glm::mat3( + glm::vec3(1.f, 0.f, 0.f), + glm::vec3(0.f, output_flip_ ? -1.f : 1.f, 0.f), + glm::vec3(0.f, output_flip_ ? 1.f : 0.f, 1.f) + ); + glm::vec2 sampler0_size = glm::vec2(texture_details.width, texture_details.height); - uniform_sets_[0] = rhi.create_uniform_set(ctx, {g1_uniforms}); + rhi.set_uniform("u_projection", projection); + rhi.set_uniform("u_modelview", modelview); + rhi.set_uniform("u_texcoord0_transform", texcoord0_transform); switch (blit_mode_) { - case BlitRectPass::BlitMode::kCrt: - { - std::array g2_uniforms = { - // ModelView - glm::scale( - glm::identity(), - glm::vec3(taller ? 2.f : 2.f * aspect, taller ? 2.f * (1.f / aspect) : 2.f, 1.f) - ), - // Texcoord0 Transform - glm::mat3( - glm::vec3(1.f, 0.f, 0.f), - glm::vec3(0.f, output_flip_ ? -1.f : 1.f, 0.f), - glm::vec3(0.f, output_flip_ ? 1.f : 0.f, 1.f) - ), - // Sampler 0 Size - glm::vec2(texture_details.width, texture_details.height) - }; - uniform_sets_[1] = rhi.create_uniform_set(ctx, {g2_uniforms}); - - std::array vbs = {{{0, quad_vbo_}}}; - std::array tbs = {{{rhi::SamplerName::kSampler0, texture_}, {rhi::SamplerName::kSampler1, dot_pattern_}}}; - binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs}); + case BlitRectPass::BlitMode::kNearest: break; - } - case BlitRectPass::BlitMode::kCrtSharp: - { - std::array g2_uniforms = { - // ModelView - glm::scale( - glm::identity(), - glm::vec3(taller ? 2.f : 2.f * aspect, taller ? 2.f * (1.f / aspect) : 2.f, 1.f) - ), - // Texcoord0 Transform - glm::mat3( - glm::vec3(1.f, 0.f, 0.f), - glm::vec3(0.f, output_flip_ ? -1.f : 1.f, 0.f), - glm::vec3(0.f, output_flip_ ? 1.f : 0.f, 1.f) - ), - // Sampler 0 Size - glm::vec2(texture_details.width, texture_details.height) - }; - uniform_sets_[1] = rhi.create_uniform_set(ctx, {g2_uniforms}); - - std::array vbs = {{{0, quad_vbo_}}}; - std::array tbs = {{{rhi::SamplerName::kSampler0, texture_}, {rhi::SamplerName::kSampler1, dot_pattern_}}}; - binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs}); - break; - } - case BlitRectPass::BlitMode::kSharpBilinear: - { - std::array g2_uniforms = { - // ModelView - glm::scale( - glm::identity(), - glm::vec3(taller ? 2.f : 2.f * aspect, taller ? 2.f * (1.f / aspect) : 2.f, 1.f) - ), - // Texcoord0 Transform - glm::mat3( - glm::vec3(1.f, 0.f, 0.f), - glm::vec3(0.f, output_flip_ ? -1.f : 1.f, 0.f), - glm::vec3(0.f, output_flip_ ? 1.f : 0.f, 1.f) - ), - // Sampler0 size - glm::vec2(texture_details.width, texture_details.height) - }; - uniform_sets_[1] = rhi.create_uniform_set(ctx, {g2_uniforms}); - - std::array vbs = {{{0, quad_vbo_}}}; - std::array tbs = {{{rhi::SamplerName::kSampler0, texture_}}}; - binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs}); - break; - } default: - { - std::array g2_uniforms = { - // ModelView - glm::scale( - glm::identity(), - glm::vec3(taller ? 2.f : 2.f * aspect, taller ? 2.f * (1.f / aspect) : 2.f, 1.f) - ), - // Texcoord0 Transform - glm::mat3( - glm::vec3(1.f, 0.f, 0.f), - glm::vec3(0.f, output_flip_ ? -1.f : 1.f, 0.f), - glm::vec3(0.f, output_flip_ ? 1.f : 0.f, 1.f) - ) - }; - uniform_sets_[1] = rhi.create_uniform_set(ctx, {g2_uniforms}); - - std::array vbs = {{{0, quad_vbo_}}}; - std::array tbs = {{{rhi::SamplerName::kSampler0, texture_}}}; - binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs}); + rhi.set_uniform("u_sampler0_size", sampler0_size); break; } + rhi.set_sampler("s_sampler0", 0, texture_); + switch (blit_mode_) + { + case BlitRectPass::BlitMode::kCrt: + rhi.set_sampler("s_sampler1", 1, dot_pattern_); + break; + case BlitRectPass::BlitMode::kCrtSharp: + rhi.set_sampler("s_sampler1", 1, dot_pattern_); + break; + default: + break; } -} - -void BlitRectPass::graphics(Rhi& rhi, Handle ctx) -{ - rhi.bind_pipeline(ctx, pipeline_); - rhi.set_viewport(ctx, output_position_); - rhi.bind_uniform_set(ctx, 0, uniform_sets_[0]); - rhi.bind_uniform_set(ctx, 1, uniform_sets_[1]); - rhi.bind_binding_set(ctx, binding_set_); - rhi.bind_index_buffer(ctx, quad_ibo_); - rhi.draw_indexed(ctx, 6, 0); + rhi.set_viewport(output_position_); + rhi.bind_index_buffer(quad_ibo_); + rhi.draw_indexed(6, 0); } diff --git a/src/hwr2/blit_rect.hpp b/src/hwr2/blit_rect.hpp index d93841fe9..a444b8354 100644 --- a/src/hwr2/blit_rect.hpp +++ b/src/hwr2/blit_rect.hpp @@ -32,7 +32,7 @@ public: }; private: - rhi::Handle pipeline_; + rhi::Handle program_; rhi::Handle texture_; uint32_t texture_width_ = 0; uint32_t texture_height_ = 0; @@ -42,8 +42,6 @@ private: bool output_flip_ = false; rhi::Handle quad_vbo_; rhi::Handle quad_ibo_; - std::array, 2> uniform_sets_; - rhi::Handle binding_set_; BlitMode blit_mode_; rhi::Handle dot_pattern_; @@ -52,8 +50,8 @@ private: bool dot_pattern_needs_upload_ = false; void prepass(rhi::Rhi& rhi); - void transfer(rhi::Rhi& rhi, rhi::Handle ctx); - void graphics(rhi::Rhi& rhi, rhi::Handle ctx); + void transfer(rhi::Rhi& rhi); + void graphics(rhi::Rhi& rhi); public: @@ -61,7 +59,7 @@ public: BlitRectPass(); ~BlitRectPass(); - void draw(rhi::Rhi& rhi, rhi::Handle ctx); + void draw(rhi::Rhi& rhi); /// @brief Set the next blit texture. Don't call during graphics phase! /// @param texture the texture to use when blitting diff --git a/src/hwr2/hardware_state.hpp b/src/hwr2/hardware_state.hpp index e78f6daf2..cb2bdbe7c 100644 --- a/src/hwr2/hardware_state.hpp +++ b/src/hwr2/hardware_state.hpp @@ -13,6 +13,7 @@ #include "blit_postimg_screens.hpp" #include "blit_rect.hpp" +#include "imgui_renderer.hpp" #include "postprocess_wipe.hpp" #include "resource_management.hpp" #include "screen_capture.hpp" @@ -44,6 +45,7 @@ struct HardwareState std::unique_ptr crtsharp_blit_rect; std::unique_ptr screen_capture; std::unique_ptr backbuffer; + std::unique_ptr imgui_renderer; WipeFrames wipe_frames; }; diff --git a/src/hwr2/pass_imgui.cpp b/src/hwr2/imgui_renderer.cpp similarity index 57% rename from src/hwr2/pass_imgui.cpp rename to src/hwr2/imgui_renderer.cpp index b11e724cf..cc13cb3bc 100644 --- a/src/hwr2/pass_imgui.cpp +++ b/src/hwr2/imgui_renderer.cpp @@ -8,9 +8,10 @@ // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -#include "pass_imgui.hpp" +#include "imgui_renderer.hpp" #include +#include #include "../v_video.h" @@ -18,39 +19,25 @@ using namespace srb2; using namespace srb2::hwr2; using namespace srb2::rhi; -static const PipelineDesc kPipelineDesc = { - PipelineProgram::kUnshaded, - {{{sizeof(ImDrawVert)}}, - {{VertexAttributeName::kPosition, 0, 0}, - {VertexAttributeName::kTexCoord0, 0, 12}, - {VertexAttributeName::kColor, 0, 24}}}, - {{{UniformName::kProjection}, {{UniformName::kModelView, UniformName::kTexCoord0Transform}}}}, - {{SamplerName::kSampler0}}, - PipelineDepthStencilStateDesc {true, true, CompareFunc::kAlways, false, {}, {}}, - {BlendDesc { - BlendFactor::kSourceAlpha, - BlendFactor::kOneMinusSourceAlpha, - BlendFunction::kAdd, - BlendFactor::kOne, - BlendFactor::kOneMinusSourceAlpha, - BlendFunction::kAdd}, - {true, true, true, true}}, - PrimitiveType::kTriangles, - CullMode::kNone, - FaceWinding::kCounterClockwise, - {0.f, 0.f, 0.f, 1.f}}; - -ImguiPass::ImguiPass() : Pass() +ImguiRenderer::ImguiRenderer() { } -ImguiPass::~ImguiPass() = default; +ImguiRenderer::~ImguiRenderer() = default; -void ImguiPass::prepass(Rhi& rhi) +void ImguiRenderer::render(Rhi& rhi) { - if (!pipeline_) + + if (!program_) { - pipeline_ = rhi.create_pipeline(kPipelineDesc); + const char* defines[2] = { + "ENABLE_VA_TEXCOORD0", + "ENABLE_VA_COLOR" + }; + ProgramDesc desc; + desc.name = "unshaded"; + desc.defines = tcb::make_span(defines); + program_ = rhi.create_program(desc); } ImGuiIO& io = ImGui::GetIO(); @@ -75,6 +62,19 @@ void ImguiPass::prepass(Rhi& rhi) io.Fonts->SetTexID(font_atlas_); } + if (!default_tex_) + { + uint32_t pixel = 0xFFFFFFFF; + default_tex_ = rhi.create_texture({ + TextureFormat::kRGBA, + 1, + 1, + TextureWrapMode::kRepeat, + TextureWrapMode::kRepeat + }); + rhi.update_texture(default_tex_, {0, 0, 1, 1}, rhi::PixelFormat::kRGBA8, tcb::as_bytes(tcb::span(&pixel, 1))); + } + ImGui::Render(); ImDrawData* data = ImGui::GetDrawData(); @@ -113,7 +113,14 @@ void ImguiPass::prepass(Rhi& rhi) DrawCmd draw_cmd; ImTextureID tex_id = cmd.GetTexID(); - draw_cmd.tex = tex_id; + if (tex_id == 0) + { + draw_cmd.tex = default_tex_; + } + else + { + draw_cmd.tex = tex_id; + } draw_cmd.v_offset = cmd.VtxOffset; draw_cmd.i_offset = cmd.IdxOffset; draw_cmd.elems = cmd.ElemCount; @@ -126,18 +133,12 @@ void ImguiPass::prepass(Rhi& rhi) } draw_lists_.push_back(std::move(hwr2_list)); } -} - -void ImguiPass::transfer(Rhi& rhi, Handle ctx) -{ - ImGuiIO& io = ImGui::GetIO(); { unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); rhi.update_texture( - ctx, font_atlas_, {0, 0, static_cast(width), static_cast(height)}, rhi::PixelFormat::kRGBA8, @@ -162,74 +163,70 @@ void ImguiPass::transfer(Rhi& rhi, Handle ctx) } tcb::span vert_span = tcb::span(im_list->VtxBuffer.Data, im_list->VtxBuffer.size()); - rhi.update_buffer(ctx, vbo, 0, tcb::as_bytes(vert_span)); + rhi.update_buffer(vbo, 0, tcb::as_bytes(vert_span)); tcb::span index_span = tcb::span(im_list->IdxBuffer.Data, im_list->IdxBuffer.size()); - rhi.update_buffer(ctx, ibo, 0, tcb::as_bytes(index_span)); - - // Uniform sets - std::array g1_uniforms = { - // Projection - glm::mat4( - glm::vec4(2.f / vid.realwidth, 0.f, 0.f, 0.f), - glm::vec4(0.f, 2.f / vid.realheight, 0.f, 0.f), - glm::vec4(0.f, 0.f, 1.f, 0.f), - glm::vec4(-1.f, 1.f, 0.f, 1.f) - ) - }; - std::array g2_uniforms = { - // ModelView - glm::mat4( - glm::vec4(1.f, 0.f, 0.f, 0.f), - glm::vec4(0.f, -1.f, 0.f, 0.f), - glm::vec4(0.f, 0.f, 1.f, 0.f), - glm::vec4(0.f, 0, 0.f, 1.f) - ), - // Texcoord0 Transform - glm::mat3( - glm::vec3(1.f, 0.f, 0.f), - glm::vec3(0.f, 1.f, 0.f), - glm::vec3(0.f, 0.f, 1.f) - ) - }; - Handle us_1 = rhi.create_uniform_set(ctx, {g1_uniforms}); - Handle us_2 = rhi.create_uniform_set(ctx, {g2_uniforms}); - - draw_list.us_1 = us_1; - draw_list.us_2 = us_2; + rhi.update_buffer(ibo, 0, tcb::as_bytes(index_span)); for (auto& draw_cmd : draw_list.cmds) { - // Binding set - std::array vbos = {{{0, vbo}}}; - std::array tbs = {{{rhi::SamplerName::kSampler0, draw_cmd.tex}}}; - rhi::Handle binding_set = rhi.create_binding_set(ctx, pipeline_, {vbos, tbs}); - draw_cmd.binding_set = binding_set; + draw_cmd.vbo = vbo; + draw_cmd.ibo = ibo; + draw_cmd.tex = draw_cmd.tex; } } -} -void ImguiPass::graphics(Rhi& rhi, Handle ctx) -{ - rhi.begin_default_render_pass(ctx, false); - rhi.bind_pipeline(ctx, pipeline_); + rhi.bind_program(program_); + RasterizerStateDesc rs; + + rs.cull = CullMode::kNone; + rs.winding = FaceWinding::kCounterClockwise; + rs.depth_test = true; + rs.depth_func = CompareFunc::kAlways; + rs.blend_enabled = true; + rs.blend_source_factor_color = BlendFactor::kSourceAlpha; + rs.blend_dest_factor_color = BlendFactor::kOneMinusSourceAlpha; + rs.blend_color_function = BlendFunction::kAdd; + rs.blend_source_factor_alpha = BlendFactor::kOne; + rs.blend_dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; + rs.blend_alpha_function = BlendFunction::kAdd; + for (auto& draw_list : draw_lists_) { - rhi.bind_uniform_set(ctx, 0, draw_list.us_1); - rhi.bind_uniform_set(ctx, 1, draw_list.us_2); + glm::mat4 projection = glm::mat4( + glm::vec4(2.f / vid.realwidth, 0.f, 0.f, 0.f), + glm::vec4(0.f, 2.f / vid.realheight, 0.f, 0.f), + glm::vec4(0.f, 0.f, 1.f, 0.f), + glm::vec4(-1.f, 1.f, 0.f, 1.f) + ); + glm::mat4 modelview = glm::mat4( + glm::vec4(1.f, 0.f, 0.f, 0.f), + glm::vec4(0.f, -1.f, 0.f, 0.f), + glm::vec4(0.f, 0.f, 1.f, 0.f), + glm::vec4(0.f, 0, 0.f, 1.f) + ); + glm::mat3 texcoord0_transform = glm::mat3( + glm::vec3(1.f, 0.f, 0.f), + glm::vec3(0.f, 1.f, 0.f), + glm::vec3(0.f, 0.f, 1.f) + ); + rhi.set_uniform("u_projection", projection); + rhi.set_uniform("u_modelview", modelview); + rhi.set_uniform("u_texcoord0_transform", texcoord0_transform); for (auto& cmd : draw_list.cmds) { - rhi.bind_binding_set(ctx, cmd.binding_set); - rhi.bind_index_buffer(ctx, draw_list.ibo); - rhi.set_scissor(ctx, cmd.clip); - rhi.draw_indexed(ctx, cmd.elems, cmd.i_offset); + rs.scissor_test = true; + rs.scissor = cmd.clip; + rhi.set_rasterizer_state(rs); + rhi.bind_vertex_attrib("a_position", cmd.vbo, VertexAttributeFormat::kFloat3, offsetof(ImDrawVert, pos), sizeof(ImDrawVert)); + rhi.bind_vertex_attrib("a_texcoord0", cmd.vbo, VertexAttributeFormat::kFloat2, offsetof(ImDrawVert, uv), sizeof(ImDrawVert)); + rhi.bind_vertex_attrib("a_color", cmd.vbo, VertexAttributeFormat::kFloat4, offsetof(ImDrawVert, colf), sizeof(ImDrawVert)); + rhi.set_sampler("s_sampler0", 0, cmd.tex); + rhi.bind_index_buffer(draw_list.ibo); + rhi.draw_indexed(cmd.elems, cmd.i_offset); } } - rhi.end_render_pass(ctx); -} -void ImguiPass::postpass(Rhi& rhi) -{ for (auto& list : draw_lists_) { rhi.destroy_buffer(list.vbo); diff --git a/src/hwr2/pass_imgui.hpp b/src/hwr2/imgui_renderer.hpp similarity index 65% rename from src/hwr2/pass_imgui.hpp rename to src/hwr2/imgui_renderer.hpp index d0fa44db5..b861ade4b 100644 --- a/src/hwr2/pass_imgui.hpp +++ b/src/hwr2/imgui_renderer.hpp @@ -14,48 +14,41 @@ #include #include "../rhi/rhi.hpp" -#include "pass.hpp" namespace srb2::hwr2 { -class ImguiPass final : public Pass +class ImguiRenderer final { struct DrawCmd { - rhi::Handle tex; uint32_t v_offset; uint32_t elems; uint32_t i_offset; rhi::Rect clip; - rhi::Handle binding_set; + rhi::Handle vbo; + rhi::Handle ibo; + rhi::Handle tex; }; struct DrawList { void* list; rhi::Handle vbo; rhi::Handle ibo; - rhi::Handle us_1; - rhi::Handle us_2; std::vector cmds; }; - rhi::Handle pipeline_; + rhi::Handle program_; rhi::Handle font_atlas_; + rhi::Handle default_tex_; std::vector draw_lists_; public: - ImguiPass(); - virtual ~ImguiPass(); + ImguiRenderer(); + virtual ~ImguiRenderer(); - virtual void prepass(rhi::Rhi& rhi) override; - - virtual void transfer(rhi::Rhi& rhi, rhi::Handle ctx) override; - - virtual void graphics(rhi::Rhi& rhi, rhi::Handle ctx) override; - - virtual void postpass(rhi::Rhi& rhi) override; + void render(rhi::Rhi& rhi); }; } // namespace srb2::hwr2 diff --git a/src/hwr2/pass.cpp b/src/hwr2/pass.cpp deleted file mode 100644 index 25c88ca52..000000000 --- a/src/hwr2/pass.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// DR. ROBOTNIK'S RING RACERS -//----------------------------------------------------------------------------- -// Copyright (C) 2024 by Ronald "Eidolon" Kinard -// Copyright (C) 2024 by Kart Krew -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- - -#include "pass.hpp" - -using namespace srb2; -using namespace srb2::hwr2; - -Pass::~Pass() = default; diff --git a/src/hwr2/pass.hpp b/src/hwr2/pass.hpp deleted file mode 100644 index 716049de3..000000000 --- a/src/hwr2/pass.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// DR. ROBOTNIK'S RING RACERS -//----------------------------------------------------------------------------- -// Copyright (C) 2024 by Ronald "Eidolon" Kinard -// Copyright (C) 2024 by Kart Krew -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- - -#ifndef __SRB2_HWR2_PASS_HPP__ -#define __SRB2_HWR2_PASS_HPP__ - -#include "../rhi/rhi.hpp" - -namespace srb2::hwr2 -{ - -/// @brief A rendering pass which performs logic during each phase of a frame render. -/// During rendering, all registered Pass's individual stages will be run together. -class Pass -{ -public: - virtual ~Pass(); - - /// @brief Perform rendering logic and create necessary GPU resources. - /// @param rhi - virtual void prepass(rhi::Rhi& rhi) = 0; - - /// @brief Upload contents for needed GPU resources. Passes must implement but this will be removed soon. - /// @param rhi - /// @param ctx - virtual void transfer(rhi::Rhi& rhi, rhi::Handle ctx) = 0; - - /// @brief Issue draw calls. - /// @param rhi - /// @param ctx - virtual void graphics(rhi::Rhi& rhi, rhi::Handle ctx) = 0; - - /// @brief Cleanup GPU resources. Transient resources should be cleaned up here. - /// @param rhi - virtual void postpass(rhi::Rhi& rhi) = 0; -}; - -} // namespace srb2::hwr2 - -#endif // __SRB2_HWR2_PASS_HPP__ diff --git a/src/hwr2/pass_manager.cpp b/src/hwr2/pass_manager.cpp deleted file mode 100644 index d846e3770..000000000 --- a/src/hwr2/pass_manager.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// DR. ROBOTNIK'S RING RACERS -//----------------------------------------------------------------------------- -// Copyright (C) 2024 by Ronald "Eidolon" Kinard -// Copyright (C) 2024 by Kart Krew -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- - -#include "pass_manager.hpp" - -using namespace srb2; -using namespace srb2::hwr2; -using namespace srb2::rhi; - -namespace -{ - -class LambdaPass final : public Pass -{ - PassManager* mgr_; - std::function prepass_func_; - std::function postpass_func_; - -public: - LambdaPass(PassManager* mgr, std::function prepass_func); - LambdaPass( - PassManager* mgr, - std::function prepass_func, - std::function postpass_func - ); - virtual ~LambdaPass(); - - virtual void prepass(rhi::Rhi& rhi) override; - virtual void transfer(rhi::Rhi& rhi, rhi::Handle ctx) override; - virtual void graphics(rhi::Rhi& rhi, rhi::Handle ctx) override; - virtual void postpass(rhi::Rhi& rhi) override; -}; - -} // namespace - -LambdaPass::LambdaPass(PassManager* mgr, std::function prepass_func) - : mgr_(mgr), prepass_func_(prepass_func) -{ -} - -LambdaPass::LambdaPass( - PassManager* mgr, - std::function prepass_func, - std::function postpass_func -) - : mgr_(mgr), prepass_func_(prepass_func), postpass_func_(postpass_func) -{ -} - -LambdaPass::~LambdaPass() = default; - -void LambdaPass::prepass(Rhi& rhi) -{ - if (prepass_func_) - { - (prepass_func_)(*mgr_, rhi); - } -} - -void LambdaPass::transfer(Rhi&, Handle) -{ -} - -void LambdaPass::graphics(Rhi&, Handle) -{ -} - -void LambdaPass::postpass(Rhi& rhi) -{ - if (postpass_func_) - { - (postpass_func_)(*mgr_, rhi); - } -} - -PassManager::PassManager() = default; -PassManager::PassManager(const PassManager&) = default; -PassManager& PassManager::operator=(const PassManager&) = default; - -void PassManager::insert(const std::string& name, std::shared_ptr pass) -{ - SRB2_ASSERT(pass_by_name_.find(name) == pass_by_name_.end()); - - std::size_t index = passes_.size(); - passes_.push_back(PassManagerEntry {name, pass, true}); - pass_by_name_.insert({name, index}); -} - -void PassManager::insert(const std::string& name, std::function prepass_func) -{ - insert(std::forward(name), std::make_shared(LambdaPass {this, prepass_func})); -} - -void PassManager::insert( - const std::string& name, - std::function prepass_func, - std::function postpass_func -) -{ - insert( - std::forward(name), - std::make_shared(LambdaPass {this, prepass_func, postpass_func}) - ); -} - -void PassManager::set_pass_enabled(const std::string& name, bool enabled) -{ - SRB2_ASSERT(pass_by_name_.find(name) != pass_by_name_.end()); - - passes_[pass_by_name_[name]].enabled = enabled; -} - -std::weak_ptr PassManager::for_name(const std::string& name) -{ - auto itr = pass_by_name_.find(name); - if (itr == pass_by_name_.end()) - { - return std::weak_ptr(); - } - return passes_[itr->second].pass; -} - -void PassManager::prepass(Rhi& rhi) -{ - for (auto& pass : passes_) - { - if (pass.enabled) - { - pass.pass->prepass(rhi); - } - } -} - -void PassManager::transfer(Rhi& rhi, Handle ctx) -{ - for (auto& pass : passes_) - { - if (pass.enabled) - { - pass.pass->transfer(rhi, ctx); - } - } -} - -void PassManager::graphics(Rhi& rhi, Handle ctx) -{ - for (auto& pass : passes_) - { - if (pass.enabled) - { - pass.pass->graphics(rhi, ctx); - } - } -} - -void PassManager::postpass(Rhi& rhi) -{ - for (auto& pass : passes_) - { - if (pass.enabled) - { - pass.pass->postpass(rhi); - } - } -} - -void PassManager::render(Rhi& rhi) -{ - if (passes_.empty()) - { - return; - } - - prepass(rhi); - - Handle gc = rhi.begin_graphics(); - transfer(rhi, gc); - graphics(rhi, gc); - rhi.end_graphics(gc); - - postpass(rhi); -} diff --git a/src/hwr2/pass_manager.hpp b/src/hwr2/pass_manager.hpp deleted file mode 100644 index 12c40187b..000000000 --- a/src/hwr2/pass_manager.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// DR. ROBOTNIK'S RING RACERS -//----------------------------------------------------------------------------- -// Copyright (C) 2024 by Ronald "Eidolon" Kinard -// Copyright (C) 2024 by Kart Krew -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- - -#ifndef __SRB2_HWR2_PASS_MANAGER_HPP__ -#define __SRB2_HWR2_PASS_MANAGER_HPP__ - -#include -#include -#include -#include -#include -#include - -#include "../rhi/rhi.hpp" -#include "pass.hpp" - -namespace srb2::hwr2 -{ - -class PassManager final : public Pass -{ - struct PassManagerEntry - { - std::string name; - std::shared_ptr pass; - bool enabled; - }; - - std::unordered_map pass_by_name_; - std::vector passes_; - -public: - PassManager(); - PassManager(const PassManager&); - PassManager(PassManager&&) = delete; - PassManager& operator=(const PassManager&); - PassManager& operator=(PassManager&&) = delete; - - virtual void prepass(rhi::Rhi& rhi) override; - virtual void transfer(rhi::Rhi& rhi, rhi::Handle ctx) override; - virtual void graphics(rhi::Rhi& rhi, rhi::Handle ctx) override; - virtual void postpass(rhi::Rhi& rhi) override; - - void insert(const std::string& name, std::shared_ptr pass); - void insert(const std::string& name, std::function prepass_func); - void insert( - const std::string& name, - std::function prepass_func, - std::function postpass_func - ); - std::weak_ptr for_name(const std::string& name); - void set_pass_enabled(const std::string& name, bool enabled); - - void render(rhi::Rhi& rhi); -}; - -} // namespace srb2::hwr2 - -#endif // __SRB2_HWR2_PASS_MANAGER_HPP__ diff --git a/src/hwr2/pass_resource_managers.cpp b/src/hwr2/pass_resource_managers.cpp index d7ace5d9b..84abc5601 100644 --- a/src/hwr2/pass_resource_managers.cpp +++ b/src/hwr2/pass_resource_managers.cpp @@ -21,7 +21,7 @@ using namespace srb2; using namespace srb2::hwr2; using namespace srb2::rhi; -FramebufferManager::FramebufferManager() : Pass() +FramebufferManager::FramebufferManager() { } @@ -120,11 +120,11 @@ void FramebufferManager::prepass(Rhi& rhi) } } -void FramebufferManager::transfer(Rhi& rhi, Handle ctx) +void FramebufferManager::transfer(Rhi& rhi) { } -void FramebufferManager::graphics(Rhi& rhi, Handle ctx) +void FramebufferManager::graphics(Rhi& rhi) { } @@ -161,28 +161,28 @@ void MainPaletteManager::prepass(Rhi& rhi) } } -void MainPaletteManager::upload_palette(Rhi& rhi, Handle ctx) +void MainPaletteManager::upload_palette(Rhi& rhi) { std::array palette_32; for (std::size_t i = 0; i < kPaletteSize; i++) { palette_32[i] = V_GetColor(i).s; } - rhi.update_texture(ctx, palette_, {0, 0, kPaletteSize, 1}, PixelFormat::kRGBA8, tcb::as_bytes(tcb::span(palette_32))); + rhi.update_texture(palette_, {0, 0, kPaletteSize, 1}, PixelFormat::kRGBA8, tcb::as_bytes(tcb::span(palette_32))); } -void MainPaletteManager::upload_lighttables(Rhi& rhi, Handle ctx) +void MainPaletteManager::upload_lighttables(Rhi& rhi) { if (colormaps != nullptr) { tcb::span colormap_bytes = tcb::as_bytes(tcb::span(colormaps, kPaletteSize * kLighttableRows)); - rhi.update_texture(ctx, lighttable_, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, colormap_bytes); + rhi.update_texture(lighttable_, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, colormap_bytes); } if (encoremap != nullptr) { tcb::span encoremap_bytes = tcb::as_bytes(tcb::span(encoremap, kPaletteSize * kLighttableRows)); - rhi.update_texture(ctx, encore_lighttable_, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, encoremap_bytes); + rhi.update_texture(encore_lighttable_, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, encoremap_bytes); } if (!lighttables_to_upload_.empty()) @@ -192,23 +192,23 @@ void MainPaletteManager::upload_lighttables(Rhi& rhi, Handle ct Handle lighttable_tex = find_extra_lighttable(lighttable); SRB2_ASSERT(lighttable_tex != kNullHandle); tcb::span lighttable_bytes = tcb::as_bytes(tcb::span(lighttable, kPaletteSize * kLighttableRows)); - rhi.update_texture(ctx, lighttable_tex, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, lighttable_bytes); + rhi.update_texture(lighttable_tex, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, lighttable_bytes); } lighttables_to_upload_.clear(); } } -void MainPaletteManager::upload_default_colormap(Rhi& rhi, Handle ctx) +void MainPaletteManager::upload_default_colormap(Rhi& rhi) { std::array data; for (std::size_t i = 0; i < kPaletteSize; i++) { data[i] = i; } - rhi.update_texture(ctx, default_colormap_, {0, 0, kPaletteSize, 1}, PixelFormat::kR8, tcb::as_bytes(tcb::span(data))); + rhi.update_texture(default_colormap_, {0, 0, kPaletteSize, 1}, PixelFormat::kR8, tcb::as_bytes(tcb::span(data))); } -void MainPaletteManager::upload_colormaps(Rhi& rhi, Handle ctx) +void MainPaletteManager::upload_colormaps(Rhi& rhi) { for (auto to_upload : colormaps_to_upload_) { @@ -218,7 +218,7 @@ void MainPaletteManager::upload_colormaps(Rhi& rhi, Handle ctx) rhi::Handle map_texture = colormaps_.at(to_upload); tcb::span map_bytes = tcb::as_bytes(tcb::span(to_upload, kPaletteSize)); - rhi.update_texture(ctx, map_texture, {0, 0, kPaletteSize, 1}, PixelFormat::kR8, map_bytes); + rhi.update_texture(map_texture, {0, 0, kPaletteSize, 1}, PixelFormat::kR8, map_bytes); } colormaps_to_upload_.clear(); } @@ -271,15 +271,15 @@ rhi::Handle MainPaletteManager::find_extra_lighttable(srb2::NotNul return lighttables_.at(lighttable); } -void MainPaletteManager::transfer(Rhi& rhi, Handle ctx) +void MainPaletteManager::transfer(Rhi& rhi) { - upload_palette(rhi, ctx); - upload_lighttables(rhi, ctx); - upload_default_colormap(rhi, ctx); - upload_colormaps(rhi, ctx); + upload_palette(rhi); + upload_lighttables(rhi); + upload_default_colormap(rhi); + upload_colormaps(rhi); } -void MainPaletteManager::graphics(Rhi& rhi, Handle ctx) +void MainPaletteManager::graphics(Rhi& rhi) { } @@ -319,7 +319,7 @@ void CommonResourcesManager::prepass(Rhi& rhi) } } -void CommonResourcesManager::transfer(Rhi& rhi, Handle ctx) +void CommonResourcesManager::transfer(Rhi& rhi) { if (!init_) { @@ -330,13 +330,13 @@ void CommonResourcesManager::transfer(Rhi& rhi, Handle ctx) uint8_t transparent[4] = {0, 0, 0, 0}; tcb::span transparent_bytes = tcb::as_bytes(tcb::span(transparent, 4)); - rhi.update_texture(ctx, black_, {0, 0, 1, 1}, PixelFormat::kRGBA8, black_bytes); - rhi.update_texture(ctx, white_, {0, 0, 1, 1}, PixelFormat::kRGBA8, white_bytes); - rhi.update_texture(ctx, transparent_, {0, 0, 1, 1}, PixelFormat::kRGBA8, transparent_bytes); + rhi.update_texture(black_, {0, 0, 1, 1}, PixelFormat::kRGBA8, black_bytes); + rhi.update_texture(white_, {0, 0, 1, 1}, PixelFormat::kRGBA8, white_bytes); + rhi.update_texture(transparent_, {0, 0, 1, 1}, PixelFormat::kRGBA8, transparent_bytes); } } -void CommonResourcesManager::graphics(Rhi& rhi, Handle ctx) +void CommonResourcesManager::graphics(Rhi& rhi) { } diff --git a/src/hwr2/pass_resource_managers.hpp b/src/hwr2/pass_resource_managers.hpp index 30e93279e..79b33db8d 100644 --- a/src/hwr2/pass_resource_managers.hpp +++ b/src/hwr2/pass_resource_managers.hpp @@ -16,12 +16,12 @@ #include #include -#include "pass.hpp" +#include "../rhi/rhi.hpp" namespace srb2::hwr2 { -class FramebufferManager final : public Pass +class FramebufferManager final { rhi::Handle main_color_; std::array, 2> post_colors_; @@ -36,10 +36,10 @@ public: FramebufferManager(); virtual ~FramebufferManager(); - virtual void prepass(rhi::Rhi& rhi) override; - virtual void transfer(rhi::Rhi& rhi, rhi::Handle ctx) override; - virtual void graphics(rhi::Rhi& rhi, rhi::Handle ctx) override; - virtual void postpass(rhi::Rhi& rhi) override; + void prepass(rhi::Rhi& rhi); + void transfer(rhi::Rhi& rhi); + void graphics(rhi::Rhi& rhi); + void postpass(rhi::Rhi& rhi); /// @brief Swap the current and previous postprocess FB textures. Use between pass prepass phases to alternate. void swap_post() noexcept @@ -70,7 +70,7 @@ public: std::size_t height() const noexcept { return height_; } }; -class MainPaletteManager final : public Pass +class MainPaletteManager final { rhi::Handle palette_; rhi::Handle lighttable_; @@ -82,19 +82,19 @@ class MainPaletteManager final : public Pass std::vector colormaps_to_upload_; std::vector lighttables_to_upload_; - void upload_palette(rhi::Rhi& rhi, rhi::Handle ctx); - void upload_lighttables(rhi::Rhi& rhi, rhi::Handle ctx); - void upload_default_colormap(rhi::Rhi& rhi, rhi::Handle ctx); - void upload_colormaps(rhi::Rhi& rhi, rhi::Handle ctx); + void upload_palette(rhi::Rhi& rhi); + void upload_lighttables(rhi::Rhi& rhi); + void upload_default_colormap(rhi::Rhi& rhi); + void upload_colormaps(rhi::Rhi& rhi); public: MainPaletteManager(); virtual ~MainPaletteManager(); - virtual void prepass(rhi::Rhi& rhi) override; - virtual void transfer(rhi::Rhi& rhi, rhi::Handle ctx) override; - virtual void graphics(rhi::Rhi& rhi, rhi::Handle ctx) override; - virtual void postpass(rhi::Rhi& rhi) override; + void prepass(rhi::Rhi& rhi); + void transfer(rhi::Rhi& rhi); + void graphics(rhi::Rhi& rhi); + void postpass(rhi::Rhi& rhi); rhi::Handle palette() const noexcept { return palette_; } rhi::Handle lighttable() const noexcept { return lighttable_; } @@ -107,7 +107,7 @@ public: rhi::Handle find_extra_lighttable(srb2::NotNull lighttable) const; }; -class CommonResourcesManager final : public Pass +class CommonResourcesManager final { bool init_ = false; rhi::Handle black_; @@ -118,10 +118,10 @@ public: CommonResourcesManager(); virtual ~CommonResourcesManager(); - virtual void prepass(rhi::Rhi& rhi) override; - virtual void transfer(rhi::Rhi& rhi, rhi::Handle ctx) override; - virtual void graphics(rhi::Rhi& rhi, rhi::Handle ctx) override; - virtual void postpass(rhi::Rhi& rhi) override; + void prepass(rhi::Rhi& rhi); + void transfer(rhi::Rhi& rhi); + void graphics(rhi::Rhi& rhi); + void postpass(rhi::Rhi& rhi); rhi::Handle black() const noexcept { return black_; } rhi::Handle white() const noexcept { return white_; } diff --git a/src/hwr2/patch_atlas.cpp b/src/hwr2/patch_atlas.cpp index b3b1d218d..8ee3c165a 100644 --- a/src/hwr2/patch_atlas.cpp +++ b/src/hwr2/patch_atlas.cpp @@ -216,7 +216,7 @@ static PatchAtlas create_atlas(Rhi& rhi, uint32_t size) return new_atlas; } -void PatchAtlasCache::pack(Rhi& rhi, Handle ctx) +void PatchAtlasCache::pack(Rhi& rhi) { // Prepare stbrp rects for patches to be loaded. std::vector rects; @@ -310,7 +310,6 @@ void PatchAtlasCache::pack(Rhi& rhi, Handle ctx) convert_patch_to_trimmed_rg8_pixels(patch_to_upload, patch_data); rhi.update_texture( - ctx, atlas->tex_, {static_cast(entry->x), static_cast(entry->y), entry->w, entry->h}, PixelFormat::kRG8, diff --git a/src/hwr2/patch_atlas.hpp b/src/hwr2/patch_atlas.hpp index f66bf7c36..e57c1daec 100644 --- a/src/hwr2/patch_atlas.hpp +++ b/src/hwr2/patch_atlas.hpp @@ -20,8 +20,8 @@ #include -#include "pass.hpp" #include "../r_defs.h" +#include "../rhi/rhi.hpp" extern "C" { @@ -113,7 +113,7 @@ public: void queue_patch(srb2::NotNull patch); /// @brief Pack queued patches, allowing them to be looked up with find_patch. - void pack(rhi::Rhi& rhi, rhi::Handle ctx); + void pack(rhi::Rhi& rhi); /// @brief Find the atlas a patch belongs to, or nullopt if it is not cached. /// This may not be called if there are still patches that need to be packed. diff --git a/src/hwr2/postprocess_wipe.cpp b/src/hwr2/postprocess_wipe.cpp index 4b5f3ced7..aafd06e3f 100644 --- a/src/hwr2/postprocess_wipe.cpp +++ b/src/hwr2/postprocess_wipe.cpp @@ -41,41 +41,28 @@ static const uint16_t kPostprocessIndices[] = {0, 1, 2, 1, 3, 2}; } // namespace -static const PipelineDesc kWipePipelineDesc = { - PipelineProgram::kPostprocessWipe, - {{{sizeof(PostprocessVertex)}}, - { - {VertexAttributeName::kPosition, 0, 0}, - {VertexAttributeName::kTexCoord0, 0, 12}, - }}, - {{{{UniformName::kProjection, UniformName::kWipeColorizeMode, UniformName::kWipeEncoreSwizzle}}}}, - {{SamplerName::kSampler0, SamplerName::kSampler1, SamplerName::kSampler2}}, - std::nullopt, - {std::nullopt, {true, true, true, true}}, - PrimitiveType::kTriangles, - CullMode::kNone, - FaceWinding::kCounterClockwise, - {0.f, 0.f, 0.f, 1.f}}; - PostprocessWipePass::PostprocessWipePass() { } PostprocessWipePass::~PostprocessWipePass() = default; -void PostprocessWipePass::draw(Rhi& rhi, Handle ctx) +void PostprocessWipePass::draw(Rhi& rhi) { prepass(rhi); - transfer(rhi, ctx); - graphics(rhi, ctx); + transfer(rhi); + graphics(rhi); postpass(rhi); } void PostprocessWipePass::prepass(Rhi& rhi) { - if (!pipeline_) + if (!program_) { - pipeline_ = rhi.create_pipeline(kWipePipelineDesc); + ProgramDesc desc; + desc.name = "postprocesswipe"; + desc.defines = tcb::span(); + program_ = rhi.create_program(desc); } if (!vbo_) @@ -169,7 +156,7 @@ void PostprocessWipePass::prepass(Rhi& rhi) }); } -void PostprocessWipePass::transfer(Rhi& rhi, Handle ctx) +void PostprocessWipePass::transfer(Rhi& rhi) { if (wipe_tex_ == kNullHandle) { @@ -183,47 +170,44 @@ void PostprocessWipePass::transfer(Rhi& rhi, Handle ctx) if (upload_vbo_) { - rhi.update_buffer(ctx, vbo_, 0, tcb::as_bytes(tcb::span(kPostprocessVerts))); + rhi.update_buffer(vbo_, 0, tcb::as_bytes(tcb::span(kPostprocessVerts))); upload_vbo_ = false; } if (upload_ibo_) { - rhi.update_buffer(ctx, ibo_, 0, tcb::as_bytes(tcb::span(kPostprocessIndices))); + rhi.update_buffer(ibo_, 0, tcb::as_bytes(tcb::span(kPostprocessIndices))); upload_ibo_ = false; } tcb::span data = tcb::as_bytes(tcb::span(mask_data_)); - rhi.update_texture(ctx, wipe_tex_, {0, 0, mask_w_, mask_h_}, PixelFormat::kR8, data); - - UniformVariant uniforms[] = { - glm::scale(glm::identity(), glm::vec3(2.f, 2.f, 1.f)), - static_cast(wipe_color_mode_), - static_cast(wipe_swizzle_) - }; - us_ = rhi.create_uniform_set(ctx, {tcb::span(uniforms)}); - - VertexAttributeBufferBinding vbos[] = {{0, vbo_}}; - TextureBinding tx[] = { - {SamplerName::kSampler0, start_}, - {SamplerName::kSampler1, end_}, - {SamplerName::kSampler2, wipe_tex_}}; - bs_ = rhi.create_binding_set(ctx, pipeline_, {vbos, tx}); + rhi.update_texture(wipe_tex_, {0, 0, mask_w_, mask_h_}, PixelFormat::kR8, data); } -void PostprocessWipePass::graphics(Rhi& rhi, Handle ctx) +void PostprocessWipePass::graphics(Rhi& rhi) { if (wipe_tex_ == kNullHandle) { return; } - rhi.bind_pipeline(ctx, pipeline_); - rhi.set_viewport(ctx, {0, 0, width_, height_}); - rhi.bind_uniform_set(ctx, 0, us_); - rhi.bind_binding_set(ctx, bs_); - rhi.bind_index_buffer(ctx, ibo_); - rhi.draw_indexed(ctx, 6, 0); + rhi.bind_program(program_); + + RasterizerStateDesc desc {}; + desc.cull = CullMode::kNone; + + rhi.set_rasterizer_state(desc); + rhi.set_uniform("u_projection", glm::scale(glm::identity(), glm::vec3(2.f, 2.f, 1.f))); + rhi.set_uniform("u_wipe_colorize_mode", static_cast(wipe_color_mode_)); + rhi.set_uniform("u_wipe_encore_swizzle", static_cast(wipe_swizzle_)); + rhi.set_sampler("s_sampler0", 0, start_); + rhi.set_sampler("s_sampler1", 1, end_); + rhi.set_sampler("s_sampler2", 2, wipe_tex_); + rhi.bind_vertex_attrib("a_position", vbo_, VertexAttributeFormat::kFloat3, offsetof(PostprocessVertex, x), sizeof(PostprocessVertex)); + rhi.bind_vertex_attrib("a_texcoord0", vbo_, VertexAttributeFormat::kFloat2, offsetof(PostprocessVertex, u), sizeof(PostprocessVertex)); + rhi.set_viewport({0, 0, width_, height_}); + rhi.bind_index_buffer(ibo_); + rhi.draw_indexed(6, 0); } void PostprocessWipePass::postpass(Rhi& rhi) diff --git a/src/hwr2/postprocess_wipe.hpp b/src/hwr2/postprocess_wipe.hpp index f1d13b4fd..49141d113 100644 --- a/src/hwr2/postprocess_wipe.hpp +++ b/src/hwr2/postprocess_wipe.hpp @@ -21,13 +21,11 @@ namespace srb2::hwr2 class PostprocessWipePass final { // Internal RHI resources - rhi::Handle pipeline_; + rhi::Handle program_; rhi::Handle vbo_; bool upload_vbo_ = false; rhi::Handle ibo_; bool upload_ibo_ = false; - rhi::Handle us_; - rhi::Handle bs_; rhi::Handle wipe_tex_; int wipe_color_mode_ = 0; int wipe_swizzle_ = 0; @@ -44,15 +42,15 @@ class PostprocessWipePass final uint32_t mask_h_ = 0; void prepass(rhi::Rhi& rhi); - void transfer(rhi::Rhi& rhi, rhi::Handle ctx); - void graphics(rhi::Rhi& rhi, rhi::Handle ctx); + void transfer(rhi::Rhi& rhi); + void graphics(rhi::Rhi& rhi); void postpass(rhi::Rhi& rhi); public: PostprocessWipePass(); virtual ~PostprocessWipePass(); - void draw(rhi::Rhi& rhi, rhi::Handle ctx); + void draw(rhi::Rhi& rhi); void set_start(rhi::Handle start) noexcept { start_ = start; } diff --git a/src/hwr2/resource_management.cpp b/src/hwr2/resource_management.cpp index e338c66dd..6e3d15e25 100644 --- a/src/hwr2/resource_management.cpp +++ b/src/hwr2/resource_management.cpp @@ -26,7 +26,7 @@ PaletteManager& PaletteManager::operator=(PaletteManager&&) = default; constexpr std::size_t kPaletteSize = 256; constexpr std::size_t kLighttableRows = LIGHTLEVELS; -void PaletteManager::update(Rhi& rhi, Handle ctx) +void PaletteManager::update(Rhi& rhi) { if (!palette_) { @@ -57,7 +57,7 @@ void PaletteManager::update(Rhi& rhi, Handle ctx) { palette_32[i] = V_GetColor(i).s; } - rhi.update_texture(ctx, palette_, {0, 0, kPaletteSize, 1}, PixelFormat::kRGBA8, tcb::as_bytes(tcb::span(palette_32))); + rhi.update_texture(palette_, {0, 0, kPaletteSize, 1}, PixelFormat::kRGBA8, tcb::as_bytes(tcb::span(palette_32))); } #if 0 @@ -66,7 +66,7 @@ void PaletteManager::update(Rhi& rhi, Handle ctx) if (colormaps != nullptr) { tcb::span colormap_bytes = tcb::as_bytes(tcb::span(colormaps, kPaletteSize * kLighttableRows)); - rhi.update_texture(ctx, lighttable_, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, colormap_bytes); + rhi.update_texture(lighttable_, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, colormap_bytes); } // FIXME: This is broken, encoremap should not be used directly. @@ -74,7 +74,7 @@ void PaletteManager::update(Rhi& rhi, Handle ctx) if (encoremap != nullptr) { tcb::span encoremap_bytes = tcb::as_bytes(tcb::span(encoremap, kPaletteSize * kLighttableRows)); - rhi.update_texture(ctx, encore_lighttable_, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, encoremap_bytes); + rhi.update_texture(encore_lighttable_, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, encoremap_bytes); } } #endif @@ -86,7 +86,7 @@ void PaletteManager::update(Rhi& rhi, Handle ctx) { data[i] = i; } - rhi.update_texture(ctx, default_colormap_, {0, 0, kPaletteSize, 1}, PixelFormat::kR8, tcb::as_bytes(tcb::span(data))); + rhi.update_texture(default_colormap_, {0, 0, kPaletteSize, 1}, PixelFormat::kR8, tcb::as_bytes(tcb::span(data))); } } @@ -107,7 +107,7 @@ void PaletteManager::destroy_per_frame_resources(Rhi& rhi) lighttables_.clear(); } -Handle PaletteManager::find_or_create_colormap(Rhi& rhi, rhi::Handle ctx, srb2::NotNull colormap) +Handle PaletteManager::find_or_create_colormap(Rhi& rhi, srb2::NotNull colormap) { if (colormaps_.find(colormap) != colormaps_.end()) { @@ -117,13 +117,13 @@ Handle PaletteManager::find_or_create_colormap(Rhi& rhi, rhi::Handle texture = rhi.create_texture({TextureFormat::kLuminance, kPaletteSize, 1, TextureWrapMode::kClamp, TextureWrapMode::kClamp}); tcb::span map_bytes = tcb::as_bytes(tcb::span(colormap.get(), kPaletteSize)); - rhi.update_texture(ctx, texture, {0, 0, kPaletteSize, 1}, PixelFormat::kR8, map_bytes); + rhi.update_texture(texture, {0, 0, kPaletteSize, 1}, PixelFormat::kR8, map_bytes); colormaps_.insert_or_assign(colormap, texture); return texture; } -Handle PaletteManager::find_or_create_extra_lighttable(Rhi& rhi, rhi::Handle ctx, srb2::NotNull lighttable) +Handle PaletteManager::find_or_create_extra_lighttable(Rhi& rhi, srb2::NotNull lighttable) { if (lighttables_.find(lighttable) != lighttables_.end()) { @@ -133,7 +133,7 @@ Handle PaletteManager::find_or_create_extra_lighttable(Rhi& rhi, rhi::H Handle texture = rhi.create_texture({TextureFormat::kLuminance, kPaletteSize, kLighttableRows, TextureWrapMode::kClamp, TextureWrapMode::kClamp}); tcb::span lighttable_bytes = tcb::as_bytes(tcb::span(lighttable.get(), kPaletteSize * kLighttableRows)); - rhi.update_texture(ctx, texture, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, lighttable_bytes); + rhi.update_texture(texture, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, lighttable_bytes); lighttables_.insert_or_assign(lighttable, texture); return texture; @@ -161,7 +161,7 @@ static uint32_t get_flat_size(lumpnum_t lump) return lumpsize; } -Handle FlatTextureManager::find_or_create_indexed(Rhi& rhi, Handle ctx, lumpnum_t lump) +Handle FlatTextureManager::find_or_create_indexed(Rhi& rhi, lumpnum_t lump) { SRB2_ASSERT(lump != LUMPERROR); @@ -206,7 +206,7 @@ Handle FlatTextureManager::find_or_create_indexed(Rhi& rhi, Handle data_bytes = tcb::as_bytes(tcb::span(flat_data)); - rhi.update_texture(ctx, new_tex, {0, 0, flat_size, flat_size}, rhi::PixelFormat::kRG8, data_bytes); + rhi.update_texture(new_tex, {0, 0, flat_size, flat_size}, rhi::PixelFormat::kRG8, data_bytes); return new_tex; } diff --git a/src/hwr2/resource_management.hpp b/src/hwr2/resource_management.hpp index 965e276c1..b3a5c1589 100644 --- a/src/hwr2/resource_management.hpp +++ b/src/hwr2/resource_management.hpp @@ -45,11 +45,11 @@ public: #endif rhi::Handle default_colormap() const noexcept { return default_colormap_; } - void update(rhi::Rhi& rhi, rhi::Handle ctx); + void update(rhi::Rhi& rhi); void destroy_per_frame_resources(rhi::Rhi& rhi); - rhi::Handle find_or_create_colormap(rhi::Rhi& rhi, rhi::Handle ctx, srb2::NotNull colormap); - rhi::Handle find_or_create_extra_lighttable(rhi::Rhi& rhi, rhi::Handle ctx, srb2::NotNull lighttable); + rhi::Handle find_or_create_colormap(rhi::Rhi& rhi, srb2::NotNull colormap); + rhi::Handle find_or_create_extra_lighttable(rhi::Rhi& rhi, srb2::NotNull lighttable); }; /* @@ -79,7 +79,7 @@ public: /// in prepass. /// @param flat_lump /// @return - rhi::Handle find_or_create_indexed(rhi::Rhi& rhi, rhi::Handle ctx, lumpnum_t flat_lump); + rhi::Handle find_or_create_indexed(rhi::Rhi& rhi, lumpnum_t flat_lump); }; } // namespace srb2::hwr2 diff --git a/src/hwr2/screen_capture.cpp b/src/hwr2/screen_capture.cpp index 69e950650..a1484b8f6 100644 --- a/src/hwr2/screen_capture.cpp +++ b/src/hwr2/screen_capture.cpp @@ -21,7 +21,7 @@ using namespace srb2::rhi; ScreenshotPass::ScreenshotPass() = default; ScreenshotPass::~ScreenshotPass() = default; -void ScreenshotPass::capture(Rhi& rhi, Handle ctx) +void ScreenshotPass::capture(Rhi& rhi) { bool doing_screenshot = takescreenshot || moviemode != MM_OFF || g_takemapthumbnail != TMT_NO; @@ -39,7 +39,7 @@ void ScreenshotPass::capture(Rhi& rhi, Handle ctx) packed_data_.resize(stride * height_); tcb::span data_bytes = tcb::as_writable_bytes(tcb::span(pixel_data_)); - rhi.read_pixels(ctx, {0, 0, width_, height_}, PixelFormat::kRGB8, data_bytes); + rhi.read_pixels({0, 0, width_, height_}, PixelFormat::kRGB8, data_bytes); for (uint32_t row = 0; row < height_; row++) { diff --git a/src/hwr2/screen_capture.hpp b/src/hwr2/screen_capture.hpp index 2b455adf2..0d00f2bbf 100644 --- a/src/hwr2/screen_capture.hpp +++ b/src/hwr2/screen_capture.hpp @@ -21,7 +21,6 @@ namespace srb2::hwr2 class ScreenshotPass { - rhi::Handle render_pass_; std::vector pixel_data_; std::vector packed_data_; uint32_t width_ = 0; @@ -31,7 +30,7 @@ public: ScreenshotPass(); ~ScreenshotPass(); - void capture(rhi::Rhi& rhi, rhi::Handle ctx); + void capture(rhi::Rhi& rhi); void set_source(uint32_t width, uint32_t height) { diff --git a/src/hwr2/software_screen_renderer.cpp b/src/hwr2/software_screen_renderer.cpp index 021f609bc..0ce2bd470 100644 --- a/src/hwr2/software_screen_renderer.cpp +++ b/src/hwr2/software_screen_renderer.cpp @@ -20,7 +20,7 @@ using namespace srb2::rhi; SoftwareScreenRenderer::SoftwareScreenRenderer() = default; SoftwareScreenRenderer::~SoftwareScreenRenderer() = default; -void SoftwareScreenRenderer::draw(Rhi& rhi, Handle ctx) +void SoftwareScreenRenderer::draw(Rhi& rhi) { // Render the player views... or not yet? Needs to be moved out of D_Display in d_main.c // Assume it's already been done and vid.buffer contains the composited splitscreen view. @@ -71,5 +71,5 @@ void SoftwareScreenRenderer::draw(Rhi& rhi, Handle ctx) screen_span = tcb::as_bytes(tcb::span(vid.buffer, width_ * height_)); } - rhi.update_texture(ctx, screen_texture_, {0, 0, width_, height_}, PixelFormat::kR8, screen_span); + rhi.update_texture(screen_texture_, {0, 0, width_, height_}, PixelFormat::kR8, screen_span); } diff --git a/src/hwr2/software_screen_renderer.hpp b/src/hwr2/software_screen_renderer.hpp index e95027eb2..6b2f85deb 100644 --- a/src/hwr2/software_screen_renderer.hpp +++ b/src/hwr2/software_screen_renderer.hpp @@ -34,7 +34,7 @@ public: SoftwareScreenRenderer(); ~SoftwareScreenRenderer(); - void draw(rhi::Rhi& rhi, rhi::Handle ctx); + void draw(rhi::Rhi& rhi); rhi::Handle screen() const { return screen_texture_; } }; diff --git a/src/hwr2/twodee_renderer.cpp b/src/hwr2/twodee_renderer.cpp index b79e5063e..39bc284f0 100644 --- a/src/hwr2/twodee_renderer.cpp +++ b/src/hwr2/twodee_renderer.cpp @@ -43,78 +43,59 @@ static TwodeePipelineKey pipeline_key_for_cmd(const Draw2dCmd& cmd) return {hwr2::get_blend_mode(cmd), hwr2::is_draw_lines(cmd)}; } -static PipelineDesc make_pipeline_desc(TwodeePipelineKey key) +static void set_blend_state(RasterizerStateDesc& desc, BlendMode blend) { - constexpr const VertexInputDesc kTwodeeVertexInput = { - {{sizeof(TwodeeVertex)}}, - {{VertexAttributeName::kPosition, 0, 0}, - {VertexAttributeName::kTexCoord0, 0, 12}, - {VertexAttributeName::kColor, 0, 20}}}; - BlendDesc blend_desc; - switch (key.blend) + switch (blend) { case BlendMode::kAlphaTransparent: - blend_desc.source_factor_color = BlendFactor::kSourceAlpha; - blend_desc.dest_factor_color = BlendFactor::kOneMinusSourceAlpha; - blend_desc.color_function = BlendFunction::kAdd; - blend_desc.source_factor_alpha = BlendFactor::kOne; - blend_desc.dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; - blend_desc.alpha_function = BlendFunction::kAdd; + desc.blend_source_factor_color = BlendFactor::kSourceAlpha; + desc.blend_dest_factor_color = BlendFactor::kOneMinusSourceAlpha; + desc.blend_color_function = BlendFunction::kAdd; + desc.blend_source_factor_alpha = BlendFactor::kOne; + desc.blend_dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; + desc.blend_alpha_function = BlendFunction::kAdd; break; case BlendMode::kModulate: - blend_desc.source_factor_color = BlendFactor::kDest; - blend_desc.dest_factor_color = BlendFactor::kZero; - blend_desc.color_function = BlendFunction::kAdd; - blend_desc.source_factor_alpha = BlendFactor::kDestAlpha; - blend_desc.dest_factor_alpha = BlendFactor::kZero; - blend_desc.alpha_function = BlendFunction::kAdd; + desc.blend_source_factor_color = BlendFactor::kDest; + desc.blend_dest_factor_color = BlendFactor::kZero; + desc.blend_color_function = BlendFunction::kAdd; + desc.blend_source_factor_alpha = BlendFactor::kDestAlpha; + desc.blend_dest_factor_alpha = BlendFactor::kZero; + desc.blend_alpha_function = BlendFunction::kAdd; break; case BlendMode::kAdditive: - blend_desc.source_factor_color = BlendFactor::kSourceAlpha; - blend_desc.dest_factor_color = BlendFactor::kOne; - blend_desc.color_function = BlendFunction::kAdd; - blend_desc.source_factor_alpha = BlendFactor::kOne; - blend_desc.dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; - blend_desc.alpha_function = BlendFunction::kAdd; + desc.blend_source_factor_color = BlendFactor::kSourceAlpha; + desc.blend_dest_factor_color = BlendFactor::kOne; + desc.blend_color_function = BlendFunction::kAdd; + desc.blend_source_factor_alpha = BlendFactor::kOne; + desc.blend_dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; + desc.blend_alpha_function = BlendFunction::kAdd; break; case BlendMode::kSubtractive: - blend_desc.source_factor_color = BlendFactor::kSourceAlpha; - blend_desc.dest_factor_color = BlendFactor::kOne; - blend_desc.color_function = BlendFunction::kSubtract; - blend_desc.source_factor_alpha = BlendFactor::kOne; - blend_desc.dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; - blend_desc.alpha_function = BlendFunction::kAdd; + desc.blend_source_factor_color = BlendFactor::kSourceAlpha; + desc.blend_dest_factor_color = BlendFactor::kOne; + desc.blend_color_function = BlendFunction::kSubtract; + desc.blend_source_factor_alpha = BlendFactor::kOne; + desc.blend_dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; + desc.blend_alpha_function = BlendFunction::kAdd; break; case BlendMode::kReverseSubtractive: - blend_desc.source_factor_color = BlendFactor::kSourceAlpha; - blend_desc.dest_factor_color = BlendFactor::kOne; - blend_desc.color_function = BlendFunction::kReverseSubtract; - blend_desc.source_factor_alpha = BlendFactor::kOne; - blend_desc.dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; - blend_desc.alpha_function = BlendFunction::kAdd; + desc.blend_source_factor_color = BlendFactor::kSourceAlpha; + desc.blend_dest_factor_color = BlendFactor::kOne; + desc.blend_color_function = BlendFunction::kReverseSubtract; + desc.blend_source_factor_alpha = BlendFactor::kOne; + desc.blend_dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; + desc.blend_alpha_function = BlendFunction::kAdd; break; case BlendMode::kInvertDest: - blend_desc.source_factor_color = BlendFactor::kOne; - blend_desc.dest_factor_color = BlendFactor::kOne; - blend_desc.color_function = BlendFunction::kSubtract; - blend_desc.source_factor_alpha = BlendFactor::kZero; - blend_desc.dest_factor_alpha = BlendFactor::kDestAlpha; - blend_desc.alpha_function = BlendFunction::kAdd; + desc.blend_source_factor_color = BlendFactor::kOne; + desc.blend_dest_factor_color = BlendFactor::kOne; + desc.blend_color_function = BlendFunction::kSubtract; + desc.blend_source_factor_alpha = BlendFactor::kZero; + desc.blend_dest_factor_alpha = BlendFactor::kDestAlpha; + desc.blend_alpha_function = BlendFunction::kAdd; break; } - - return { - PipelineProgram::kUnshadedPaletted, - kTwodeeVertexInput, - {{{UniformName::kProjection}, - {{UniformName::kModelView, UniformName::kTexCoord0Transform, UniformName::kSampler0IsIndexedAlpha}}}}, - {{SamplerName::kSampler0, SamplerName::kSampler1, SamplerName::kSampler2}}, - std::nullopt, - {blend_desc, {true, true, true, true}}, - key.lines ? PrimitiveType::kLines : PrimitiveType::kTriangles, - CullMode::kNone, - FaceWinding::kCounterClockwise, - {0.f, 0.f, 0.f, 1.f}}; } void TwodeeRenderer::rewrite_patch_quad_vertices(Draw2dList& list, const Draw2dPatchQuad& cmd) const @@ -231,34 +212,18 @@ void TwodeeRenderer::rewrite_patch_quad_vertices(Draw2dList& list, const Draw2dP list.vertices[vtx_offs + 3].v = clipped_vmax; } -void TwodeeRenderer::initialize(Rhi& rhi, Handle ctx) +void TwodeeRenderer::initialize(Rhi& rhi) { - { - TwodeePipelineKey alpha_transparent_tris = {BlendMode::kAlphaTransparent, false}; - TwodeePipelineKey modulate_tris = {BlendMode::kModulate, false}; - TwodeePipelineKey additive_tris = {BlendMode::kAdditive, false}; - TwodeePipelineKey subtractive_tris = {BlendMode::kSubtractive, false}; - TwodeePipelineKey revsubtractive_tris = {BlendMode::kReverseSubtractive, false}; - TwodeePipelineKey invertdest_tris = {BlendMode::kInvertDest, false}; - TwodeePipelineKey alpha_transparent_lines = {BlendMode::kAlphaTransparent, true}; - TwodeePipelineKey modulate_lines = {BlendMode::kModulate, true}; - TwodeePipelineKey additive_lines = {BlendMode::kAdditive, true}; - TwodeePipelineKey subtractive_lines = {BlendMode::kSubtractive, true}; - TwodeePipelineKey revsubtractive_lines = {BlendMode::kReverseSubtractive, true}; - TwodeePipelineKey invertdest_lines = {BlendMode::kInvertDest, true}; - pipelines_.insert({alpha_transparent_tris, rhi.create_pipeline(make_pipeline_desc(alpha_transparent_tris))}); - pipelines_.insert({modulate_tris, rhi.create_pipeline(make_pipeline_desc(modulate_tris))}); - pipelines_.insert({additive_tris, rhi.create_pipeline(make_pipeline_desc(additive_tris))}); - pipelines_.insert({subtractive_tris, rhi.create_pipeline(make_pipeline_desc(subtractive_tris))}); - pipelines_.insert({revsubtractive_tris, rhi.create_pipeline(make_pipeline_desc(revsubtractive_tris))}); - pipelines_.insert({invertdest_tris, rhi.create_pipeline(make_pipeline_desc(invertdest_tris))}); - pipelines_.insert({alpha_transparent_lines, rhi.create_pipeline(make_pipeline_desc(alpha_transparent_lines))}); - pipelines_.insert({modulate_lines, rhi.create_pipeline(make_pipeline_desc(modulate_lines))}); - pipelines_.insert({additive_lines, rhi.create_pipeline(make_pipeline_desc(additive_lines))}); - pipelines_.insert({subtractive_lines, rhi.create_pipeline(make_pipeline_desc(subtractive_lines))}); - pipelines_.insert({revsubtractive_lines, rhi.create_pipeline(make_pipeline_desc(revsubtractive_lines))}); - pipelines_.insert({invertdest_lines, rhi.create_pipeline(make_pipeline_desc(revsubtractive_lines))}); - } + ProgramDesc prog_desc; + prog_desc.name = "unshadedpaletted"; + const char* defines[] = { + "ENABLE_U_SAMPLER0_IS_INDEXED_ALPHA", + "ENABLE_S_SAMPLER2", + "ENABLE_VA_TEXCOORD0", + "ENABLE_VA_COLOR" + }; + prog_desc.defines = tcb::make_span(defines); + program_ = rhi.create_program(prog_desc); { default_tex_ = rhi.create_texture({ @@ -269,17 +234,17 @@ void TwodeeRenderer::initialize(Rhi& rhi, Handle ctx) TextureWrapMode::kClamp }); std::array data = {0, 255, 0, 255}; - rhi.update_texture(ctx, default_tex_, {0, 0, 2, 1}, PixelFormat::kRG8, tcb::as_bytes(tcb::span(data))); + rhi.update_texture(default_tex_, {0, 0, 2, 1}, PixelFormat::kRG8, tcb::as_bytes(tcb::span(data))); } initialized_ = true; } -void TwodeeRenderer::flush(Rhi& rhi, Handle ctx, Twodee& twodee) +void TwodeeRenderer::flush(Rhi& rhi, Twodee& twodee) { if (!initialized_) { - initialize(rhi, ctx); + initialize(rhi); } // Stage 1 - command list patch detection @@ -297,7 +262,7 @@ void TwodeeRenderer::flush(Rhi& rhi, Handle ctx, Twodee& twodee } if (cmd.colormap != nullptr) { - palette_manager_->find_or_create_colormap(rhi, ctx, cmd.colormap); + palette_manager_->find_or_create_colormap(rhi, cmd.colormap); } }, [&](const Draw2dVertices& cmd) {}}; @@ -309,7 +274,7 @@ void TwodeeRenderer::flush(Rhi& rhi, Handle ctx, Twodee& twodee { patch_atlas_cache_->queue_patch(patch); } - patch_atlas_cache_->pack(rhi, ctx); + patch_atlas_cache_->pack(rhi); size_t list_index = 0; for (auto& list : twodee) @@ -377,6 +342,8 @@ void TwodeeRenderer::flush(Rhi& rhi, Handle ctx, Twodee& twodee new_cmd.colormap = nullptr; // safety: a command list is required to have at least 1 command new_cmd.pipeline_key = pipeline_key_for_cmd(list.cmds[0]); + new_cmd.primitive = new_cmd.pipeline_key.lines ? PrimitiveType::kLines : PrimitiveType::kTriangles; + new_cmd.blend_mode = new_cmd.pipeline_key.blend; merged_list.cmds.push_back(std::move(new_cmd)); for (auto& cmd : list.cmds) @@ -445,7 +412,7 @@ void TwodeeRenderer::flush(Rhi& rhi, Handle ctx, Twodee& twodee { if (cmd.flat_lump != LUMPERROR) { - flat_manager_->find_or_create_indexed(rhi, ctx, cmd.flat_lump); + flat_manager_->find_or_create_indexed(rhi, cmd.flat_lump); std::optional t = MergedTwodeeCommandFlatTexture {cmd.flat_lump}; the_new_one.texture = t; } @@ -458,6 +425,8 @@ void TwodeeRenderer::flush(Rhi& rhi, Handle ctx, Twodee& twodee }}; std::visit(tex_visitor_again, cmd); the_new_one.pipeline_key = pipeline_key_for_cmd(cmd); + the_new_one.primitive = the_new_one.pipeline_key.lines ? PrimitiveType::kLines : PrimitiveType::kTriangles; + the_new_one.blend_mode = the_new_one.pipeline_key.blend; merged_list.cmds.push_back(std::move(the_new_one)); } @@ -492,26 +461,21 @@ void TwodeeRenderer::flush(Rhi& rhi, Handle ctx, Twodee& twodee tcb::span vertex_data = tcb::as_bytes(tcb::span(orig_list.vertices)); tcb::span index_data = tcb::as_bytes(tcb::span(orig_list.indices)); - rhi.update_buffer(ctx, merged_list.vbo, 0, vertex_data); - rhi.update_buffer(ctx, merged_list.ibo, 0, index_data); + rhi.update_buffer(merged_list.vbo, 0, vertex_data); + rhi.update_buffer(merged_list.ibo, 0, index_data); - // Update the binding sets for each individual merged command - VertexAttributeBufferBinding vbos[] = {{0, merged_list.vbo}}; for (auto& mcmd : merged_list.cmds) { - TextureBinding tx[3]; auto tex_visitor = srb2::Overload { [&](Handle texture) { - tx[0] = {SamplerName::kSampler0, texture}; - tx[1] = {SamplerName::kSampler1, palette_tex}; + mcmd.texture_handle = texture; }, [&](const MergedTwodeeCommandFlatTexture& tex) { - Handle th = flat_manager_->find_or_create_indexed(rhi, ctx, tex.lump); + Handle th = flat_manager_->find_or_create_indexed(rhi, tex.lump); SRB2_ASSERT(th != kNullHandle); - tx[0] = {SamplerName::kSampler0, th}; - tx[1] = {SamplerName::kSampler1, palette_tex}; + mcmd.texture_handle = th; }}; if (mcmd.texture) { @@ -519,49 +483,39 @@ void TwodeeRenderer::flush(Rhi& rhi, Handle ctx, Twodee& twodee } else { - tx[0] = {SamplerName::kSampler0, default_tex_}; - tx[1] = {SamplerName::kSampler1, palette_tex}; + mcmd.texture_handle = default_tex_; } const uint8_t* colormap = mcmd.colormap; Handle colormap_h = palette_manager_->default_colormap(); if (colormap) { - colormap_h = palette_manager_->find_or_create_colormap(rhi, ctx, colormap); + colormap_h = palette_manager_->find_or_create_colormap(rhi, colormap); SRB2_ASSERT(colormap_h != kNullHandle); } - tx[2] = {SamplerName::kSampler2, colormap_h}; - mcmd.binding_set = - rhi.create_binding_set(ctx, pipelines_[mcmd.pipeline_key], {tcb::span(vbos), tcb::span(tx)}); + mcmd.colormap_handle = colormap_h; } ctx_list_itr++; } - // Uniform sets - std::array g1_uniforms = { - // Projection - glm::mat4( - glm::vec4(2.f / vid.width, 0.f, 0.f, 0.f), - glm::vec4(0.f, -2.f / vid.height, 0.f, 0.f), - glm::vec4(0.f, 0.f, 1.f, 0.f), - glm::vec4(-1.f, 1.f, 0.f, 1.f) - ), - }; - std::array g2_uniforms = { - // ModelView - glm::identity(), - // Texcoord0 Transform - glm::identity(), - // Sampler 0 Is Indexed Alpha (yes, it always is) - static_cast(1) - }; - Handle us_1 = rhi.create_uniform_set(ctx, {tcb::span(g1_uniforms)}); - Handle us_2 = rhi.create_uniform_set(ctx, {tcb::span(g2_uniforms)}); - // Presumably, we're already in a renderpass when flush is called + rhi.bind_program(program_); + rhi.set_uniform("u_projection", glm::mat4( + glm::vec4(2.f / vid.width, 0.f, 0.f, 0.f), + glm::vec4(0.f, -2.f / vid.height, 0.f, 0.f), + glm::vec4(0.f, 0.f, 1.f, 0.f), + glm::vec4(-1.f, 1.f, 0.f, 1.f) + )); + rhi.set_uniform("u_modelview", glm::identity()); + rhi.set_uniform("u_texcoord0_transform", glm::identity()); + rhi.set_uniform("u_sampler0_is_indexed_alpha", static_cast(1)); + rhi.set_sampler("s_sampler1", 1, palette_tex); for (auto& list : cmd_lists_) { + rhi.bind_vertex_attrib("a_position", list.vbo, VertexAttributeFormat::kFloat3, offsetof(TwodeeVertex, x), sizeof(TwodeeVertex)); + rhi.bind_vertex_attrib("a_texcoord0", list.vbo, VertexAttributeFormat::kFloat2, offsetof(TwodeeVertex, u), sizeof(TwodeeVertex)); + rhi.bind_vertex_attrib("a_color", list.vbo, VertexAttributeFormat::kFloat4, offsetof(TwodeeVertex, r), sizeof(TwodeeVertex)); for (auto& cmd : list.cmds) { if (cmd.elements == 0) @@ -570,15 +524,18 @@ void TwodeeRenderer::flush(Rhi& rhi, Handle ctx, Twodee& twodee // This shouldn't happen, but, just in case... continue; } - SRB2_ASSERT(pipelines_.find(cmd.pipeline_key) != pipelines_.end()); - Handle pl = pipelines_[cmd.pipeline_key]; - rhi.bind_pipeline(ctx, pl); - rhi.set_viewport(ctx, {0, 0, static_cast(vid.width), static_cast(vid.height)}); - rhi.bind_uniform_set(ctx, 0, us_1); - rhi.bind_uniform_set(ctx, 1, us_2); - rhi.bind_binding_set(ctx, cmd.binding_set); - rhi.bind_index_buffer(ctx, list.ibo); - rhi.draw_indexed(ctx, cmd.elements, cmd.index_offset); + RasterizerStateDesc desc; + desc.cull = CullMode::kNone; + desc.primitive = cmd.primitive; + desc.blend_enabled = true; + set_blend_state(desc, cmd.blend_mode); + // Set blend and primitives + rhi.set_rasterizer_state(desc); + rhi.set_viewport({0, 0, static_cast(vid.width), static_cast(vid.height)}); + rhi.set_sampler("s_sampler0", 0, cmd.texture_handle); + rhi.set_sampler("s_sampler2", 2, cmd.colormap_handle); + rhi.bind_index_buffer(list.ibo); + rhi.draw_indexed(cmd.elements, cmd.index_offset); } } diff --git a/src/hwr2/twodee_renderer.hpp b/src/hwr2/twodee_renderer.hpp index 9b3a895c9..9632ce119 100644 --- a/src/hwr2/twodee_renderer.hpp +++ b/src/hwr2/twodee_renderer.hpp @@ -11,10 +11,8 @@ #ifndef __SRB2_HWR2_PASS_TWODEE_HPP__ #define __SRB2_HWR2_PASS_TWODEE_HPP__ -#include #include #include -#include #include #include @@ -65,10 +63,13 @@ struct MergedTwodeeCommandFlatTexture struct MergedTwodeeCommand { using Texture = std::variant, MergedTwodeeCommandFlatTexture>; - TwodeePipelineKey pipeline_key = {}; - rhi::Handle binding_set = {}; + rhi::PrimitiveType primitive; + BlendMode blend_mode; std::optional texture; + TwodeePipelineKey pipeline_key; + rhi::Handle texture_handle; const uint8_t* colormap; + rhi::Handle colormap_handle; uint32_t index_offset = 0; uint32_t elements = 0; }; @@ -94,14 +95,13 @@ class TwodeeRenderer final std::vector cmd_lists_; std::vector, std::size_t>> vbos_; std::vector, std::size_t>> ibos_; - rhi::Handle render_pass_; rhi::Handle output_; rhi::Handle default_tex_; - std::unordered_map> pipelines_; + rhi::Handle program_; void rewrite_patch_quad_vertices(Draw2dList& list, const Draw2dPatchQuad& cmd) const; - void initialize(rhi::Rhi& rhi, rhi::Handle ctx); + void initialize(rhi::Rhi& rhi); public: TwodeeRenderer( @@ -118,7 +118,7 @@ public: /// @brief Flush accumulated Twodee state and perform draws. /// @param rhi /// @param ctx - void flush(rhi::Rhi& rhi, rhi::Handle ctx, Twodee& twodee); + void flush(rhi::Rhi& rhi, Twodee& twodee); }; } // namespace srb2::hwr2 diff --git a/src/hwr2/upscale_backbuffer.cpp b/src/hwr2/upscale_backbuffer.cpp index 790f5b332..d7efb5c3e 100644 --- a/src/hwr2/upscale_backbuffer.cpp +++ b/src/hwr2/upscale_backbuffer.cpp @@ -27,7 +27,7 @@ static bool size_equal(Rhi& rhi, Handle tex, uint32_t width, uint32_t h return deets.width == width && deets.height == height; } -void UpscaleBackbuffer::begin_pass(Rhi& rhi, Handle ctx) +void UpscaleBackbuffer::begin_pass(Rhi& rhi) { uint32_t vid_width = static_cast(vid.width); uint32_t vid_height = static_cast(vid.height); @@ -38,19 +38,6 @@ void UpscaleBackbuffer::begin_pass(Rhi& rhi, Handle ctx) remake = true; } - auto new_renderpass = [&rhi = rhi](AttachmentLoadOp load_op, AttachmentStoreOp store_op) - { - RenderPassDesc desc {}; - desc.use_depth_stencil = false; - desc.color_load_op = load_op; - desc.color_store_op = store_op; - desc.depth_load_op = load_op; - desc.depth_store_op = store_op; - desc.stencil_load_op = load_op; - desc.stencil_store_op = store_op; - return rhi.create_render_pass(desc); - }; - if (remake) { if (color_) @@ -70,23 +57,16 @@ void UpscaleBackbuffer::begin_pass(Rhi& rhi, Handle ctx) RenderbufferDesc depth_tex {}; depth_tex.width = vid_width; depth_tex.height = vid_height; - - if (!renderpass_clear_) - { - renderpass_clear_ = new_renderpass(AttachmentLoadOp::kClear, AttachmentStoreOp::kStore); - } - } - else - { - if (!renderpass_) - { - renderpass_ = new_renderpass(AttachmentLoadOp::kLoad, AttachmentStoreOp::kStore); - } } RenderPassBeginInfo begin_info {}; - begin_info.render_pass = remake ? renderpass_clear_ : renderpass_; begin_info.clear_color = {0, 0, 0, 1}; begin_info.color_attachment = color_; - rhi.begin_render_pass(ctx, begin_info); + begin_info.color_load_op = rhi::AttachmentLoadOp::kLoad; + begin_info.color_store_op = rhi::AttachmentStoreOp::kStore; + begin_info.depth_load_op = rhi::AttachmentLoadOp::kLoad; + begin_info.depth_store_op = rhi::AttachmentStoreOp::kStore; + begin_info.stencil_load_op = rhi::AttachmentLoadOp::kLoad; + begin_info.stencil_store_op = rhi::AttachmentStoreOp::kStore; + rhi.push_render_pass(begin_info); } diff --git a/src/hwr2/upscale_backbuffer.hpp b/src/hwr2/upscale_backbuffer.hpp index a60f30172..0bf087663 100644 --- a/src/hwr2/upscale_backbuffer.hpp +++ b/src/hwr2/upscale_backbuffer.hpp @@ -19,8 +19,6 @@ namespace srb2::hwr2 class UpscaleBackbuffer { rhi::Handle color_; - rhi::Handle renderpass_; - rhi::Handle renderpass_clear_; public: UpscaleBackbuffer(); @@ -31,7 +29,7 @@ public: UpscaleBackbuffer& operator=(const UpscaleBackbuffer&) = delete; UpscaleBackbuffer& operator=(UpscaleBackbuffer&&); - void begin_pass(rhi::Rhi& rhi, rhi::Handle ctx); + void begin_pass(rhi::Rhi& rhi); rhi::Handle color() const noexcept { return color_; } }; diff --git a/src/i_video.h b/src/i_video.h index 1617a7305..d12d5f782 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -28,7 +28,6 @@ extern rhi::Handle g_current_rhi; rhi::Rhi* get_rhi(rhi::Handle handle); -rhi::Handle main_graphics_context(); hwr2::HardwareState* main_hardware_state(); } // namespace srb2::sys diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp index 82ab995c3..f9cf8f4f7 100644 --- a/src/i_video_common.cpp +++ b/src/i_video_common.cpp @@ -56,7 +56,6 @@ using namespace srb2::rhi; static Rhi* g_last_known_rhi = nullptr; static bool g_imgui_frame_active = false; -static Handle g_main_graphics_context; static HardwareState g_hw_state; Handle srb2::sys::g_current_rhi = kNullHandle; @@ -88,6 +87,7 @@ static void reset_hardware_state(Rhi* rhi) g_hw_state.crtsharp_blit_rect = std::make_unique(BlitRectPass::BlitMode::kCrtSharp); g_hw_state.screen_capture = std::make_unique(); g_hw_state.backbuffer = std::make_unique(); + g_hw_state.imgui_renderer = std::make_unique(); g_hw_state.wipe_frames = {}; g_last_known_rhi = rhi; @@ -98,9 +98,7 @@ static void new_imgui_frame(); static void preframe_update(Rhi& rhi) { - SRB2_ASSERT(g_main_graphics_context != kNullHandle); - - g_hw_state.palette_manager->update(rhi, g_main_graphics_context); + g_hw_state.palette_manager->update(rhi); new_twodee_frame(); new_imgui_frame(); } @@ -196,11 +194,6 @@ static void new_imgui_frame() g_imgui_frame_active = true; } -rhi::Handle sys::main_graphics_context() -{ - return g_main_graphics_context; -} - HardwareState* sys::main_hardware_state() { return &g_hw_state; @@ -209,11 +202,10 @@ HardwareState* sys::main_hardware_state() void I_CaptureVideoFrame() { rhi::Rhi* rhi = srb2::sys::get_rhi(srb2::sys::g_current_rhi); - rhi::Handle ctx = srb2::sys::main_graphics_context(); hwr2::HardwareState* hw_state = srb2::sys::main_hardware_state(); hw_state->screen_capture->set_source(static_cast(vid.width), static_cast(vid.height)); - hw_state->screen_capture->capture(*rhi, ctx); + hw_state->screen_capture->capture(*rhi); } void I_StartDisplayUpdate(void) @@ -244,12 +236,9 @@ void I_StartDisplayUpdate(void) reset_hardware_state(rhi); } - rhi::Handle ctx = rhi->begin_graphics(); HardwareState* hw_state = &g_hw_state; - hw_state->backbuffer->begin_pass(*rhi, ctx); - - g_main_graphics_context = ctx; + hw_state->backbuffer->begin_pass(*rhi); preframe_update(*rhi); } @@ -283,68 +272,63 @@ void I_FinishUpdate(void) return; } - rhi::Handle ctx = g_main_graphics_context; + // better hope the drawing code left the context in a render pass, I guess + g_hw_state.twodee_renderer->flush(*rhi, g_2d); + rhi->pop_render_pass(); - if (ctx != kNullHandle) + rhi->push_default_render_pass(true); + + // Upscale draw the backbuffer (with postprocessing maybe?) + if (cv_scr_scale.value != FRACUNIT) { - // better hope the drawing code left the context in a render pass, I guess - g_hw_state.twodee_renderer->flush(*rhi, ctx, g_2d); - rhi->end_render_pass(ctx); + float f = std::max(FixedToFloat(cv_scr_scale.value), 0.f); + float w = vid.realwidth * f; + float h = vid.realheight * f; + float x = (vid.realwidth - w) * (0.5f + (FixedToFloat(cv_scr_x.value) * 0.5f)); + float y = (vid.realheight - h) * (0.5f + (FixedToFloat(cv_scr_y.value) * 0.5f)); - rhi->begin_default_render_pass(ctx, true); - - // Upscale draw the backbuffer (with postprocessing maybe?) - if (cv_scr_scale.value != FRACUNIT) - { - float f = std::max(FixedToFloat(cv_scr_scale.value), 0.f); - float w = vid.realwidth * f; - float h = vid.realheight * f; - float x = (vid.realwidth - w) * (0.5f + (FixedToFloat(cv_scr_x.value) * 0.5f)); - float y = (vid.realheight - h) * (0.5f + (FixedToFloat(cv_scr_y.value) * 0.5f)); - - g_hw_state.blit_rect->set_output(x, y, w, h, true, true); - g_hw_state.sharp_bilinear_blit_rect->set_output(x, y, w, h, true, true); - g_hw_state.crt_blit_rect->set_output(x, y, w, h, true, true); - g_hw_state.crtsharp_blit_rect->set_output(x, y, w, h, true, true); - } - else - { - g_hw_state.blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); - g_hw_state.sharp_bilinear_blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); - g_hw_state.crt_blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); - g_hw_state.crtsharp_blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); - } - g_hw_state.blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); - g_hw_state.sharp_bilinear_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); - g_hw_state.crt_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); - g_hw_state.crtsharp_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); - - switch (cv_scr_effect.value) - { - case 1: - rhi->update_texture_settings(ctx, g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kLinear, TextureFilterMode::kLinear); - g_hw_state.sharp_bilinear_blit_rect->draw(*rhi, ctx); - break; - case 2: - rhi->update_texture_settings(ctx, g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kLinear, TextureFilterMode::kLinear); - g_hw_state.crt_blit_rect->draw(*rhi, ctx); - break; - case 3: - rhi->update_texture_settings(ctx, g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kLinear, TextureFilterMode::kLinear); - g_hw_state.crtsharp_blit_rect->draw(*rhi, ctx); - break; - default: - rhi->update_texture_settings(ctx, g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kNearest, TextureFilterMode::kNearest); - g_hw_state.blit_rect->draw(*rhi, ctx); - break; - } - rhi->end_render_pass(ctx); - - rhi->end_graphics(ctx); - g_main_graphics_context = kNullHandle; - - postframe_update(*rhi); + g_hw_state.blit_rect->set_output(x, y, w, h, true, true); + g_hw_state.sharp_bilinear_blit_rect->set_output(x, y, w, h, true, true); + g_hw_state.crt_blit_rect->set_output(x, y, w, h, true, true); + g_hw_state.crtsharp_blit_rect->set_output(x, y, w, h, true, true); } + else + { + g_hw_state.blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); + g_hw_state.sharp_bilinear_blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); + g_hw_state.crt_blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); + g_hw_state.crtsharp_blit_rect->set_output(0, 0, vid.realwidth, vid.realheight, true, true); + } + g_hw_state.blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); + g_hw_state.sharp_bilinear_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); + g_hw_state.crt_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); + g_hw_state.crtsharp_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast(vid.width), static_cast(vid.height)); + + switch (cv_scr_effect.value) + { + case 1: + rhi->update_texture_settings(g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kLinear, TextureFilterMode::kLinear); + g_hw_state.sharp_bilinear_blit_rect->draw(*rhi); + break; + case 2: + rhi->update_texture_settings(g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kLinear, TextureFilterMode::kLinear); + g_hw_state.crt_blit_rect->draw(*rhi); + break; + case 3: + rhi->update_texture_settings(g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kLinear, TextureFilterMode::kLinear); + g_hw_state.crtsharp_blit_rect->draw(*rhi); + break; + default: + rhi->update_texture_settings(g_hw_state.backbuffer->color(), TextureWrapMode::kClamp, TextureWrapMode::kClamp, TextureFilterMode::kNearest, TextureFilterMode::kNearest); + g_hw_state.blit_rect->draw(*rhi); + break; + } + + g_hw_state.imgui_renderer->render(*rhi); + + rhi->pop_render_pass(); + + postframe_update(*rhi); rhi->present(); rhi->finish(); diff --git a/src/rhi/gl2/gl2_rhi.cpp b/src/rhi/gl2/gl2_rhi.cpp index 340d24dbb..0c3e49516 100644 --- a/src/rhi/gl2/gl2_rhi.cpp +++ b/src/rhi/gl2/gl2_rhi.cpp @@ -573,6 +573,31 @@ constexpr GLenum map_uniform_format(rhi::UniformFormat format) } } +constexpr GLenum map_stencil_op(rhi::StencilOp op) +{ + switch (op) + { + case rhi::StencilOp::kKeep: + return GL_KEEP; + case rhi::StencilOp::kZero: + return GL_ZERO; + case rhi::StencilOp::kReplace: + return GL_REPLACE; + case rhi::StencilOp::kIncrementClamp: + return GL_INCR; + case rhi::StencilOp::kIncrementWrap: + return GL_INCR_WRAP; + case rhi::StencilOp::kDecrementClamp: + return GL_DECR; + case rhi::StencilOp::kDecrementWrap: + return GL_DECR_WRAP; + case rhi::StencilOp::kInvert: + return GL_INVERT; + default: + return GL_ZERO; + } +} + } // namespace Gl2Platform::~Gl2Platform() = default; @@ -585,19 +610,6 @@ Gl2Rhi::Gl2Rhi(std::unique_ptr&& platform, GlLoadFunc load_func) : Gl2Rhi::~Gl2Rhi() = default; -rhi::Handle Gl2Rhi::create_render_pass(const rhi::RenderPassDesc& desc) -{ - // GL has no formal render pass object - Gl2RenderPass pass; - pass.desc = desc; - return render_pass_slab_.insert(std::move(pass)); -} - -void Gl2Rhi::destroy_render_pass(rhi::Handle handle) -{ - render_pass_slab_.remove(handle); -} - rhi::Handle Gl2Rhi::create_texture(const rhi::TextureDesc& desc) { GLenum internal_format = map_internal_texture_format(desc.format); @@ -636,15 +648,12 @@ void Gl2Rhi::destroy_texture(rhi::Handle handle) } void Gl2Rhi::update_texture( - Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data ) { - SRB2_ASSERT(graphics_context_active_ == true); - if (data.empty()) { return; @@ -687,7 +696,6 @@ void Gl2Rhi::update_texture( } void Gl2Rhi::update_texture_settings( - Handle ctx, Handle texture, TextureWrapMode u_wrap, TextureWrapMode v_wrap, @@ -695,8 +703,6 @@ void Gl2Rhi::update_texture_settings( TextureFilterMode mag ) { - SRB2_ASSERT(graphics_context_active_ == true); - SRB2_ASSERT(texture_slab_.is_valid(texture) == true); auto& t = texture_slab_[texture]; @@ -749,15 +755,11 @@ void Gl2Rhi::destroy_buffer(rhi::Handle handle) } void Gl2Rhi::update_buffer( - rhi::Handle ctx, rhi::Handle handle, uint32_t offset, tcb::span data ) { - SRB2_ASSERT(graphics_context_active_ == true); - SRB2_ASSERT(ctx.generation() == graphics_context_generation_); - if (data.empty()) { return; @@ -785,58 +787,6 @@ void Gl2Rhi::update_buffer( GL_ASSERT; } -rhi::Handle -Gl2Rhi::create_uniform_set(rhi::Handle ctx, const rhi::CreateUniformSetInfo& info) -{ - SRB2_ASSERT(graphics_context_active_ == true); - SRB2_ASSERT(ctx.generation() == graphics_context_generation_); - - Gl2UniformSet uniform_set; - - for (auto& uniform : info.uniforms) - { - uniform_set.uniforms.push_back(uniform); - } - - return uniform_set_slab_.insert(std::move(uniform_set)); -} - -rhi::Handle Gl2Rhi::create_binding_set( - rhi::Handle ctx, - Handle pipeline, - const rhi::CreateBindingSetInfo& info -) -{ - SRB2_ASSERT(graphics_context_active_ == true); - SRB2_ASSERT(ctx.generation() == graphics_context_generation_); - - SRB2_ASSERT(pipeline_slab_.is_valid(pipeline) == true); - auto& pl = pipeline_slab_[pipeline]; - - SRB2_ASSERT(info.vertex_buffers.size() == pl.desc.vertex_input.buffer_layouts.size()); - - Gl2BindingSet binding_set; - - for (auto& vertex_buffer : info.vertex_buffers) - { - binding_set.vertex_buffer_bindings.push_back(vertex_buffer); - } - - // Set textures - for (size_t i = 0; i < info.sampler_textures.size(); i++) - { - auto& binding = info.sampler_textures[i]; - auto& sampler_name = pl.desc.sampler_input.enabled_samplers[i]; - SRB2_ASSERT(binding.name == sampler_name); - - SRB2_ASSERT(texture_slab_.is_valid(binding.texture)); - auto& tx = texture_slab_[binding.texture]; - binding_set.textures.insert({sampler_name, tx.texture}); - } - - return binding_set_slab_.insert(std::move(binding_set)); -} - rhi::Handle Gl2Rhi::create_renderbuffer(const rhi::RenderbufferDesc& desc) { GLuint name = 0; @@ -878,367 +828,165 @@ void Gl2Rhi::destroy_renderbuffer(rhi::Handle handle) GL_ASSERT; } -rhi::Handle Gl2Rhi::create_pipeline(const PipelineDesc& desc) +rhi::Handle Gl2Rhi::create_program(const ProgramDesc& desc) { SRB2_ASSERT(platform_ != nullptr); - // TODO assert compatibility of pipeline description with program using ProgramRequirements + Gl2Program program; - const rhi::ProgramRequirements& reqs = rhi::program_requirements_for_program(desc.program); - - GLuint vertex = 0; - GLuint fragment = 0; - GLuint program = 0; - Gl2Pipeline pipeline; - - auto [vert_srcs, frag_srcs] = platform_->find_shader_sources(desc.program); + auto [vert_srcs, frag_srcs] = platform_->find_shader_sources(desc.name); // GL 2 note: // Do not explicitly set GLSL version. Unversioned sources are required to be treated as 110, but writing 110 // breaks the AMD driver's program linker in a bizarre way. - // Process vertex shader sources + // Process shader sources std::vector vert_sources; + std::vector frag_sources; ShaderLoadContext vert_ctx; + ShaderLoadContext frag_ctx; vert_ctx.set_version("120"); - for (auto& attribute : desc.vertex_input.attr_layouts) + frag_ctx.set_version("120"); + for (auto def : desc.defines) { - for (auto const& require_attr : reqs.vertex_input.attributes) - { - if (require_attr.name == attribute.name && !require_attr.required) - { - vert_ctx.define(map_vertex_attribute_enable_define(attribute.name)); - } - } - } - for (auto& uniform_group : desc.uniform_input.enabled_uniforms) - { - for (auto& uniform : uniform_group) - { - for (auto const& req_uni_group : reqs.uniforms.uniform_groups) - { - for (auto const& req_uni : req_uni_group) - { - if (req_uni.name == uniform && !req_uni.required) - { - vert_ctx.define(map_uniform_enable_define(uniform)); - } - } - } - } + vert_ctx.define(def); + frag_ctx.define(def); } for (auto& src : vert_srcs) { vert_ctx.add_source(std::move(src)); } - vert_sources = vert_ctx.get_sources_array(); - - // Process vertex shader sources - std::vector frag_sources; - ShaderLoadContext frag_ctx; - frag_ctx.set_version("120"); - for (auto& sampler : desc.sampler_input.enabled_samplers) - { - for (auto const& require_sampler : reqs.samplers.samplers) - { - if (sampler == require_sampler.name && !require_sampler.required) - { - frag_ctx.define(map_sampler_enable_define(sampler)); - } - } - } - for (auto& uniform_group : desc.uniform_input.enabled_uniforms) - { - for (auto& uniform : uniform_group) - { - for (auto const& req_uni_group : reqs.uniforms.uniform_groups) - { - for (auto const& req_uni : req_uni_group) - { - if (req_uni.name == uniform && !req_uni.required) - { - frag_ctx.define(map_uniform_enable_define(uniform)); - } - } - } - } - } for (auto& src : frag_srcs) { frag_ctx.add_source(std::move(src)); } + vert_sources = vert_ctx.get_sources_array(); frag_sources = frag_ctx.get_sources_array(); - vertex = gl_->CreateShader(GL_VERTEX_SHADER); - gl_->ShaderSource(vertex, vert_sources.size(), vert_sources.data(), NULL); - gl_->CompileShader(vertex); GLint is_compiled = 0; - gl_->GetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); + + program.vertex_shader = gl_->CreateShader(GL_VERTEX_SHADER); + GL_ASSERT; + gl_->ShaderSource(program.vertex_shader, vert_sources.size(), vert_sources.data(), nullptr); + gl_->CompileShader(program.vertex_shader); + gl_->GetShaderiv(program.vertex_shader, GL_COMPILE_STATUS, &is_compiled); if (is_compiled == GL_FALSE) { GLint max_length = 0; - gl_->GetShaderiv(vertex, GL_INFO_LOG_LENGTH, &max_length); + gl_->GetShaderiv(program.vertex_shader, GL_INFO_LOG_LENGTH, &max_length); std::vector compile_error(max_length); - gl_->GetShaderInfoLog(vertex, max_length, &max_length, compile_error.data()); + gl_->GetShaderInfoLog(program.vertex_shader, max_length, &max_length, compile_error.data()); - gl_->DeleteShader(vertex); - throw std::runtime_error(fmt::format("Vertex shader compilation failed: {}", std::string(compile_error.data())) - ); - } - fragment = gl_->CreateShader(GL_FRAGMENT_SHADER); - gl_->ShaderSource(fragment, frag_sources.size(), frag_sources.data(), NULL); - gl_->CompileShader(fragment); - gl_->GetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) - { - GLint max_length = 0; - gl_->GetShaderiv(fragment, GL_INFO_LOG_LENGTH, &max_length); - std::vector compile_error(max_length); - gl_->GetShaderInfoLog(fragment, max_length, &max_length, compile_error.data()); - - gl_->DeleteShader(fragment); - gl_->DeleteShader(vertex); - throw std::runtime_error( - fmt::format("Fragment shader compilation failed: {}", std::string(compile_error.data())) - ); + gl_->DeleteShader(program.vertex_shader); + throw std::runtime_error(fmt::format("Vertex shader compilation failed: {}", std::string(compile_error.data()))); } - // Program link - - program = gl_->CreateProgram(); - gl_->AttachShader(program, vertex); - gl_->AttachShader(program, fragment); - gl_->LinkProgram(program); - gl_->GetProgramiv(program, GL_LINK_STATUS, &is_compiled); + program.fragment_shader = gl_->CreateShader(GL_FRAGMENT_SHADER); + GL_ASSERT; + gl_->ShaderSource(program.fragment_shader, frag_sources.size(), frag_sources.data(), nullptr); + gl_->CompileShader(program.fragment_shader); + gl_->GetShaderiv(program.fragment_shader, GL_COMPILE_STATUS, &is_compiled); if (is_compiled == GL_FALSE) { GLint max_length = 0; - gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &max_length); + gl_->GetShaderiv(program.fragment_shader, GL_INFO_LOG_LENGTH, &max_length); + std::vector compile_error(max_length); + gl_->GetShaderInfoLog(program.fragment_shader, max_length, &max_length, compile_error.data()); + + gl_->DeleteShader(program.fragment_shader); + throw std::runtime_error(fmt::format("Fragment shader compilation failed: {}", std::string(compile_error.data()))); + } + + program.program = gl_->CreateProgram(); + GL_ASSERT; + + gl_->AttachShader(program.program, program.vertex_shader); + gl_->AttachShader(program.program, program.fragment_shader); + gl_->LinkProgram(program.program); + gl_->GetProgramiv(program.program, GL_LINK_STATUS, &is_compiled); + if (is_compiled == GL_FALSE) + { + GLint max_length = 0; + gl_->GetProgramiv(program.program, GL_INFO_LOG_LENGTH, &max_length); std::vector link_error(max_length); - gl_->GetProgramInfoLog(program, max_length, &max_length, link_error.data()); + gl_->GetProgramInfoLog(program.program, max_length, &max_length, link_error.data()); - gl_->DeleteProgram(program); - gl_->DeleteShader(fragment); - gl_->DeleteShader(vertex); + gl_->DeleteProgram(program.program); + gl_->DeleteShader(program.fragment_shader); + gl_->DeleteShader(program.vertex_shader); throw std::runtime_error(fmt::format("Pipeline program link failed: {}", std::string(link_error.data()))); } - std::unordered_map active_attributes; + // get attribute information GLint active_attribute_total = -1; - gl_->GetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attribute_total); + gl_->GetProgramiv(program.program, GL_ACTIVE_ATTRIBUTES, &active_attribute_total); if (active_attribute_total < 0) { - gl_->DeleteProgram(program); - gl_->DeleteShader(fragment); - gl_->DeleteShader(vertex); + gl_->DeleteProgram(program.program); + gl_->DeleteShader(program.fragment_shader); + gl_->DeleteShader(program.vertex_shader); throw std::runtime_error("Unable to retrieve program active attributes"); } - if (desc.vertex_input.attr_layouts.size() != static_cast(active_attribute_total)) - { - gl_->DeleteProgram(program); - gl_->DeleteShader(fragment); - gl_->DeleteShader(vertex); - throw std::runtime_error(fmt::format( - "Pipeline's enabled attribute count does not match the linked program's total: {} vs {}", - desc.vertex_input.attr_layouts.size(), - static_cast(active_attribute_total) - )); - } for (GLint i = 0; i < active_attribute_total; i++) { GLsizei name_len = 0; GLint size = 0; GLenum type = GL_ZERO; char name[256]; - gl_->GetActiveAttrib(program, i, 255, &name_len, &size, &type, name); + gl_->GetActiveAttrib(program.program, i, 255, &name_len, &size, &type, name); GL_ASSERT; - GLint location = gl_->GetAttribLocation(program, name); + GLint location = gl_->GetAttribLocation(program.program, name); GL_ASSERT; - active_attributes.insert({std::string(name), Gl2ActiveUniform {type, static_cast(location)}}); + program.attrib_locations[std::string(name)] = location; } - std::unordered_map active_uniforms; - size_t total_enabled_uniforms = 0; - for (auto g = desc.uniform_input.enabled_uniforms.cbegin(); g != desc.uniform_input.enabled_uniforms.cend(); - g = std::next(g)) - { - total_enabled_uniforms += g->size(); - } + // get uniform information GLint active_uniform_total = -1; - gl_->GetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_total); + gl_->GetProgramiv(program.program, GL_ACTIVE_UNIFORMS, &active_uniform_total); if (active_uniform_total < 0) { - gl_->DeleteProgram(program); - gl_->DeleteShader(fragment); - gl_->DeleteShader(vertex); + gl_->DeleteProgram(program.program); + gl_->DeleteShader(program.fragment_shader); + gl_->DeleteShader(program.vertex_shader); throw std::runtime_error("Unable to retrieve program active uniforms"); } - if (total_enabled_uniforms + desc.sampler_input.enabled_samplers.size() != - static_cast(active_uniform_total)) - { - gl_->DeleteProgram(program); - gl_->DeleteShader(fragment); - gl_->DeleteShader(vertex); - throw std::runtime_error(fmt::format( - "Pipeline's enabled uniform count (uniforms + samplers) does not match the linked program's total: {} vs " - "{}", - total_enabled_uniforms + desc.sampler_input.enabled_samplers.size(), - static_cast(active_uniform_total) - )); - } for (GLint i = 0; i < active_uniform_total; i++) { GLsizei name_len = 0; GLint size = 0; GLenum type = GL_ZERO; char name[256]; - gl_->GetActiveUniform(program, i, 255, &name_len, &size, &type, name); + gl_->GetActiveUniform(program.program, i, 255, &name_len, &size, &type, name); GL_ASSERT; - GLint location = gl_->GetUniformLocation(program, name); + GLint location = gl_->GetUniformLocation(program.program, name); GL_ASSERT; - active_uniforms.insert({std::string(name), Gl2ActiveUniform {type, static_cast(location)}}); + program.uniform_locations[std::string(name)] = location; } - for (auto& attr : desc.vertex_input.attr_layouts) - { - const char* symbol_name = map_vertex_attribute_symbol_name(attr.name); - SRB2_ASSERT(symbol_name != nullptr); - if (active_attributes.find(symbol_name) == active_attributes.end()) - { - gl_->DeleteProgram(program); - gl_->DeleteShader(fragment); - gl_->DeleteShader(vertex); - throw std::runtime_error("Enabled attribute not found in linked program"); - } - auto& active_attr = active_attributes[symbol_name]; - auto expected_format = rhi::vertex_attribute_format(attr.name); - auto expected_gl_type = map_vertex_attribute_format(expected_format); - SRB2_ASSERT(expected_gl_type != GL_ZERO); - if (expected_gl_type != active_attr.type) - { - gl_->DeleteProgram(program); - gl_->DeleteShader(fragment); - gl_->DeleteShader(vertex); - throw std::runtime_error("Active attribute type does not match expected type"); - } - - pipeline.attrib_locations.insert({attr.name, active_attr.location}); - } - - for (auto group_itr = desc.uniform_input.enabled_uniforms.cbegin(); - group_itr != desc.uniform_input.enabled_uniforms.cend(); - group_itr = std::next(group_itr)) - { - auto& group = *group_itr; - for (auto itr = group.cbegin(); itr != group.cend(); itr = std::next(itr)) - { - auto& uniform = *itr; - const char* symbol_name = map_uniform_attribute_symbol_name(uniform); - SRB2_ASSERT(symbol_name != nullptr); - if (active_uniforms.find(symbol_name) == active_uniforms.end()) - { - gl_->DeleteProgram(program); - gl_->DeleteShader(fragment); - gl_->DeleteShader(vertex); - throw std::runtime_error("Enabled uniform not found in linked program"); - } - auto& active_uniform = active_uniforms[symbol_name]; - auto expected_format = rhi::uniform_format(uniform); - auto expected_gl_type = map_uniform_format(expected_format); - SRB2_ASSERT(expected_gl_type != GL_ZERO); - if (expected_gl_type != active_uniform.type) - { - gl_->DeleteProgram(program); - gl_->DeleteShader(fragment); - gl_->DeleteShader(vertex); - throw std::runtime_error("Active uniform type does not match expected type"); - } - SRB2_ASSERT(pipeline.uniform_locations.find(uniform) == pipeline.uniform_locations.end()); - pipeline.uniform_locations.insert({uniform, active_uniform.location}); - } - } - - for (auto& sampler : desc.sampler_input.enabled_samplers) - { - const char* symbol_name = map_sampler_symbol_name(sampler); - SRB2_ASSERT(symbol_name != nullptr); - if (active_uniforms.find(symbol_name) == active_uniforms.end()) - { - gl_->DeleteProgram(program); - gl_->DeleteShader(fragment); - gl_->DeleteShader(vertex); - throw std::runtime_error("Enabled sampler not found in linked program"); - } - auto& active_sampler = active_uniforms[symbol_name]; - if (active_sampler.type != GL_SAMPLER_2D) - { - gl_->DeleteProgram(program); - gl_->DeleteShader(fragment); - gl_->DeleteShader(vertex); - throw std::runtime_error("Active sampler type does not match expected type"); - } - - pipeline.sampler_locations.insert({sampler, active_sampler.location}); - } - - pipeline.desc = desc; - pipeline.vertex_shader = vertex; - pipeline.fragment_shader = fragment; - pipeline.program = program; - - return pipeline_slab_.insert(std::move(pipeline)); + Handle program_handle = program_slab_.insert(std::move(program)); + return program_handle; } -void Gl2Rhi::destroy_pipeline(rhi::Handle handle) +void Gl2Rhi::destroy_program(Handle handle) { - SRB2_ASSERT(pipeline_slab_.is_valid(handle) == true); - Gl2Pipeline casted = pipeline_slab_.remove(handle); - GLuint vertex_shader = casted.vertex_shader; - GLuint fragment_shader = casted.fragment_shader; - GLuint program = casted.program; - - gl_->DeleteProgram(program); + SRB2_ASSERT(program_slab_.is_valid(handle) == true); + Gl2Program casted = program_slab_.remove(handle); + gl_->DeleteProgram(casted.program); GL_ASSERT; - gl_->DeleteShader(vertex_shader); + gl_->DeleteShader(casted.fragment_shader); GL_ASSERT; - gl_->DeleteShader(fragment_shader); - GL_ASSERT; -} - -rhi::Handle Gl2Rhi::begin_graphics() -{ - SRB2_ASSERT(graphics_context_active_ == false); - graphics_context_active_ = true; - return rhi::Handle(0, graphics_context_generation_); -} - -void Gl2Rhi::end_graphics(rhi::Handle handle) -{ - SRB2_ASSERT(graphics_context_active_ == true); - SRB2_ASSERT(current_pipeline_.has_value() == false && current_render_pass_.has_value() == false); - graphics_context_generation_ += 1; - if (graphics_context_generation_ == 0) - { - graphics_context_generation_ = 1; - } - graphics_context_active_ = false; - gl_->Flush(); + gl_->DeleteShader(casted.vertex_shader); GL_ASSERT; } void Gl2Rhi::present() { SRB2_ASSERT(platform_ != nullptr); - SRB2_ASSERT(graphics_context_active_ == false); platform_->present(); } -void Gl2Rhi::begin_default_render_pass(Handle ctx, bool clear) +void Gl2Rhi::apply_default_framebuffer(bool clear) { - SRB2_ASSERT(platform_ != nullptr); - SRB2_ASSERT(graphics_context_active_ == true); - SRB2_ASSERT(current_render_pass_.has_value() == false); - const Rect fb_rect = platform_->get_default_framebuffer_dimensions(); gl_->BindFramebuffer(GL_FRAMEBUFFER, 0); @@ -1256,19 +1004,10 @@ void Gl2Rhi::begin_default_render_pass(Handle ctx, bool clear) gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); GL_ASSERT; } - - current_render_pass_ = Gl2Rhi::DefaultRenderPassState {}; } -void Gl2Rhi::begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) +void Gl2Rhi::apply_framebuffer(const RenderPassBeginInfo& info, bool allow_clear) { - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value() == false); - - SRB2_ASSERT(render_pass_slab_.is_valid(info.render_pass) == true); - auto& rp = render_pass_slab_[info.render_pass]; - SRB2_ASSERT(rp.desc.use_depth_stencil == info.depth_stencil_attachment.has_value()); - auto fb_itr = framebuffers_.find(Gl2FramebufferKey {info.color_attachment, info.depth_stencil_attachment}); if (fb_itr == framebuffers_.end()) { @@ -1278,12 +1017,10 @@ void Gl2Rhi::begin_render_pass(Handle ctx, const RenderPassBegi GL_ASSERT; gl_->BindFramebuffer(GL_FRAMEBUFFER, fb_name); GL_ASSERT; - fb_itr = framebuffers_ - .insert( - {Gl2FramebufferKey {info.color_attachment, info.depth_stencil_attachment}, - static_cast(fb_name)} - ) - .first; + fb_itr = framebuffers_.insert({ + Gl2FramebufferKey {info.color_attachment, info.depth_stencil_attachment}, + static_cast(fb_name) + }).first; SRB2_ASSERT(texture_slab_.is_valid(info.color_attachment)); auto& texture = texture_slab_[info.color_attachment]; @@ -1291,7 +1028,7 @@ void Gl2Rhi::begin_render_pass(Handle ctx, const RenderPassBegi gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.texture, 0); GL_ASSERT; - if (rp.desc.use_depth_stencil && info.depth_stencil_attachment.has_value()) + if (info.depth_stencil_attachment.has_value()) { SRB2_ASSERT(renderbuffer_slab_.is_valid(*info.depth_stencil_attachment)); auto& renderbuffer = renderbuffer_slab_[*info.depth_stencil_attachment]; @@ -1307,388 +1044,124 @@ void Gl2Rhi::begin_render_pass(Handle ctx, const RenderPassBegi auto& fb = *fb_itr; gl_->BindFramebuffer(GL_FRAMEBUFFER, fb.second); GL_ASSERT; - gl_->Disable(GL_SCISSOR_TEST); - GL_ASSERT; GLint clear_bits = 0; - if (rp.desc.color_load_op == rhi::AttachmentLoadOp::kClear) + if (info.color_load_op == rhi::AttachmentLoadOp::kClear) { gl_->ClearColor(info.clear_color.r, info.clear_color.g, info.clear_color.b, info.clear_color.a); clear_bits |= GL_COLOR_BUFFER_BIT; } - if (rp.desc.use_depth_stencil) + if (info.depth_load_op == rhi::AttachmentLoadOp::kClear) { - if (rp.desc.depth_load_op == rhi::AttachmentLoadOp::kClear) - { - gl_->ClearDepth(1.f); - clear_bits |= GL_DEPTH_BUFFER_BIT; - } - if (rp.desc.stencil_load_op == rhi::AttachmentLoadOp::kClear) - { - gl_->ClearStencil(0); - clear_bits |= GL_STENCIL_BUFFER_BIT; - } + gl_->ClearDepth(1.f); + clear_bits |= GL_DEPTH_BUFFER_BIT; + } + if (info.stencil_load_op == rhi::AttachmentLoadOp::kClear) + { + gl_->ClearStencil(0); + clear_bits |= GL_STENCIL_BUFFER_BIT; } - if (clear_bits != 0) + if (clear_bits != 0 && allow_clear) { gl_->Clear(clear_bits); GL_ASSERT; } - - current_render_pass_ = info; } -void Gl2Rhi::end_render_pass(Handle ctx) +void Gl2Rhi::push_default_render_pass(bool clear) { - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value() == true); + SRB2_ASSERT(platform_ != nullptr); - current_pipeline_ = std::nullopt; - current_render_pass_ = std::nullopt; + render_pass_stack_.emplace_back(Gl2Rhi::DefaultRenderPassState { clear }); + apply_default_framebuffer(clear); } -void Gl2Rhi::bind_pipeline(Handle ctx, Handle pipeline) +void Gl2Rhi::push_render_pass(const RenderPassBeginInfo& info) { - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value() == true); - - SRB2_ASSERT(pipeline_slab_.is_valid(pipeline) == true); - auto& pl = pipeline_slab_[pipeline]; - auto& desc = pl.desc; - - gl_->UseProgram(pl.program); - GL_ASSERT; - - gl_->Disable(GL_SCISSOR_TEST); - GL_ASSERT; - - if (desc.depth_stencil_state) - { - if (desc.depth_stencil_state->depth_test) - { - gl_->Enable(GL_DEPTH_TEST); - GL_ASSERT; - GLenum depth_func = map_compare_func(desc.depth_stencil_state->depth_func); - SRB2_ASSERT(depth_func != GL_ZERO); - gl_->DepthFunc(depth_func); - GL_ASSERT; - gl_->DepthMask(desc.depth_stencil_state->depth_write ? GL_TRUE : GL_FALSE); - GL_ASSERT; - } - else - { - gl_->Disable(GL_DEPTH_TEST); - GL_ASSERT; - } - - if (desc.depth_stencil_state->depth_write) - { - gl_->DepthMask(GL_TRUE); - GL_ASSERT; - } - else - { - gl_->DepthMask(GL_FALSE); - GL_ASSERT; - } - - if (desc.depth_stencil_state->stencil_test) - { - gl_->Enable(GL_STENCIL_TEST); - stencil_front_reference_ = 0; - stencil_back_reference_ = 0; - stencil_front_compare_mask_ = 0xFF; - stencil_back_compare_mask_ = 0xFF; - stencil_front_write_mask_ = 0xFF; - stencil_back_write_mask_ = 0xFF; - GL_ASSERT; - - gl_->StencilFuncSeparate( - GL_FRONT, - map_compare_func(desc.depth_stencil_state->front.stencil_compare), - stencil_front_reference_, - stencil_front_compare_mask_ - ); - GL_ASSERT; - gl_->StencilFuncSeparate( - GL_BACK, - map_compare_func(desc.depth_stencil_state->back.stencil_compare), - stencil_back_reference_, - stencil_back_compare_mask_ - ); - GL_ASSERT; - - gl_->StencilMaskSeparate(GL_FRONT, stencil_front_write_mask_); - GL_ASSERT; - gl_->StencilMaskSeparate(GL_BACK, stencil_back_write_mask_); - GL_ASSERT; - } - else - { - gl_->Disable(GL_STENCIL_TEST); - GL_ASSERT; - } - } - else - { - gl_->Disable(GL_DEPTH_TEST); - GL_ASSERT; - gl_->Disable(GL_STENCIL_TEST); - GL_ASSERT; - gl_->StencilMask(0); - GL_ASSERT; - } - - if (desc.color_state.blend) - { - rhi::BlendDesc& bl = *desc.color_state.blend; - gl_->Enable(GL_BLEND); - GL_ASSERT; - gl_->BlendFuncSeparate( - map_blend_factor(bl.source_factor_color), - map_blend_factor(bl.dest_factor_color), - map_blend_factor(bl.source_factor_alpha), - map_blend_factor(bl.dest_factor_alpha) - ); - GL_ASSERT; - gl_->BlendEquationSeparate(map_blend_function(bl.color_function), map_blend_function(bl.alpha_function)); - GL_ASSERT; - gl_->BlendColor(desc.blend_color.r, desc.blend_color.g, desc.blend_color.b, desc.blend_color.a); - GL_ASSERT; - } - else - { - gl_->Disable(GL_BLEND); - } - - gl_->ColorMask( - desc.color_state.color_mask.r ? GL_TRUE : GL_FALSE, - desc.color_state.color_mask.g ? GL_TRUE : GL_FALSE, - desc.color_state.color_mask.b ? GL_TRUE : GL_FALSE, - desc.color_state.color_mask.a ? GL_TRUE : GL_FALSE - ); - GL_ASSERT; - - GLenum cull_face = map_cull_mode(desc.cull); - if (cull_face == GL_NONE) - { - gl_->Disable(GL_CULL_FACE); - GL_ASSERT; - } - else - { - gl_->Enable(GL_CULL_FACE); - GL_ASSERT; - gl_->CullFace(cull_face); - GL_ASSERT; - } - gl_->FrontFace(map_winding(desc.winding)); - GL_ASSERT; - - current_pipeline_ = pipeline; - current_primitive_type_ = desc.primitive; + render_pass_stack_.push_back(info); + apply_framebuffer(info, false); } -void Gl2Rhi::bind_uniform_set(Handle ctx, uint32_t slot, Handle set) +void Gl2Rhi::pop_render_pass() { - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + SRB2_ASSERT(render_pass_stack_.empty() == false); - SRB2_ASSERT(pipeline_slab_.is_valid(*current_pipeline_)); - auto& pl = pipeline_slab_[*current_pipeline_]; + current_program_ = std::nullopt; - SRB2_ASSERT(uniform_set_slab_.is_valid(set)); - auto& us = uniform_set_slab_[set]; + render_pass_stack_.pop_back(); - auto& uniform_input = pl.desc.uniform_input; - SRB2_ASSERT(slot < uniform_input.enabled_uniforms.size()); - SRB2_ASSERT(us.uniforms.size() == uniform_input.enabled_uniforms[slot].size()); - - // Assert compatibility of uniform set with pipeline's set slot - for (size_t i = 0; i < us.uniforms.size(); i++) + if (!render_pass_stack_.empty()) { - SRB2_ASSERT( - rhi::uniform_format(uniform_input.enabled_uniforms[slot][i]) == rhi::uniform_variant_format(us.uniforms[i]) - ); - } - - // Apply uniforms - // TODO use Uniform Buffer Objects to optimize this. - // We don't really *need* to, though, probably... - // Also, we know that any given uniform name is uniquely present in a single uniform group asserted during pipeline - // compilation. This is an RHI requirement to support backends that don't have UBOs. - for (size_t i = 0; i < us.uniforms.size(); i++) - { - auto& uniform_name = uniform_input.enabled_uniforms[slot][i]; - auto& update_data = us.uniforms[i]; - SRB2_ASSERT(pl.uniform_locations.find(uniform_name) != pl.uniform_locations.end()); - GLuint pipeline_uniform = pl.uniform_locations[uniform_name]; - + RenderPassState& state = *render_pass_stack_.rbegin(); + // We must not clear the framebuffer when restoring a previous framebuffer, + // even if the clear was previously requested. auto visitor = srb2::Overload { - [&](const float& value) - { - gl_->Uniform1f(pipeline_uniform, value); - GL_ASSERT; - }, - [&](const glm::vec2& value) - { - gl_->Uniform2f(pipeline_uniform, value.x, value.y); - GL_ASSERT; - }, - [&](const glm::vec3& value) - { - gl_->Uniform3f(pipeline_uniform, value.x, value.y, value.z); - GL_ASSERT; - }, - [&](const glm::vec4& value) - { - gl_->Uniform4f(pipeline_uniform, value.x, value.y, value.z, value.w); - GL_ASSERT; - }, - [&](const int32_t& value) - { - gl_->Uniform1i(pipeline_uniform, value); - GL_ASSERT; - }, - [&](const glm::ivec2& value) - { - gl_->Uniform2i(pipeline_uniform, value.x, value.y); - GL_ASSERT; - }, - [&](const glm::ivec3& value) - { - gl_->Uniform3i(pipeline_uniform, value.x, value.y, value.z); - GL_ASSERT; - }, - [&](const glm::ivec4& value) - { - gl_->Uniform4i(pipeline_uniform, value.x, value.y, value.z, value.w); - GL_ASSERT; - }, - [&](const glm::mat2& value) - { - gl_->UniformMatrix2fv(pipeline_uniform, 1, false, glm::value_ptr(value)); - GL_ASSERT; - }, - [&](const glm::mat3& value) - { - gl_->UniformMatrix3fv(pipeline_uniform, 1, false, glm::value_ptr(value)); - GL_ASSERT; - }, - [&](const glm::mat4& value) - { - gl_->UniformMatrix4fv(pipeline_uniform, 1, false, glm::value_ptr(value)); - GL_ASSERT; + [this](const DefaultRenderPassState& s) { + apply_default_framebuffer(false); }, + [this](const RenderPassBeginInfo& info) { + apply_framebuffer(info, false); + } }; - std::visit(visitor, update_data); + std::visit(visitor, state); } } -void Gl2Rhi::bind_binding_set(Handle ctx, Handle set) +void Gl2Rhi::bind_program(Handle program) { - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + SRB2_ASSERT(render_pass_stack_.empty() == false); + Gl2Program& prog = program_slab_[program]; - SRB2_ASSERT(pipeline_slab_.is_valid(*current_pipeline_)); - auto& pl = pipeline_slab_[*current_pipeline_]; - - SRB2_ASSERT(binding_set_slab_.is_valid(set)); - auto& bs = binding_set_slab_[set]; - - SRB2_ASSERT(bs.textures.size() == pl.desc.sampler_input.enabled_samplers.size()); - - // TODO only disable the vertex attributes of the previously bound pipeline (performance) - for (GLuint i = 0; i < kMaxVertexAttributes; i++) + gl_->UseProgram(prog.program); + current_program_ = program; + GLint max_attribs; + gl_->GetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_attribs); + GL_ASSERT; + for (GLint i = 0; i < max_attribs; i++) { gl_->DisableVertexAttribArray(i); - } - - // Update the vertex attributes with the new vertex buffer bindings. - - // OpenGL 2 does not require binding buffers to the pipeline the same way Vulkan does. - // Instead, we need to find the pipeline vertex attributes which would be affected by - // the changing set of vertex buffers, and reassign their Vertex Attribute Pointers. - for (size_t i = 0; i < pl.desc.vertex_input.attr_layouts.size(); i++) - { - auto& attr_layout = pl.desc.vertex_input.attr_layouts[i]; - uint32_t attr_buffer_index = attr_layout.buffer_index; - VertexAttributeName attr_name = attr_layout.name; - - auto& buffer_layout = pl.desc.vertex_input.buffer_layouts[attr_buffer_index]; - - SRB2_ASSERT(pl.attrib_locations.find(attr_name) != pl.attrib_locations.end()); - auto gl_attr_location = pl.attrib_locations[pl.desc.vertex_input.attr_layouts[i].name]; - - VertexAttributeFormat vert_attr_format = rhi::vertex_attribute_format(attr_name); - GLenum vertex_attr_type = map_vertex_attribute_type(vert_attr_format); - SRB2_ASSERT(vertex_attr_type != GL_ZERO); - GLint vertex_attr_size = map_vertex_attribute_format_size(vert_attr_format); - SRB2_ASSERT(vertex_attr_size != 0); - - uint32_t vertex_buffer_offset = 0; - auto& vertex_binding = bs.vertex_buffer_bindings[attr_layout.buffer_index]; - rhi::Handle vertex_buffer_handle = vertex_binding.vertex_buffer; - SRB2_ASSERT(buffer_slab_.is_valid(vertex_binding.vertex_buffer) == true); - auto& buffer = *static_cast(&buffer_slab_[vertex_buffer_handle]); - SRB2_ASSERT(buffer.desc.type == rhi::BufferType::kVertexBuffer); - - gl_->BindBuffer(GL_ARRAY_BUFFER, buffer.buffer); - gl_->EnableVertexAttribArray(gl_attr_location); - gl_->VertexAttribPointer( - gl_attr_location, - vertex_attr_size, - vertex_attr_type, - GL_FALSE, - buffer_layout.stride, - reinterpret_cast(vertex_buffer_offset + attr_layout.offset) - ); - } - - gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - // Bind the samplers to the uniforms - for (auto& texture_binding : bs.textures) - { - auto sampler_name = texture_binding.first; - GLuint texture_gl_name = texture_binding.second; - GLuint sampler_uniform_loc = pl.sampler_locations[sampler_name]; - GLenum active_texture = GL_TEXTURE0; - GLuint uniform_value = 0; - switch (sampler_name) - { - case rhi::SamplerName::kSampler0: - active_texture = GL_TEXTURE0; - uniform_value = 0; - break; - case rhi::SamplerName::kSampler1: - active_texture = GL_TEXTURE0 + 1; - uniform_value = 1; - break; - case rhi::SamplerName::kSampler2: - active_texture = GL_TEXTURE0 + 2; - uniform_value = 2; - break; - case rhi::SamplerName::kSampler3: - active_texture = GL_TEXTURE0 + 3; - uniform_value = 3; - break; - } - gl_->ActiveTexture(active_texture); - GL_ASSERT; - gl_->BindTexture(GL_TEXTURE_2D, texture_gl_name); - GL_ASSERT; - gl_->Uniform1i(sampler_uniform_loc, uniform_value); GL_ASSERT; } } -void Gl2Rhi::bind_index_buffer(Handle ctx, Handle buffer) +void Gl2Rhi::bind_vertex_attrib(const char* name, Handle buffer, VertexAttributeFormat format, uint32_t offset, uint32_t stride) { - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + SRB2_ASSERT(current_program_.has_value()); + SRB2_ASSERT(buffer_slab_.is_valid(buffer)); + + GLenum vertex_attr_type = map_vertex_attribute_type(format); + SRB2_ASSERT(vertex_attr_type != GL_ZERO); + GLint vertex_attr_size = map_vertex_attribute_format_size(format); + SRB2_ASSERT(vertex_attr_size != 0); + + Gl2Program& prog = program_slab_[*current_program_]; + Gl2Buffer& cast_buffer = buffer_slab_[buffer]; + + SRB2_ASSERT(cast_buffer.desc.type == rhi::BufferType::kVertexBuffer); + + GLint location = gl_->GetAttribLocation(prog.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + gl_->BindBuffer(GL_ARRAY_BUFFER, cast_buffer.buffer); + GL_ASSERT; + gl_->EnableVertexAttribArray(location); + GL_ASSERT; + gl_->VertexAttribPointer( + location, + vertex_attr_size, + vertex_attr_type, + GL_FALSE, + stride, + reinterpret_cast(offset) + ); + GL_ASSERT; +} + +void Gl2Rhi::bind_index_buffer(Handle buffer) +{ + SRB2_ASSERT(current_program_.has_value()); SRB2_ASSERT(buffer_slab_.is_valid(buffer)); auto& ib = buffer_slab_[buffer]; @@ -1698,39 +1171,287 @@ void Gl2Rhi::bind_index_buffer(Handle ctx, Handle buffe current_index_buffer_ = buffer; gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.buffer); + GL_ASSERT; } -void Gl2Rhi::set_scissor(Handle ctx, const Rect& rect) +void Gl2Rhi::set_uniform(const char* name, float value) { - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); - - gl_->Enable(GL_SCISSOR_TEST); - gl_->Scissor(rect.x, rect.y, rect.w, rect.h); + SRB2_ASSERT(current_program_.has_value()); + Gl2Program& cast = program_slab_[*current_program_]; + GLint location = gl_->GetUniformLocation(cast.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + gl_->Uniform1f(location, value); + GL_ASSERT; } -void Gl2Rhi::set_viewport(Handle ctx, const Rect& rect) +void Gl2Rhi::set_uniform(const char* name, int value) { - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + SRB2_ASSERT(current_program_.has_value()); + Gl2Program& cast = program_slab_[*current_program_]; + GLint location = gl_->GetUniformLocation(cast.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + gl_->Uniform1i(location, value); + GL_ASSERT; +} + +void Gl2Rhi::set_uniform(const char* name, glm::vec2 value) +{ + SRB2_ASSERT(current_program_.has_value()); + Gl2Program& cast = program_slab_[*current_program_]; + GLint location = gl_->GetUniformLocation(cast.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + gl_->Uniform2f(location, value.x, value.y); + GL_ASSERT; +} + +void Gl2Rhi::set_uniform(const char* name, glm::vec3 value) +{ + SRB2_ASSERT(current_program_.has_value()); + Gl2Program& cast = program_slab_[*current_program_]; + GLint location = gl_->GetUniformLocation(cast.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + gl_->Uniform3f(location, value.x, value.y, value.z); + GL_ASSERT; +} + +void Gl2Rhi::set_uniform(const char* name, glm::vec4 value) +{ + SRB2_ASSERT(current_program_.has_value()); + Gl2Program& cast = program_slab_[*current_program_]; + GLint location = gl_->GetUniformLocation(cast.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + gl_->Uniform4f(location, value.x, value.y, value.z, value.w); + GL_ASSERT; +} + +void Gl2Rhi::set_uniform(const char* name, glm::ivec2 value) +{ + SRB2_ASSERT(current_program_.has_value()); + Gl2Program& cast = program_slab_[*current_program_]; + GLint location = gl_->GetUniformLocation(cast.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + gl_->Uniform2i(location, value.x, value.y); + GL_ASSERT; +} + +void Gl2Rhi::set_uniform(const char* name, glm::ivec3 value) +{ + SRB2_ASSERT(current_program_.has_value()); + Gl2Program& cast = program_slab_[*current_program_]; + GLint location = gl_->GetUniformLocation(cast.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + gl_->Uniform3i(location, value.x, value.y, value.z); + GL_ASSERT; +} + +void Gl2Rhi::set_uniform(const char* name, glm::ivec4 value) +{ + SRB2_ASSERT(current_program_.has_value()); + Gl2Program& cast = program_slab_[*current_program_]; + GLint location = gl_->GetUniformLocation(cast.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + gl_->Uniform4i(location, value.x, value.y, value.z, value.w); + GL_ASSERT; +} + +void Gl2Rhi::set_uniform(const char* name, glm::mat2 value) +{ + SRB2_ASSERT(current_program_.has_value()); + Gl2Program& cast = program_slab_[*current_program_]; + GLint location = gl_->GetUniformLocation(cast.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + gl_->UniformMatrix2fv(location, 1, false, glm::value_ptr(value)); + GL_ASSERT; +} + +void Gl2Rhi::set_uniform(const char* name, glm::mat3 value) +{ + SRB2_ASSERT(current_program_.has_value()); + Gl2Program& cast = program_slab_[*current_program_]; + GLint location = gl_->GetUniformLocation(cast.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + gl_->UniformMatrix3fv(location, 1, false, glm::value_ptr(value)); + GL_ASSERT; +} + +void Gl2Rhi::set_uniform(const char* name, glm::mat4 value) +{ + SRB2_ASSERT(current_program_.has_value()); + Gl2Program& cast = program_slab_[*current_program_]; + GLint location = gl_->GetUniformLocation(cast.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + gl_->UniformMatrix4fv(location, 1, false, glm::value_ptr(value)); + GL_ASSERT; +} + +void Gl2Rhi::set_sampler(const char* name, uint32_t slot, Handle texture) +{ + SRB2_ASSERT(slot >= 0 && slot < kMaxSamplers); + SRB2_ASSERT(current_program_.has_value() && render_pass_stack_.empty() == false); + + Gl2Program& prog = program_slab_[*current_program_]; + SRB2_ASSERT(texture_slab_.is_valid(texture)); + Gl2Texture& tex = texture_slab_[texture]; + GLint location = gl_->GetUniformLocation(prog.program, name); + GL_ASSERT; + SRB2_ASSERT(location >= 0); + GLenum active_texture = GL_TEXTURE0 + slot; + GLuint uniform_value = slot; + gl_->ActiveTexture(active_texture); + GL_ASSERT; + gl_->BindTexture(GL_TEXTURE_2D, tex.texture); + GL_ASSERT; + gl_->Uniform1i(location, uniform_value); + GL_ASSERT; + gl_->ActiveTexture(GL_TEXTURE0); + GL_ASSERT; +} + +void Gl2Rhi::set_rasterizer_state(const RasterizerStateDesc& desc) +{ + current_primitive_type_ = desc.primitive; + if (desc.cull == CullMode::kNone) + { + gl_->Disable(GL_CULL_FACE); + } + else + { + gl_->Enable(GL_CULL_FACE); + gl_->CullFace(map_cull_mode(desc.cull)); + } + gl_->ColorMask(desc.color_mask.r, desc.color_mask.g, desc.color_mask.b, desc.color_mask.a); + + GL_ASSERT; + gl_->FrontFace(map_winding(desc.winding)); + GL_ASSERT; + if (desc.blend_enabled) + { + gl_->Enable(GL_BLEND); + } + else + { + gl_->Disable(GL_BLEND); + } + GL_ASSERT; + gl_->BlendFuncSeparate( + map_blend_factor(desc.blend_source_factor_color), + map_blend_factor(desc.blend_dest_factor_color), + map_blend_factor(desc.blend_source_factor_alpha), + map_blend_factor(desc.blend_dest_factor_alpha) + ); + GL_ASSERT; + gl_->BlendEquationSeparate( + map_blend_function(desc.blend_color_function), + map_blend_function(desc.blend_alpha_function) + ); + GL_ASSERT; + gl_->BlendColor(desc.blend_color.r, desc.blend_color.g, desc.blend_color.b, desc.blend_color.a); + GL_ASSERT; + if (desc.depth_test) + { + gl_->Enable(GL_DEPTH_TEST); + } + else + { + gl_->Disable(GL_DEPTH_TEST); + } + GL_ASSERT; + gl_->DepthMask(desc.depth_write); + GL_ASSERT; + gl_->DepthFunc(map_compare_func(desc.depth_func)); + GL_ASSERT; + if (desc.stencil_test) + { + gl_->Enable(GL_STENCIL_TEST); + } + else + { + gl_->Disable(GL_STENCIL_TEST); + } + GL_ASSERT; + stencil_front_reference_ = 0; + stencil_back_reference_ = 0; + stencil_front_compare_mask_ = 0xFF; + stencil_back_compare_mask_ = 0xFF; + stencil_front_write_mask_ = 0xFF; + stencil_back_write_mask_ = 0xFF; + stencil_front_func_ = desc.front_stencil_compare; + stencil_back_func_ = desc.back_stencil_compare; + gl_->StencilFuncSeparate( + GL_FRONT, + map_compare_func(stencil_front_func_), + stencil_front_reference_, + stencil_front_compare_mask_ + ); + GL_ASSERT; + gl_->StencilFuncSeparate( + GL_BACK, + map_compare_func(stencil_back_func_), + stencil_back_reference_, + stencil_back_compare_mask_ + ); + GL_ASSERT; + gl_->StencilMaskSeparate(GL_FRONT, stencil_front_write_mask_); + GL_ASSERT; + gl_->StencilMaskSeparate(GL_BACK, stencil_back_write_mask_); + GL_ASSERT; + + gl_->StencilOpSeparate( + GL_FRONT, + map_stencil_op(desc.front_fail), + map_stencil_op(desc.front_depth_fail), + map_stencil_op(desc.front_pass) + ); + GL_ASSERT; + gl_->StencilOpSeparate( + GL_BACK, + map_stencil_op(desc.back_fail), + map_stencil_op(desc.back_depth_fail), + map_stencil_op(desc.back_pass) + ); + GL_ASSERT; + if (desc.scissor_test) + { + gl_->Enable(GL_SCISSOR_TEST); + GL_ASSERT; + } + else + { + gl_->Disable(GL_SCISSOR_TEST); + } + gl_->Scissor(desc.scissor.x, desc.scissor.y, desc.scissor.w, desc.scissor.h); + GL_ASSERT; +} + +void Gl2Rhi::set_viewport(const Rect& rect) +{ + SRB2_ASSERT(render_pass_stack_.empty() == false); gl_->Viewport(rect.x, rect.y, rect.w, rect.h); GL_ASSERT; } -void Gl2Rhi::draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) +void Gl2Rhi::draw(uint32_t vertex_count, uint32_t first_vertex) { - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); + SRB2_ASSERT(render_pass_stack_.empty() == false); gl_->DrawArrays(map_primitive_mode(current_primitive_type_), first_vertex, vertex_count); GL_ASSERT; } -void Gl2Rhi::draw_indexed(Handle ctx, uint32_t index_count, uint32_t first_index) +void Gl2Rhi::draw_indexed(uint32_t index_count, uint32_t first_index) { - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_index_buffer_ != kNullHandle); #ifndef NDEBUG { @@ -1748,10 +1469,9 @@ void Gl2Rhi::draw_indexed(Handle ctx, uint32_t index_count, uin GL_ASSERT; } -void Gl2Rhi::read_pixels(Handle ctx, const Rect& rect, PixelFormat format, tcb::span out) +void Gl2Rhi::read_pixels(const Rect& rect, PixelFormat format, tcb::span out) { - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value()); + SRB2_ASSERT(render_pass_stack_.empty() == false); std::tuple gl_format = map_pixel_data_format(format); GLenum layout = std::get<0>(gl_format); @@ -1777,7 +1497,7 @@ void Gl2Rhi::read_pixels(Handle ctx, const Rect& rect, PixelFor src_dim = {0, 0, attach_tex.desc.width, attach_tex.desc.height}; } }; - std::visit(render_pass_visitor, *current_render_pass_); + std::visit(render_pass_visitor, *render_pass_stack_.rbegin()); SRB2_ASSERT(rect.x >= 0); SRB2_ASSERT(rect.y >= 0); @@ -1792,21 +1512,17 @@ void Gl2Rhi::read_pixels(Handle ctx, const Rect& rect, PixelFor GL_ASSERT; } -void Gl2Rhi::set_stencil_reference(Handle ctx, CullMode face, uint8_t reference) +void Gl2Rhi::set_stencil_reference(CullMode face, uint8_t reference) { SRB2_ASSERT(face != CullMode::kNone); - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value()); - SRB2_ASSERT(current_pipeline_.has_value()); - - auto& pl = pipeline_slab_[*current_pipeline_]; + SRB2_ASSERT(render_pass_stack_.empty() == false); if (face == CullMode::kFront) { stencil_front_reference_ = reference; gl_->StencilFuncSeparate( GL_FRONT, - map_compare_func(pl.desc.depth_stencil_state->front.stencil_compare), + map_compare_func(stencil_front_func_), stencil_front_reference_, stencil_front_compare_mask_ ); @@ -1816,28 +1532,24 @@ void Gl2Rhi::set_stencil_reference(Handle ctx, CullMode face, u stencil_back_reference_ = reference; gl_->StencilFuncSeparate( GL_BACK, - map_compare_func(pl.desc.depth_stencil_state->back.stencil_compare), + map_compare_func(stencil_back_func_), stencil_back_reference_, stencil_back_compare_mask_ ); } } -void Gl2Rhi::set_stencil_compare_mask(Handle ctx, CullMode face, uint8_t compare_mask) +void Gl2Rhi::set_stencil_compare_mask(CullMode face, uint8_t compare_mask) { SRB2_ASSERT(face != CullMode::kNone); - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value()); - SRB2_ASSERT(current_pipeline_.has_value()); - - auto& pl = pipeline_slab_[*current_pipeline_]; + SRB2_ASSERT(render_pass_stack_.empty() == false); if (face == CullMode::kFront) { stencil_front_compare_mask_ = compare_mask; gl_->StencilFuncSeparate( GL_FRONT, - map_compare_func(pl.desc.depth_stencil_state->front.stencil_compare), + map_compare_func(stencil_front_func_), stencil_front_reference_, stencil_front_compare_mask_ ); @@ -1847,19 +1559,17 @@ void Gl2Rhi::set_stencil_compare_mask(Handle ctx, CullMode face stencil_back_compare_mask_ = compare_mask; gl_->StencilFuncSeparate( GL_BACK, - map_compare_func(pl.desc.depth_stencil_state->back.stencil_compare), + map_compare_func(stencil_back_func_), stencil_back_reference_, stencil_back_compare_mask_ ); } } -void Gl2Rhi::set_stencil_write_mask(Handle ctx, CullMode face, uint8_t write_mask) +void Gl2Rhi::set_stencil_write_mask(CullMode face, uint8_t write_mask) { SRB2_ASSERT(face != CullMode::kNone); - SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - SRB2_ASSERT(current_render_pass_.has_value()); - SRB2_ASSERT(current_pipeline_.has_value()); + SRB2_ASSERT(render_pass_stack_.empty() == false); if (face == CullMode::kFront) { @@ -1910,11 +1620,6 @@ uint32_t Gl2Rhi::get_buffer_size(Handle buffer) void Gl2Rhi::finish() { - SRB2_ASSERT(graphics_context_active_ == false); - - binding_set_slab_.clear(); - uniform_set_slab_.clear(); - // I sure hope creating FBOs isn't costly on the driver! for (auto& fbset : framebuffers_) { @@ -1925,14 +1630,12 @@ void Gl2Rhi::finish() } void Gl2Rhi::copy_framebuffer_to_texture( - Handle ctx, Handle dst_tex, const Rect& dst_region, const Rect& src_region ) { - SRB2_ASSERT(graphics_context_active_ == true); - SRB2_ASSERT(current_render_pass_.has_value()); + SRB2_ASSERT(render_pass_stack_.empty() == false); SRB2_ASSERT(texture_slab_.is_valid(dst_tex)); auto& tex = texture_slab_[dst_tex]; @@ -1957,7 +1660,7 @@ void Gl2Rhi::copy_framebuffer_to_texture( src_dim = {0, 0, attach_tex.desc.width, attach_tex.desc.height}; } }; - std::visit(render_pass_visitor, *current_render_pass_); + std::visit(render_pass_visitor, *render_pass_stack_.rbegin()); SRB2_ASSERT(src_region.x >= 0); SRB2_ASSERT(src_region.y >= 0); diff --git a/src/rhi/gl2/gl2_rhi.hpp b/src/rhi/gl2/gl2_rhi.hpp index 93f04446e..0863ed311 100644 --- a/src/rhi/gl2/gl2_rhi.hpp +++ b/src/rhi/gl2/gl2_rhi.hpp @@ -71,7 +71,7 @@ struct Gl2Platform virtual ~Gl2Platform(); virtual void present() = 0; - virtual std::tuple, std::vector> find_shader_sources(PipelineProgram program) = 0; + virtual std::tuple, std::vector> find_shader_sources(const char* name) = 0; virtual Rect get_default_framebuffer_dimensions() = 0; }; @@ -87,41 +87,19 @@ struct Gl2Buffer : public rhi::Buffer rhi::BufferDesc desc; }; -struct Gl2RenderPass : public rhi::RenderPass -{ - rhi::RenderPassDesc desc; -}; - struct Gl2Renderbuffer : public rhi::Renderbuffer { uint32_t renderbuffer; rhi::RenderbufferDesc desc; }; -struct Gl2UniformSet : public rhi::UniformSet -{ - std::vector uniforms; -}; - -struct Gl2BindingSet : public rhi::BindingSet -{ - std::vector vertex_buffer_bindings; - std::unordered_map textures {4}; -}; - -struct Gl2Pipeline : public rhi::Pipeline +struct Gl2Program : public rhi::Program { uint32_t vertex_shader = 0; uint32_t fragment_shader = 0; uint32_t program = 0; - std::unordered_map attrib_locations {2}; - std::unordered_map uniform_locations {2}; - std::unordered_map sampler_locations {2}; - rhi::PipelineDesc desc; -}; - -struct Gl2GraphicsContext : public rhi::GraphicsContext -{ + std::unordered_map attrib_locations; + std::unordered_map uniform_locations; }; struct Gl2ActiveUniform @@ -136,13 +114,10 @@ class Gl2Rhi final : public Rhi std::unique_ptr gl_; - Slab render_pass_slab_; Slab texture_slab_; Slab buffer_slab_; Slab renderbuffer_slab_; - Slab pipeline_slab_; - Slab uniform_set_slab_; - Slab binding_set_slab_; + Slab program_slab_; Handle current_index_buffer_; @@ -150,13 +125,12 @@ class Gl2Rhi final : public Rhi struct DefaultRenderPassState { + bool clear = false; }; using RenderPassState = std::variant; - std::optional current_render_pass_; - std::optional> current_pipeline_; + std::vector render_pass_stack_; + std::optional> current_program_; PrimitiveType current_primitive_type_ = PrimitiveType::kPoints; - bool graphics_context_active_ = false; - uint32_t graphics_context_generation_ = 1; uint32_t index_buffer_offset_ = 0; uint8_t stencil_front_reference_ = 0; @@ -165,15 +139,18 @@ class Gl2Rhi final : public Rhi uint8_t stencil_back_reference_ = 0; uint8_t stencil_back_compare_mask_ = 0xFF; uint8_t stencil_back_write_mask_ = 0xFF; + CompareFunc stencil_front_func_; + CompareFunc stencil_back_func_; + + void apply_default_framebuffer(bool clear); + void apply_framebuffer(const RenderPassBeginInfo& info, bool allow_clear); public: Gl2Rhi(std::unique_ptr&& platform, GlLoadFunc load_func); virtual ~Gl2Rhi(); - virtual Handle create_render_pass(const RenderPassDesc& desc) override; - virtual void destroy_render_pass(Handle handle) override; - virtual Handle create_pipeline(const PipelineDesc& desc) override; - virtual void destroy_pipeline(Handle handle) override; + virtual Handle create_program(const ProgramDesc& desc) override; + virtual void destroy_program(Handle handle) override; virtual Handle create_texture(const TextureDesc& desc) override; virtual void destroy_texture(Handle handle) override; @@ -187,58 +164,63 @@ public: virtual uint32_t get_buffer_size(Handle buffer) override; virtual void update_buffer( - Handle ctx, Handle buffer, uint32_t offset, tcb::span data ) override; virtual void update_texture( - Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data ) override; virtual void update_texture_settings( - Handle ctx, Handle texture, TextureWrapMode u_wrap, TextureWrapMode v_wrap, TextureFilterMode min, TextureFilterMode mag ) override; - virtual Handle - create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) override; - virtual Handle - create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) - override; - - virtual Handle begin_graphics() override; - virtual void end_graphics(Handle ctx) override; // Graphics context functions - virtual void begin_default_render_pass(Handle ctx, bool clear) override; - virtual void begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) override; - virtual void end_render_pass(Handle ctx) override; - virtual void bind_pipeline(Handle ctx, Handle pipeline) override; - virtual void bind_uniform_set(Handle ctx, uint32_t slot, Handle set) override; - virtual void bind_binding_set(Handle ctx, Handle set) override; - virtual void bind_index_buffer(Handle ctx, Handle buffer) override; - virtual void set_scissor(Handle ctx, const Rect& rect) override; - virtual void set_viewport(Handle ctx, const Rect& rect) override; - virtual void draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) override; - virtual void draw_indexed(Handle ctx, uint32_t index_count, uint32_t first_index) override; + virtual void push_default_render_pass(bool clear) override; + virtual void push_render_pass(const RenderPassBeginInfo& info) override; + virtual void pop_render_pass() override; + virtual void bind_program(Handle program) override; + virtual void bind_vertex_attrib( + const char* name, + Handle buffer, + VertexAttributeFormat format, + uint32_t offset, + uint32_t stride + ) override; + virtual void bind_index_buffer(Handle buffer) override; + virtual void set_uniform(const char* name, float value) override; + virtual void set_uniform(const char* name, int value) override; + virtual void set_uniform(const char* name, glm::vec2 value) override; + virtual void set_uniform(const char* name, glm::vec3 value) override; + virtual void set_uniform(const char* name, glm::vec4 value) override; + virtual void set_uniform(const char* name, glm::ivec2 value) override; + virtual void set_uniform(const char* name, glm::ivec3 value) override; + virtual void set_uniform(const char* name, glm::ivec4 value) override; + virtual void set_uniform(const char* name, glm::mat2 value) override; + virtual void set_uniform(const char* name, glm::mat3 value) override; + virtual void set_uniform(const char* name, glm::mat4 value) override; + virtual void set_sampler(const char* name, uint32_t slot, Handle texture) override; + virtual void set_rasterizer_state(const RasterizerStateDesc& desc) override; + virtual void set_viewport(const Rect& rect) override; + virtual void draw(uint32_t vertex_count, uint32_t first_vertex) override; + virtual void draw_indexed(uint32_t index_count, uint32_t first_index) override; virtual void - read_pixels(Handle ctx, const Rect& rect, PixelFormat format, tcb::span out) override; + read_pixels(const Rect& rect, PixelFormat format, tcb::span out) override; virtual void copy_framebuffer_to_texture( - Handle ctx, Handle dst_tex, const Rect& dst_region, const Rect& src_region ) override; - virtual void set_stencil_reference(Handle ctx, CullMode face, uint8_t reference) override; - virtual void set_stencil_compare_mask(Handle ctx, CullMode face, uint8_t mask) override; - virtual void set_stencil_write_mask(Handle ctx, CullMode face, uint8_t mask) override; + virtual void set_stencil_reference(CullMode face, uint8_t reference) override; + virtual void set_stencil_compare_mask(CullMode face, uint8_t mask) override; + virtual void set_stencil_write_mask(CullMode face, uint8_t mask) override; virtual void present() override; diff --git a/src/rhi/gles2/gles2_rhi.cpp b/src/rhi/gles2/gles2_rhi.cpp index 3bdfff0f5..0faf3b5d6 100644 --- a/src/rhi/gles2/gles2_rhi.cpp +++ b/src/rhi/gles2/gles2_rhi.cpp @@ -923,7 +923,7 @@ void Gles2Rhi::present() platform_->present(); } -void Gles2Rhi::begin_default_render_pass(Handle ctx) +void Gles2Rhi::push_default_render_pass(Handle ctx) { SRB2_ASSERT(platform_ != nullptr); SRB2_ASSERT(graphics_context_active_ == true); @@ -942,7 +942,7 @@ void Gles2Rhi::begin_default_render_pass(Handle ctx) current_render_pass_ = Gles2Rhi::DefaultRenderPassState {}; } -void Gles2Rhi::begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) +void Gles2Rhi::push_render_pass(Handle ctx, const RenderPassBeginInfo& info) { SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == false); @@ -981,7 +981,7 @@ void Gles2Rhi::begin_render_pass(Handle ctx, const RenderPassBe current_render_pass_ = info; } -void Gles2Rhi::end_render_pass(Handle ctx) +void Gles2Rhi::pop_render_pass(Handle ctx) { SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true); diff --git a/src/rhi/gles2/gles2_rhi.hpp b/src/rhi/gles2/gles2_rhi.hpp index d9e7a63cb..7c3829e1e 100644 --- a/src/rhi/gles2/gles2_rhi.hpp +++ b/src/rhi/gles2/gles2_rhi.hpp @@ -133,9 +133,9 @@ public: virtual void end_graphics(Handle&& ctx) override; // Graphics context functions - virtual void begin_default_render_pass(Handle ctx) override; - virtual void begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) override; - virtual void end_render_pass(Handle ctx) override; + virtual void push_default_render_pass(Handle ctx) override; + virtual void push_render_pass(Handle ctx, const RenderPassBeginInfo& info) override; + virtual void pop_render_pass(Handle ctx) override; virtual void bind_pipeline(Handle ctx, Handle pipeline) override; virtual void update_bindings(Handle ctx, const UpdateBindingsInfo& info) override; virtual void update_uniforms(Handle ctx, tcb::span uniforms) override; diff --git a/src/rhi/rhi.hpp b/src/rhi/rhi.hpp index 1a6f68236..4f141574b 100644 --- a/src/rhi/rhi.hpp +++ b/src/rhi/rhi.hpp @@ -13,9 +13,7 @@ #include #include -#include #include -#include #include #include @@ -26,6 +24,7 @@ #include #include "../core/static_vec.hpp" +#include "glm/ext/vector_float2.hpp" #include "handle.hpp" namespace srb2::rhi @@ -40,11 +39,8 @@ struct Texture { }; -struct Pipeline -{ -}; - -struct RenderPass +/// @brief A linked rendering pipeline program combining a vertex shader and fragment shader. +struct Program { }; @@ -403,16 +399,6 @@ struct ColorMask bool a; }; -struct BlendDesc -{ - BlendFactor source_factor_color; - BlendFactor dest_factor_color; - BlendFunction color_function; - BlendFactor source_factor_alpha; - BlendFactor dest_factor_alpha; - BlendFunction alpha_function; -}; - enum class StencilOp { kKeep, @@ -425,53 +411,41 @@ enum class StencilOp kDecrementWrap }; -struct PipelineStencilOpStateDesc + +struct ProgramDesc { - StencilOp fail; - StencilOp pass; - StencilOp depth_fail; - CompareFunc stencil_compare; + const char* name; + tcb::span defines; }; -struct PipelineDepthStencilStateDesc +struct RasterizerStateDesc { - bool depth_test; - bool depth_write; - CompareFunc depth_func; - bool stencil_test; - PipelineStencilOpStateDesc front; - PipelineStencilOpStateDesc back; -}; - -struct PipelineColorStateDesc -{ - std::optional blend; - ColorMask color_mask; -}; - -struct PipelineDesc -{ - PipelineProgram program; - VertexInputDesc vertex_input; - UniformInputDesc uniform_input; - SamplerInputDesc sampler_input; - std::optional depth_stencil_state; - PipelineColorStateDesc color_state; - PrimitiveType primitive; - CullMode cull; - FaceWinding winding; - glm::vec4 blend_color; -}; - -struct RenderPassDesc -{ - bool use_depth_stencil; - AttachmentLoadOp color_load_op; - AttachmentStoreOp color_store_op; - AttachmentLoadOp depth_load_op; - AttachmentStoreOp depth_store_op; - AttachmentLoadOp stencil_load_op; - AttachmentStoreOp stencil_store_op; + PrimitiveType primitive = PrimitiveType::kTriangles; + CullMode cull = CullMode::kBack; + FaceWinding winding = FaceWinding::kCounterClockwise; + ColorMask color_mask = {true, true, true, true}; + bool blend_enabled = false; + glm::vec4 blend_color = {0.0, 0.0, 0.0, 0.0}; + BlendFactor blend_source_factor_color = BlendFactor::kOne; + BlendFactor blend_dest_factor_color = BlendFactor::kZero; + BlendFunction blend_color_function = BlendFunction::kAdd; + BlendFactor blend_source_factor_alpha = BlendFactor::kOne; + BlendFactor blend_dest_factor_alpha = BlendFactor::kZero; + BlendFunction blend_alpha_function = BlendFunction::kAdd; + bool depth_test = false; + bool depth_write = true; + CompareFunc depth_func = CompareFunc::kLess; + bool stencil_test = false; + StencilOp front_fail = StencilOp::kKeep; + StencilOp front_pass = StencilOp::kKeep; + StencilOp front_depth_fail = StencilOp::kKeep; + CompareFunc front_stencil_compare = CompareFunc::kAlways; + StencilOp back_fail = StencilOp::kKeep; + StencilOp back_pass = StencilOp::kKeep; + StencilOp back_depth_fail = StencilOp::kKeep; + CompareFunc back_stencil_compare = CompareFunc::kAlways; + bool scissor_test = false; + Rect scissor = {}; }; struct RenderbufferDesc @@ -513,10 +487,15 @@ struct BufferDesc struct RenderPassBeginInfo { - Handle render_pass; Handle color_attachment; std::optional> depth_stencil_attachment; glm::vec4 clear_color; + AttachmentLoadOp color_load_op; + AttachmentStoreOp color_store_op; + AttachmentLoadOp depth_load_op; + AttachmentStoreOp depth_store_op; + AttachmentLoadOp stencil_load_op; + AttachmentStoreOp stencil_store_op; }; using UniformVariant = std::variant< @@ -577,17 +556,6 @@ struct CreateBindingSetInfo tcb::span sampler_textures; }; -struct UniformSet -{ -}; -struct BindingSet -{ -}; - -struct GraphicsContext -{ -}; - struct TextureDetails { uint32_t width; @@ -604,10 +572,8 @@ struct Rhi { virtual ~Rhi(); - virtual Handle create_render_pass(const RenderPassDesc& desc) = 0; - virtual void destroy_render_pass(Handle handle) = 0; - virtual Handle create_pipeline(const PipelineDesc& desc) = 0; - virtual void destroy_pipeline(Handle handle) = 0; + virtual Handle create_program(const ProgramDesc& desc) = 0; + virtual void destroy_program(Handle handle) = 0; virtual Handle create_texture(const TextureDesc& desc) = 0; virtual void destroy_texture(Handle handle) = 0; @@ -621,56 +587,63 @@ struct Rhi virtual uint32_t get_buffer_size(Handle buffer) = 0; virtual void update_buffer( - Handle ctx, Handle buffer, uint32_t offset, tcb::span data ) = 0; virtual void update_texture( - Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data ) = 0; virtual void update_texture_settings( - Handle ctx, Handle texture, TextureWrapMode u_wrap, TextureWrapMode v_wrap, TextureFilterMode min, TextureFilterMode mag ) = 0; - virtual Handle create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) = 0; - virtual Handle - create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) = 0; - - virtual Handle begin_graphics() = 0; - virtual void end_graphics(Handle ctx) = 0; // Graphics context functions - virtual void begin_default_render_pass(Handle ctx, bool clear) = 0; - virtual void begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) = 0; - virtual void end_render_pass(Handle ctx) = 0; - virtual void bind_pipeline(Handle ctx, Handle pipeline) = 0; - virtual void bind_uniform_set(Handle ctx, uint32_t slot, Handle set) = 0; - virtual void bind_binding_set(Handle ctx, Handle set) = 0; - virtual void bind_index_buffer(Handle ctx, Handle buffer) = 0; - virtual void set_scissor(Handle ctx, const Rect& rect) = 0; - virtual void set_viewport(Handle ctx, const Rect& rect) = 0; - virtual void draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) = 0; - virtual void draw_indexed(Handle ctx, uint32_t index_count, uint32_t first_index) = 0; + virtual void push_default_render_pass(bool clear) = 0; + virtual void push_render_pass(const RenderPassBeginInfo& info) = 0; + virtual void pop_render_pass() = 0; + virtual void bind_program(Handle program) = 0; + virtual void bind_vertex_attrib( + const char* name, + Handle buffer, + VertexAttributeFormat format, + uint32_t offset, + uint32_t stride + ) = 0; + virtual void bind_index_buffer(Handle buffer) = 0; + virtual void set_uniform(const char* name, float value) = 0; + virtual void set_uniform(const char* name, int value) = 0; + virtual void set_uniform(const char* name, glm::vec2 value) = 0; + virtual void set_uniform(const char* name, glm::vec3 value) = 0; + virtual void set_uniform(const char* name, glm::vec4 value) = 0; + virtual void set_uniform(const char* name, glm::ivec2 value) = 0; + virtual void set_uniform(const char* name, glm::ivec3 value) = 0; + virtual void set_uniform(const char* name, glm::ivec4 value) = 0; + virtual void set_uniform(const char* name, glm::mat2 value) = 0; + virtual void set_uniform(const char* name, glm::mat3 value) = 0; + virtual void set_uniform(const char* name, glm::mat4 value) = 0; + virtual void set_sampler(const char* name, uint32_t slot, Handle texture) = 0; + virtual void set_rasterizer_state(const RasterizerStateDesc& desc) = 0; + virtual void set_viewport(const Rect& rect) = 0; + virtual void draw(uint32_t vertex_count, uint32_t first_vertex) = 0; + virtual void draw_indexed(uint32_t index_count, uint32_t first_index) = 0; virtual void - read_pixels(Handle ctx, const Rect& rect, PixelFormat format, tcb::span out) = 0; + read_pixels(const Rect& rect, PixelFormat format, tcb::span out) = 0; virtual void copy_framebuffer_to_texture( - Handle ctx, Handle dst_tex, const Rect& dst_region, const Rect& src_region ) = 0; - virtual void set_stencil_reference(Handle ctx, CullMode face, uint8_t reference) = 0; - virtual void set_stencil_compare_mask(Handle ctx, CullMode face, uint8_t mask) = 0; - virtual void set_stencil_write_mask(Handle ctx, CullMode face, uint8_t mask) = 0; + virtual void set_stencil_reference(CullMode face, uint8_t reference) = 0; + virtual void set_stencil_compare_mask(CullMode face, uint8_t mask) = 0; + virtual void set_stencil_write_mask(CullMode face, uint8_t mask) = 0; virtual void present() = 0; diff --git a/src/sdl/i_video.cpp b/src/sdl/i_video.cpp index 6a2694938..3be4a69ab 100644 --- a/src/sdl/i_video.cpp +++ b/src/sdl/i_video.cpp @@ -12,6 +12,7 @@ /// \file /// \brief SRB2 graphics stuff for SDL +#include #include #include #include diff --git a/src/sdl/rhi_gl2_platform.cpp b/src/sdl/rhi_gl2_platform.cpp index ec35c7b97..4a9bd8ffc 100644 --- a/src/sdl/rhi_gl2_platform.cpp +++ b/src/sdl/rhi_gl2_platform.cpp @@ -34,35 +34,10 @@ void SdlGl2Platform::present() SDL_GL_SwapWindow(window); } -static constexpr const char* pipeline_lump_slug(rhi::PipelineProgram program) +static std::array glsllist_lump_names(const char* name) { - switch (program) - { - case rhi::PipelineProgram::kUnshaded: - return "unshaded"; - case rhi::PipelineProgram::kUnshadedPaletted: - return "unshadedpaletted"; - case rhi::PipelineProgram::kPostprocessWipe: - return "postprocesswipe"; - case rhi::PipelineProgram::kPostimg: - return "postimg"; - case rhi::PipelineProgram::kSharpBilinear: - return "sharpbilinear"; - case rhi::PipelineProgram::kCrt: - return "crt"; - case rhi::PipelineProgram::kCrtSharp: - return "crtsharp"; - default: - return ""; - } -} - -static std::array glsllist_lump_names(rhi::PipelineProgram program) -{ - const char* pipeline_slug = pipeline_lump_slug(program); - - std::string vertex_list_name = fmt::format("rhi_glsllist_{}_vertex", pipeline_slug); - std::string fragment_list_name = fmt::format("rhi_glsllist_{}_fragment", pipeline_slug); + std::string vertex_list_name = fmt::format("rhi_glsllist_{}_vertex", name); + std::string fragment_list_name = fmt::format("rhi_glsllist_{}_fragment", name); return {std::move(vertex_list_name), std::move(fragment_list_name)}; } @@ -132,9 +107,9 @@ static std::vector get_sources_from_glsllist_lump(const char* lumpn } std::tuple, std::vector> -SdlGl2Platform::find_shader_sources(rhi::PipelineProgram program) +SdlGl2Platform::find_shader_sources(const char* name) { - std::array glsllist_names = glsllist_lump_names(program); + std::array glsllist_names = glsllist_lump_names(name); std::vector vertex_sources = get_sources_from_glsllist_lump(glsllist_names[0].c_str()); std::vector fragment_sources = get_sources_from_glsllist_lump(glsllist_names[1].c_str()); diff --git a/src/sdl/rhi_gl2_platform.hpp b/src/sdl/rhi_gl2_platform.hpp index 93829dbf6..9daa71e7d 100644 --- a/src/sdl/rhi_gl2_platform.hpp +++ b/src/sdl/rhi_gl2_platform.hpp @@ -27,7 +27,7 @@ struct SdlGl2Platform final : public Gl2Platform virtual void present() override; virtual std::tuple, std::vector> - find_shader_sources(PipelineProgram program) override; + find_shader_sources(const char* name) override; virtual Rect get_default_framebuffer_dimensions() override; }; diff --git a/src/v_video.cpp b/src/v_video.cpp index 310171a41..05f6c4ed7 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -2986,7 +2986,7 @@ void V_DrawStringScaled( case gb_dpad: return {{1, 4, Draw::GenericButton::dpad}}; default: return {}; } - }(); + }(); } if (bt_inst) @@ -3766,11 +3766,10 @@ void VID_DisplaySoftwareScreen() // TODO implement // upload framebuffer, bind pipeline, draw rhi::Rhi* rhi = srb2::sys::get_rhi(srb2::sys::g_current_rhi); - rhi::Handle ctx = srb2::sys::main_graphics_context(); hwr2::HardwareState* hw_state = srb2::sys::main_hardware_state(); // Misnomer; this just uploads the screen to the software indexed screen texture - hw_state->software_screen_renderer->draw(*rhi, ctx); + hw_state->software_screen_renderer->draw(*rhi); const int screens = std::clamp(r_splitscreen + 1, 1, MAXSPLITSCREENPLAYERS); hw_state->blit_postimg_screens->set_num_screens(screens); @@ -3827,7 +3826,7 @@ void VID_DisplaySoftwareScreen() } // Post-process blit to the 'default' framebuffer - hw_state->blit_postimg_screens->draw(*rhi, ctx); + hw_state->blit_postimg_screens->draw(*rhi); } char *V_ParseText(const char *rawText)