mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'rhi-refactoring' into 'master'
RHI Refactors See merge request KartKrew/Kart!2486
This commit is contained in:
commit
37f70cb0a2
40 changed files with 1146 additions and 2120 deletions
|
|
@ -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<rhi::GraphicsContext> ctx, rhi::Handle<rhi::Texture>& tex)
|
||||
static void refresh_wipe_screen_texture(rhi::Rhi& rhi, rhi::Handle<rhi::Texture>& tex)
|
||||
{
|
||||
bool recreate = false;
|
||||
if (!tex)
|
||||
|
|
@ -371,24 +371,17 @@ void F_WipeStartScreen(void)
|
|||
return;
|
||||
}
|
||||
|
||||
rhi::Handle<rhi::GraphicsContext> 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<uint32_t>(vid.width), static_cast<uint32_t>(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<rhi::GraphicsContext> 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<uint32_t>(vid.width), static_cast<uint32_t>(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<rhi::GraphicsContext> 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<uint32_t>(vid.width), static_cast<uint32_t>(vid.height));
|
||||
hw_state->wipe->draw(*rhi, ctx);
|
||||
hw_state->wipe->draw(*rhi);
|
||||
}
|
||||
|
||||
I_OsPolling();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -10,11 +10,14 @@
|
|||
|
||||
#include "blit_postimg_screens.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <glm/mat3x3.hpp>
|
||||
#include <glm/mat4x4.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <tcb/span.hpp>
|
||||
|
||||
#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<GraphicsContext> 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<GraphicsContext> 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::mat4>(), glm::vec3(2.f, -2.f, 1.f));
|
||||
glm::mat4 modelview = glm::identity<glm::mat4>();
|
||||
|
|
@ -222,19 +107,95 @@ void BlitPostimgScreens::transfer(Rhi& rhi, Handle<GraphicsContext> 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<float>(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<float>(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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,14 +46,11 @@ public:
|
|||
private:
|
||||
struct ScreenData
|
||||
{
|
||||
rhi::Handle<rhi::Pipeline> pipeline;
|
||||
rhi::Handle<rhi::BindingSet> binding_set;
|
||||
rhi::Handle<rhi::UniformSet> uniform_set;
|
||||
rhi::Handle<rhi::Program> program;
|
||||
};
|
||||
|
||||
rhi::Handle<rhi::Pipeline> pipeline_;
|
||||
rhi::Handle<rhi::Pipeline> indexed_pipeline_;
|
||||
rhi::Handle<rhi::RenderPass> renderpass_;
|
||||
rhi::Handle<rhi::Program> program_;
|
||||
rhi::Handle<rhi::Program> indexed_program_;
|
||||
rhi::Handle<rhi::Buffer> quad_vbo_;
|
||||
rhi::Handle<rhi::Buffer> 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<rhi::GraphicsContext> ctx);
|
||||
void transfer(rhi::Rhi& rhi);
|
||||
|
||||
public:
|
||||
explicit BlitPostimgScreens(PaletteManager* palette_mgr);
|
||||
|
||||
void draw(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx);
|
||||
void draw(rhi::Rhi& rhi);
|
||||
|
||||
void set_num_screens(uint32_t screens) noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "blit_rect.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <tcb/span.hpp>
|
||||
|
|
@ -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<GraphicsContext> 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<GraphicsContext> 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<GraphicsContext> 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<GraphicsContext> ctx)
|
|||
|
||||
rhi::TextureDetails texture_details = rhi.get_texture_details(texture_);
|
||||
|
||||
std::array<rhi::UniformVariant, 1> g1_uniforms = {{
|
||||
// Projection
|
||||
glm::scale(
|
||||
glm::identity<glm::mat4>(),
|
||||
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::mat4>(),
|
||||
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::mat4>(),
|
||||
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<rhi::UniformVariant, 3> g2_uniforms = {
|
||||
// ModelView
|
||||
glm::scale(
|
||||
glm::identity<glm::mat4>(),
|
||||
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<rhi::VertexAttributeBufferBinding, 1> vbs = {{{0, quad_vbo_}}};
|
||||
std::array<rhi::TextureBinding, 2> 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<rhi::UniformVariant, 3> g2_uniforms = {
|
||||
// ModelView
|
||||
glm::scale(
|
||||
glm::identity<glm::mat4>(),
|
||||
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<rhi::VertexAttributeBufferBinding, 1> vbs = {{{0, quad_vbo_}}};
|
||||
std::array<rhi::TextureBinding, 2> 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<rhi::UniformVariant, 3> g2_uniforms = {
|
||||
// ModelView
|
||||
glm::scale(
|
||||
glm::identity<glm::mat4>(),
|
||||
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<rhi::VertexAttributeBufferBinding, 1> vbs = {{{0, quad_vbo_}}};
|
||||
std::array<rhi::TextureBinding, 1> tbs = {{{rhi::SamplerName::kSampler0, texture_}}};
|
||||
binding_set_ = rhi.create_binding_set(ctx, pipeline_, {vbs, tbs});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
std::array<rhi::UniformVariant, 2> g2_uniforms = {
|
||||
// ModelView
|
||||
glm::scale(
|
||||
glm::identity<glm::mat4>(),
|
||||
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<rhi::VertexAttributeBufferBinding, 1> vbs = {{{0, quad_vbo_}}};
|
||||
std::array<rhi::TextureBinding, 1> 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<GraphicsContext> 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
rhi::Handle<rhi::Pipeline> pipeline_;
|
||||
rhi::Handle<rhi::Program> program_;
|
||||
rhi::Handle<rhi::Texture> texture_;
|
||||
uint32_t texture_width_ = 0;
|
||||
uint32_t texture_height_ = 0;
|
||||
|
|
@ -42,8 +42,6 @@ private:
|
|||
bool output_flip_ = false;
|
||||
rhi::Handle<rhi::Buffer> quad_vbo_;
|
||||
rhi::Handle<rhi::Buffer> quad_ibo_;
|
||||
std::array<rhi::Handle<rhi::UniformSet>, 2> uniform_sets_;
|
||||
rhi::Handle<rhi::BindingSet> binding_set_;
|
||||
BlitMode blit_mode_;
|
||||
rhi::Handle<rhi::Texture> 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<rhi::GraphicsContext> ctx);
|
||||
void graphics(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> 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<rhi::GraphicsContext> 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
|
||||
|
|
|
|||
|
|
@ -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<BlitRectPass> crtsharp_blit_rect;
|
||||
std::unique_ptr<ScreenshotPass> screen_capture;
|
||||
std::unique_ptr<UpscaleBackbuffer> backbuffer;
|
||||
std::unique_ptr<ImguiRenderer> imgui_renderer;
|
||||
WipeFrames wipe_frames;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@
|
|||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "pass_imgui.hpp"
|
||||
#include "imgui_renderer.hpp"
|
||||
|
||||
#include <imgui.h>
|
||||
#include <tcb/span.hpp>
|
||||
|
||||
#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<GraphicsContext> 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<uint32_t>(width), static_cast<uint32_t>(height)},
|
||||
rhi::PixelFormat::kRGBA8,
|
||||
|
|
@ -162,74 +163,70 @@ void ImguiPass::transfer(Rhi& rhi, Handle<GraphicsContext> ctx)
|
|||
}
|
||||
|
||||
tcb::span<ImDrawVert> 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<ImDrawIdx> 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<UniformVariant, 1> 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<UniformVariant, 2> 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<UniformSet> us_1 = rhi.create_uniform_set(ctx, {g1_uniforms});
|
||||
Handle<UniformSet> 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<rhi::VertexAttributeBufferBinding, 1> vbos = {{{0, vbo}}};
|
||||
std::array<rhi::TextureBinding, 1> tbs = {{{rhi::SamplerName::kSampler0, draw_cmd.tex}}};
|
||||
rhi::Handle<rhi::BindingSet> 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<GraphicsContext> 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);
|
||||
|
|
@ -14,48 +14,41 @@
|
|||
#include <vector>
|
||||
|
||||
#include "../rhi/rhi.hpp"
|
||||
#include "pass.hpp"
|
||||
|
||||
namespace srb2::hwr2
|
||||
{
|
||||
|
||||
class ImguiPass final : public Pass
|
||||
class ImguiRenderer final
|
||||
{
|
||||
struct DrawCmd
|
||||
{
|
||||
rhi::Handle<rhi::Texture> tex;
|
||||
uint32_t v_offset;
|
||||
uint32_t elems;
|
||||
uint32_t i_offset;
|
||||
rhi::Rect clip;
|
||||
rhi::Handle<rhi::BindingSet> binding_set;
|
||||
rhi::Handle<rhi::Buffer> vbo;
|
||||
rhi::Handle<rhi::Buffer> ibo;
|
||||
rhi::Handle<rhi::Texture> tex;
|
||||
};
|
||||
struct DrawList
|
||||
{
|
||||
void* list;
|
||||
rhi::Handle<rhi::Buffer> vbo;
|
||||
rhi::Handle<rhi::Buffer> ibo;
|
||||
rhi::Handle<rhi::UniformSet> us_1;
|
||||
rhi::Handle<rhi::UniformSet> us_2;
|
||||
std::vector<DrawCmd> cmds;
|
||||
};
|
||||
|
||||
rhi::Handle<rhi::Pipeline> pipeline_;
|
||||
rhi::Handle<rhi::Program> program_;
|
||||
rhi::Handle<rhi::Texture> font_atlas_;
|
||||
rhi::Handle<rhi::Texture> default_tex_;
|
||||
|
||||
std::vector<DrawList> draw_lists_;
|
||||
|
||||
public:
|
||||
ImguiPass();
|
||||
virtual ~ImguiPass();
|
||||
ImguiRenderer();
|
||||
virtual ~ImguiRenderer();
|
||||
|
||||
virtual void prepass(rhi::Rhi& rhi) override;
|
||||
|
||||
virtual void transfer(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx) override;
|
||||
|
||||
virtual void graphics(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx) override;
|
||||
|
||||
virtual void postpass(rhi::Rhi& rhi) override;
|
||||
void render(rhi::Rhi& rhi);
|
||||
};
|
||||
|
||||
} // namespace srb2::hwr2
|
||||
|
|
@ -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;
|
||||
|
|
@ -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<rhi::GraphicsContext> ctx) = 0;
|
||||
|
||||
/// @brief Issue draw calls.
|
||||
/// @param rhi
|
||||
/// @param ctx
|
||||
virtual void graphics(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> 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__
|
||||
|
|
@ -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<void(PassManager&, rhi::Rhi&)> prepass_func_;
|
||||
std::function<void(PassManager&, rhi::Rhi&)> postpass_func_;
|
||||
|
||||
public:
|
||||
LambdaPass(PassManager* mgr, std::function<void(PassManager&, rhi::Rhi&)> prepass_func);
|
||||
LambdaPass(
|
||||
PassManager* mgr,
|
||||
std::function<void(PassManager&, rhi::Rhi&)> prepass_func,
|
||||
std::function<void(PassManager&, rhi::Rhi&)> postpass_func
|
||||
);
|
||||
virtual ~LambdaPass();
|
||||
|
||||
virtual void prepass(rhi::Rhi& rhi) override;
|
||||
virtual void transfer(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx) override;
|
||||
virtual void graphics(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx) override;
|
||||
virtual void postpass(rhi::Rhi& rhi) override;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
LambdaPass::LambdaPass(PassManager* mgr, std::function<void(PassManager&, rhi::Rhi&)> prepass_func)
|
||||
: mgr_(mgr), prepass_func_(prepass_func)
|
||||
{
|
||||
}
|
||||
|
||||
LambdaPass::LambdaPass(
|
||||
PassManager* mgr,
|
||||
std::function<void(PassManager&, rhi::Rhi&)> prepass_func,
|
||||
std::function<void(PassManager&, rhi::Rhi&)> 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<GraphicsContext>)
|
||||
{
|
||||
}
|
||||
|
||||
void LambdaPass::graphics(Rhi&, Handle<GraphicsContext>)
|
||||
{
|
||||
}
|
||||
|
||||
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> 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<void(PassManager&, Rhi&)> prepass_func)
|
||||
{
|
||||
insert(std::forward<const std::string>(name), std::make_shared<LambdaPass>(LambdaPass {this, prepass_func}));
|
||||
}
|
||||
|
||||
void PassManager::insert(
|
||||
const std::string& name,
|
||||
std::function<void(PassManager&, Rhi&)> prepass_func,
|
||||
std::function<void(PassManager&, Rhi&)> postpass_func
|
||||
)
|
||||
{
|
||||
insert(
|
||||
std::forward<const std::string>(name),
|
||||
std::make_shared<LambdaPass>(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<Pass> PassManager::for_name(const std::string& name)
|
||||
{
|
||||
auto itr = pass_by_name_.find(name);
|
||||
if (itr == pass_by_name_.end())
|
||||
{
|
||||
return std::weak_ptr<Pass>();
|
||||
}
|
||||
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<GraphicsContext> ctx)
|
||||
{
|
||||
for (auto& pass : passes_)
|
||||
{
|
||||
if (pass.enabled)
|
||||
{
|
||||
pass.pass->transfer(rhi, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PassManager::graphics(Rhi& rhi, Handle<GraphicsContext> 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<GraphicsContext> gc = rhi.begin_graphics();
|
||||
transfer(rhi, gc);
|
||||
graphics(rhi, gc);
|
||||
rhi.end_graphics(gc);
|
||||
|
||||
postpass(rhi);
|
||||
}
|
||||
|
|
@ -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 <cstddef>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "../rhi/rhi.hpp"
|
||||
#include "pass.hpp"
|
||||
|
||||
namespace srb2::hwr2
|
||||
{
|
||||
|
||||
class PassManager final : public Pass
|
||||
{
|
||||
struct PassManagerEntry
|
||||
{
|
||||
std::string name;
|
||||
std::shared_ptr<Pass> pass;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::size_t> pass_by_name_;
|
||||
std::vector<PassManagerEntry> 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<rhi::GraphicsContext> ctx) override;
|
||||
virtual void graphics(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx) override;
|
||||
virtual void postpass(rhi::Rhi& rhi) override;
|
||||
|
||||
void insert(const std::string& name, std::shared_ptr<Pass> pass);
|
||||
void insert(const std::string& name, std::function<void(PassManager&, rhi::Rhi&)> prepass_func);
|
||||
void insert(
|
||||
const std::string& name,
|
||||
std::function<void(PassManager&, rhi::Rhi&)> prepass_func,
|
||||
std::function<void(PassManager&, rhi::Rhi&)> postpass_func
|
||||
);
|
||||
std::weak_ptr<Pass> 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__
|
||||
|
|
@ -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<GraphicsContext> ctx)
|
||||
void FramebufferManager::transfer(Rhi& rhi)
|
||||
{
|
||||
}
|
||||
|
||||
void FramebufferManager::graphics(Rhi& rhi, Handle<GraphicsContext> ctx)
|
||||
void FramebufferManager::graphics(Rhi& rhi)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -161,28 +161,28 @@ void MainPaletteManager::prepass(Rhi& rhi)
|
|||
}
|
||||
}
|
||||
|
||||
void MainPaletteManager::upload_palette(Rhi& rhi, Handle<GraphicsContext> ctx)
|
||||
void MainPaletteManager::upload_palette(Rhi& rhi)
|
||||
{
|
||||
std::array<byteColor_t, kPaletteSize> 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<GraphicsContext> ctx)
|
||||
void MainPaletteManager::upload_lighttables(Rhi& rhi)
|
||||
{
|
||||
if (colormaps != nullptr)
|
||||
{
|
||||
tcb::span<const std::byte> 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<const std::byte> 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<GraphicsContext> ct
|
|||
Handle<Texture> lighttable_tex = find_extra_lighttable(lighttable);
|
||||
SRB2_ASSERT(lighttable_tex != kNullHandle);
|
||||
tcb::span<const std::byte> 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<GraphicsContext> ctx)
|
||||
void MainPaletteManager::upload_default_colormap(Rhi& rhi)
|
||||
{
|
||||
std::array<uint8_t, kPaletteSize> 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<GraphicsContext> 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<GraphicsContext> ctx)
|
|||
rhi::Handle<rhi::Texture> map_texture = colormaps_.at(to_upload);
|
||||
|
||||
tcb::span<const std::byte> 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<rhi::Texture> MainPaletteManager::find_extra_lighttable(srb2::NotNul
|
|||
return lighttables_.at(lighttable);
|
||||
}
|
||||
|
||||
void MainPaletteManager::transfer(Rhi& rhi, Handle<GraphicsContext> 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<GraphicsContext> ctx)
|
||||
void MainPaletteManager::graphics(Rhi& rhi)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -319,7 +319,7 @@ void CommonResourcesManager::prepass(Rhi& rhi)
|
|||
}
|
||||
}
|
||||
|
||||
void CommonResourcesManager::transfer(Rhi& rhi, Handle<GraphicsContext> ctx)
|
||||
void CommonResourcesManager::transfer(Rhi& rhi)
|
||||
{
|
||||
if (!init_)
|
||||
{
|
||||
|
|
@ -330,13 +330,13 @@ void CommonResourcesManager::transfer(Rhi& rhi, Handle<GraphicsContext> ctx)
|
|||
uint8_t transparent[4] = {0, 0, 0, 0};
|
||||
tcb::span<const std::byte> 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<GraphicsContext> ctx)
|
||||
void CommonResourcesManager::graphics(Rhi& rhi)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@
|
|||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "pass.hpp"
|
||||
#include "../rhi/rhi.hpp"
|
||||
|
||||
namespace srb2::hwr2
|
||||
{
|
||||
|
||||
class FramebufferManager final : public Pass
|
||||
class FramebufferManager final
|
||||
{
|
||||
rhi::Handle<rhi::Texture> main_color_;
|
||||
std::array<rhi::Handle<rhi::Texture>, 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<rhi::GraphicsContext> ctx) override;
|
||||
virtual void graphics(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> 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<rhi::Texture> palette_;
|
||||
rhi::Handle<rhi::Texture> lighttable_;
|
||||
|
|
@ -82,19 +82,19 @@ class MainPaletteManager final : public Pass
|
|||
std::vector<const uint8_t*> colormaps_to_upload_;
|
||||
std::vector<const uint8_t*> lighttables_to_upload_;
|
||||
|
||||
void upload_palette(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx);
|
||||
void upload_lighttables(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx);
|
||||
void upload_default_colormap(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx);
|
||||
void upload_colormaps(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> 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<rhi::GraphicsContext> ctx) override;
|
||||
virtual void graphics(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> 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<rhi::Texture> palette() const noexcept { return palette_; }
|
||||
rhi::Handle<rhi::Texture> lighttable() const noexcept { return lighttable_; }
|
||||
|
|
@ -107,7 +107,7 @@ public:
|
|||
rhi::Handle<rhi::Texture> find_extra_lighttable(srb2::NotNull<const uint8_t*> lighttable) const;
|
||||
};
|
||||
|
||||
class CommonResourcesManager final : public Pass
|
||||
class CommonResourcesManager final
|
||||
{
|
||||
bool init_ = false;
|
||||
rhi::Handle<rhi::Texture> black_;
|
||||
|
|
@ -118,10 +118,10 @@ public:
|
|||
CommonResourcesManager();
|
||||
virtual ~CommonResourcesManager();
|
||||
|
||||
virtual void prepass(rhi::Rhi& rhi) override;
|
||||
virtual void transfer(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx) override;
|
||||
virtual void graphics(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> 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<rhi::Texture> black() const noexcept { return black_; }
|
||||
rhi::Handle<rhi::Texture> white() const noexcept { return white_; }
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ static PatchAtlas create_atlas(Rhi& rhi, uint32_t size)
|
|||
return new_atlas;
|
||||
}
|
||||
|
||||
void PatchAtlasCache::pack(Rhi& rhi, Handle<GraphicsContext> ctx)
|
||||
void PatchAtlasCache::pack(Rhi& rhi)
|
||||
{
|
||||
// Prepare stbrp rects for patches to be loaded.
|
||||
std::vector<stbrp_rect> rects;
|
||||
|
|
@ -310,7 +310,6 @@ void PatchAtlasCache::pack(Rhi& rhi, Handle<GraphicsContext> ctx)
|
|||
convert_patch_to_trimmed_rg8_pixels(patch_to_upload, patch_data);
|
||||
|
||||
rhi.update_texture(
|
||||
ctx,
|
||||
atlas->tex_,
|
||||
{static_cast<int32_t>(entry->x), static_cast<int32_t>(entry->y), entry->w, entry->h},
|
||||
PixelFormat::kRG8,
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
#include <tcb/span.hpp>
|
||||
|
||||
#include "pass.hpp"
|
||||
#include "../r_defs.h"
|
||||
#include "../rhi/rhi.hpp"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
|
@ -113,7 +113,7 @@ public:
|
|||
void queue_patch(srb2::NotNull<const patch_t*> patch);
|
||||
|
||||
/// @brief Pack queued patches, allowing them to be looked up with find_patch.
|
||||
void pack(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> 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.
|
||||
|
|
|
|||
|
|
@ -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<GraphicsContext> 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<const char*>();
|
||||
program_ = rhi.create_program(desc);
|
||||
}
|
||||
|
||||
if (!vbo_)
|
||||
|
|
@ -169,7 +156,7 @@ void PostprocessWipePass::prepass(Rhi& rhi)
|
|||
});
|
||||
}
|
||||
|
||||
void PostprocessWipePass::transfer(Rhi& rhi, Handle<GraphicsContext> ctx)
|
||||
void PostprocessWipePass::transfer(Rhi& rhi)
|
||||
{
|
||||
if (wipe_tex_ == kNullHandle)
|
||||
{
|
||||
|
|
@ -183,47 +170,44 @@ void PostprocessWipePass::transfer(Rhi& rhi, Handle<GraphicsContext> 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<const std::byte> 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::mat4>(), glm::vec3(2.f, 2.f, 1.f)),
|
||||
static_cast<int32_t>(wipe_color_mode_),
|
||||
static_cast<int32_t>(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<GraphicsContext> 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::mat4>(), glm::vec3(2.f, 2.f, 1.f)));
|
||||
rhi.set_uniform("u_wipe_colorize_mode", static_cast<int32_t>(wipe_color_mode_));
|
||||
rhi.set_uniform("u_wipe_encore_swizzle", static_cast<int32_t>(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)
|
||||
|
|
|
|||
|
|
@ -21,13 +21,11 @@ namespace srb2::hwr2
|
|||
class PostprocessWipePass final
|
||||
{
|
||||
// Internal RHI resources
|
||||
rhi::Handle<rhi::Pipeline> pipeline_;
|
||||
rhi::Handle<rhi::Program> program_;
|
||||
rhi::Handle<rhi::Buffer> vbo_;
|
||||
bool upload_vbo_ = false;
|
||||
rhi::Handle<rhi::Buffer> ibo_;
|
||||
bool upload_ibo_ = false;
|
||||
rhi::Handle<rhi::UniformSet> us_;
|
||||
rhi::Handle<rhi::BindingSet> bs_;
|
||||
rhi::Handle<rhi::Texture> 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<rhi::GraphicsContext> ctx);
|
||||
void graphics(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> 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<rhi::GraphicsContext> ctx);
|
||||
void draw(rhi::Rhi& rhi);
|
||||
|
||||
void set_start(rhi::Handle<rhi::Texture> start) noexcept { start_ = start; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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<GraphicsContext> ctx)
|
||||
void PaletteManager::update(Rhi& rhi)
|
||||
{
|
||||
if (!palette_)
|
||||
{
|
||||
|
|
@ -57,7 +57,7 @@ void PaletteManager::update(Rhi& rhi, Handle<GraphicsContext> 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<GraphicsContext> ctx)
|
|||
if (colormaps != nullptr)
|
||||
{
|
||||
tcb::span<const std::byte> 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<GraphicsContext> ctx)
|
|||
if (encoremap != nullptr)
|
||||
{
|
||||
tcb::span<const std::byte> 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<GraphicsContext> 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<Texture> PaletteManager::find_or_create_colormap(Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx, srb2::NotNull<const uint8_t*> colormap)
|
||||
Handle<Texture> PaletteManager::find_or_create_colormap(Rhi& rhi, srb2::NotNull<const uint8_t*> colormap)
|
||||
{
|
||||
if (colormaps_.find(colormap) != colormaps_.end())
|
||||
{
|
||||
|
|
@ -117,13 +117,13 @@ Handle<Texture> PaletteManager::find_or_create_colormap(Rhi& rhi, rhi::Handle<rh
|
|||
Handle<Texture> texture = rhi.create_texture({TextureFormat::kLuminance, kPaletteSize, 1, TextureWrapMode::kClamp, TextureWrapMode::kClamp});
|
||||
|
||||
tcb::span<const std::byte> 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<Texture> PaletteManager::find_or_create_extra_lighttable(Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx, srb2::NotNull<const uint8_t*> lighttable)
|
||||
Handle<Texture> PaletteManager::find_or_create_extra_lighttable(Rhi& rhi, srb2::NotNull<const uint8_t*> lighttable)
|
||||
{
|
||||
if (lighttables_.find(lighttable) != lighttables_.end())
|
||||
{
|
||||
|
|
@ -133,7 +133,7 @@ Handle<Texture> PaletteManager::find_or_create_extra_lighttable(Rhi& rhi, rhi::H
|
|||
Handle<Texture> texture = rhi.create_texture({TextureFormat::kLuminance, kPaletteSize, kLighttableRows, TextureWrapMode::kClamp, TextureWrapMode::kClamp});
|
||||
|
||||
tcb::span<const std::byte> 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<Texture> FlatTextureManager::find_or_create_indexed(Rhi& rhi, Handle<GraphicsContext> ctx, lumpnum_t lump)
|
||||
Handle<Texture> FlatTextureManager::find_or_create_indexed(Rhi& rhi, lumpnum_t lump)
|
||||
{
|
||||
SRB2_ASSERT(lump != LUMPERROR);
|
||||
|
||||
|
|
@ -206,7 +206,7 @@ Handle<Texture> FlatTextureManager::find_or_create_indexed(Rhi& rhi, Handle<Grap
|
|||
}
|
||||
|
||||
tcb::span<const std::byte> 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,11 +45,11 @@ public:
|
|||
#endif
|
||||
rhi::Handle<rhi::Texture> default_colormap() const noexcept { return default_colormap_; }
|
||||
|
||||
void update(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx);
|
||||
void update(rhi::Rhi& rhi);
|
||||
void destroy_per_frame_resources(rhi::Rhi& rhi);
|
||||
|
||||
rhi::Handle<rhi::Texture> find_or_create_colormap(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx, srb2::NotNull<const uint8_t*> colormap);
|
||||
rhi::Handle<rhi::Texture> find_or_create_extra_lighttable(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx, srb2::NotNull<const uint8_t*> lighttable);
|
||||
rhi::Handle<rhi::Texture> find_or_create_colormap(rhi::Rhi& rhi, srb2::NotNull<const uint8_t*> colormap);
|
||||
rhi::Handle<rhi::Texture> find_or_create_extra_lighttable(rhi::Rhi& rhi, srb2::NotNull<const uint8_t*> lighttable);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -79,7 +79,7 @@ public:
|
|||
/// in prepass.
|
||||
/// @param flat_lump
|
||||
/// @return
|
||||
rhi::Handle<rhi::Texture> find_or_create_indexed(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx, lumpnum_t flat_lump);
|
||||
rhi::Handle<rhi::Texture> find_or_create_indexed(rhi::Rhi& rhi, lumpnum_t flat_lump);
|
||||
};
|
||||
|
||||
} // namespace srb2::hwr2
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ using namespace srb2::rhi;
|
|||
ScreenshotPass::ScreenshotPass() = default;
|
||||
ScreenshotPass::~ScreenshotPass() = default;
|
||||
|
||||
void ScreenshotPass::capture(Rhi& rhi, Handle<GraphicsContext> 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<GraphicsContext> ctx)
|
|||
packed_data_.resize(stride * height_);
|
||||
|
||||
tcb::span<std::byte> 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++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ namespace srb2::hwr2
|
|||
|
||||
class ScreenshotPass
|
||||
{
|
||||
rhi::Handle<rhi::RenderPass> render_pass_;
|
||||
std::vector<uint8_t> pixel_data_;
|
||||
std::vector<uint8_t> packed_data_;
|
||||
uint32_t width_ = 0;
|
||||
|
|
@ -31,7 +30,7 @@ public:
|
|||
ScreenshotPass();
|
||||
~ScreenshotPass();
|
||||
|
||||
void capture(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx);
|
||||
void capture(rhi::Rhi& rhi);
|
||||
|
||||
void set_source(uint32_t width, uint32_t height)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ using namespace srb2::rhi;
|
|||
SoftwareScreenRenderer::SoftwareScreenRenderer() = default;
|
||||
SoftwareScreenRenderer::~SoftwareScreenRenderer() = default;
|
||||
|
||||
void SoftwareScreenRenderer::draw(Rhi& rhi, Handle<GraphicsContext> 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<GraphicsContext> 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public:
|
|||
SoftwareScreenRenderer();
|
||||
~SoftwareScreenRenderer();
|
||||
|
||||
void draw(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx);
|
||||
void draw(rhi::Rhi& rhi);
|
||||
|
||||
rhi::Handle<rhi::Texture> screen() const { return screen_texture_; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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<GraphicsContext> 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<GraphicsContext> ctx)
|
|||
TextureWrapMode::kClamp
|
||||
});
|
||||
std::array<uint8_t, 4> 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<GraphicsContext> 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<GraphicsContext> 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<GraphicsContext> 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<GraphicsContext> 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<GraphicsContext> 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<MergedTwodeeCommand::Texture> t = MergedTwodeeCommandFlatTexture {cmd.flat_lump};
|
||||
the_new_one.texture = t;
|
||||
}
|
||||
|
|
@ -458,6 +425,8 @@ void TwodeeRenderer::flush(Rhi& rhi, Handle<GraphicsContext> 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<GraphicsContext> ctx, Twodee& twodee
|
|||
|
||||
tcb::span<const std::byte> vertex_data = tcb::as_bytes(tcb::span(orig_list.vertices));
|
||||
tcb::span<const std::byte> 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> texture)
|
||||
{
|
||||
tx[0] = {SamplerName::kSampler0, texture};
|
||||
tx[1] = {SamplerName::kSampler1, palette_tex};
|
||||
mcmd.texture_handle = texture;
|
||||
},
|
||||
[&](const MergedTwodeeCommandFlatTexture& tex)
|
||||
{
|
||||
Handle<Texture> th = flat_manager_->find_or_create_indexed(rhi, ctx, tex.lump);
|
||||
Handle<Texture> 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<GraphicsContext> 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<Texture> 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<UniformVariant, 1> 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<UniformVariant, 3> g2_uniforms = {
|
||||
// ModelView
|
||||
glm::identity<glm::mat4>(),
|
||||
// Texcoord0 Transform
|
||||
glm::identity<glm::mat3>(),
|
||||
// Sampler 0 Is Indexed Alpha (yes, it always is)
|
||||
static_cast<int32_t>(1)
|
||||
};
|
||||
Handle<UniformSet> us_1 = rhi.create_uniform_set(ctx, {tcb::span(g1_uniforms)});
|
||||
Handle<UniformSet> 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<glm::mat4>());
|
||||
rhi.set_uniform("u_texcoord0_transform", glm::identity<glm::mat3>());
|
||||
rhi.set_uniform("u_sampler0_is_indexed_alpha", static_cast<int32_t>(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<GraphicsContext> ctx, Twodee& twodee
|
|||
// This shouldn't happen, but, just in case...
|
||||
continue;
|
||||
}
|
||||
SRB2_ASSERT(pipelines_.find(cmd.pipeline_key) != pipelines_.end());
|
||||
Handle<Pipeline> pl = pipelines_[cmd.pipeline_key];
|
||||
rhi.bind_pipeline(ctx, pl);
|
||||
rhi.set_viewport(ctx, {0, 0, static_cast<uint32_t>(vid.width), static_cast<uint32_t>(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<uint32_t>(vid.width), static_cast<uint32_t>(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,8 @@
|
|||
#ifndef __SRB2_HWR2_PASS_TWODEE_HPP__
|
||||
#define __SRB2_HWR2_PASS_TWODEE_HPP__
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -65,10 +63,13 @@ struct MergedTwodeeCommandFlatTexture
|
|||
struct MergedTwodeeCommand
|
||||
{
|
||||
using Texture = std::variant<rhi::Handle<rhi::Texture>, MergedTwodeeCommandFlatTexture>;
|
||||
TwodeePipelineKey pipeline_key = {};
|
||||
rhi::Handle<rhi::BindingSet> binding_set = {};
|
||||
rhi::PrimitiveType primitive;
|
||||
BlendMode blend_mode;
|
||||
std::optional<Texture> texture;
|
||||
TwodeePipelineKey pipeline_key;
|
||||
rhi::Handle<rhi::Texture> texture_handle;
|
||||
const uint8_t* colormap;
|
||||
rhi::Handle<rhi::Texture> colormap_handle;
|
||||
uint32_t index_offset = 0;
|
||||
uint32_t elements = 0;
|
||||
};
|
||||
|
|
@ -94,14 +95,13 @@ class TwodeeRenderer final
|
|||
std::vector<MergedTwodeeCommandList> cmd_lists_;
|
||||
std::vector<std::tuple<rhi::Handle<rhi::Buffer>, std::size_t>> vbos_;
|
||||
std::vector<std::tuple<rhi::Handle<rhi::Buffer>, std::size_t>> ibos_;
|
||||
rhi::Handle<rhi::RenderPass> render_pass_;
|
||||
rhi::Handle<rhi::Texture> output_;
|
||||
rhi::Handle<rhi::Texture> default_tex_;
|
||||
std::unordered_map<TwodeePipelineKey, rhi::Handle<rhi::Pipeline>> pipelines_;
|
||||
rhi::Handle<rhi::Program> program_;
|
||||
|
||||
void rewrite_patch_quad_vertices(Draw2dList& list, const Draw2dPatchQuad& cmd) const;
|
||||
|
||||
void initialize(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> 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<rhi::GraphicsContext> ctx, Twodee& twodee);
|
||||
void flush(rhi::Rhi& rhi, Twodee& twodee);
|
||||
};
|
||||
|
||||
} // namespace srb2::hwr2
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ static bool size_equal(Rhi& rhi, Handle<Texture> tex, uint32_t width, uint32_t h
|
|||
return deets.width == width && deets.height == height;
|
||||
}
|
||||
|
||||
void UpscaleBackbuffer::begin_pass(Rhi& rhi, Handle<GraphicsContext> ctx)
|
||||
void UpscaleBackbuffer::begin_pass(Rhi& rhi)
|
||||
{
|
||||
uint32_t vid_width = static_cast<uint32_t>(vid.width);
|
||||
uint32_t vid_height = static_cast<uint32_t>(vid.height);
|
||||
|
|
@ -38,19 +38,6 @@ void UpscaleBackbuffer::begin_pass(Rhi& rhi, Handle<GraphicsContext> 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<GraphicsContext> 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ namespace srb2::hwr2
|
|||
class UpscaleBackbuffer
|
||||
{
|
||||
rhi::Handle<rhi::Texture> color_;
|
||||
rhi::Handle<rhi::RenderPass> renderpass_;
|
||||
rhi::Handle<rhi::RenderPass> 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<rhi::GraphicsContext> ctx);
|
||||
void begin_pass(rhi::Rhi& rhi);
|
||||
rhi::Handle<rhi::Texture> color() const noexcept { return color_; }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ extern rhi::Handle<rhi::Rhi> g_current_rhi;
|
|||
|
||||
rhi::Rhi* get_rhi(rhi::Handle<rhi::Rhi> handle);
|
||||
|
||||
rhi::Handle<rhi::GraphicsContext> main_graphics_context();
|
||||
hwr2::HardwareState* main_hardware_state();
|
||||
|
||||
} // namespace srb2::sys
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ using namespace srb2::rhi;
|
|||
|
||||
static Rhi* g_last_known_rhi = nullptr;
|
||||
static bool g_imgui_frame_active = false;
|
||||
static Handle<GraphicsContext> g_main_graphics_context;
|
||||
static HardwareState g_hw_state;
|
||||
|
||||
Handle<Rhi> 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>(BlitRectPass::BlitMode::kCrtSharp);
|
||||
g_hw_state.screen_capture = std::make_unique<ScreenshotPass>();
|
||||
g_hw_state.backbuffer = std::make_unique<UpscaleBackbuffer>();
|
||||
g_hw_state.imgui_renderer = std::make_unique<ImguiRenderer>();
|
||||
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<rhi::GraphicsContext> 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<rhi::GraphicsContext> ctx = srb2::sys::main_graphics_context();
|
||||
hwr2::HardwareState* hw_state = srb2::sys::main_hardware_state();
|
||||
|
||||
hw_state->screen_capture->set_source(static_cast<uint32_t>(vid.width), static_cast<uint32_t>(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<rhi::GraphicsContext> 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<rhi::GraphicsContext> 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<uint32_t>(vid.width), static_cast<uint32_t>(vid.height));
|
||||
g_hw_state.sharp_bilinear_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast<uint32_t>(vid.width), static_cast<uint32_t>(vid.height));
|
||||
g_hw_state.crt_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast<uint32_t>(vid.width), static_cast<uint32_t>(vid.height));
|
||||
g_hw_state.crtsharp_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast<uint32_t>(vid.width), static_cast<uint32_t>(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<uint32_t>(vid.width), static_cast<uint32_t>(vid.height));
|
||||
g_hw_state.sharp_bilinear_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast<uint32_t>(vid.width), static_cast<uint32_t>(vid.height));
|
||||
g_hw_state.crt_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast<uint32_t>(vid.width), static_cast<uint32_t>(vid.height));
|
||||
g_hw_state.crtsharp_blit_rect->set_texture(g_hw_state.backbuffer->color(), static_cast<uint32_t>(vid.width), static_cast<uint32_t>(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();
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -71,7 +71,7 @@ struct Gl2Platform
|
|||
virtual ~Gl2Platform();
|
||||
|
||||
virtual void present() = 0;
|
||||
virtual std::tuple<std::vector<std::string>, std::vector<std::string>> find_shader_sources(PipelineProgram program) = 0;
|
||||
virtual std::tuple<std::vector<std::string>, std::vector<std::string>> 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<rhi::UniformVariant> uniforms;
|
||||
};
|
||||
|
||||
struct Gl2BindingSet : public rhi::BindingSet
|
||||
{
|
||||
std::vector<rhi::VertexAttributeBufferBinding> vertex_buffer_bindings;
|
||||
std::unordered_map<rhi::SamplerName, uint32_t> 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<rhi::VertexAttributeName, uint32_t> attrib_locations {2};
|
||||
std::unordered_map<rhi::UniformName, uint32_t> uniform_locations {2};
|
||||
std::unordered_map<rhi::SamplerName, uint32_t> sampler_locations {2};
|
||||
rhi::PipelineDesc desc;
|
||||
};
|
||||
|
||||
struct Gl2GraphicsContext : public rhi::GraphicsContext
|
||||
{
|
||||
std::unordered_map<std::string, uint32_t> attrib_locations;
|
||||
std::unordered_map<std::string, uint32_t> uniform_locations;
|
||||
};
|
||||
|
||||
struct Gl2ActiveUniform
|
||||
|
|
@ -136,13 +114,10 @@ class Gl2Rhi final : public Rhi
|
|||
|
||||
std::unique_ptr<GladGLContext> gl_;
|
||||
|
||||
Slab<Gl2RenderPass> render_pass_slab_;
|
||||
Slab<Gl2Texture> texture_slab_;
|
||||
Slab<Gl2Buffer> buffer_slab_;
|
||||
Slab<Gl2Renderbuffer> renderbuffer_slab_;
|
||||
Slab<Gl2Pipeline> pipeline_slab_;
|
||||
Slab<Gl2UniformSet> uniform_set_slab_;
|
||||
Slab<Gl2BindingSet> binding_set_slab_;
|
||||
Slab<Gl2Program> program_slab_;
|
||||
|
||||
Handle<Buffer> current_index_buffer_;
|
||||
|
||||
|
|
@ -150,13 +125,12 @@ class Gl2Rhi final : public Rhi
|
|||
|
||||
struct DefaultRenderPassState
|
||||
{
|
||||
bool clear = false;
|
||||
};
|
||||
using RenderPassState = std::variant<DefaultRenderPassState, RenderPassBeginInfo>;
|
||||
std::optional<RenderPassState> current_render_pass_;
|
||||
std::optional<Handle<Pipeline>> current_pipeline_;
|
||||
std::vector<RenderPassState> render_pass_stack_;
|
||||
std::optional<Handle<Program>> 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<Gl2Platform>&& platform, GlLoadFunc load_func);
|
||||
virtual ~Gl2Rhi();
|
||||
|
||||
virtual Handle<RenderPass> create_render_pass(const RenderPassDesc& desc) override;
|
||||
virtual void destroy_render_pass(Handle<RenderPass> handle) override;
|
||||
virtual Handle<Pipeline> create_pipeline(const PipelineDesc& desc) override;
|
||||
virtual void destroy_pipeline(Handle<Pipeline> handle) override;
|
||||
virtual Handle<Program> create_program(const ProgramDesc& desc) override;
|
||||
virtual void destroy_program(Handle<Program> handle) override;
|
||||
|
||||
virtual Handle<Texture> create_texture(const TextureDesc& desc) override;
|
||||
virtual void destroy_texture(Handle<Texture> handle) override;
|
||||
|
|
@ -187,58 +164,63 @@ public:
|
|||
virtual uint32_t get_buffer_size(Handle<Buffer> buffer) override;
|
||||
|
||||
virtual void update_buffer(
|
||||
Handle<GraphicsContext> ctx,
|
||||
Handle<Buffer> buffer,
|
||||
uint32_t offset,
|
||||
tcb::span<const std::byte> data
|
||||
) override;
|
||||
virtual void update_texture(
|
||||
Handle<GraphicsContext> ctx,
|
||||
Handle<Texture> texture,
|
||||
Rect region,
|
||||
srb2::rhi::PixelFormat data_format,
|
||||
tcb::span<const std::byte> data
|
||||
) override;
|
||||
virtual void update_texture_settings(
|
||||
Handle<GraphicsContext> ctx,
|
||||
Handle<Texture> texture,
|
||||
TextureWrapMode u_wrap,
|
||||
TextureWrapMode v_wrap,
|
||||
TextureFilterMode min,
|
||||
TextureFilterMode mag
|
||||
) override;
|
||||
virtual Handle<UniformSet>
|
||||
create_uniform_set(Handle<GraphicsContext> ctx, const CreateUniformSetInfo& info) override;
|
||||
virtual Handle<BindingSet>
|
||||
create_binding_set(Handle<GraphicsContext> ctx, Handle<Pipeline> pipeline, const CreateBindingSetInfo& info)
|
||||
override;
|
||||
|
||||
virtual Handle<GraphicsContext> begin_graphics() override;
|
||||
virtual void end_graphics(Handle<GraphicsContext> ctx) override;
|
||||
|
||||
// Graphics context functions
|
||||
virtual void begin_default_render_pass(Handle<GraphicsContext> ctx, bool clear) override;
|
||||
virtual void begin_render_pass(Handle<GraphicsContext> ctx, const RenderPassBeginInfo& info) override;
|
||||
virtual void end_render_pass(Handle<GraphicsContext> ctx) override;
|
||||
virtual void bind_pipeline(Handle<GraphicsContext> ctx, Handle<Pipeline> pipeline) override;
|
||||
virtual void bind_uniform_set(Handle<GraphicsContext> ctx, uint32_t slot, Handle<UniformSet> set) override;
|
||||
virtual void bind_binding_set(Handle<GraphicsContext> ctx, Handle<BindingSet> set) override;
|
||||
virtual void bind_index_buffer(Handle<GraphicsContext> ctx, Handle<Buffer> buffer) override;
|
||||
virtual void set_scissor(Handle<GraphicsContext> ctx, const Rect& rect) override;
|
||||
virtual void set_viewport(Handle<GraphicsContext> ctx, const Rect& rect) override;
|
||||
virtual void draw(Handle<GraphicsContext> ctx, uint32_t vertex_count, uint32_t first_vertex) override;
|
||||
virtual void draw_indexed(Handle<GraphicsContext> 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> program) override;
|
||||
virtual void bind_vertex_attrib(
|
||||
const char* name,
|
||||
Handle<Buffer> buffer,
|
||||
VertexAttributeFormat format,
|
||||
uint32_t offset,
|
||||
uint32_t stride
|
||||
) override;
|
||||
virtual void bind_index_buffer(Handle<Buffer> 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> 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<GraphicsContext> ctx, const Rect& rect, PixelFormat format, tcb::span<std::byte> out) override;
|
||||
read_pixels(const Rect& rect, PixelFormat format, tcb::span<std::byte> out) override;
|
||||
virtual void copy_framebuffer_to_texture(
|
||||
Handle<GraphicsContext> ctx,
|
||||
Handle<Texture> dst_tex,
|
||||
const Rect& dst_region,
|
||||
const Rect& src_region
|
||||
) override;
|
||||
virtual void set_stencil_reference(Handle<GraphicsContext> ctx, CullMode face, uint8_t reference) override;
|
||||
virtual void set_stencil_compare_mask(Handle<GraphicsContext> ctx, CullMode face, uint8_t mask) override;
|
||||
virtual void set_stencil_write_mask(Handle<GraphicsContext> 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -923,7 +923,7 @@ void Gles2Rhi::present()
|
|||
platform_->present();
|
||||
}
|
||||
|
||||
void Gles2Rhi::begin_default_render_pass(Handle<GraphicsContext> ctx)
|
||||
void Gles2Rhi::push_default_render_pass(Handle<GraphicsContext> ctx)
|
||||
{
|
||||
SRB2_ASSERT(platform_ != nullptr);
|
||||
SRB2_ASSERT(graphics_context_active_ == true);
|
||||
|
|
@ -942,7 +942,7 @@ void Gles2Rhi::begin_default_render_pass(Handle<GraphicsContext> ctx)
|
|||
current_render_pass_ = Gles2Rhi::DefaultRenderPassState {};
|
||||
}
|
||||
|
||||
void Gles2Rhi::begin_render_pass(Handle<GraphicsContext> ctx, const RenderPassBeginInfo& info)
|
||||
void Gles2Rhi::push_render_pass(Handle<GraphicsContext> 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<GraphicsContext> ctx, const RenderPassBe
|
|||
current_render_pass_ = info;
|
||||
}
|
||||
|
||||
void Gles2Rhi::end_render_pass(Handle<GraphicsContext> ctx)
|
||||
void Gles2Rhi::pop_render_pass(Handle<GraphicsContext> ctx)
|
||||
{
|
||||
SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation());
|
||||
SRB2_ASSERT(current_render_pass_.has_value() == true);
|
||||
|
|
|
|||
|
|
@ -133,9 +133,9 @@ public:
|
|||
virtual void end_graphics(Handle<GraphicsContext>&& ctx) override;
|
||||
|
||||
// Graphics context functions
|
||||
virtual void begin_default_render_pass(Handle<GraphicsContext> ctx) override;
|
||||
virtual void begin_render_pass(Handle<GraphicsContext> ctx, const RenderPassBeginInfo& info) override;
|
||||
virtual void end_render_pass(Handle<GraphicsContext> ctx) override;
|
||||
virtual void push_default_render_pass(Handle<GraphicsContext> ctx) override;
|
||||
virtual void push_render_pass(Handle<GraphicsContext> ctx, const RenderPassBeginInfo& info) override;
|
||||
virtual void pop_render_pass(Handle<GraphicsContext> ctx) override;
|
||||
virtual void bind_pipeline(Handle<GraphicsContext> ctx, Handle<Pipeline> pipeline) override;
|
||||
virtual void update_bindings(Handle<GraphicsContext> ctx, const UpdateBindingsInfo& info) override;
|
||||
virtual void update_uniforms(Handle<GraphicsContext> ctx, tcb::span<UniformUpdateData> uniforms) override;
|
||||
|
|
|
|||
175
src/rhi/rhi.hpp
175
src/rhi/rhi.hpp
|
|
@ -13,9 +13,7 @@
|
|||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
|
|
@ -26,6 +24,7 @@
|
|||
#include <tcb/span.hpp>
|
||||
|
||||
#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<const char*> 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<BlendDesc> blend;
|
||||
ColorMask color_mask;
|
||||
};
|
||||
|
||||
struct PipelineDesc
|
||||
{
|
||||
PipelineProgram program;
|
||||
VertexInputDesc vertex_input;
|
||||
UniformInputDesc uniform_input;
|
||||
SamplerInputDesc sampler_input;
|
||||
std::optional<PipelineDepthStencilStateDesc> 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<RenderPass> render_pass;
|
||||
Handle<Texture> color_attachment;
|
||||
std::optional<Handle<Renderbuffer>> 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<TextureBinding> sampler_textures;
|
||||
};
|
||||
|
||||
struct UniformSet
|
||||
{
|
||||
};
|
||||
struct BindingSet
|
||||
{
|
||||
};
|
||||
|
||||
struct GraphicsContext
|
||||
{
|
||||
};
|
||||
|
||||
struct TextureDetails
|
||||
{
|
||||
uint32_t width;
|
||||
|
|
@ -604,10 +572,8 @@ struct Rhi
|
|||
{
|
||||
virtual ~Rhi();
|
||||
|
||||
virtual Handle<RenderPass> create_render_pass(const RenderPassDesc& desc) = 0;
|
||||
virtual void destroy_render_pass(Handle<RenderPass> handle) = 0;
|
||||
virtual Handle<Pipeline> create_pipeline(const PipelineDesc& desc) = 0;
|
||||
virtual void destroy_pipeline(Handle<Pipeline> handle) = 0;
|
||||
virtual Handle<Program> create_program(const ProgramDesc& desc) = 0;
|
||||
virtual void destroy_program(Handle<Program> handle) = 0;
|
||||
|
||||
virtual Handle<Texture> create_texture(const TextureDesc& desc) = 0;
|
||||
virtual void destroy_texture(Handle<Texture> handle) = 0;
|
||||
|
|
@ -621,56 +587,63 @@ struct Rhi
|
|||
virtual uint32_t get_buffer_size(Handle<Buffer> buffer) = 0;
|
||||
|
||||
virtual void update_buffer(
|
||||
Handle<GraphicsContext> ctx,
|
||||
Handle<Buffer> buffer,
|
||||
uint32_t offset,
|
||||
tcb::span<const std::byte> data
|
||||
) = 0;
|
||||
virtual void update_texture(
|
||||
Handle<GraphicsContext> ctx,
|
||||
Handle<Texture> texture,
|
||||
Rect region,
|
||||
srb2::rhi::PixelFormat data_format,
|
||||
tcb::span<const std::byte> data
|
||||
) = 0;
|
||||
virtual void update_texture_settings(
|
||||
Handle<GraphicsContext> ctx,
|
||||
Handle<Texture> texture,
|
||||
TextureWrapMode u_wrap,
|
||||
TextureWrapMode v_wrap,
|
||||
TextureFilterMode min,
|
||||
TextureFilterMode mag
|
||||
) = 0;
|
||||
virtual Handle<UniformSet> create_uniform_set(Handle<GraphicsContext> ctx, const CreateUniformSetInfo& info) = 0;
|
||||
virtual Handle<BindingSet>
|
||||
create_binding_set(Handle<GraphicsContext> ctx, Handle<Pipeline> pipeline, const CreateBindingSetInfo& info) = 0;
|
||||
|
||||
virtual Handle<GraphicsContext> begin_graphics() = 0;
|
||||
virtual void end_graphics(Handle<GraphicsContext> ctx) = 0;
|
||||
|
||||
// Graphics context functions
|
||||
virtual void begin_default_render_pass(Handle<GraphicsContext> ctx, bool clear) = 0;
|
||||
virtual void begin_render_pass(Handle<GraphicsContext> ctx, const RenderPassBeginInfo& info) = 0;
|
||||
virtual void end_render_pass(Handle<GraphicsContext> ctx) = 0;
|
||||
virtual void bind_pipeline(Handle<GraphicsContext> ctx, Handle<Pipeline> pipeline) = 0;
|
||||
virtual void bind_uniform_set(Handle<GraphicsContext> ctx, uint32_t slot, Handle<UniformSet> set) = 0;
|
||||
virtual void bind_binding_set(Handle<GraphicsContext> ctx, Handle<BindingSet> set) = 0;
|
||||
virtual void bind_index_buffer(Handle<GraphicsContext> ctx, Handle<Buffer> buffer) = 0;
|
||||
virtual void set_scissor(Handle<GraphicsContext> ctx, const Rect& rect) = 0;
|
||||
virtual void set_viewport(Handle<GraphicsContext> ctx, const Rect& rect) = 0;
|
||||
virtual void draw(Handle<GraphicsContext> ctx, uint32_t vertex_count, uint32_t first_vertex) = 0;
|
||||
virtual void draw_indexed(Handle<GraphicsContext> 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> program) = 0;
|
||||
virtual void bind_vertex_attrib(
|
||||
const char* name,
|
||||
Handle<Buffer> buffer,
|
||||
VertexAttributeFormat format,
|
||||
uint32_t offset,
|
||||
uint32_t stride
|
||||
) = 0;
|
||||
virtual void bind_index_buffer(Handle<Buffer> 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> 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<GraphicsContext> ctx, const Rect& rect, PixelFormat format, tcb::span<std::byte> out) = 0;
|
||||
read_pixels(const Rect& rect, PixelFormat format, tcb::span<std::byte> out) = 0;
|
||||
virtual void copy_framebuffer_to_texture(
|
||||
Handle<GraphicsContext> ctx,
|
||||
Handle<Texture> dst_tex,
|
||||
const Rect& dst_region,
|
||||
const Rect& src_region
|
||||
) = 0;
|
||||
virtual void set_stencil_reference(Handle<GraphicsContext> ctx, CullMode face, uint8_t reference) = 0;
|
||||
virtual void set_stencil_compare_mask(Handle<GraphicsContext> ctx, CullMode face, uint8_t mask) = 0;
|
||||
virtual void set_stencil_write_mask(Handle<GraphicsContext> 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
/// \file
|
||||
/// \brief SRB2 graphics stuff for SDL
|
||||
|
||||
#include <SDL_video.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <memory>
|
||||
|
|
|
|||
|
|
@ -34,35 +34,10 @@ void SdlGl2Platform::present()
|
|||
SDL_GL_SwapWindow(window);
|
||||
}
|
||||
|
||||
static constexpr const char* pipeline_lump_slug(rhi::PipelineProgram program)
|
||||
static std::array<std::string, 2> 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<std::string, 2> 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<std::string> get_sources_from_glsllist_lump(const char* lumpn
|
|||
}
|
||||
|
||||
std::tuple<std::vector<std::string>, std::vector<std::string>>
|
||||
SdlGl2Platform::find_shader_sources(rhi::PipelineProgram program)
|
||||
SdlGl2Platform::find_shader_sources(const char* name)
|
||||
{
|
||||
std::array<std::string, 2> glsllist_names = glsllist_lump_names(program);
|
||||
std::array<std::string, 2> glsllist_names = glsllist_lump_names(name);
|
||||
|
||||
std::vector<std::string> vertex_sources = get_sources_from_glsllist_lump(glsllist_names[0].c_str());
|
||||
std::vector<std::string> fragment_sources = get_sources_from_glsllist_lump(glsllist_names[1].c_str());
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ struct SdlGl2Platform final : public Gl2Platform
|
|||
|
||||
virtual void present() override;
|
||||
virtual std::tuple<std::vector<std::string>, std::vector<std::string>>
|
||||
find_shader_sources(PipelineProgram program) override;
|
||||
find_shader_sources(const char* name) override;
|
||||
virtual Rect get_default_framebuffer_dimensions() override;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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<rhi::GraphicsContext> 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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue