rhi: Remove Pipeline, Uniform/BindingSet, add dynamic state

The pipeline abstraction mimicked Vulkan and d3d12 explicit pipeline state objects
but, like GraphicsContext, was ill-considered for the kinds of drawing
behavior SRB2 uses. Rather than push this complexity into the drawing
code, it will instead be the responsibility of the backend to manage
explicit pipeline objects if necessary.

Now, drawing code must create a Program instance, bind it, and set the
rasterizer state to do the equivalent. Uniform, sampler, and vertex
attribute bindings are significantly simpler to set up now.
This commit is contained in:
Eidolon 2024-10-26 13:49:22 -05:00
parent 4499979458
commit 136761cf3b
17 changed files with 795 additions and 1275 deletions

View file

@ -10,11 +10,14 @@
#include "blit_postimg_screens.hpp" #include "blit_postimg_screens.hpp"
#include <cstddef>
#include <glm/mat3x3.hpp> #include <glm/mat3x3.hpp>
#include <glm/mat4x4.hpp> #include <glm/mat4x4.hpp>
#include <glm/vec3.hpp> #include <glm/vec3.hpp>
#include <glm/vec4.hpp> #include <glm/vec4.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <tcb/span.hpp>
#include "../p_tick.h" #include "../p_tick.h"
#include "../i_time.h" #include "../i_time.h"
@ -36,34 +39,6 @@ struct BlitVertex
}; };
} // namespace } // 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[] = 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}}; {{-.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}};
@ -106,27 +81,81 @@ void BlitPostimgScreens::draw(Rhi& rhi)
for (uint32_t i = 0; i < screens_; i++) for (uint32_t i = 0; i < screens_; i++)
{ {
BlitPostimgScreens::ScreenConfig& screen_config = screen_configs_[i];
BlitPostimgScreens::ScreenData& data = screen_data_[i]; BlitPostimgScreens::ScreenData& data = screen_data_[i];
rhi.bind_pipeline(data.pipeline); glm::mat4 projection = glm::scale(glm::identity<glm::mat4>(), glm::vec3(2.f, -2.f, 1.f));
glm::mat4 modelview = glm::identity<glm::mat4>();
glm::vec2 flip_mirror_uv_displace {0.0, 0.0};
if (screen_config.post.mirror)
{
flip_mirror_uv_displace.x = 1 - (1 - screen_config.uv_size.x);
}
if (screen_config.post.flip)
{
flip_mirror_uv_displace.y = 1 - (1 - screen_config.uv_size.y);
}
glm::mat3 texcoord_transform =
{
glm::vec3(screen_config.uv_size.x * (screen_config.post.mirror ? -1 : 1), 0.0, 0.0),
glm::vec3(0.0, screen_config.uv_size.y * (screen_config.post.flip ? -1 : 1), 0.0),
glm::vec3(screen_config.uv_offset + flip_mirror_uv_displace, 1.0)
};
glm::vec2 texcoord_min = screen_config.uv_offset;
glm::vec2 texcoord_max = screen_config.uv_offset + screen_config.uv_size;
RasterizerStateDesc r_state {};
r_state.cull = CullMode::kNone;
rhi.bind_program(data.program);
rhi.set_rasterizer_state(r_state);
rhi.set_viewport(get_screen_viewport(i, screens_, target_width_, target_height_)); rhi.set_viewport(get_screen_viewport(i, screens_, target_width_, target_height_));
rhi.bind_uniform_set(0, data.uniform_set); rhi.bind_vertex_attrib("a_position", quad_vbo_, rhi::VertexAttributeFormat::kFloat3, offsetof(BlitVertex, x), sizeof(BlitVertex));
rhi.bind_binding_set(data.binding_set); rhi.bind_vertex_attrib("a_texcoord0", quad_vbo_, rhi::VertexAttributeFormat::kFloat2, offsetof(BlitVertex, u), sizeof(BlitVertex));
rhi.bind_index_buffer(quad_ibo_); 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); rhi.draw_indexed(6, 0);
} }
} }
void BlitPostimgScreens::prepass(Rhi& rhi) void BlitPostimgScreens::prepass(Rhi& rhi)
{ {
if (!pipeline_) if (!program_)
{ {
pipeline_ = rhi.create_pipeline(kPostimgPipelineDesc); 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_pipeline_) if (!indexed_program_)
{ {
indexed_pipeline_ = rhi.create_pipeline(kPostimgIndexedPipelineDesc); 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_) if (!quad_vbo_)
@ -161,65 +190,13 @@ void BlitPostimgScreens::transfer(Rhi& rhi)
if (screen_config.indexed) if (screen_config.indexed)
{ {
data.pipeline = indexed_pipeline_; data.program = program_;
} }
else else
{ {
data.pipeline = pipeline_; data.program = indexed_program_;
} }
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(
data.pipeline,
{
vertex_bindings,
tcb::span(sampler_bindings, screen_config.indexed ? 2 : 1)
}
);
glm::mat4 projection = glm::scale(glm::identity<glm::mat4>(), glm::vec3(2.f, -2.f, 1.f));
glm::mat4 modelview = glm::identity<glm::mat4>();
glm::vec2 flip_mirror_uv_displace {0.0, 0.0};
if (screen_config.post.mirror)
{
flip_mirror_uv_displace.x = 1 - (1 - screen_config.uv_size.x);
}
if (screen_config.post.flip)
{
flip_mirror_uv_displace.y = 1 - (1 - screen_config.uv_size.y);
}
glm::mat3 texcoord_transform =
{
glm::vec3(screen_config.uv_size.x * (screen_config.post.mirror ? -1 : 1), 0.0, 0.0),
glm::vec3(0.0, screen_config.uv_size.y * (screen_config.post.flip ? -1 : 1), 0.0),
glm::vec3(screen_config.uv_offset + flip_mirror_uv_displace, 1.0)
};
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
};
data.uniform_set = rhi.create_uniform_set({uniforms});
screen_data_[i] = std::move(data); screen_data_[i] = std::move(data);
} }
} }

View file

@ -46,13 +46,11 @@ public:
private: private:
struct ScreenData struct ScreenData
{ {
rhi::Handle<rhi::Pipeline> pipeline; rhi::Handle<rhi::Program> program;
rhi::Handle<rhi::BindingSet> binding_set;
rhi::Handle<rhi::UniformSet> uniform_set;
}; };
rhi::Handle<rhi::Pipeline> pipeline_; rhi::Handle<rhi::Program> program_;
rhi::Handle<rhi::Pipeline> indexed_pipeline_; rhi::Handle<rhi::Program> indexed_program_;
rhi::Handle<rhi::Buffer> quad_vbo_; rhi::Handle<rhi::Buffer> quad_vbo_;
rhi::Handle<rhi::Buffer> quad_ibo_; rhi::Handle<rhi::Buffer> quad_ibo_;
bool upload_quad_buffer_; bool upload_quad_buffer_;

View file

@ -11,6 +11,7 @@
#include "blit_rect.hpp" #include "blit_rect.hpp"
#include <optional> #include <optional>
#include <vector>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <tcb/span.hpp> #include <tcb/span.hpp>
@ -38,62 +39,6 @@ static const BlitVertex kVerts[] =
static const uint16_t kIndices[] = {0, 1, 2, 1, 3, 2}; 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(BlitRectPass::BlitMode::kNearest) {}
BlitRectPass::BlitRectPass(BlitRectPass::BlitMode blit_mode) : blit_mode_(blit_mode) {} BlitRectPass::BlitRectPass(BlitRectPass::BlitMode blit_mode) : blit_mode_(blit_mode) {}
BlitRectPass::~BlitRectPass() = default; BlitRectPass::~BlitRectPass() = default;
@ -107,26 +52,29 @@ void BlitRectPass::draw(Rhi& rhi)
void BlitRectPass::prepass(Rhi& 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_) switch (blit_mode_)
{ {
case BlitRectPass::BlitMode::kNearest: case BlitRectPass::BlitMode::kNearest:
pipeline_ = rhi.create_pipeline(kUnshadedPipelineDescription); desc.name = "unshaded";
break; break;
case BlitRectPass::BlitMode::kSharpBilinear: case BlitRectPass::BlitMode::kSharpBilinear:
pipeline_ = rhi.create_pipeline(kSharpBilinearPipelineDescription); desc.name = "sharpbilinear";
break; break;
case BlitRectPass::BlitMode::kCrt: case BlitRectPass::BlitMode::kCrt:
pipeline_ = rhi.create_pipeline(kCrtPipelineDescription); desc.name = "crt";
break; break;
case BlitRectPass::BlitMode::kCrtSharp: case BlitRectPass::BlitMode::kCrtSharp:
pipeline_ = rhi.create_pipeline(kCrtSharpPipelineDescription); desc.name = "crtsharp";
break; break;
default: default:
std::terminate(); std::terminate();
} }
program_ = rhi.create_program(desc);
} }
if (!quad_vbo_) if (!quad_vbo_)
@ -230,6 +178,18 @@ void BlitRectPass::transfer(Rhi& rhi)
rhi.update_texture(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; 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 aspect = 1.0;
float output_aspect = 1.0; float output_aspect = 1.0;
@ -242,122 +202,46 @@ void BlitRectPass::transfer(Rhi& rhi)
rhi::TextureDetails texture_details = rhi.get_texture_details(texture_); rhi::TextureDetails texture_details = rhi.get_texture_details(texture_);
std::array<rhi::UniformVariant, 1> g1_uniforms = {{ glm::mat4 projection = glm::scale(
// Projection glm::identity<glm::mat4>(),
glm::scale( glm::vec3(taller ? 1.f : 1.f / output_aspect, taller ? -1.f / (1.f / output_aspect) : -1.f, 1.f)
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({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_) switch (blit_mode_)
{ {
case BlitRectPass::BlitMode::kCrt: case BlitRectPass::BlitMode::kNearest:
{
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({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(pipeline_, {vbs, tbs});
break; 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({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(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({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(pipeline_, {vbs, tbs});
break;
}
default: default:
{ rhi.set_uniform("u_sampler0_size", sampler0_size);
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({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(pipeline_, {vbs, tbs});
break; 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)
{
rhi.bind_pipeline(pipeline_);
rhi.set_viewport(output_position_); rhi.set_viewport(output_position_);
rhi.bind_uniform_set(0, uniform_sets_[0]);
rhi.bind_uniform_set(1, uniform_sets_[1]);
rhi.bind_binding_set(binding_set_);
rhi.bind_index_buffer(quad_ibo_); rhi.bind_index_buffer(quad_ibo_);
rhi.draw_indexed(6, 0); rhi.draw_indexed(6, 0);
} }

View file

@ -32,7 +32,7 @@ public:
}; };
private: private:
rhi::Handle<rhi::Pipeline> pipeline_; rhi::Handle<rhi::Program> program_;
rhi::Handle<rhi::Texture> texture_; rhi::Handle<rhi::Texture> texture_;
uint32_t texture_width_ = 0; uint32_t texture_width_ = 0;
uint32_t texture_height_ = 0; uint32_t texture_height_ = 0;
@ -42,8 +42,6 @@ private:
bool output_flip_ = false; bool output_flip_ = false;
rhi::Handle<rhi::Buffer> quad_vbo_; rhi::Handle<rhi::Buffer> quad_vbo_;
rhi::Handle<rhi::Buffer> quad_ibo_; rhi::Handle<rhi::Buffer> quad_ibo_;
std::array<rhi::Handle<rhi::UniformSet>, 2> uniform_sets_;
rhi::Handle<rhi::BindingSet> binding_set_;
BlitMode blit_mode_; BlitMode blit_mode_;
rhi::Handle<rhi::Texture> dot_pattern_; rhi::Handle<rhi::Texture> dot_pattern_;

View file

@ -11,6 +11,7 @@
#include "pass_imgui.hpp" #include "pass_imgui.hpp"
#include <imgui.h> #include <imgui.h>
#include <tcb/span.hpp>
#include "../v_video.h" #include "../v_video.h"
@ -18,28 +19,6 @@ using namespace srb2;
using namespace srb2::hwr2; using namespace srb2::hwr2;
using namespace srb2::rhi; 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() ImguiPass::ImguiPass()
{ {
} }
@ -48,9 +27,16 @@ ImguiPass::~ImguiPass() = default;
void ImguiPass::prepass(Rhi& rhi) void ImguiPass::prepass(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(); ImGuiIO& io = ImGui::GetIO();
@ -166,65 +152,67 @@ void ImguiPass::transfer(Rhi& rhi)
tcb::span<ImDrawIdx> index_span = tcb::span(im_list->IdxBuffer.Data, im_list->IdxBuffer.size()); tcb::span<ImDrawIdx> index_span = tcb::span(im_list->IdxBuffer.Data, im_list->IdxBuffer.size());
rhi.update_buffer(ibo, 0, tcb::as_bytes(index_span)); rhi.update_buffer(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({g1_uniforms});
Handle<UniformSet> us_2 = rhi.create_uniform_set({g2_uniforms});
draw_list.us_1 = us_1;
draw_list.us_2 = us_2;
for (auto& draw_cmd : draw_list.cmds) for (auto& draw_cmd : draw_list.cmds)
{ {
// Binding set draw_cmd.vbo = vbo;
std::array<rhi::VertexAttributeBufferBinding, 1> vbos = {{{0, vbo}}}; draw_cmd.ibo = ibo;
std::array<rhi::TextureBinding, 1> tbs = {{{rhi::SamplerName::kSampler0, draw_cmd.tex}}}; draw_cmd.tex = draw_cmd.tex;
rhi::Handle<rhi::BindingSet> binding_set = rhi.create_binding_set(pipeline_, {vbos, tbs});
draw_cmd.binding_set = binding_set;
} }
} }
} }
void ImguiPass::graphics(Rhi& rhi) void ImguiPass::graphics(Rhi& rhi)
{ {
rhi.begin_default_render_pass(false); rhi.bind_program(program_);
rhi.bind_pipeline(pipeline_); 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_) for (auto& draw_list : draw_lists_)
{ {
rhi.bind_uniform_set(0, draw_list.us_1); glm::mat4 projection = glm::mat4(
rhi.bind_uniform_set(1, draw_list.us_2); 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) for (auto& cmd : draw_list.cmds)
{ {
rhi.bind_binding_set(cmd.binding_set); 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.bind_index_buffer(draw_list.ibo);
rhi.set_scissor(cmd.clip);
rhi.draw_indexed(cmd.elems, cmd.i_offset); rhi.draw_indexed(cmd.elems, cmd.i_offset);
} }
} }
rhi.end_render_pass();
} }
void ImguiPass::postpass(Rhi& rhi) void ImguiPass::postpass(Rhi& rhi)

View file

@ -22,24 +22,23 @@ class ImguiPass final
{ {
struct DrawCmd struct DrawCmd
{ {
rhi::Handle<rhi::Texture> tex;
uint32_t v_offset; uint32_t v_offset;
uint32_t elems; uint32_t elems;
uint32_t i_offset; uint32_t i_offset;
rhi::Rect clip; 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 struct DrawList
{ {
void* list; void* list;
rhi::Handle<rhi::Buffer> vbo; rhi::Handle<rhi::Buffer> vbo;
rhi::Handle<rhi::Buffer> ibo; rhi::Handle<rhi::Buffer> ibo;
rhi::Handle<rhi::UniformSet> us_1;
rhi::Handle<rhi::UniformSet> us_2;
std::vector<DrawCmd> cmds; std::vector<DrawCmd> cmds;
}; };
rhi::Handle<rhi::Pipeline> pipeline_; rhi::Handle<rhi::Program> program_;
rhi::Handle<rhi::Texture> font_atlas_; rhi::Handle<rhi::Texture> font_atlas_;
std::vector<DrawList> draw_lists_; std::vector<DrawList> draw_lists_;

View file

@ -41,22 +41,6 @@ static const uint16_t kPostprocessIndices[] = {0, 1, 2, 1, 3, 2};
} // namespace } // 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()
{ {
} }
@ -73,9 +57,12 @@ void PostprocessWipePass::draw(Rhi& rhi)
void PostprocessWipePass::prepass(Rhi& 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_) if (!vbo_)
@ -195,20 +182,6 @@ void PostprocessWipePass::transfer(Rhi& rhi)
tcb::span<const std::byte> data = tcb::as_bytes(tcb::span(mask_data_)); tcb::span<const std::byte> data = tcb::as_bytes(tcb::span(mask_data_));
rhi.update_texture(wipe_tex_, {0, 0, mask_w_, mask_h_}, PixelFormat::kR8, data); rhi.update_texture(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({tcb::span(uniforms)});
VertexAttributeBufferBinding vbos[] = {{0, vbo_}};
TextureBinding tx[] = {
{SamplerName::kSampler0, start_},
{SamplerName::kSampler1, end_},
{SamplerName::kSampler2, wipe_tex_}};
bs_ = rhi.create_binding_set(pipeline_, {vbos, tx});
} }
void PostprocessWipePass::graphics(Rhi& rhi) void PostprocessWipePass::graphics(Rhi& rhi)
@ -218,10 +191,21 @@ void PostprocessWipePass::graphics(Rhi& rhi)
return; return;
} }
rhi.bind_pipeline(pipeline_); 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.set_viewport({0, 0, width_, height_});
rhi.bind_uniform_set(0, us_);
rhi.bind_binding_set(bs_);
rhi.bind_index_buffer(ibo_); rhi.bind_index_buffer(ibo_);
rhi.draw_indexed(6, 0); rhi.draw_indexed(6, 0);
} }

View file

@ -21,13 +21,11 @@ namespace srb2::hwr2
class PostprocessWipePass final class PostprocessWipePass final
{ {
// Internal RHI resources // Internal RHI resources
rhi::Handle<rhi::Pipeline> pipeline_; rhi::Handle<rhi::Program> program_;
rhi::Handle<rhi::Buffer> vbo_; rhi::Handle<rhi::Buffer> vbo_;
bool upload_vbo_ = false; bool upload_vbo_ = false;
rhi::Handle<rhi::Buffer> ibo_; rhi::Handle<rhi::Buffer> ibo_;
bool upload_ibo_ = false; bool upload_ibo_ = false;
rhi::Handle<rhi::UniformSet> us_;
rhi::Handle<rhi::BindingSet> bs_;
rhi::Handle<rhi::Texture> wipe_tex_; rhi::Handle<rhi::Texture> wipe_tex_;
int wipe_color_mode_ = 0; int wipe_color_mode_ = 0;
int wipe_swizzle_ = 0; int wipe_swizzle_ = 0;

View file

@ -43,78 +43,59 @@ static TwodeePipelineKey pipeline_key_for_cmd(const Draw2dCmd& cmd)
return {hwr2::get_blend_mode(cmd), hwr2::is_draw_lines(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 = { switch (blend)
{{sizeof(TwodeeVertex)}},
{{VertexAttributeName::kPosition, 0, 0},
{VertexAttributeName::kTexCoord0, 0, 12},
{VertexAttributeName::kColor, 0, 20}}};
BlendDesc blend_desc;
switch (key.blend)
{ {
case BlendMode::kAlphaTransparent: case BlendMode::kAlphaTransparent:
blend_desc.source_factor_color = BlendFactor::kSourceAlpha; desc.blend_source_factor_color = BlendFactor::kSourceAlpha;
blend_desc.dest_factor_color = BlendFactor::kOneMinusSourceAlpha; desc.blend_dest_factor_color = BlendFactor::kOneMinusSourceAlpha;
blend_desc.color_function = BlendFunction::kAdd; desc.blend_color_function = BlendFunction::kAdd;
blend_desc.source_factor_alpha = BlendFactor::kOne; desc.blend_source_factor_alpha = BlendFactor::kOne;
blend_desc.dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; desc.blend_dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha;
blend_desc.alpha_function = BlendFunction::kAdd; desc.blend_alpha_function = BlendFunction::kAdd;
break; break;
case BlendMode::kModulate: case BlendMode::kModulate:
blend_desc.source_factor_color = BlendFactor::kDest; desc.blend_source_factor_color = BlendFactor::kDest;
blend_desc.dest_factor_color = BlendFactor::kZero; desc.blend_dest_factor_color = BlendFactor::kZero;
blend_desc.color_function = BlendFunction::kAdd; desc.blend_color_function = BlendFunction::kAdd;
blend_desc.source_factor_alpha = BlendFactor::kDestAlpha; desc.blend_source_factor_alpha = BlendFactor::kDestAlpha;
blend_desc.dest_factor_alpha = BlendFactor::kZero; desc.blend_dest_factor_alpha = BlendFactor::kZero;
blend_desc.alpha_function = BlendFunction::kAdd; desc.blend_alpha_function = BlendFunction::kAdd;
break; break;
case BlendMode::kAdditive: case BlendMode::kAdditive:
blend_desc.source_factor_color = BlendFactor::kSourceAlpha; desc.blend_source_factor_color = BlendFactor::kSourceAlpha;
blend_desc.dest_factor_color = BlendFactor::kOne; desc.blend_dest_factor_color = BlendFactor::kOne;
blend_desc.color_function = BlendFunction::kAdd; desc.blend_color_function = BlendFunction::kAdd;
blend_desc.source_factor_alpha = BlendFactor::kOne; desc.blend_source_factor_alpha = BlendFactor::kOne;
blend_desc.dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; desc.blend_dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha;
blend_desc.alpha_function = BlendFunction::kAdd; desc.blend_alpha_function = BlendFunction::kAdd;
break; break;
case BlendMode::kSubtractive: case BlendMode::kSubtractive:
blend_desc.source_factor_color = BlendFactor::kSourceAlpha; desc.blend_source_factor_color = BlendFactor::kSourceAlpha;
blend_desc.dest_factor_color = BlendFactor::kOne; desc.blend_dest_factor_color = BlendFactor::kOne;
blend_desc.color_function = BlendFunction::kSubtract; desc.blend_color_function = BlendFunction::kSubtract;
blend_desc.source_factor_alpha = BlendFactor::kOne; desc.blend_source_factor_alpha = BlendFactor::kOne;
blend_desc.dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; desc.blend_dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha;
blend_desc.alpha_function = BlendFunction::kAdd; desc.blend_alpha_function = BlendFunction::kAdd;
break; break;
case BlendMode::kReverseSubtractive: case BlendMode::kReverseSubtractive:
blend_desc.source_factor_color = BlendFactor::kSourceAlpha; desc.blend_source_factor_color = BlendFactor::kSourceAlpha;
blend_desc.dest_factor_color = BlendFactor::kOne; desc.blend_dest_factor_color = BlendFactor::kOne;
blend_desc.color_function = BlendFunction::kReverseSubtract; desc.blend_color_function = BlendFunction::kReverseSubtract;
blend_desc.source_factor_alpha = BlendFactor::kOne; desc.blend_source_factor_alpha = BlendFactor::kOne;
blend_desc.dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha; desc.blend_dest_factor_alpha = BlendFactor::kOneMinusSourceAlpha;
blend_desc.alpha_function = BlendFunction::kAdd; desc.blend_alpha_function = BlendFunction::kAdd;
break; break;
case BlendMode::kInvertDest: case BlendMode::kInvertDest:
blend_desc.source_factor_color = BlendFactor::kOne; desc.blend_source_factor_color = BlendFactor::kOne;
blend_desc.dest_factor_color = BlendFactor::kOne; desc.blend_dest_factor_color = BlendFactor::kOne;
blend_desc.color_function = BlendFunction::kSubtract; desc.blend_color_function = BlendFunction::kSubtract;
blend_desc.source_factor_alpha = BlendFactor::kZero; desc.blend_source_factor_alpha = BlendFactor::kZero;
blend_desc.dest_factor_alpha = BlendFactor::kDestAlpha; desc.blend_dest_factor_alpha = BlendFactor::kDestAlpha;
blend_desc.alpha_function = BlendFunction::kAdd; desc.blend_alpha_function = BlendFunction::kAdd;
break; 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 void TwodeeRenderer::rewrite_patch_quad_vertices(Draw2dList& list, const Draw2dPatchQuad& cmd) const
@ -233,32 +214,16 @@ void TwodeeRenderer::rewrite_patch_quad_vertices(Draw2dList& list, const Draw2dP
void TwodeeRenderer::initialize(Rhi& rhi) void TwodeeRenderer::initialize(Rhi& rhi)
{ {
{ ProgramDesc prog_desc;
TwodeePipelineKey alpha_transparent_tris = {BlendMode::kAlphaTransparent, false}; prog_desc.name = "unshadedpaletted";
TwodeePipelineKey modulate_tris = {BlendMode::kModulate, false}; const char* defines[] = {
TwodeePipelineKey additive_tris = {BlendMode::kAdditive, false}; "ENABLE_U_SAMPLER0_IS_INDEXED_ALPHA",
TwodeePipelineKey subtractive_tris = {BlendMode::kSubtractive, false}; "ENABLE_S_SAMPLER2",
TwodeePipelineKey revsubtractive_tris = {BlendMode::kReverseSubtractive, false}; "ENABLE_VA_TEXCOORD0",
TwodeePipelineKey invertdest_tris = {BlendMode::kInvertDest, false}; "ENABLE_VA_COLOR"
TwodeePipelineKey alpha_transparent_lines = {BlendMode::kAlphaTransparent, true}; };
TwodeePipelineKey modulate_lines = {BlendMode::kModulate, true}; prog_desc.defines = tcb::make_span(defines);
TwodeePipelineKey additive_lines = {BlendMode::kAdditive, true}; program_ = rhi.create_program(prog_desc);
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))});
}
{ {
default_tex_ = rhi.create_texture({ default_tex_ = rhi.create_texture({
@ -377,6 +342,8 @@ void TwodeeRenderer::flush(Rhi& rhi, Twodee& twodee)
new_cmd.colormap = nullptr; new_cmd.colormap = nullptr;
// safety: a command list is required to have at least 1 command // 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.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)); merged_list.cmds.push_back(std::move(new_cmd));
for (auto& cmd : list.cmds) for (auto& cmd : list.cmds)
@ -458,6 +425,8 @@ void TwodeeRenderer::flush(Rhi& rhi, Twodee& twodee)
}}; }};
std::visit(tex_visitor_again, cmd); std::visit(tex_visitor_again, cmd);
the_new_one.pipeline_key = pipeline_key_for_cmd(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)); merged_list.cmds.push_back(std::move(the_new_one));
} }
@ -495,23 +464,18 @@ void TwodeeRenderer::flush(Rhi& rhi, Twodee& twodee)
rhi.update_buffer(merged_list.vbo, 0, vertex_data); rhi.update_buffer(merged_list.vbo, 0, vertex_data);
rhi.update_buffer(merged_list.ibo, 0, index_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) for (auto& mcmd : merged_list.cmds)
{ {
TextureBinding tx[3];
auto tex_visitor = srb2::Overload { auto tex_visitor = srb2::Overload {
[&](Handle<Texture> texture) [&](Handle<Texture> texture)
{ {
tx[0] = {SamplerName::kSampler0, texture}; mcmd.texture_handle = texture;
tx[1] = {SamplerName::kSampler1, palette_tex};
}, },
[&](const MergedTwodeeCommandFlatTexture& tex) [&](const MergedTwodeeCommandFlatTexture& tex)
{ {
Handle<Texture> th = flat_manager_->find_or_create_indexed(rhi, tex.lump); Handle<Texture> th = flat_manager_->find_or_create_indexed(rhi, tex.lump);
SRB2_ASSERT(th != kNullHandle); SRB2_ASSERT(th != kNullHandle);
tx[0] = {SamplerName::kSampler0, th}; mcmd.texture_handle = th;
tx[1] = {SamplerName::kSampler1, palette_tex};
}}; }};
if (mcmd.texture) if (mcmd.texture)
{ {
@ -519,8 +483,7 @@ void TwodeeRenderer::flush(Rhi& rhi, Twodee& twodee)
} }
else else
{ {
tx[0] = {SamplerName::kSampler0, default_tex_}; mcmd.texture_handle = default_tex_;
tx[1] = {SamplerName::kSampler1, palette_tex};
} }
const uint8_t* colormap = mcmd.colormap; const uint8_t* colormap = mcmd.colormap;
@ -530,38 +493,29 @@ void TwodeeRenderer::flush(Rhi& rhi, Twodee& twodee)
colormap_h = palette_manager_->find_or_create_colormap(rhi, colormap); colormap_h = palette_manager_->find_or_create_colormap(rhi, colormap);
SRB2_ASSERT(colormap_h != kNullHandle); SRB2_ASSERT(colormap_h != kNullHandle);
} }
tx[2] = {SamplerName::kSampler2, colormap_h}; mcmd.colormap_handle = colormap_h;
mcmd.binding_set =
rhi.create_binding_set(pipelines_[mcmd.pipeline_key], {tcb::span(vbos), tcb::span(tx)});
} }
ctx_list_itr++; 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({tcb::span(g1_uniforms)});
Handle<UniformSet> us_2 = rhi.create_uniform_set({tcb::span(g2_uniforms)});
// Presumably, we're already in a renderpass when flush is called // 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_) 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) for (auto& cmd : list.cmds)
{ {
if (cmd.elements == 0) if (cmd.elements == 0)
@ -570,13 +524,16 @@ void TwodeeRenderer::flush(Rhi& rhi, Twodee& twodee)
// This shouldn't happen, but, just in case... // This shouldn't happen, but, just in case...
continue; continue;
} }
SRB2_ASSERT(pipelines_.find(cmd.pipeline_key) != pipelines_.end()); RasterizerStateDesc desc;
Handle<Pipeline> pl = pipelines_[cmd.pipeline_key]; desc.cull = CullMode::kNone;
rhi.bind_pipeline(pl); 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_viewport({0, 0, static_cast<uint32_t>(vid.width), static_cast<uint32_t>(vid.height)});
rhi.bind_uniform_set(0, us_1); rhi.set_sampler("s_sampler0", 0, cmd.texture_handle);
rhi.bind_uniform_set(1, us_2); rhi.set_sampler("s_sampler2", 2, cmd.colormap_handle);
rhi.bind_binding_set(cmd.binding_set);
rhi.bind_index_buffer(list.ibo); rhi.bind_index_buffer(list.ibo);
rhi.draw_indexed(cmd.elements, cmd.index_offset); rhi.draw_indexed(cmd.elements, cmd.index_offset);
} }

View file

@ -11,10 +11,8 @@
#ifndef __SRB2_HWR2_PASS_TWODEE_HPP__ #ifndef __SRB2_HWR2_PASS_TWODEE_HPP__
#define __SRB2_HWR2_PASS_TWODEE_HPP__ #define __SRB2_HWR2_PASS_TWODEE_HPP__
#include <memory>
#include <optional> #include <optional>
#include <tuple> #include <tuple>
#include <unordered_map>
#include <variant> #include <variant>
#include <vector> #include <vector>
@ -65,10 +63,13 @@ struct MergedTwodeeCommandFlatTexture
struct MergedTwodeeCommand struct MergedTwodeeCommand
{ {
using Texture = std::variant<rhi::Handle<rhi::Texture>, MergedTwodeeCommandFlatTexture>; using Texture = std::variant<rhi::Handle<rhi::Texture>, MergedTwodeeCommandFlatTexture>;
TwodeePipelineKey pipeline_key = {}; rhi::PrimitiveType primitive;
rhi::Handle<rhi::BindingSet> binding_set = {}; BlendMode blend_mode;
std::optional<Texture> texture; std::optional<Texture> texture;
TwodeePipelineKey pipeline_key;
rhi::Handle<rhi::Texture> texture_handle;
const uint8_t* colormap; const uint8_t* colormap;
rhi::Handle<rhi::Texture> colormap_handle;
uint32_t index_offset = 0; uint32_t index_offset = 0;
uint32_t elements = 0; uint32_t elements = 0;
}; };
@ -96,7 +97,7 @@ class TwodeeRenderer final
std::vector<std::tuple<rhi::Handle<rhi::Buffer>, std::size_t>> ibos_; std::vector<std::tuple<rhi::Handle<rhi::Buffer>, std::size_t>> ibos_;
rhi::Handle<rhi::Texture> output_; rhi::Handle<rhi::Texture> output_;
rhi::Handle<rhi::Texture> default_tex_; 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 rewrite_patch_quad_vertices(Draw2dList& list, const Draw2dPatchQuad& cmd) const;

View file

@ -322,6 +322,7 @@ void I_FinishUpdate(void)
g_hw_state.blit_rect->draw(*rhi); g_hw_state.blit_rect->draw(*rhi);
break; break;
} }
rhi->end_render_pass(); rhi->end_render_pass();
postframe_update(*rhi); postframe_update(*rhi);

File diff suppressed because it is too large Load diff

View file

@ -71,7 +71,7 @@ struct Gl2Platform
virtual ~Gl2Platform(); virtual ~Gl2Platform();
virtual void present() = 0; 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; virtual Rect get_default_framebuffer_dimensions() = 0;
}; };
@ -93,26 +93,13 @@ struct Gl2Renderbuffer : public rhi::Renderbuffer
rhi::RenderbufferDesc desc; rhi::RenderbufferDesc desc;
}; };
struct Gl2UniformSet : public rhi::UniformSet struct Gl2Program : public rhi::Program
{
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
{ {
uint32_t vertex_shader = 0; uint32_t vertex_shader = 0;
uint32_t fragment_shader = 0; uint32_t fragment_shader = 0;
uint32_t program = 0; uint32_t program = 0;
std::unordered_map<rhi::VertexAttributeName, uint32_t> attrib_locations {2}; std::unordered_map<std::string, uint32_t> attrib_locations;
std::unordered_map<rhi::UniformName, uint32_t> uniform_locations {2}; std::unordered_map<std::string, uint32_t> uniform_locations;
std::unordered_map<rhi::SamplerName, uint32_t> sampler_locations {2};
rhi::PipelineDesc desc;
}; };
struct Gl2ActiveUniform struct Gl2ActiveUniform
@ -130,9 +117,7 @@ class Gl2Rhi final : public Rhi
Slab<Gl2Texture> texture_slab_; Slab<Gl2Texture> texture_slab_;
Slab<Gl2Buffer> buffer_slab_; Slab<Gl2Buffer> buffer_slab_;
Slab<Gl2Renderbuffer> renderbuffer_slab_; Slab<Gl2Renderbuffer> renderbuffer_slab_;
Slab<Gl2Pipeline> pipeline_slab_; Slab<Gl2Program> program_slab_;
Slab<Gl2UniformSet> uniform_set_slab_;
Slab<Gl2BindingSet> binding_set_slab_;
Handle<Buffer> current_index_buffer_; Handle<Buffer> current_index_buffer_;
@ -143,7 +128,7 @@ class Gl2Rhi final : public Rhi
}; };
using RenderPassState = std::variant<DefaultRenderPassState, RenderPassBeginInfo>; using RenderPassState = std::variant<DefaultRenderPassState, RenderPassBeginInfo>;
std::optional<RenderPassState> current_render_pass_; std::optional<RenderPassState> current_render_pass_;
std::optional<Handle<Pipeline>> current_pipeline_; std::optional<Handle<Program>> current_program_;
PrimitiveType current_primitive_type_ = PrimitiveType::kPoints; PrimitiveType current_primitive_type_ = PrimitiveType::kPoints;
uint32_t index_buffer_offset_ = 0; uint32_t index_buffer_offset_ = 0;
@ -153,13 +138,15 @@ class Gl2Rhi final : public Rhi
uint8_t stencil_back_reference_ = 0; uint8_t stencil_back_reference_ = 0;
uint8_t stencil_back_compare_mask_ = 0xFF; uint8_t stencil_back_compare_mask_ = 0xFF;
uint8_t stencil_back_write_mask_ = 0xFF; uint8_t stencil_back_write_mask_ = 0xFF;
CompareFunc stencil_front_func_;
CompareFunc stencil_back_func_;
public: public:
Gl2Rhi(std::unique_ptr<Gl2Platform>&& platform, GlLoadFunc load_func); Gl2Rhi(std::unique_ptr<Gl2Platform>&& platform, GlLoadFunc load_func);
virtual ~Gl2Rhi(); virtual ~Gl2Rhi();
virtual Handle<Pipeline> create_pipeline(const PipelineDesc& desc) override; virtual Handle<Program> create_program(const ProgramDesc& desc) override;
virtual void destroy_pipeline(Handle<Pipeline> handle) override; virtual void destroy_program(Handle<Program> handle) override;
virtual Handle<Texture> create_texture(const TextureDesc& desc) override; virtual Handle<Texture> create_texture(const TextureDesc& desc) override;
virtual void destroy_texture(Handle<Texture> handle) override; virtual void destroy_texture(Handle<Texture> handle) override;
@ -190,21 +177,33 @@ public:
TextureFilterMode min, TextureFilterMode min,
TextureFilterMode mag TextureFilterMode mag
) override; ) override;
virtual Handle<UniformSet>
create_uniform_set(const CreateUniformSetInfo& info) override;
virtual Handle<BindingSet>
create_binding_set(Handle<Pipeline> pipeline, const CreateBindingSetInfo& info)
override;
// Graphics context functions // Graphics context functions
virtual void begin_default_render_pass(bool clear) override; virtual void begin_default_render_pass(bool clear) override;
virtual void begin_render_pass(const RenderPassBeginInfo& info) override; virtual void begin_render_pass(const RenderPassBeginInfo& info) override;
virtual void end_render_pass() override; virtual void end_render_pass() override;
virtual void bind_pipeline(Handle<Pipeline> pipeline) override; virtual void bind_program(Handle<Program> program) override;
virtual void bind_uniform_set(uint32_t slot, Handle<UniformSet> set) override; virtual void bind_vertex_attrib(
virtual void bind_binding_set(Handle<BindingSet> set) override; 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 bind_index_buffer(Handle<Buffer> buffer) override;
virtual void set_scissor(const Rect& rect) 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 set_viewport(const Rect& rect) override;
virtual void draw(uint32_t vertex_count, uint32_t first_vertex) 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 draw_indexed(uint32_t index_count, uint32_t first_index) override;

View file

@ -24,6 +24,7 @@
#include <tcb/span.hpp> #include <tcb/span.hpp>
#include "../core/static_vec.hpp" #include "../core/static_vec.hpp"
#include "glm/ext/vector_float2.hpp"
#include "handle.hpp" #include "handle.hpp"
namespace srb2::rhi namespace srb2::rhi
@ -38,7 +39,8 @@ struct Texture
{ {
}; };
struct Pipeline /// @brief A linked rendering pipeline program combining a vertex shader and fragment shader.
struct Program
{ {
}; };
@ -397,16 +399,6 @@ struct ColorMask
bool a; 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 enum class StencilOp
{ {
kKeep, kKeep,
@ -419,42 +411,41 @@ enum class StencilOp
kDecrementWrap kDecrementWrap
}; };
struct PipelineStencilOpStateDesc
struct ProgramDesc
{ {
StencilOp fail; const char* name;
StencilOp pass; tcb::span<const char*> defines;
StencilOp depth_fail;
CompareFunc stencil_compare;
}; };
struct PipelineDepthStencilStateDesc struct RasterizerStateDesc
{ {
bool depth_test; PrimitiveType primitive = PrimitiveType::kTriangles;
bool depth_write; CullMode cull = CullMode::kBack;
CompareFunc depth_func; FaceWinding winding = FaceWinding::kCounterClockwise;
bool stencil_test; ColorMask color_mask = {true, true, true, true};
PipelineStencilOpStateDesc front; bool blend_enabled = false;
PipelineStencilOpStateDesc back; 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;
struct PipelineColorStateDesc BlendFunction blend_color_function = BlendFunction::kAdd;
{ BlendFactor blend_source_factor_alpha = BlendFactor::kOne;
std::optional<BlendDesc> blend; BlendFactor blend_dest_factor_alpha = BlendFactor::kZero;
ColorMask color_mask; BlendFunction blend_alpha_function = BlendFunction::kAdd;
}; bool depth_test = false;
bool depth_write = true;
struct PipelineDesc CompareFunc depth_func = CompareFunc::kLess;
{ bool stencil_test = false;
PipelineProgram program; StencilOp front_fail = StencilOp::kKeep;
VertexInputDesc vertex_input; StencilOp front_pass = StencilOp::kKeep;
UniformInputDesc uniform_input; StencilOp front_depth_fail = StencilOp::kKeep;
SamplerInputDesc sampler_input; CompareFunc front_stencil_compare = CompareFunc::kAlways;
std::optional<PipelineDepthStencilStateDesc> depth_stencil_state; StencilOp back_fail = StencilOp::kKeep;
PipelineColorStateDesc color_state; StencilOp back_pass = StencilOp::kKeep;
PrimitiveType primitive; StencilOp back_depth_fail = StencilOp::kKeep;
CullMode cull; CompareFunc back_stencil_compare = CompareFunc::kAlways;
FaceWinding winding; bool scissor_test = false;
glm::vec4 blend_color; Rect scissor = {};
}; };
struct RenderbufferDesc struct RenderbufferDesc
@ -565,13 +556,6 @@ struct CreateBindingSetInfo
tcb::span<TextureBinding> sampler_textures; tcb::span<TextureBinding> sampler_textures;
}; };
struct UniformSet
{
};
struct BindingSet
{
};
struct TextureDetails struct TextureDetails
{ {
uint32_t width; uint32_t width;
@ -588,8 +572,8 @@ struct Rhi
{ {
virtual ~Rhi(); virtual ~Rhi();
virtual Handle<Pipeline> create_pipeline(const PipelineDesc& desc) = 0; virtual Handle<Program> create_program(const ProgramDesc& desc) = 0;
virtual void destroy_pipeline(Handle<Pipeline> handle) = 0; virtual void destroy_program(Handle<Program> handle) = 0;
virtual Handle<Texture> create_texture(const TextureDesc& desc) = 0; virtual Handle<Texture> create_texture(const TextureDesc& desc) = 0;
virtual void destroy_texture(Handle<Texture> handle) = 0; virtual void destroy_texture(Handle<Texture> handle) = 0;
@ -620,19 +604,33 @@ struct Rhi
TextureFilterMode min, TextureFilterMode min,
TextureFilterMode mag TextureFilterMode mag
) = 0; ) = 0;
virtual Handle<UniformSet> create_uniform_set(const CreateUniformSetInfo& info) = 0;
virtual Handle<BindingSet>
create_binding_set(Handle<Pipeline> pipeline, const CreateBindingSetInfo& info) = 0;
// Graphics context functions // Graphics context functions
virtual void begin_default_render_pass(bool clear) = 0; virtual void begin_default_render_pass(bool clear) = 0;
virtual void begin_render_pass(const RenderPassBeginInfo& info) = 0; virtual void begin_render_pass(const RenderPassBeginInfo& info) = 0;
virtual void end_render_pass() = 0; virtual void end_render_pass() = 0;
virtual void bind_pipeline(Handle<Pipeline> pipeline) = 0; virtual void bind_program(Handle<Program> program) = 0;
virtual void bind_uniform_set(uint32_t slot, Handle<UniformSet> set) = 0; virtual void bind_vertex_attrib(
virtual void bind_binding_set(Handle<BindingSet> set) = 0; 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 bind_index_buffer(Handle<Buffer> buffer) = 0;
virtual void set_scissor(const Rect& rect) = 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 set_viewport(const Rect& rect) = 0;
virtual void draw(uint32_t vertex_count, uint32_t first_vertex) = 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 draw_indexed(uint32_t index_count, uint32_t first_index) = 0;

View file

@ -12,6 +12,7 @@
/// \file /// \file
/// \brief SRB2 graphics stuff for SDL /// \brief SRB2 graphics stuff for SDL
#include <SDL_video.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <memory> #include <memory>

View file

@ -34,35 +34,10 @@ void SdlGl2Platform::present()
SDL_GL_SwapWindow(window); 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) std::string vertex_list_name = fmt::format("rhi_glsllist_{}_vertex", name);
{ std::string fragment_list_name = fmt::format("rhi_glsllist_{}_fragment", name);
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);
return {std::move(vertex_list_name), std::move(fragment_list_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>> 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> 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()); std::vector<std::string> fragment_sources = get_sources_from_glsllist_lump(glsllist_names[1].c_str());

View file

@ -27,7 +27,7 @@ struct SdlGl2Platform final : public Gl2Platform
virtual void present() override; virtual void present() override;
virtual std::tuple<std::vector<std::string>, std::vector<std::string>> 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; virtual Rect get_default_framebuffer_dimensions() override;
}; };