diff --git a/src/core/static_vec.hpp b/src/core/static_vec.hpp index f7bd26d69..823469649 100644 --- a/src/core/static_vec.hpp +++ b/src/core/static_vec.hpp @@ -5,14 +5,15 @@ #include #include #include -#include #include +#include #include #include #include "../cxxutil.hpp" -namespace srb2 { +namespace srb2 +{ template class StaticVec @@ -98,15 +99,9 @@ public: return *this; } - void push_back(const T& value) - { - arr_[size_++] = value; - } + void push_back(const T& value) { arr_[size_++] = value; } - void pop_back() - { - arr_[size_--] = T(); - } + void pop_back() { arr_[size_--] = T(); } void resize(size_t size, T value = T()) { @@ -135,80 +130,35 @@ public: } } - constexpr T* begin() noexcept - { - return &arr_[0]; - } + constexpr T* begin() noexcept { return &arr_[0]; } - constexpr const T* begin() const noexcept - { - return cbegin(); - } + constexpr const T* begin() const noexcept { return cbegin(); } - constexpr const T* cbegin() const noexcept - { - return &arr_[0]; - } + constexpr const T* cbegin() const noexcept { return &arr_[0]; } - constexpr T* end() noexcept - { - return &arr_[size_]; - } + constexpr T* end() noexcept { return &arr_[size_]; } - constexpr const T* end() const noexcept - { - return cend(); - } + constexpr const T* end() const noexcept { return cend(); } - constexpr const T* cend() const noexcept - { - return &arr_[size_]; - } + constexpr const T* cend() const noexcept { return &arr_[size_]; } - constexpr std::reverse_iterator rbegin() noexcept - { - return &arr_[size_]; - } + constexpr std::reverse_iterator rbegin() noexcept { return &arr_[size_]; } - constexpr std::reverse_iterator crbegin() const noexcept - { - return &arr_[size_]; - } + constexpr std::reverse_iterator crbegin() const noexcept { return &arr_[size_]; } - constexpr std::reverse_iterator rend() noexcept - { - return &arr_[0]; - } + constexpr std::reverse_iterator rend() noexcept { return &arr_[0]; } - constexpr std::reverse_iterator crend() const noexcept - { - return &arr_[0]; - } + constexpr std::reverse_iterator crend() const noexcept { return &arr_[0]; } - constexpr bool empty() const noexcept - { - return size_ == 0; - } + constexpr bool empty() const noexcept { return size_ == 0; } - constexpr size_t size() const noexcept - { - return size_; - } + constexpr size_t size() const noexcept { return size_; } - constexpr size_t capacity() const noexcept - { - return Limit; - } + constexpr size_t capacity() const noexcept { return Limit; } - constexpr size_t max_size() const noexcept - { - return Limit; - } + constexpr size_t max_size() const noexcept { return Limit; } - constexpr T& operator[](size_t index) noexcept - { - return arr_[index]; - } + constexpr T& operator[](size_t index) noexcept { return arr_[index]; } T& at(size_t index) { @@ -219,10 +169,7 @@ public: return this[index]; } - constexpr const T& operator[](size_t index) const noexcept - { - return arr_[index]; - } + constexpr const T& operator[](size_t index) const noexcept { return arr_[index]; } const T& at(size_t index) const { @@ -233,15 +180,9 @@ public: return this[index]; } - T& front() - { - return *arr_[0]; - } + T& front() { return *arr_[0]; } - T& back() - { - return *arr_[size_ - 1]; - } + T& back() { return *arr_[size_ - 1]; } }; } // namespace srb2 @@ -254,7 +195,8 @@ bool operator==(const srb2::StaticVec& lhs, const srb2::StaticVec& { return false; } - for (size_t i = 0; i < lhs; i++) { + for (size_t i = 0; i < lhs; i++) + { if (rhs[i] != lhs[i]) { return false; @@ -274,8 +216,8 @@ struct std::hash> { uint64_t operator()(const srb2::StaticVec& input) const { - constexpr const uint64_t prime { 0x00000100000001B3 }; - std::size_t ret { 0xcbf29ce484222325 }; + constexpr const uint64_t prime {0x00000100000001B3}; + std::size_t ret {0xcbf29ce484222325}; for (auto itr = input.begin(); itr != input.end(); itr++) { diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp index 3e9dabaa0..d80818e9f 100644 --- a/src/i_video_common.cpp +++ b/src/i_video_common.cpp @@ -7,9 +7,9 @@ #include #include "cxxutil.hpp" -#include "v_video.h" #include "hwr2/pass_imgui.hpp" #include "hwr2/pass_software.hpp" +#include "v_video.h" // KILL THIS WHEN WE KILL OLD OGL SUPPORT PLEASE #include "sdl/ogl_sdl.h" diff --git a/src/rhi/gl3_core/gl3_core_rhi.cpp b/src/rhi/gl3_core/gl3_core_rhi.cpp index 55e77fe00..55d9b3948 100644 --- a/src/rhi/gl3_core/gl3_core_rhi.cpp +++ b/src/rhi/gl3_core/gl3_core_rhi.cpp @@ -16,21 +16,32 @@ using srb2::rhi::GlCorePlatform; using srb2::rhi::GlCoreRhi; #if 1 -#define GL_ASSERT {GLenum __err = gl_->GetError(); if (__err != GL_NO_ERROR) { I_Error("GL Error at %s %d: %d", __FILE__, __LINE__, __err); }} +#define GL_ASSERT \ + { \ + GLenum __err = gl_->GetError(); \ + if (__err != GL_NO_ERROR) \ + { \ + I_Error("GL Error at %s %d: %d", __FILE__, __LINE__, __err); \ + } \ + } #else #define GL_ASSERT ; #endif -namespace { +namespace +{ template -std::unique_ptr> static_unique_ptr_cast(std::unique_ptr> ptr) { +std::unique_ptr> static_unique_ptr_cast(std::unique_ptr> ptr) +{ D* derived = static_cast(ptr.release()); return std::unique_ptr>(derived, std::default_delete()); } -constexpr GLenum map_pixel_format(rhi::PixelFormat format) { - switch (format) { +constexpr GLenum map_pixel_format(rhi::PixelFormat format) +{ + switch (format) + { case rhi::PixelFormat::kRGBA8: return GL_RGBA8; case rhi::PixelFormat::kDepth16: @@ -42,11 +53,13 @@ constexpr GLenum map_pixel_format(rhi::PixelFormat format) { } } -constexpr std::tuple map_pixel_data_format(rhi::PixelFormat format) { +constexpr std::tuple map_pixel_data_format(rhi::PixelFormat format) +{ GLenum layout = GL_ZERO; GLenum type = GL_ZERO; GLuint size = 0; - switch (format) { + switch (format) + { case rhi::PixelFormat::kR8: layout = GL_RED; type = GL_UNSIGNED_BYTE; @@ -63,8 +76,10 @@ constexpr std::tuple map_pixel_data_format(rhi::PixelFor return std::tuple(layout, type, size); } -constexpr GLenum map_texture_format(rhi::TextureFormat format) { - switch (format) { +constexpr GLenum map_texture_format(rhi::TextureFormat format) +{ + switch (format) + { case rhi::TextureFormat::kRGBA: return GL_RGBA; case rhi::TextureFormat::kRGB: @@ -76,8 +91,10 @@ constexpr GLenum map_texture_format(rhi::TextureFormat format) { } } -constexpr GLenum map_buffer_type(rhi::BufferType type) { - switch (type) { +constexpr GLenum map_buffer_type(rhi::BufferType type) +{ + switch (type) + { case rhi::BufferType::kVertexBuffer: return GL_ARRAY_BUFFER; case rhi::BufferType::kIndexBuffer: @@ -87,8 +104,10 @@ constexpr GLenum map_buffer_type(rhi::BufferType type) { } } -constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) { - switch (usage) { +constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) +{ + switch (usage) + { case rhi::BufferUsage::kImmutable: return GL_STATIC_DRAW; case rhi::BufferUsage::kDynamic: @@ -98,8 +117,10 @@ constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) { } } -constexpr GLenum map_compare_func(rhi::CompareFunc func) { - switch (func) { +constexpr GLenum map_compare_func(rhi::CompareFunc func) +{ + switch (func) + { case rhi::CompareFunc::kNever: return GL_NEVER; case rhi::CompareFunc::kLess: @@ -121,8 +142,10 @@ constexpr GLenum map_compare_func(rhi::CompareFunc func) { } } -constexpr GLenum map_blend_factor(rhi::BlendFactor factor) { - switch (factor) { +constexpr GLenum map_blend_factor(rhi::BlendFactor factor) +{ + switch (factor) + { case rhi::BlendFactor::kZero: return GL_ZERO; case rhi::BlendFactor::kOne: @@ -158,8 +181,10 @@ constexpr GLenum map_blend_factor(rhi::BlendFactor factor) { } } -constexpr GLenum map_blend_function(rhi::BlendFunction function) { - switch (function) { +constexpr GLenum map_blend_function(rhi::BlendFunction function) +{ + switch (function) + { case rhi::BlendFunction::kAdd: return GL_FUNC_ADD; case rhi::BlendFunction::kSubtract: @@ -171,8 +196,10 @@ constexpr GLenum map_blend_function(rhi::BlendFunction function) { } } -constexpr GLenum map_cull_mode(rhi::CullMode mode) { - switch (mode) { +constexpr GLenum map_cull_mode(rhi::CullMode mode) +{ + switch (mode) + { case rhi::CullMode::kNone: return GL_NONE; case rhi::CullMode::kFront: @@ -184,8 +211,10 @@ constexpr GLenum map_cull_mode(rhi::CullMode mode) { } } -constexpr GLenum map_winding(rhi::FaceWinding winding) { - switch (winding) { +constexpr GLenum map_winding(rhi::FaceWinding winding) +{ + switch (winding) + { case rhi::FaceWinding::kCounterClockwise: return GL_CCW; case rhi::FaceWinding::kClockwise: @@ -195,8 +224,10 @@ constexpr GLenum map_winding(rhi::FaceWinding winding) { } } -constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) { - switch (type) { +constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) +{ + switch (type) + { case rhi::PrimitiveType::kPoints: return GL_POINTS; case rhi::PrimitiveType::kLines: @@ -214,8 +245,10 @@ constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) { } } -constexpr const char* map_vertex_attribute_symbol_name(rhi::VertexAttributeName name) { - switch (name) { +constexpr const char* map_vertex_attribute_symbol_name(rhi::VertexAttributeName name) +{ + switch (name) + { case rhi::VertexAttributeName::kPosition: return "a_position"; case rhi::VertexAttributeName::kNormal: @@ -231,8 +264,10 @@ constexpr const char* map_vertex_attribute_symbol_name(rhi::VertexAttributeName } } -constexpr const char* map_vertex_attribute_enable_define(rhi::VertexAttributeName name) { - switch (name) { +constexpr const char* map_vertex_attribute_enable_define(rhi::VertexAttributeName name) +{ + switch (name) + { case rhi::VertexAttributeName::kPosition: return "ENABLE_VA_POSITION"; case rhi::VertexAttributeName::kNormal: @@ -248,8 +283,10 @@ constexpr const char* map_vertex_attribute_enable_define(rhi::VertexAttributeNam } } -constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) { - switch (name) { +constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) +{ + switch (name) + { case rhi::UniformName::kTime: return "u_time"; case rhi::UniformName::kModelView: @@ -263,8 +300,10 @@ constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) { } } -constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) { - switch (name) { +constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) +{ + switch (name) + { case rhi::SamplerName::kSampler0: return "s_sampler0"; case rhi::SamplerName::kSampler1: @@ -278,8 +317,10 @@ constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) { } } -constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) { - switch (format) { +constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) +{ + switch (format) + { case rhi::VertexAttributeFormat::kFloat: return GL_FLOAT; case rhi::VertexAttributeFormat::kFloat2: @@ -293,8 +334,10 @@ constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) } } -constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) { - switch (format) { +constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) +{ + switch (format) + { case rhi::VertexAttributeFormat::kFloat: return GL_FLOAT; case rhi::VertexAttributeFormat::kFloat2: @@ -308,8 +351,10 @@ constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) { } } -constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat format) { - switch (format) { +constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat format) +{ + switch (format) + { case rhi::VertexAttributeFormat::kFloat: return 1; case rhi::VertexAttributeFormat::kFloat2: @@ -323,8 +368,10 @@ constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat form } } -constexpr GLenum map_uniform_format(rhi::UniformFormat format) { - switch (format) { +constexpr GLenum map_uniform_format(rhi::UniformFormat format) +{ + switch (format) + { case rhi::UniformFormat::kFloat: return GL_FLOAT; case rhi::UniformFormat::kFloat2: @@ -352,24 +399,28 @@ constexpr GLenum map_uniform_format(rhi::UniformFormat format) { } } -struct GlCoreTexture : public rhi::Texture { +struct GlCoreTexture : public rhi::Texture +{ GLuint texture; rhi::TextureDesc desc; GlCoreTexture(GLuint texture, const rhi::TextureDesc& desc) noexcept : texture(texture), desc(desc) {} }; -struct GlCoreBuffer : public rhi::Buffer { +struct GlCoreBuffer : public rhi::Buffer +{ GLuint buffer; rhi::BufferDesc desc; GlCoreBuffer(GLuint buffer, const rhi::BufferDesc& desc) noexcept : buffer(buffer), desc(desc) {} }; -struct GlCoreRenderPass : public rhi::RenderPass { +struct GlCoreRenderPass : public rhi::RenderPass +{ rhi::RenderPassDesc desc; explicit GlCoreRenderPass(const rhi::RenderPassDesc& desc) noexcept : desc(desc) {} }; -struct GlCoreRenderbuffer : public rhi::Renderbuffer { +struct GlCoreRenderbuffer : public rhi::Renderbuffer +{ GLuint renderbuffer; explicit GlCoreRenderbuffer(GLuint renderbuffer) noexcept : renderbuffer(renderbuffer) {} @@ -386,7 +437,8 @@ struct GlCoreBindingSet : public rhi::BindingSet std::unordered_map textures {4}; }; -struct GlCorePipeline : public rhi::Pipeline { +struct GlCorePipeline : public rhi::Pipeline +{ GLuint vertex_shader = 0; GLuint fragment_shader = 0; GLuint program = 0; @@ -396,11 +448,16 @@ struct GlCorePipeline : public rhi::Pipeline { rhi::PipelineDesc desc; }; -struct GlCoreGraphicsContext : public rhi::GraphicsContext {}; +struct GlCoreGraphicsContext : public rhi::GraphicsContext +{ +}; -struct GlCoreTransferContext : public rhi::TransferContext {}; +struct GlCoreTransferContext : public rhi::TransferContext +{ +}; -struct GlCoreActiveUniform { +struct GlCoreActiveUniform +{ GLenum type; GLuint location; }; @@ -409,29 +466,32 @@ struct GlCoreActiveUniform { GlCorePlatform::~GlCorePlatform() = default; -GlCoreRhi::GlCoreRhi(std::unique_ptr&& platform, GlLoadFunc load_func) - : platform_(std::move(platform)) { +GlCoreRhi::GlCoreRhi(std::unique_ptr&& platform, GlLoadFunc load_func) : platform_(std::move(platform)) +{ gl_ = std::make_unique(); gladLoadGLContext(gl_.get(), load_func); } GlCoreRhi::~GlCoreRhi() = default; -rhi::Handle GlCoreRhi::create_render_pass(const rhi::RenderPassDesc& desc) { +rhi::Handle GlCoreRhi::create_render_pass(const rhi::RenderPassDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); // GL has no formal render pass object return render_pass_slab_.insert(std::make_unique(desc)); } -void GlCoreRhi::destroy_render_pass(rhi::Handle handle) { +void GlCoreRhi::destroy_render_pass(rhi::Handle handle) +{ SRB2_ASSERT(graphics_context_active_ == false); std::unique_ptr buffer = render_pass_slab_.remove(handle); std::unique_ptr casted(static_cast(buffer.release())); } -rhi::Handle GlCoreRhi::create_texture(const rhi::TextureDesc& desc) { +rhi::Handle GlCoreRhi::create_texture(const rhi::TextureDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); GLenum internal_format = map_texture_format(desc.format); @@ -442,16 +502,22 @@ rhi::Handle GlCoreRhi::create_texture(const rhi::TextureDesc& desc gl_->BindTexture(GL_TEXTURE_2D, name); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); GL_ASSERT - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); GL_ASSERT - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); GL_ASSERT - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); GL_ASSERT - gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.width, desc.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); GL_ASSERT + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + GL_ASSERT + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + GL_ASSERT + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + GL_ASSERT + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + GL_ASSERT + gl_->TexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.width, desc.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + GL_ASSERT return texture_slab_.insert(std::make_unique(name, desc)); } -void GlCoreRhi::destroy_texture(rhi::Handle handle) { +void GlCoreRhi::destroy_texture(rhi::Handle handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(texture_slab_.is_valid(handle) == true); @@ -460,7 +526,14 @@ void GlCoreRhi::destroy_texture(rhi::Handle handle) { disposal_.push_back([this, name] { gl_->DeleteTextures(1, &name); }); } -void GlCoreRhi::update_texture(Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) { +void GlCoreRhi::update_texture( + Handle ctx, + Handle texture, + Rect region, + srb2::rhi::PixelFormat data_format, + tcb::span data +) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(transfer_context_active_ == true); SRB2_ASSERT(ctx.generation() == transfer_context_generation_); @@ -482,12 +555,26 @@ void GlCoreRhi::update_texture(Handle ctx, Handle text SRB2_ASSERT(region.w * region.h * size == data.size_bytes()); SRB2_ASSERT(region.x + region.w <= t.desc.width && region.y + region.h <= t.desc.height); - gl_->ActiveTexture(GL_TEXTURE0); GL_ASSERT - gl_->BindTexture(GL_TEXTURE_2D, t.texture); GL_ASSERT - gl_->TexSubImage2D(GL_TEXTURE_2D, 0, region.x, region.y, region.w, region.h, format, type, reinterpret_cast(data.data())); GL_ASSERT + gl_->ActiveTexture(GL_TEXTURE0); + GL_ASSERT + gl_->BindTexture(GL_TEXTURE_2D, t.texture); + GL_ASSERT + gl_->TexSubImage2D( + GL_TEXTURE_2D, + 0, + region.x, + region.y, + region.w, + region.h, + format, + type, + reinterpret_cast(data.data()) + ); + GL_ASSERT } -rhi::Handle GlCoreRhi::create_buffer(const rhi::BufferDesc& desc) { +rhi::Handle GlCoreRhi::create_buffer(const rhi::BufferDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); GLenum target = map_buffer_type(desc.type); @@ -497,16 +584,20 @@ rhi::Handle GlCoreRhi::create_buffer(const rhi::BufferDesc& desc) { SRB2_ASSERT(usage != GL_ZERO); GLuint name = 0; - gl_->GenBuffers(1, &name); GL_ASSERT + gl_->GenBuffers(1, &name); + GL_ASSERT - gl_->BindBuffer(target, name); GL_ASSERT + gl_->BindBuffer(target, name); + GL_ASSERT - gl_->BufferData(target, desc.size, nullptr, usage); GL_ASSERT + gl_->BufferData(target, desc.size, nullptr, usage); + GL_ASSERT return buffer_slab_.insert(std::make_unique(name, desc)); } -void GlCoreRhi::destroy_buffer(rhi::Handle handle) { +void GlCoreRhi::destroy_buffer(rhi::Handle handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(buffer_slab_.is_valid(handle) == true); @@ -517,7 +608,13 @@ void GlCoreRhi::destroy_buffer(rhi::Handle handle) { disposal_.push_back([this, name] { gl_->DeleteBuffers(1, &name); }); } -void GlCoreRhi::update_buffer_contents(rhi::Handle ctx, rhi::Handle handle, uint32_t offset, tcb::span data) { +void GlCoreRhi::update_buffer_contents( + rhi::Handle ctx, + rhi::Handle handle, + uint32_t offset, + tcb::span data +) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(transfer_context_active_ == true); SRB2_ASSERT(ctx.generation() == transfer_context_generation_); @@ -533,7 +630,8 @@ void GlCoreRhi::update_buffer_contents(rhi::Handle ctx, rhi::Ha SRB2_ASSERT(offset < b.desc.size && offset + data.size() <= b.desc.size); GLenum target = GL_ZERO; - switch (b.desc.type) { + switch (b.desc.type) + { case rhi::BufferType::kVertexBuffer: target = GL_ARRAY_BUFFER; break; @@ -542,11 +640,14 @@ void GlCoreRhi::update_buffer_contents(rhi::Handle ctx, rhi::Ha break; } - gl_->BindBuffer(target, b.buffer); GL_ASSERT - gl_->BufferSubData(target, offset, data.size(), data.data()); GL_ASSERT + gl_->BindBuffer(target, b.buffer); + GL_ASSERT + gl_->BufferSubData(target, offset, data.size(), data.data()); + GL_ASSERT } -rhi::Handle GlCoreRhi::create_uniform_set(rhi::Handle ctx, const rhi::CreateUniformSetInfo& info) +rhi::Handle +GlCoreRhi::create_uniform_set(rhi::Handle ctx, const rhi::CreateUniformSetInfo& info) { SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(transfer_context_active_ == true); @@ -562,7 +663,11 @@ rhi::Handle GlCoreRhi::create_uniform_set(rhi::Handle(std::move(uniform_set))); } -rhi::Handle GlCoreRhi::create_binding_set(rhi::Handle ctx, Handle pipeline, const rhi::CreateBindingSetInfo& info) +rhi::Handle GlCoreRhi::create_binding_set( + rhi::Handle ctx, + Handle pipeline, + const rhi::CreateBindingSetInfo& info +) { SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(transfer_context_active_ == true); @@ -576,18 +681,22 @@ rhi::Handle GlCoreRhi::create_binding_set(rhi::HandleGenVertexArrays(1, &vao); GL_ASSERT - gl_->BindVertexArray(vao); GL_ASSERT + gl_->GenVertexArrays(1, &vao); + GL_ASSERT + gl_->BindVertexArray(vao); + GL_ASSERT for (auto& attr_layout : pl.desc.vertex_input.attr_layouts) { SRB2_ASSERT(buffer_slab_.is_valid(info.vertex_buffers[attr_layout.buffer_index].vertex_buffer)); - auto& buf = *static_cast(&buffer_slab_[info.vertex_buffers[attr_layout.buffer_index].vertex_buffer]); + auto& buf = + *static_cast(&buffer_slab_[info.vertex_buffers[attr_layout.buffer_index].vertex_buffer]); SRB2_ASSERT(buf.desc.type == rhi::BufferType::kVertexBuffer); auto& buffer_layout = pl.desc.vertex_input.buffer_layouts[attr_layout.buffer_index]; - gl_->BindBuffer(GL_ARRAY_BUFFER, buf.buffer); GL_ASSERT + gl_->BindBuffer(GL_ARRAY_BUFFER, buf.buffer); + GL_ASSERT GLuint attrib_location = pl.attrib_locations[attr_layout.name]; VertexAttributeFormat vert_attr_format = rhi::vertex_attribute_format(attr_layout.name); @@ -596,8 +705,17 @@ rhi::Handle GlCoreRhi::create_binding_set(rhi::HandleEnableVertexAttribArray(pl.attrib_locations[attr_layout.name]); GL_ASSERT - gl_->VertexAttribPointer(attrib_location, vertex_attr_size, vertex_attr_type, GL_FALSE, buffer_layout.stride, reinterpret_cast(vertex_buffer_offset + attr_layout.offset)); GL_ASSERT + gl_->EnableVertexAttribArray(pl.attrib_locations[attr_layout.name]); + GL_ASSERT + gl_->VertexAttribPointer( + attrib_location, + vertex_attr_size, + vertex_attr_type, + GL_FALSE, + buffer_layout.stride, + reinterpret_cast(vertex_buffer_offset + attr_layout.offset) + ); + GL_ASSERT } binding_set.vao = vao; @@ -617,20 +735,24 @@ rhi::Handle GlCoreRhi::create_binding_set(rhi::Handle(std::move(binding_set))); } -rhi::Handle GlCoreRhi::create_renderbuffer(const rhi::RenderbufferDesc& desc) { +rhi::Handle GlCoreRhi::create_renderbuffer(const rhi::RenderbufferDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); GLuint name = 0; gl_->GenRenderbuffers(1, &name); // Obtain storage up-front. - gl_->BindRenderbuffer(GL_RENDERBUFFER, name); GL_ASSERT - gl_->RenderbufferStorage(GL_RENDERBUFFER, map_pixel_format(desc.format), desc.width, desc.height); GL_ASSERT + gl_->BindRenderbuffer(GL_RENDERBUFFER, name); + GL_ASSERT + gl_->RenderbufferStorage(GL_RENDERBUFFER, map_pixel_format(desc.format), desc.width, desc.height); + GL_ASSERT return renderbuffer_slab_.insert(std::make_unique(GlCoreRenderbuffer {name})); } -void GlCoreRhi::destroy_renderbuffer(rhi::Handle handle) { +void GlCoreRhi::destroy_renderbuffer(rhi::Handle handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(renderbuffer_slab_.is_valid(handle) == true); @@ -640,7 +762,8 @@ void GlCoreRhi::destroy_renderbuffer(rhi::Handle handle) { disposal_.push_back([this, name] { gl_->DeleteRenderbuffers(1, &name); }); } -rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) { +rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(platform_ != nullptr); // TODO assert compatibility of pipeline description with program using ProgramRequirements @@ -696,20 +819,23 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) gl_->CompileShader(vertex); GLint is_compiled = 0; gl_->GetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + if (is_compiled == GL_FALSE) + { GLint max_length = 0; gl_->GetShaderiv(vertex, GL_INFO_LOG_LENGTH, &max_length); std::vector compile_error(max_length); gl_->GetShaderInfoLog(vertex, max_length, &max_length, compile_error.data()); gl_->DeleteShader(vertex); - throw std::runtime_error(fmt::format("Vertex shader compilation failed: {}", std::string(compile_error.data()))); + throw std::runtime_error(fmt::format("Vertex shader compilation failed: {}", std::string(compile_error.data())) + ); } fragment = gl_->CreateShader(GL_FRAGMENT_SHADER); gl_->ShaderSource(fragment, 1, frag_src_arr, frag_src_arr_lens); gl_->CompileShader(fragment); gl_->GetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + if (is_compiled == GL_FALSE) + { GLint max_length = 0; gl_->GetShaderiv(fragment, GL_INFO_LOG_LENGTH, &max_length); std::vector compile_error(max_length); @@ -717,7 +843,9 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); - throw std::runtime_error(fmt::format("Fragment shader compilation failed: {}", std::string(compile_error.data()))); + throw std::runtime_error( + fmt::format("Fragment shader compilation failed: {}", std::string(compile_error.data())) + ); } // Program link @@ -727,7 +855,8 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) gl_->AttachShader(program, fragment); gl_->LinkProgram(program); gl_->GetProgramiv(program, GL_LINK_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + if (is_compiled == GL_FALSE) + { GLint max_length = 0; gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &max_length); std::vector link_error(max_length); @@ -742,74 +871,85 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) std::unordered_map active_attributes; GLint active_attribute_total = -1; gl_->GetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attribute_total); - if (active_attribute_total < 0) { + if (active_attribute_total < 0) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); throw std::runtime_error("Unable to retrieve program active attributes"); } - if (desc.vertex_input.attr_layouts.size() != static_cast(active_attribute_total)) { + if (desc.vertex_input.attr_layouts.size() != static_cast(active_attribute_total)) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); - throw std::runtime_error( - fmt::format( - "Pipeline's enabled attribute count does not match the linked program's total: {} vs {}", - desc.vertex_input.attr_layouts.size(), - static_cast(active_attribute_total) - ) - ); + throw std::runtime_error(fmt::format( + "Pipeline's enabled attribute count does not match the linked program's total: {} vs {}", + desc.vertex_input.attr_layouts.size(), + static_cast(active_attribute_total) + )); } - for (GLint i = 0; i < active_attribute_total; i++) { + for (GLint i = 0; i < active_attribute_total; i++) + { GLsizei name_len = 0; GLint size = 0; GLenum type = GL_ZERO; char name[256]; - gl_->GetActiveAttrib(program, i, 255, &name_len, &size, &type, name); GL_ASSERT - GLint location = gl_->GetAttribLocation(program, name); GL_ASSERT + gl_->GetActiveAttrib(program, i, 255, &name_len, &size, &type, name); + GL_ASSERT + GLint location = gl_->GetAttribLocation(program, name); + GL_ASSERT active_attributes.insert({std::string(name), GlCoreActiveUniform {type, static_cast(location)}}); } std::unordered_map active_uniforms; size_t total_enabled_uniforms = 0; - for (auto g = desc.uniform_input.enabled_uniforms.cbegin() ; g != desc.uniform_input.enabled_uniforms.cend(); g = std::next(g)) + for (auto g = desc.uniform_input.enabled_uniforms.cbegin(); g != desc.uniform_input.enabled_uniforms.cend(); + g = std::next(g)) { total_enabled_uniforms += g->size(); } GLint active_uniform_total = -1; gl_->GetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_total); - if (active_uniform_total < 0) { + if (active_uniform_total < 0) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); throw std::runtime_error("Unable to retrieve program active uniforms"); } - if (total_enabled_uniforms + desc.sampler_input.enabled_samplers.size() != static_cast(active_uniform_total)) { + if (total_enabled_uniforms + desc.sampler_input.enabled_samplers.size() != + static_cast(active_uniform_total)) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); - throw std::runtime_error( - fmt::format( - "Pipeline's enabled uniform count (uniforms + samplers) does not match the linked program's total: {} vs {}", - total_enabled_uniforms + desc.sampler_input.enabled_samplers.size(), - static_cast(active_uniform_total) - ) - ); + throw std::runtime_error(fmt::format( + "Pipeline's enabled uniform count (uniforms + samplers) does not match the linked program's total: {} vs " + "{}", + total_enabled_uniforms + desc.sampler_input.enabled_samplers.size(), + static_cast(active_uniform_total) + )); } - for (GLint i = 0; i < active_uniform_total; i++) { + for (GLint i = 0; i < active_uniform_total; i++) + { GLsizei name_len = 0; GLint size = 0; GLenum type = GL_ZERO; char name[256]; - gl_->GetActiveUniform(program, i, 255, &name_len, &size, &type, name); GL_ASSERT - GLint location = gl_->GetUniformLocation(program, name); GL_ASSERT + gl_->GetActiveUniform(program, i, 255, &name_len, &size, &type, name); + GL_ASSERT + GLint location = gl_->GetUniformLocation(program, name); + GL_ASSERT active_uniforms.insert({std::string(name), GlCoreActiveUniform {type, static_cast(location)}}); } - for (auto& attr : desc.vertex_input.attr_layouts) { + for (auto& attr : desc.vertex_input.attr_layouts) + { const char* symbol_name = map_vertex_attribute_symbol_name(attr.name); SRB2_ASSERT(symbol_name != nullptr); - if (active_attributes.find(symbol_name) == active_attributes.end()) { + if (active_attributes.find(symbol_name) == active_attributes.end()) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); @@ -819,7 +959,8 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) auto expected_format = rhi::vertex_attribute_format(attr.name); auto expected_gl_type = map_vertex_attribute_format(expected_format); SRB2_ASSERT(expected_gl_type != GL_ZERO); - if (expected_gl_type != active_attr.type) { + if (expected_gl_type != active_attr.type) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); @@ -829,7 +970,9 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) pipeline.attrib_locations.insert({attr.name, active_attr.location}); } - for (auto group_itr = desc.uniform_input.enabled_uniforms.cbegin(); group_itr != desc.uniform_input.enabled_uniforms.cend(); group_itr = std::next(group_itr)) + for (auto group_itr = desc.uniform_input.enabled_uniforms.cbegin(); + group_itr != desc.uniform_input.enabled_uniforms.cend(); + group_itr = std::next(group_itr)) { auto& group = *group_itr; for (auto itr = group.cbegin(); itr != group.cend(); itr = std::next(itr)) @@ -837,7 +980,8 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) auto& uniform = *itr; const char* symbol_name = map_uniform_attribute_symbol_name(uniform); SRB2_ASSERT(symbol_name != nullptr); - if (active_uniforms.find(symbol_name) == active_uniforms.end()) { + if (active_uniforms.find(symbol_name) == active_uniforms.end()) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); @@ -847,7 +991,8 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) auto expected_format = rhi::uniform_format(uniform); auto expected_gl_type = map_uniform_format(expected_format); SRB2_ASSERT(expected_gl_type != GL_ZERO); - if (expected_gl_type != active_uniform.type) { + if (expected_gl_type != active_uniform.type) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); @@ -858,17 +1003,20 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) } } - for (auto& sampler : desc.sampler_input.enabled_samplers) { + for (auto& sampler : desc.sampler_input.enabled_samplers) + { const char* symbol_name = map_sampler_symbol_name(sampler); SRB2_ASSERT(symbol_name != nullptr); - if (active_uniforms.find(symbol_name) == active_uniforms.end()) { + if (active_uniforms.find(symbol_name) == active_uniforms.end()) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); throw std::runtime_error("Enabled sampler not found in linked program"); } auto& active_sampler = active_uniforms[symbol_name]; - if (active_sampler.type != GL_SAMPLER_2D) { + if (active_sampler.type != GL_SAMPLER_2D) + { gl_->DeleteProgram(program); gl_->DeleteShader(fragment); gl_->DeleteShader(vertex); @@ -886,7 +1034,8 @@ rhi::Handle GlCoreRhi::create_pipeline(const PipelineDesc& desc) return pipeline_slab_.insert(std::make_unique(std::move(pipeline))); } -void GlCoreRhi::destroy_pipeline(rhi::Handle handle) { +void GlCoreRhi::destroy_pipeline(rhi::Handle handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(pipeline_slab_.is_valid(handle) == true); @@ -900,18 +1049,21 @@ void GlCoreRhi::destroy_pipeline(rhi::Handle handle) { disposal_.push_back([this, program] { gl_->DeleteProgram(program); }); } -rhi::Handle GlCoreRhi::begin_graphics() { +rhi::Handle GlCoreRhi::begin_graphics() +{ SRB2_ASSERT(graphics_context_active_ == false); graphics_context_active_ = true; return rhi::Handle(0, graphics_context_generation_); } -void GlCoreRhi::end_graphics(rhi::Handle handle) { +void GlCoreRhi::end_graphics(rhi::Handle handle) +{ SRB2_ASSERT(graphics_context_active_ == true); SRB2_ASSERT(current_pipeline_.has_value() == false && current_render_pass_.has_value() == false); graphics_context_generation_ += 1; graphics_context_active_ = false; - gl_->Flush(); GL_ASSERT + gl_->Flush(); + GL_ASSERT } rhi::Handle GlCoreRhi::begin_transfer() @@ -933,36 +1085,43 @@ void GlCoreRhi::end_transfer(rhi::Handle ctx) transfer_context_active_ = false; } -void GlCoreRhi::present() { +void GlCoreRhi::present() +{ SRB2_ASSERT(platform_ != nullptr); SRB2_ASSERT(graphics_context_active_ == false); platform_->present(); } -void GlCoreRhi::begin_default_render_pass(Handle ctx, bool clear) { +void GlCoreRhi::begin_default_render_pass(Handle ctx, bool clear) +{ SRB2_ASSERT(platform_ != nullptr); SRB2_ASSERT(graphics_context_active_ == true); SRB2_ASSERT(current_render_pass_.has_value() == false); const Rect fb_rect = platform_->get_default_framebuffer_dimensions(); - gl_->BindFramebuffer(GL_FRAMEBUFFER, 0); GL_ASSERT - gl_->Disable(GL_SCISSOR_TEST); GL_ASSERT - gl_->Viewport(0, 0, fb_rect.w, fb_rect.h); GL_ASSERT + gl_->BindFramebuffer(GL_FRAMEBUFFER, 0); + GL_ASSERT + gl_->Disable(GL_SCISSOR_TEST); + GL_ASSERT + gl_->Viewport(0, 0, fb_rect.w, fb_rect.h); + GL_ASSERT if (clear) { gl_->ClearColor(0.0f, 0.0f, 0.0f, 1.0f); gl_->ClearDepth(1.0f); gl_->ClearStencil(0); - gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GL_ASSERT + gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GL_ASSERT } current_render_pass_ = GlCoreRhi::DefaultRenderPassState {}; } -void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) { +void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == false); @@ -971,13 +1130,20 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB SRB2_ASSERT(rp.desc.depth_format.has_value() == info.depth_attachment.has_value()); auto fb_itr = framebuffers_.find(GlCoreFramebufferKey {info.color_attachment, info.depth_attachment}); - if (fb_itr == framebuffers_.end()) { + if (fb_itr == framebuffers_.end()) + { // Create a new framebuffer for this color-depth pair GLuint fb_name; - gl_->GenFramebuffers(1, &fb_name); GL_ASSERT - gl_->BindFramebuffer(GL_FRAMEBUFFER, fb_name); GL_ASSERT - fb_itr = framebuffers_.insert( - {GlCoreFramebufferKey {info.color_attachment, info.depth_attachment}, static_cast(fb_name)}).first; + gl_->GenFramebuffers(1, &fb_name); + GL_ASSERT + gl_->BindFramebuffer(GL_FRAMEBUFFER, fb_name); + GL_ASSERT + fb_itr = framebuffers_ + .insert( + {GlCoreFramebufferKey {info.color_attachment, info.depth_attachment}, + static_cast(fb_name)} + ) + .first; GLuint attachment = GL_COLOR_ATTACHMENT0; auto visitor = srb2::Overload { @@ -985,13 +1151,8 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB { SRB2_ASSERT(texture_slab_.is_valid(handle)); auto& texture = *static_cast(&texture_slab_[handle]); - gl_->FramebufferTexture2D( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - texture.texture, - 0 - ); GL_ASSERT + gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.texture, 0); + GL_ASSERT }, [&, this](const Handle& handle) { @@ -1002,9 +1163,9 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer.renderbuffer - ); GL_ASSERT - } - }; + ); + GL_ASSERT + }}; std::visit(visitor, info.color_attachment); if (info.depth_attachment) { @@ -1013,20 +1174,25 @@ void GlCoreRhi::begin_render_pass(Handle ctx, const RenderPassB } } auto& fb = *fb_itr; - gl_->BindFramebuffer(GL_FRAMEBUFFER, fb.second); GL_ASSERT - gl_->Disable(GL_SCISSOR_TEST); GL_ASSERT + gl_->BindFramebuffer(GL_FRAMEBUFFER, fb.second); + GL_ASSERT + gl_->Disable(GL_SCISSOR_TEST); + GL_ASSERT - if (rp.desc.load_op == rhi::AttachmentLoadOp::kClear) { + if (rp.desc.load_op == rhi::AttachmentLoadOp::kClear) + { gl_->ClearColor(info.clear_color.r, info.clear_color.g, info.clear_color.b, info.clear_color.a); gl_->ClearDepth(1.f); gl_->ClearStencil(0); - gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); GL_ASSERT + gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + GL_ASSERT } current_render_pass_ = info; } -void GlCoreRhi::end_render_pass(Handle ctx) { +void GlCoreRhi::end_render_pass(Handle ctx) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true); @@ -1034,7 +1200,8 @@ void GlCoreRhi::end_render_pass(Handle ctx) { current_render_pass_ = std::nullopt; } -void GlCoreRhi::bind_pipeline(Handle ctx, Handle pipeline) { +void GlCoreRhi::bind_pipeline(Handle ctx, Handle pipeline) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true); @@ -1042,46 +1209,74 @@ void GlCoreRhi::bind_pipeline(Handle ctx, Handle pipe auto& pl = *static_cast(&pipeline_slab_[pipeline]); auto& desc = pl.desc; - gl_->UseProgram(pl.program); GL_ASSERT + gl_->UseProgram(pl.program); + GL_ASSERT - gl_->Disable(GL_SCISSOR_TEST); GL_ASSERT + gl_->Disable(GL_SCISSOR_TEST); + GL_ASSERT - if (desc.depth_attachment) { - gl_->Enable(GL_DEPTH_TEST); GL_ASSERT + if (desc.depth_attachment) + { + gl_->Enable(GL_DEPTH_TEST); + GL_ASSERT GLenum depth_func = map_compare_func(desc.depth_attachment->func); SRB2_ASSERT(depth_func != GL_ZERO); - gl_->DepthFunc(depth_func); GL_ASSERT - gl_->DepthMask(desc.depth_attachment->write ? GL_TRUE : GL_FALSE); GL_ASSERT - } else { - gl_->Disable(GL_DEPTH_TEST); GL_ASSERT + gl_->DepthFunc(depth_func); + GL_ASSERT + gl_->DepthMask(desc.depth_attachment->write ? GL_TRUE : GL_FALSE); + GL_ASSERT + } + else + { + gl_->Disable(GL_DEPTH_TEST); + GL_ASSERT } - if (desc.color_attachment.blend) { + if (desc.color_attachment.blend) + { rhi::BlendDesc& bl = *desc.color_attachment.blend; - gl_->Enable(GL_BLEND); GL_ASSERT - gl_->BlendFuncSeparate(map_blend_factor(bl.source_factor_color), - map_blend_factor(bl.dest_factor_color), - map_blend_factor(bl.source_factor_alpha), - map_blend_factor(bl.dest_factor_alpha)); GL_ASSERT - gl_->BlendEquationSeparate(map_blend_function(bl.color_function), map_blend_function(bl.alpha_function)); GL_ASSERT - gl_->BlendColor(desc.blend_color.r, desc.blend_color.g, desc.blend_color.b, desc.blend_color.a); GL_ASSERT - } else { + gl_->Enable(GL_BLEND); + GL_ASSERT + gl_->BlendFuncSeparate( + map_blend_factor(bl.source_factor_color), + map_blend_factor(bl.dest_factor_color), + map_blend_factor(bl.source_factor_alpha), + map_blend_factor(bl.dest_factor_alpha) + ); + GL_ASSERT + gl_->BlendEquationSeparate(map_blend_function(bl.color_function), map_blend_function(bl.alpha_function)); + GL_ASSERT + gl_->BlendColor(desc.blend_color.r, desc.blend_color.g, desc.blend_color.b, desc.blend_color.a); + GL_ASSERT + } + else + { gl_->Disable(GL_BLEND); } - gl_->ColorMask(desc.color_attachment.color_mask.r ? GL_TRUE : GL_FALSE, - desc.color_attachment.color_mask.g ? GL_TRUE : GL_FALSE, - desc.color_attachment.color_mask.b ? GL_TRUE : GL_FALSE, - desc.color_attachment.color_mask.a ? GL_TRUE : GL_FALSE); GL_ASSERT + gl_->ColorMask( + desc.color_attachment.color_mask.r ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.g ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.b ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.a ? GL_TRUE : GL_FALSE + ); + GL_ASSERT GLenum cull_face = map_cull_mode(desc.cull); - if (cull_face == GL_NONE) { - gl_->Disable(GL_CULL_FACE); GL_ASSERT - } else { - gl_->Enable(GL_CULL_FACE); GL_ASSERT - gl_->CullFace(cull_face); GL_ASSERT + if (cull_face == GL_NONE) + { + gl_->Disable(GL_CULL_FACE); + GL_ASSERT } - gl_->FrontFace(map_winding(desc.winding)); GL_ASSERT + else + { + gl_->Enable(GL_CULL_FACE); + GL_ASSERT + gl_->CullFace(cull_face); + GL_ASSERT + } + gl_->FrontFace(map_winding(desc.winding)); + GL_ASSERT current_pipeline_ = pipeline; current_primitive_type_ = desc.primitive; @@ -1122,42 +1317,61 @@ void GlCoreRhi::bind_uniform_set(Handle ctx, uint32_t slot, Han SRB2_ASSERT(pl.uniform_locations.find(uniform_name) != pl.uniform_locations.end()); GLuint pipeline_uniform = pl.uniform_locations[uniform_name]; - auto visitor = srb2::Overload - { - [&](const float& value){ gl_->Uniform1f(pipeline_uniform, value); GL_ASSERT }, - [&](const std::array& value) { gl_->Uniform2f(pipeline_uniform, value[0], value[1]); GL_ASSERT }, + auto visitor = srb2::Overload { + [&](const float& value) + { + gl_->Uniform1f(pipeline_uniform, value); + GL_ASSERT + }, + [&](const std::array& value) + { + gl_->Uniform2f(pipeline_uniform, value[0], value[1]); + GL_ASSERT + }, [&](const std::array& value) { - gl_->Uniform3f(pipeline_uniform, value[0], value[1], value[2]); GL_ASSERT + gl_->Uniform3f(pipeline_uniform, value[0], value[1], value[2]); + GL_ASSERT }, [&](const std::array& value) { - gl_->Uniform4f(pipeline_uniform, value[0], value[1], value[2], value[3]); GL_ASSERT + gl_->Uniform4f(pipeline_uniform, value[0], value[1], value[2], value[3]); + GL_ASSERT + }, + [&](const int32_t& value) + { + gl_->Uniform1i(pipeline_uniform, value); + GL_ASSERT }, - [&](const int32_t& value) { gl_->Uniform1i(pipeline_uniform, value); GL_ASSERT }, [&](const std::array& value) { - gl_->Uniform2i(pipeline_uniform, value[0], value[1]); GL_ASSERT + gl_->Uniform2i(pipeline_uniform, value[0], value[1]); + GL_ASSERT }, [&](const std::array& value) { - gl_->Uniform3i(pipeline_uniform, value[0], value[1], value[2]); GL_ASSERT + gl_->Uniform3i(pipeline_uniform, value[0], value[1], value[2]); + GL_ASSERT }, [&](const std::array& value) { - gl_->Uniform4i(pipeline_uniform, value[0], value[1], value[2], value[3]); GL_ASSERT + gl_->Uniform4i(pipeline_uniform, value[0], value[1], value[2], value[3]); + GL_ASSERT }, [&](const std::array, 2>& value) { - gl_->UniformMatrix2fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT + gl_->UniformMatrix2fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); + GL_ASSERT }, [&](const std::array, 3>& value) { - gl_->UniformMatrix3fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT + gl_->UniformMatrix3fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); + GL_ASSERT }, [&](const std::array, 4>& value) { - gl_->UniformMatrix4fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); GL_ASSERT + gl_->UniformMatrix4fv(pipeline_uniform, 1, false, reinterpret_cast(&value)); + GL_ASSERT }, }; std::visit(visitor, update_data); @@ -1192,7 +1406,8 @@ void GlCoreRhi::bind_binding_set(Handle ctx, Handle GLuint sampler_uniform_loc = pl.sampler_locations[sampler_name]; GLenum active_texture = GL_TEXTURE0; GLuint uniform_value = 0; - switch (sampler_name) { + switch (sampler_name) + { case rhi::SamplerName::kSampler0: active_texture = GL_TEXTURE0; uniform_value = 0; @@ -1210,9 +1425,12 @@ void GlCoreRhi::bind_binding_set(Handle ctx, Handle uniform_value = 3; break; } - gl_->ActiveTexture(active_texture); GL_ASSERT - gl_->BindTexture(GL_TEXTURE_2D, texture_gl_name); GL_ASSERT - gl_->Uniform1i(sampler_uniform_loc, uniform_value); GL_ASSERT + gl_->ActiveTexture(active_texture); + GL_ASSERT + gl_->BindTexture(GL_TEXTURE_2D, texture_gl_name); + GL_ASSERT + gl_->Uniform1i(sampler_uniform_loc, uniform_value); + GL_ASSERT } } @@ -1230,7 +1448,8 @@ void GlCoreRhi::bind_index_buffer(Handle ctx, Handle bu gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.buffer); } -void GlCoreRhi::set_scissor(Handle ctx, const Rect& rect) { +void GlCoreRhi::set_scissor(Handle ctx, const Rect& rect) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); @@ -1238,28 +1457,35 @@ void GlCoreRhi::set_scissor(Handle ctx, const Rect& rect) { gl_->Scissor(rect.x, rect.y, rect.w, rect.h); } -void GlCoreRhi::set_viewport(Handle ctx, const Rect& rect) { +void GlCoreRhi::set_viewport(Handle ctx, const Rect& rect) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); gl_->Viewport(rect.x, rect.y, rect.w, rect.h); } -void GlCoreRhi::draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) { +void GlCoreRhi::draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); - gl_->DrawArrays(map_primitive_mode(current_primitive_type_), first_vertex, vertex_count); GL_ASSERT + gl_->DrawArrays(map_primitive_mode(current_primitive_type_), first_vertex, vertex_count); + GL_ASSERT } -void GlCoreRhi::draw_indexed(Handle ctx, - uint32_t index_count, - uint32_t first_index) { +void GlCoreRhi::draw_indexed(Handle ctx, uint32_t index_count, uint32_t first_index) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - gl_->DrawElements(map_primitive_mode(current_primitive_type_), index_count, GL_UNSIGNED_SHORT, reinterpret_cast(first_index * 2 + index_buffer_offset_)); GL_ASSERT + gl_->DrawElements( + map_primitive_mode(current_primitive_type_), + index_count, + GL_UNSIGNED_SHORT, + reinterpret_cast(first_index * 2 + index_buffer_offset_) + ); + GL_ASSERT } - void GlCoreRhi::read_pixels(Handle ctx, const Rect& rect, tcb::span out) { SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); @@ -1269,14 +1495,17 @@ void GlCoreRhi::read_pixels(Handle ctx, const Rect& rect, tcb:: gl_->ReadPixels(rect.x, rect.y, rect.w, rect.h, GL_RGBA, GL_UNSIGNED_BYTE, out.data()); } -void GlCoreRhi::finish() { +void GlCoreRhi::finish() +{ SRB2_ASSERT(graphics_context_active_ == false); for (auto it = binding_set_slab_.cbegin(); it != binding_set_slab_.cend(); it++) { - gl_->BindVertexArray(0); GL_ASSERT + gl_->BindVertexArray(0); + GL_ASSERT GLuint vao = reinterpret_cast(*it).vao; - gl_->DeleteVertexArrays(1, &vao); GL_ASSERT + gl_->DeleteVertexArrays(1, &vao); + GL_ASSERT } binding_set_slab_.clear(); uniform_set_slab_.clear(); @@ -1293,5 +1522,6 @@ void GlCoreRhi::finish() { (*it)(); } - disposal_.clear(); GL_ASSERT + disposal_.clear(); + GL_ASSERT } diff --git a/src/rhi/gl3_core/gl3_core_rhi.hpp b/src/rhi/gl3_core/gl3_core_rhi.hpp index a11d58d52..d20747cc6 100644 --- a/src/rhi/gl3_core/gl3_core_rhi.hpp +++ b/src/rhi/gl3_core/gl3_core_rhi.hpp @@ -11,19 +11,17 @@ #include "../rhi.hpp" -namespace srb2::rhi { +namespace srb2::rhi +{ -struct GlCoreFramebufferKey { +struct GlCoreFramebufferKey +{ TextureOrRenderbuffer color; std::optional depth; - bool operator==(const GlCoreFramebufferKey& rhs) const noexcept { - return color == rhs.color && depth == rhs.depth; - } + bool operator==(const GlCoreFramebufferKey& rhs) const noexcept { return color == rhs.color && depth == rhs.depth; } - bool operator!=(const GlCoreFramebufferKey& rhs) const noexcept { - return !(*this == rhs); - } + bool operator!=(const GlCoreFramebufferKey& rhs) const noexcept { return !(*this == rhs); } }; } // namespace srb2::rhi @@ -32,19 +30,25 @@ struct GlCoreFramebufferKey { // we need to split the namespace declarations _before_ the instantiation of std::unordered_map. template <> -struct std::hash { - std::size_t operator()(const srb2::rhi::GlCoreFramebufferKey& key) const { - struct GetHandleHashVisitor { - uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept { +struct std::hash +{ + std::size_t operator()(const srb2::rhi::GlCoreFramebufferKey& key) const + { + struct GetHandleHashVisitor + { + uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept + { return std::hash>()(handle); } - uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept { + uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept + { return std::hash>()(handle); } }; std::size_t color_hash = std::visit(GetHandleHashVisitor {}, key.color); std::size_t depth_hash = 0; - if (key.depth) { + if (key.depth) + { depth_hash = std::visit(GetHandleHashVisitor {}, *key.depth); } return color_hash ^ (depth_hash << 1); @@ -53,13 +57,15 @@ struct std::hash { struct GladGLContext; -namespace srb2::rhi { +namespace srb2::rhi +{ typedef void (*GlProc)(void); typedef GlProc (*GlLoadFunc)(const char* name); /// @brief Platform-specific implementation details for the GLES2 backend. -struct GlCorePlatform { +struct GlCorePlatform +{ virtual ~GlCorePlatform(); virtual void present() = 0; @@ -67,7 +73,8 @@ struct GlCorePlatform { virtual Rect get_default_framebuffer_dimensions() = 0; }; -class GlCoreRhi final : public Rhi { +class GlCoreRhi final : public Rhi +{ std::unique_ptr platform_; std::unique_ptr gl_; @@ -82,7 +89,9 @@ class GlCoreRhi final : public Rhi { std::unordered_map framebuffers_ {16}; - struct DefaultRenderPassState {}; + struct DefaultRenderPassState + { + }; using RenderPassState = std::variant; std::optional current_render_pass_; std::optional> current_pipeline_; @@ -114,10 +123,24 @@ public: virtual Handle begin_transfer() override; virtual void end_transfer(Handle handle) override; - virtual void update_buffer_contents(Handle ctx, Handle buffer, uint32_t offset, tcb::span data) override; - virtual void update_texture(Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) override; - virtual Handle create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) override; - virtual Handle create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) override; + virtual void update_buffer_contents( + Handle ctx, + Handle buffer, + uint32_t offset, + tcb::span data + ) override; + virtual void update_texture( + Handle ctx, + Handle texture, + Rect region, + srb2::rhi::PixelFormat data_format, + tcb::span data + ) override; + virtual Handle + create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) override; + virtual Handle + create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) + override; virtual Handle begin_graphics() override; virtual void end_graphics(Handle ctx) override; @@ -133,9 +156,7 @@ public: virtual void set_scissor(Handle ctx, const Rect& rect) override; virtual void set_viewport(Handle ctx, const Rect& rect) override; virtual void draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) override; - virtual void draw_indexed(Handle ctx, - uint32_t index_count, - uint32_t first_index) override; + virtual void draw_indexed(Handle ctx, uint32_t index_count, uint32_t first_index) override; virtual void read_pixels(Handle ctx, const Rect& rect, tcb::span out) override; virtual void present() override; diff --git a/src/rhi/gles2/gles2_rhi.cpp b/src/rhi/gles2/gles2_rhi.cpp index 8e9d61f7d..5c8134eb6 100644 --- a/src/rhi/gles2/gles2_rhi.cpp +++ b/src/rhi/gles2/gles2_rhi.cpp @@ -13,16 +13,20 @@ using namespace srb2; using srb2::rhi::Gles2Platform; using srb2::rhi::Gles2Rhi; -namespace { +namespace +{ template -std::unique_ptr> static_unique_ptr_cast(std::unique_ptr> ptr) { +std::unique_ptr> static_unique_ptr_cast(std::unique_ptr> ptr) +{ D* derived = static_cast(ptr.release()); return std::unique_ptr>(derived, std::default_delete()); } -constexpr GLenum map_pixel_format(rhi::PixelFormat format) { - switch (format) { +constexpr GLenum map_pixel_format(rhi::PixelFormat format) +{ + switch (format) + { case rhi::PixelFormat::kRGBA8: // requires extension GL_OES_rgb8_rgba8, which is always requested return GL_RGBA8_OES; @@ -35,11 +39,13 @@ constexpr GLenum map_pixel_format(rhi::PixelFormat format) { } } -constexpr std::tuple map_pixel_data_format(rhi::PixelFormat format) { +constexpr std::tuple map_pixel_data_format(rhi::PixelFormat format) +{ GLenum layout = GL_ZERO; GLenum type = GL_ZERO; GLuint size = 0; - switch (format) { + switch (format) + { case rhi::PixelFormat::kR8: layout = GL_LUMINANCE; type = GL_UNSIGNED_BYTE; @@ -56,8 +62,10 @@ constexpr std::tuple map_pixel_data_format(rhi::PixelFor return std::tuple(layout, type, size); } -constexpr GLenum map_texture_format(rhi::TextureFormat format) { - switch (format) { +constexpr GLenum map_texture_format(rhi::TextureFormat format) +{ + switch (format) + { case rhi::TextureFormat::kRGBA: return GL_RGBA; case rhi::TextureFormat::kRGB: @@ -69,8 +77,10 @@ constexpr GLenum map_texture_format(rhi::TextureFormat format) { } } -constexpr GLenum map_buffer_type(rhi::BufferType type) { - switch (type) { +constexpr GLenum map_buffer_type(rhi::BufferType type) +{ + switch (type) + { case rhi::BufferType::kVertexBuffer: return GL_ARRAY_BUFFER; case rhi::BufferType::kIndexBuffer: @@ -80,8 +90,10 @@ constexpr GLenum map_buffer_type(rhi::BufferType type) { } } -constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) { - switch (usage) { +constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) +{ + switch (usage) + { case rhi::BufferUsage::kImmutable: return GL_STATIC_DRAW; case rhi::BufferUsage::kDynamic: @@ -91,8 +103,10 @@ constexpr GLenum map_buffer_usage(rhi::BufferUsage usage) { } } -constexpr GLenum map_compare_func(rhi::CompareFunc func) { - switch (func) { +constexpr GLenum map_compare_func(rhi::CompareFunc func) +{ + switch (func) + { case rhi::CompareFunc::kNever: return GL_NEVER; case rhi::CompareFunc::kLess: @@ -114,8 +128,10 @@ constexpr GLenum map_compare_func(rhi::CompareFunc func) { } } -constexpr GLenum map_blend_factor(rhi::BlendFactor factor) { - switch (factor) { +constexpr GLenum map_blend_factor(rhi::BlendFactor factor) +{ + switch (factor) + { case rhi::BlendFactor::kZero: return GL_ZERO; case rhi::BlendFactor::kOne: @@ -151,8 +167,10 @@ constexpr GLenum map_blend_factor(rhi::BlendFactor factor) { } } -constexpr GLenum map_blend_function(rhi::BlendFunction function) { - switch (function) { +constexpr GLenum map_blend_function(rhi::BlendFunction function) +{ + switch (function) + { case rhi::BlendFunction::kAdd: return GL_FUNC_ADD; case rhi::BlendFunction::kSubtract: @@ -164,8 +182,10 @@ constexpr GLenum map_blend_function(rhi::BlendFunction function) { } } -constexpr GLenum map_cull_mode(rhi::CullMode mode) { - switch (mode) { +constexpr GLenum map_cull_mode(rhi::CullMode mode) +{ + switch (mode) + { case rhi::CullMode::kNone: return GL_NONE; case rhi::CullMode::kFront: @@ -177,8 +197,10 @@ constexpr GLenum map_cull_mode(rhi::CullMode mode) { } } -constexpr GLenum map_winding(rhi::FaceWinding winding) { - switch (winding) { +constexpr GLenum map_winding(rhi::FaceWinding winding) +{ + switch (winding) + { case rhi::FaceWinding::kCounterClockwise: return GL_CCW; case rhi::FaceWinding::kClockwise: @@ -188,8 +210,10 @@ constexpr GLenum map_winding(rhi::FaceWinding winding) { } } -constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) { - switch (type) { +constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) +{ + switch (type) + { case rhi::PrimitiveType::kPoints: return GL_POINTS; case rhi::PrimitiveType::kLines: @@ -207,8 +231,10 @@ constexpr GLenum map_primitive_mode(rhi::PrimitiveType type) { } } -constexpr const char* map_vertex_attribute_symbol_name(rhi::VertexAttributeName name) { - switch (name) { +constexpr const char* map_vertex_attribute_symbol_name(rhi::VertexAttributeName name) +{ + switch (name) + { case rhi::VertexAttributeName::kPosition: return "a_position"; case rhi::VertexAttributeName::kNormal: @@ -243,8 +269,10 @@ constexpr const char* map_vertex_attribute_enable_define(rhi::VertexAttributeNam } */ -constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) { - switch (name) { +constexpr const char* map_uniform_attribute_symbol_name(rhi::UniformName name) +{ + switch (name) + { case rhi::UniformName::kTime: return "u_time"; case rhi::UniformName::kModelView: @@ -271,8 +299,10 @@ constexpr const char* map_uniform_attribute_enable_define(rhi::UniformName name) } */ -constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) { - switch (name) { +constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) +{ + switch (name) + { case rhi::SamplerName::kSampler0: return "s_sampler0"; case rhi::SamplerName::kSampler1: @@ -286,8 +316,10 @@ constexpr const char* map_sampler_symbol_name(rhi::SamplerName name) { } } -constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) { - switch (format) { +constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) +{ + switch (format) + { case rhi::VertexAttributeFormat::kFloat: return GL_FLOAT; case rhi::VertexAttributeFormat::kFloat2: @@ -301,8 +333,10 @@ constexpr GLenum map_vertex_attribute_format(rhi::VertexAttributeFormat format) } } -constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) { - switch (format) { +constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) +{ + switch (format) + { case rhi::VertexAttributeFormat::kFloat: return GL_FLOAT; case rhi::VertexAttributeFormat::kFloat2: @@ -316,8 +350,10 @@ constexpr GLenum map_vertex_attribute_type(rhi::VertexAttributeFormat format) { } } -constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat format) { - switch (format) { +constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat format) +{ + switch (format) + { case rhi::VertexAttributeFormat::kFloat: return 1; case rhi::VertexAttributeFormat::kFloat2: @@ -331,8 +367,10 @@ constexpr GLint map_vertex_attribute_format_size(rhi::VertexAttributeFormat form } } -constexpr GLenum map_uniform_format(rhi::UniformFormat format) { - switch (format) { +constexpr GLenum map_uniform_format(rhi::UniformFormat format) +{ + switch (format) + { case rhi::UniformFormat::kFloat: return GL_FLOAT; case rhi::UniformFormat::kFloat2: @@ -360,30 +398,35 @@ constexpr GLenum map_uniform_format(rhi::UniformFormat format) { } } -struct Gles2Texture : public rhi::Texture { +struct Gles2Texture : public rhi::Texture +{ GLuint texture; rhi::TextureDesc desc; Gles2Texture(GLuint texture, const rhi::TextureDesc& desc) noexcept : texture(texture), desc(desc) {} }; -struct Gles2Buffer : public rhi::Buffer { +struct Gles2Buffer : public rhi::Buffer +{ GLuint buffer; rhi::BufferDesc desc; Gles2Buffer(GLuint buffer, const rhi::BufferDesc& desc) noexcept : buffer(buffer), desc(desc) {} }; -struct Gles2RenderPass : public rhi::RenderPass { +struct Gles2RenderPass : public rhi::RenderPass +{ rhi::RenderPassDesc desc; explicit Gles2RenderPass(const rhi::RenderPassDesc& desc) noexcept : desc(desc) {} }; -struct Gles2Renderbuffer : public rhi::Renderbuffer { +struct Gles2Renderbuffer : public rhi::Renderbuffer +{ GLuint renderbuffer; explicit Gles2Renderbuffer(GLuint renderbuffer) noexcept : renderbuffer(renderbuffer) {} }; -struct Gles2Pipeline : public rhi::Pipeline { +struct Gles2Pipeline : public rhi::Pipeline +{ GLuint vertex_shader = 0; GLuint fragment_shader = 0; GLuint program = 0; @@ -393,16 +436,23 @@ struct Gles2Pipeline : public rhi::Pipeline { rhi::PipelineDesc desc; Gles2Pipeline() = default; - explicit Gles2Pipeline(GLuint vertex_shader, - GLuint fragment_shader, - GLuint program, - const rhi::PipelineDesc& desc) noexcept - : vertex_shader(vertex_shader), fragment_shader(fragment_shader), program(program), desc(desc) {} + explicit Gles2Pipeline( + GLuint vertex_shader, + GLuint fragment_shader, + GLuint program, + const rhi::PipelineDesc& desc + ) noexcept + : vertex_shader(vertex_shader), fragment_shader(fragment_shader), program(program), desc(desc) + { + } }; -struct Gles2GraphicsContext : public rhi::GraphicsContext {}; +struct Gles2GraphicsContext : public rhi::GraphicsContext +{ +}; -struct Gles2ActiveUniform { +struct Gles2ActiveUniform +{ GLenum type; GLuint location; }; @@ -411,27 +461,34 @@ struct Gles2ActiveUniform { Gles2Platform::~Gles2Platform() = default; -Gles2Rhi::Gles2Rhi(std::unique_ptr&& platform) - : platform_(std::move(platform)) { +Gles2Rhi::Gles2Rhi(std::unique_ptr&& platform) : platform_(std::move(platform)) +{ } Gles2Rhi::~Gles2Rhi() = default; -rhi::Handle Gles2Rhi::create_render_pass(const rhi::RenderPassDesc& desc) { +rhi::Handle Gles2Rhi::create_render_pass(const rhi::RenderPassDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); // GL has no formal render pass object return render_pass_slab_.insert(std::make_unique(desc)); } -void Gles2Rhi::destroy_render_pass(rhi::Handle&& handle) { +void Gles2Rhi::destroy_render_pass(rhi::Handle&& handle) +{ SRB2_ASSERT(graphics_context_active_ == false); std::unique_ptr buffer = render_pass_slab_.remove(handle); std::unique_ptr casted(static_cast(buffer.release())); } -rhi::Handle Gles2Rhi::create_texture(const rhi::TextureDesc& desc, srb2::rhi::PixelFormat data_format, tcb::span data) { +rhi::Handle Gles2Rhi::create_texture( + const rhi::TextureDesc& desc, + srb2::rhi::PixelFormat data_format, + tcb::span data +) +{ SRB2_ASSERT(graphics_context_active_ == false); GLint internal_format = map_texture_format(desc.format); @@ -451,7 +508,8 @@ rhi::Handle Gles2Rhi::create_texture(const rhi::TextureDesc& desc, std::tie(format, type, size) = map_pixel_data_format(data_format); SRB2_ASSERT(format != GL_ZERO && type != GL_ZERO); SRB2_ASSERT(internal_format == format); - if (!data.empty()) { + if (!data.empty()) + { SRB2_ASSERT(size * desc.width * desc.height == data.size_bytes()); raw_data = static_cast(data.data()); } @@ -464,7 +522,8 @@ rhi::Handle Gles2Rhi::create_texture(const rhi::TextureDesc& desc, return texture_slab_.insert(std::make_unique(name, desc)); } -void Gles2Rhi::destroy_texture(rhi::Handle&& handle) { +void Gles2Rhi::destroy_texture(rhi::Handle&& handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(texture_slab_.is_valid(handle) == true); @@ -473,7 +532,13 @@ void Gles2Rhi::destroy_texture(rhi::Handle&& handle) { disposal_.push_back([name] { glDeleteTextures(1, &name); }); } -void Gles2Rhi::update_texture(Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) { +void Gles2Rhi::update_texture( + Handle texture, + Rect region, + srb2::rhi::PixelFormat data_format, + tcb::span data +) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(texture_slab_.is_valid(texture) == true); @@ -490,10 +555,21 @@ void Gles2Rhi::update_texture(Handle texture, Rect region, srb2::rhi::P glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, t.texture); - glTexSubImage2D(GL_TEXTURE_2D, 0, region.x, region.y, region.w, region.h, format, type, reinterpret_cast(data.data())); + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + region.x, + region.y, + region.w, + region.h, + format, + type, + reinterpret_cast(data.data()) + ); } -rhi::Handle Gles2Rhi::create_buffer(const rhi::BufferDesc& desc, tcb::span data) { +rhi::Handle Gles2Rhi::create_buffer(const rhi::BufferDesc& desc, tcb::span data) +{ SRB2_ASSERT(graphics_context_active_ == false); // If data is provided, it must match the buffer description size exactly @@ -512,7 +588,8 @@ rhi::Handle Gles2Rhi::create_buffer(const rhi::BufferDesc& desc, tc // if no data is provided, the initial buffer data is undefined const void* raw_data = nullptr; - if (!data.empty()) { + if (!data.empty()) + { raw_data = static_cast(data.data()); } glBufferData(target, desc.size, raw_data, usage); @@ -520,7 +597,8 @@ rhi::Handle Gles2Rhi::create_buffer(const rhi::BufferDesc& desc, tc return buffer_slab_.insert(std::make_unique(name, desc)); } -void Gles2Rhi::destroy_buffer(rhi::Handle&& handle) { +void Gles2Rhi::destroy_buffer(rhi::Handle&& handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(buffer_slab_.is_valid(handle) == true); @@ -531,7 +609,8 @@ void Gles2Rhi::destroy_buffer(rhi::Handle&& handle) { disposal_.push_back([name] { glDeleteBuffers(1, &name); }); } -void Gles2Rhi::update_buffer_contents(rhi::Handle handle, uint32_t offset, tcb::span data) { +void Gles2Rhi::update_buffer_contents(rhi::Handle handle, uint32_t offset, tcb::span data) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(buffer_slab_.is_valid(handle) == true); @@ -542,7 +621,8 @@ void Gles2Rhi::update_buffer_contents(rhi::Handle handle, uint32_t SRB2_ASSERT(offset < b.desc.size && offset + data.size() < b.desc.size); - switch (b.desc.type) { + switch (b.desc.type) + { case rhi::BufferType::kVertexBuffer: glBindBuffer(GL_ARRAY_BUFFER, b.buffer); glBufferSubData(GL_ARRAY_BUFFER, offset, data.size(), data.data()); @@ -554,7 +634,8 @@ void Gles2Rhi::update_buffer_contents(rhi::Handle handle, uint32_t } } -rhi::Handle Gles2Rhi::create_renderbuffer(const rhi::RenderbufferDesc& desc) { +rhi::Handle Gles2Rhi::create_renderbuffer(const rhi::RenderbufferDesc& desc) +{ SRB2_ASSERT(graphics_context_active_ == false); GLuint name = 0; @@ -567,7 +648,8 @@ rhi::Handle Gles2Rhi::create_renderbuffer(const rhi::Renderbu return renderbuffer_slab_.insert(std::make_unique(Gles2Renderbuffer {name})); } -void Gles2Rhi::destroy_renderbuffer(rhi::Handle&& handle) { +void Gles2Rhi::destroy_renderbuffer(rhi::Handle&& handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(renderbuffer_slab_.is_valid(handle) == true); @@ -577,7 +659,8 @@ void Gles2Rhi::destroy_renderbuffer(rhi::Handle&& handle) { disposal_.push_back([name] { glDeleteRenderbuffers(1, &name); }); } -rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { +rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) +{ SRB2_ASSERT(platform_ != nullptr); // TODO assert compatibility of pipeline description with program using ProgramRequirements @@ -600,7 +683,8 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { glCompileShader(vertex); GLint is_compiled = 0; glGetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + if (is_compiled == GL_FALSE) + { GLint max_length = 0; glGetShaderiv(vertex, GL_INFO_LOG_LENGTH, &max_length); std::vector compile_error(max_length); @@ -613,7 +697,8 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { glShaderSource(fragment, 1, frag_src_arr, frag_src_arr_lens); glCompileShader(fragment); glGetShaderiv(vertex, GL_COMPILE_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + if (is_compiled == GL_FALSE) + { GLint max_length = 0; glGetShaderiv(fragment, GL_INFO_LOG_LENGTH, &max_length); std::vector compile_error(max_length); @@ -621,14 +706,17 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { glDeleteShader(fragment); glDeleteShader(vertex); - throw std::runtime_error(std::string("Fragment shader compilation failed: ") + std::string(compile_error.data())); + throw std::runtime_error( + std::string("Fragment shader compilation failed: ") + std::string(compile_error.data()) + ); } program = glCreateProgram(); glAttachShader(program, vertex); glAttachShader(program, fragment); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &is_compiled); - if (is_compiled == GL_FALSE) { + if (is_compiled == GL_FALSE) + { GLint max_length = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &max_length); std::vector link_error(max_length); @@ -643,13 +731,15 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { std::unordered_map active_attributes; GLint active_attribute_total = -1; glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attribute_total); - if (active_attribute_total < 0) { + if (active_attribute_total < 0) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); throw std::runtime_error("Unable to retrieve program active attributes"); } - if (desc.vertex_input.attr_layouts.size() != static_cast(active_attribute_total)) { + if (desc.vertex_input.attr_layouts.size() != static_cast(active_attribute_total)) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); @@ -659,7 +749,8 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { ex_msg.append(std::to_string(static_cast(active_attribute_total))); throw std::runtime_error(std::move(ex_msg)); } - for (GLint i = 0; i < active_attribute_total; i++) { + for (GLint i = 0; i < active_attribute_total; i++) + { GLsizei name_len = 0; GLint size = 0; GLenum type = GL_ZERO; @@ -671,23 +762,29 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { std::unordered_map active_uniforms; GLint active_uniform_total = -1; glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_total); - if (active_uniform_total < 0) { + if (active_uniform_total < 0) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); throw std::runtime_error("Unable to retrieve program active uniforms"); } - if (desc.uniform_input.enabled_uniforms.size() + desc.sampler_input.enabled_samplers.size() != static_cast(active_uniform_total)) { + if (desc.uniform_input.enabled_uniforms.size() + desc.sampler_input.enabled_samplers.size() != + static_cast(active_uniform_total)) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); - std::string ex_msg("Pipeline's enabled uniform count (uniforms + samplers) does not match the linked program's total: "); + std::string ex_msg( + "Pipeline's enabled uniform count (uniforms + samplers) does not match the linked program's total: " + ); ex_msg.append(std::to_string(desc.uniform_input.enabled_uniforms.size())); ex_msg.append(" vs "); ex_msg.append(std::to_string(static_cast(active_uniform_total))); throw std::runtime_error(std::move(ex_msg)); } - for (GLint i = 0; i < active_uniform_total; i++) { + for (GLint i = 0; i < active_uniform_total; i++) + { GLsizei name_len = 0; GLint size = 0; GLenum type = GL_ZERO; @@ -696,10 +793,12 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { active_uniforms.insert({std::string(name), Gles2ActiveUniform {type, static_cast(i)}}); } - for (auto& attr : desc.vertex_input.attr_layouts) { + for (auto& attr : desc.vertex_input.attr_layouts) + { const char* symbol_name = map_vertex_attribute_symbol_name(attr.name); SRB2_ASSERT(symbol_name != nullptr); - if (active_attributes.find(symbol_name) == active_attributes.end()) { + if (active_attributes.find(symbol_name) == active_attributes.end()) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); @@ -709,7 +808,8 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { auto expected_format = rhi::vertex_attribute_format(attr.name); auto expected_gl_type = map_vertex_attribute_format(expected_format); SRB2_ASSERT(expected_gl_type != GL_ZERO); - if (expected_gl_type != active_attr.type) { + if (expected_gl_type != active_attr.type) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); @@ -718,10 +818,12 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { pipeline.attrib_locations.insert({attr.name, active_attr.location}); } - for (auto& uniform : desc.uniform_input.enabled_uniforms) { + for (auto& uniform : desc.uniform_input.enabled_uniforms) + { const char* symbol_name = map_uniform_attribute_symbol_name(uniform); SRB2_ASSERT(symbol_name != nullptr); - if (active_uniforms.find(symbol_name) == active_uniforms.end()) { + if (active_uniforms.find(symbol_name) == active_uniforms.end()) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); @@ -731,7 +833,8 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { auto expected_format = rhi::uniform_format(uniform); auto expected_gl_type = map_uniform_format(expected_format); SRB2_ASSERT(expected_gl_type != GL_ZERO); - if (expected_gl_type != active_uniform.type) { + if (expected_gl_type != active_uniform.type) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); @@ -740,17 +843,20 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { pipeline.uniform_locations.insert({uniform, active_uniform.location}); } - for (auto& sampler : desc.sampler_input.enabled_samplers) { + for (auto& sampler : desc.sampler_input.enabled_samplers) + { const char* symbol_name = map_sampler_symbol_name(sampler); SRB2_ASSERT(symbol_name != nullptr); - if (active_uniforms.find(symbol_name) == active_uniforms.end()) { + if (active_uniforms.find(symbol_name) == active_uniforms.end()) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); throw std::runtime_error("Enabled sampler not found in linked program"); } auto& active_sampler = active_uniforms[symbol_name]; - if (active_sampler.type != GL_SAMPLER_2D) { + if (active_sampler.type != GL_SAMPLER_2D) + { glDeleteProgram(program); glDeleteShader(fragment); glDeleteShader(vertex); @@ -768,7 +874,8 @@ rhi::Handle Gles2Rhi::create_pipeline(const PipelineDesc& desc) { return pipeline_slab_.insert(std::make_unique(std::move(pipeline))); } -void Gles2Rhi::destroy_pipeline(rhi::Handle&& handle) { +void Gles2Rhi::destroy_pipeline(rhi::Handle&& handle) +{ SRB2_ASSERT(graphics_context_active_ == false); SRB2_ASSERT(pipeline_slab_.is_valid(handle) == true); @@ -782,13 +889,15 @@ void Gles2Rhi::destroy_pipeline(rhi::Handle&& handle) { disposal_.push_back([=] { glDeleteProgram(program); }); } -rhi::Handle Gles2Rhi::begin_graphics() { +rhi::Handle Gles2Rhi::begin_graphics() +{ SRB2_ASSERT(graphics_context_active_ == false); graphics_context_active_ = true; return rhi::Handle(0, graphics_context_generation_); } -void Gles2Rhi::end_graphics(rhi::Handle&& handle) { +void Gles2Rhi::end_graphics(rhi::Handle&& handle) +{ SRB2_ASSERT(graphics_context_active_ == true); SRB2_ASSERT(current_pipeline_.has_value() == false && current_render_pass_.has_value() == false); graphics_context_generation_ += 1; @@ -796,14 +905,16 @@ void Gles2Rhi::end_graphics(rhi::Handle&& handle) { glFlush(); } -void Gles2Rhi::present() { +void Gles2Rhi::present() +{ SRB2_ASSERT(platform_ != nullptr); SRB2_ASSERT(graphics_context_active_ == false); platform_->present(); } -void Gles2Rhi::begin_default_render_pass(Handle ctx) { +void Gles2Rhi::begin_default_render_pass(Handle ctx) +{ SRB2_ASSERT(platform_ != nullptr); SRB2_ASSERT(graphics_context_active_ == true); SRB2_ASSERT(current_render_pass_.has_value() == false); @@ -821,7 +932,8 @@ void Gles2Rhi::begin_default_render_pass(Handle ctx) { current_render_pass_ = Gles2Rhi::DefaultRenderPassState {}; } -void Gles2Rhi::begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) { +void Gles2Rhi::begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == false); @@ -830,20 +942,26 @@ void Gles2Rhi::begin_render_pass(Handle ctx, const RenderPassBe SRB2_ASSERT(rp.desc.depth_format.has_value() == info.depth_attachment.has_value()); auto fb_itr = framebuffers_.find(Gles2FramebufferKey {info.color_attachment, info.depth_attachment}); - if (fb_itr == framebuffers_.end()) { + if (fb_itr == framebuffers_.end()) + { // Create a new framebuffer for this color-depth pair GLuint fb_name; glGenFramebuffers(1, &fb_name); glBindFramebuffer(GL_FRAMEBUFFER, fb_name); - fb_itr = framebuffers_.insert( - {Gles2FramebufferKey {info.color_attachment, info.depth_attachment}, static_cast(fb_name)}).first; + fb_itr = + framebuffers_ + .insert( + {Gles2FramebufferKey {info.color_attachment, info.depth_attachment}, static_cast(fb_name)} + ) + .first; // TODO bind buffers correctly } auto& fb = *fb_itr; glBindFramebuffer(GL_FRAMEBUFFER, fb.second); - if (rp.desc.load_op == rhi::AttachmentLoadOp::kClear) { + if (rp.desc.load_op == rhi::AttachmentLoadOp::kClear) + { glClearColor(info.clear_color.r, info.clear_color.g, info.clear_color.b, info.clear_color.a); glClearDepthf(1.f); glClearStencil(0); @@ -853,7 +971,8 @@ void Gles2Rhi::begin_render_pass(Handle ctx, const RenderPassBe current_render_pass_ = info; } -void Gles2Rhi::end_render_pass(Handle ctx) { +void Gles2Rhi::end_render_pass(Handle ctx) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true); @@ -861,7 +980,8 @@ void Gles2Rhi::end_render_pass(Handle ctx) { current_render_pass_ = std::nullopt; } -void Gles2Rhi::bind_pipeline(Handle ctx, Handle pipeline) { +void Gles2Rhi::bind_pipeline(Handle ctx, Handle pipeline) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true); @@ -873,38 +993,51 @@ void Gles2Rhi::bind_pipeline(Handle ctx, Handle pipel glDisable(GL_SCISSOR_TEST); - if (desc.depth_attachment) { + if (desc.depth_attachment) + { glEnable(GL_DEPTH_TEST); GLenum depth_func = map_compare_func(desc.depth_attachment->func); SRB2_ASSERT(depth_func != GL_ZERO); glDepthFunc(depth_func); glDepthMask(desc.depth_attachment->write ? GL_TRUE : GL_FALSE); - } else { + } + else + { glDisable(GL_DEPTH_TEST); } - if (desc.color_attachment.blend) { + if (desc.color_attachment.blend) + { rhi::BlendDesc& bl = *desc.color_attachment.blend; glEnable(GL_BLEND); - glBlendFuncSeparate(map_blend_factor(bl.source_factor_color), - map_blend_factor(bl.dest_factor_color), - map_blend_factor(bl.source_factor_alpha), - map_blend_factor(bl.dest_factor_alpha)); + glBlendFuncSeparate( + map_blend_factor(bl.source_factor_color), + map_blend_factor(bl.dest_factor_color), + map_blend_factor(bl.source_factor_alpha), + map_blend_factor(bl.dest_factor_alpha) + ); glBlendEquationSeparate(map_blend_function(bl.color_function), map_blend_function(bl.alpha_function)); glBlendColor(desc.blend_color.r, desc.blend_color.g, desc.blend_color.b, desc.blend_color.a); - } else { + } + else + { glDisable(GL_BLEND); } - glColorMask(desc.color_attachment.color_mask.r ? GL_TRUE : GL_FALSE, - desc.color_attachment.color_mask.g ? GL_TRUE : GL_FALSE, - desc.color_attachment.color_mask.b ? GL_TRUE : GL_FALSE, - desc.color_attachment.color_mask.a ? GL_TRUE : GL_FALSE); + glColorMask( + desc.color_attachment.color_mask.r ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.g ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.b ? GL_TRUE : GL_FALSE, + desc.color_attachment.color_mask.a ? GL_TRUE : GL_FALSE + ); GLenum cull_face = map_cull_mode(desc.cull); - if (cull_face == GL_NONE) { + if (cull_face == GL_NONE) + { glDisable(GL_CULL_FACE); - } else { + } + else + { glEnable(GL_CULL_FACE); glCullFace(cull_face); } @@ -914,7 +1047,8 @@ void Gles2Rhi::bind_pipeline(Handle ctx, Handle pipel current_primitive_type_ = desc.primitive; } -void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindingsInfo& info) { +void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindingsInfo& info) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); @@ -926,7 +1060,8 @@ void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindings SRB2_ASSERT(info.sampler_textures.size() == pl.desc.sampler_input.enabled_samplers.size()); // TODO only disable the vertex attributes of the previously bound pipeline (performance) - for (GLuint i = 0; i < kMaxVertexAttributes; i++) { + for (GLuint i = 0; i < kMaxVertexAttributes; i++) + { glDisableVertexAttribArray(i); } @@ -935,7 +1070,8 @@ void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindings // OpenGL ES does not require binding buffers to the pipeline the same way Vulkan does. // Instead, we need to find the pipeline vertex attributes which would be affected by // the changing set of vertex buffers, and reassign their Vertex Attribute Pointers. - for (size_t i = 0; i < pl.desc.vertex_input.attr_layouts.size(); i++) { + for (size_t i = 0; i < pl.desc.vertex_input.attr_layouts.size(); i++) + { auto& attr_layout = pl.desc.vertex_input.attr_layouts[i]; uint32_t attr_buffer_index = attr_layout.buffer_index; VertexAttributeName attr_name = attr_layout.name; @@ -960,21 +1096,32 @@ void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindings glBindBuffer(GL_ARRAY_BUFFER, buffer.buffer); glEnableVertexAttribArray(gl_attr_location); - glVertexAttribPointer(gl_attr_location, vertex_attr_size, vertex_attr_type, GL_FALSE, buffer_layout.stride, reinterpret_cast(vertex_buffer_offset + attr_layout.offset)); + glVertexAttribPointer( + gl_attr_location, + vertex_attr_size, + vertex_attr_type, + GL_FALSE, + buffer_layout.stride, + reinterpret_cast(vertex_buffer_offset + attr_layout.offset) + ); } rhi::Handle index_buffer_handle; std::tie(index_buffer_handle, index_buffer_offset_) = info.index_buffer; - if (index_buffer_handle == rhi::kNullHandle) { + if (index_buffer_handle == rhi::kNullHandle) + { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } else { + } + else + { SRB2_ASSERT(buffer_slab_.is_valid(index_buffer_handle)); auto& ib = *static_cast(&buffer_slab_[index_buffer_handle]); SRB2_ASSERT(ib.desc.type == rhi::BufferType::kIndexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.buffer); } - for (size_t i = 0; i < info.sampler_textures.size(); i++) { + for (size_t i = 0; i < info.sampler_textures.size(); i++) + { auto& sampler_name = pl.desc.sampler_input.enabled_samplers[i]; rhi::Handle texture_handle = info.sampler_textures[i]; SRB2_ASSERT(texture_slab_.is_valid(texture_handle)); @@ -985,7 +1132,8 @@ void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindings GLenum active_texture = GL_TEXTURE0; GLuint uniform_value = 0; - switch (sampler_name) { + switch (sampler_name) + { case rhi::SamplerName::kSampler0: active_texture = GL_TEXTURE0; uniform_value = 0; @@ -1009,7 +1157,8 @@ void Gles2Rhi::update_bindings(Handle ctx, const UpdateBindings } } -void Gles2Rhi::update_uniforms(Handle ctx, tcb::span uniforms) { +void Gles2Rhi::update_uniforms(Handle ctx, tcb::span uniforms) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); @@ -1021,58 +1170,71 @@ void Gles2Rhi::update_uniforms(Handle ctx, tcb::span& value) const noexcept { + void operator()(const std::array& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kFloat2); glUniform2f(uniform, value[0], value[1]); } - void operator()(const std::array& value) const noexcept { + void operator()(const std::array& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kFloat3); glUniform3f(uniform, value[0], value[1], value[2]); } - void operator()(const std::array& value) const noexcept { + void operator()(const std::array& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kFloat4); glUniform4f(uniform, value[0], value[1], value[2], value[3]); } - void operator()(const int32_t& value) const noexcept { + void operator()(const int32_t& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kInt); glUniform1i(uniform, value); } - void operator()(const std::array& value) const noexcept { + void operator()(const std::array& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kInt2); glUniform2i(uniform, value[0], value[1]); } - void operator()(const std::array& value) const noexcept { + void operator()(const std::array& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kInt3); glUniform3i(uniform, value[0], value[1], value[2]); } - void operator()(const std::array& value) const noexcept { + void operator()(const std::array& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kInt4); glUniform4i(uniform, value[0], value[1], value[2], value[3]); } - void operator()(const std::array, 2>& value) const noexcept { + void operator()(const std::array, 2>& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kMat2); glUniformMatrix2fv(uniform, 1, false, reinterpret_cast(&value)); } - void operator()(const std::array, 3>& value) const noexcept { + void operator()(const std::array, 3>& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kMat3); glUniformMatrix3fv(uniform, 1, false, reinterpret_cast(&value)); } - void operator()(const std::array, 4>& value) const noexcept { + void operator()(const std::array, 4>& value) const noexcept + { SRB2_ASSERT(rhi::uniform_format(name) == rhi::UniformFormat::kMat4); glUniformMatrix4fv(uniform, 1, false, reinterpret_cast(&value)); } @@ -1081,42 +1243,56 @@ void Gles2Rhi::update_uniforms(Handle ctx, tcb::span ctx, const Rect& rect) { +void Gles2Rhi::set_scissor(Handle ctx, const Rect& rect) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); // TODO handle scissor pipeline state } -void Gles2Rhi::set_viewport(Handle ctx, const Rect& rect) { +void Gles2Rhi::set_viewport(Handle ctx, const Rect& rect) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); // TODO handle viewport pipeline state } -void Gles2Rhi::draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) { +void Gles2Rhi::draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true); glDrawArrays(map_primitive_mode(current_primitive_type_), first_vertex, vertex_count); } -void Gles2Rhi::draw_indexed(Handle ctx, - uint32_t index_count, - uint32_t first_index, - uint32_t vertex_offset) { +void Gles2Rhi::draw_indexed( + Handle ctx, + uint32_t index_count, + uint32_t first_index, + uint32_t vertex_offset +) +{ SRB2_ASSERT(graphics_context_active_ == true && graphics_context_generation_ == ctx.generation()); - glDrawElements(map_primitive_mode(current_primitive_type_), first_index, GL_UNSIGNED_SHORT, reinterpret_cast(index_buffer_offset_)); + glDrawElements( + map_primitive_mode(current_primitive_type_), + first_index, + GL_UNSIGNED_SHORT, + reinterpret_cast(index_buffer_offset_) + ); } -void Gles2Rhi::finish() { +void Gles2Rhi::finish() +{ SRB2_ASSERT(graphics_context_active_ == false); - for (auto it = disposal_.begin(); it != disposal_.end(); it++) { + for (auto it = disposal_.begin(); it != disposal_.end(); it++) + { (*it)(); } disposal_.clear(); } -void rhi::load_gles2(Gles2LoadFunc func) { +void rhi::load_gles2(Gles2LoadFunc func) +{ gladLoadGLES2(static_cast(func)); } diff --git a/src/rhi/gles2/gles2_rhi.hpp b/src/rhi/gles2/gles2_rhi.hpp index 4f19aa7c5..9858e770b 100644 --- a/src/rhi/gles2/gles2_rhi.hpp +++ b/src/rhi/gles2/gles2_rhi.hpp @@ -11,19 +11,17 @@ #include "../rhi.hpp" -namespace srb2::rhi { +namespace srb2::rhi +{ -struct Gles2FramebufferKey { +struct Gles2FramebufferKey +{ TextureOrRenderbuffer color; std::optional depth; - bool operator==(const Gles2FramebufferKey& rhs) const noexcept { - return color == rhs.color && depth == rhs.depth; - } + bool operator==(const Gles2FramebufferKey& rhs) const noexcept { return color == rhs.color && depth == rhs.depth; } - bool operator!=(const Gles2FramebufferKey& rhs) const noexcept { - return !(*this == rhs); - } + bool operator!=(const Gles2FramebufferKey& rhs) const noexcept { return !(*this == rhs); } }; } // namespace srb2::rhi @@ -32,29 +30,37 @@ struct Gles2FramebufferKey { // we need to split the namespace declarations _before_ the instantiation of std::unordered_map. template <> -struct std::hash { - std::size_t operator()(const srb2::rhi::Gles2FramebufferKey& key) const { - struct GetHandleHashVisitor { - uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept { +struct std::hash +{ + std::size_t operator()(const srb2::rhi::Gles2FramebufferKey& key) const + { + struct GetHandleHashVisitor + { + uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept + { return std::hash>()(handle); } - uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept { + uint32_t operator()(const srb2::rhi::Handle& handle) const noexcept + { return std::hash>()(handle); } }; std::size_t color_hash = std::visit(GetHandleHashVisitor {}, key.color); std::size_t depth_hash = 0; - if (key.depth) { + if (key.depth) + { depth_hash = std::visit(GetHandleHashVisitor {}, *key.depth); } return color_hash ^ (depth_hash << 1); } }; -namespace srb2::rhi { +namespace srb2::rhi +{ /// @brief Platform-specific implementation details for the GLES2 backend. -struct Gles2Platform { +struct Gles2Platform +{ virtual ~Gles2Platform(); virtual void present() = 0; @@ -62,7 +68,8 @@ struct Gles2Platform { virtual Rect get_default_framebuffer_dimensions() = 0; }; -class Gles2Rhi final : public Rhi { +class Gles2Rhi final : public Rhi +{ std::unique_ptr platform_; Slab render_pass_slab_; @@ -73,7 +80,9 @@ class Gles2Rhi final : public Rhi { std::unordered_map framebuffers_ {16}; - struct DefaultRenderPassState {}; + struct DefaultRenderPassState + { + }; using RenderPassState = std::variant; std::optional current_render_pass_; std::optional> current_pipeline_; @@ -90,7 +99,9 @@ public: virtual Handle create_render_pass(const RenderPassDesc& desc) override; virtual void destroy_render_pass(Handle&& handle) override; - virtual Handle create_texture(const TextureDesc& desc, srb2::rhi::PixelFormat data_format, tcb::span data) override; + virtual Handle + create_texture(const TextureDesc& desc, srb2::rhi::PixelFormat data_format, tcb::span data) + override; virtual void destroy_texture(Handle&& handle) override; virtual Handle create_buffer(const BufferDesc& desc, tcb::span data) override; virtual void destroy_buffer(Handle&& handle) override; @@ -99,8 +110,14 @@ public: virtual Handle create_pipeline(const PipelineDesc& desc) override; virtual void destroy_pipeline(Handle&& handle) override; - virtual void update_buffer_contents(Handle buffer, uint32_t offset, tcb::span data) override; - virtual void update_texture(Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) override; + virtual void + update_buffer_contents(Handle buffer, uint32_t offset, tcb::span data) override; + virtual void update_texture( + Handle texture, + Rect region, + srb2::rhi::PixelFormat data_format, + tcb::span data + ) override; virtual Handle begin_graphics() override; virtual void end_graphics(Handle&& ctx) override; @@ -115,10 +132,9 @@ public: virtual void set_scissor(Handle ctx, const Rect& rect) override; virtual void set_viewport(Handle ctx, const Rect& rect) override; virtual void draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) override; - virtual void draw_indexed(Handle ctx, - uint32_t index_count, - uint32_t first_index, - uint32_t vertex_offset) override; + virtual void + draw_indexed(Handle ctx, uint32_t index_count, uint32_t first_index, uint32_t vertex_offset) + override; virtual void present() override; diff --git a/src/rhi/handle.hpp b/src/rhi/handle.hpp index 7a780d8ca..110783538 100644 --- a/src/rhi/handle.hpp +++ b/src/rhi/handle.hpp @@ -10,35 +10,40 @@ #include "../cxxutil.hpp" -namespace srb2::rhi { +namespace srb2::rhi +{ -struct NullHandleType {}; +struct NullHandleType +{ +}; constexpr const NullHandleType kNullHandle = NullHandleType {}; template -class Handle { +class Handle +{ uint32_t id_; uint32_t generation_; public: Handle(uint32_t id, uint32_t generation) noexcept : id_(id), generation_(generation) {} - Handle(uint64_t combined) noexcept - : id_(combined & 0xFFFFFFFF) - , generation_((combined & 0xFFFFFFFF00000000) >> 32) - {} + Handle(uint64_t combined) noexcept : id_(combined & 0xFFFFFFFF), generation_((combined & 0xFFFFFFFF00000000) >> 32) + { + } Handle() noexcept : Handle(0, 0) {} Handle(NullHandleType) noexcept : Handle() {} Handle(const Handle&) = default; - Handle(Handle&& rhs) noexcept { + Handle(Handle&& rhs) noexcept + { id_ = std::exchange(rhs.id_, 0); generation_ = std::exchange(rhs.generation_, 0); }; Handle& operator=(const Handle&) = default; - Handle& operator=(Handle&& rhs) noexcept { + Handle& operator=(Handle&& rhs) noexcept + { id_ = std::exchange(rhs.id_, 0); generation_ = std::exchange(rhs.generation_, 0); return *this; @@ -47,22 +52,27 @@ public: // Conversions from Handles of derived type U to base type T template , bool> = true> - Handle(const Handle& rhs) noexcept : id_(rhs.id_), generation_(rhs.generation_) {} + Handle(const Handle& rhs) noexcept : id_(rhs.id_), generation_(rhs.generation_) + { + } template , bool> = true> - Handle(Handle&& rhs) noexcept { + Handle(Handle&& rhs) noexcept + { id_ = std::exchange(rhs.id_, 0); generation_ = std::exchange(rhs.generation_, 0); } template , bool> = true> - Handle& operator=(const Handle& rhs) noexcept { + Handle& operator=(const Handle& rhs) noexcept + { id_ = rhs.id_; generation_ = rhs.generation_; } template , bool> = true> - Handle& operator=(Handle&& rhs) noexcept { + Handle& operator=(Handle&& rhs) noexcept + { id_ = std::exchange(rhs.id_, 0); generation_ = std::exchange(rhs.generation_, 0); return *this; @@ -74,7 +84,8 @@ public: /// @return true if this Handle is valid (belonging to a generation > 0); false otherwise bool valid() const noexcept { return generation_ != 0; } - bool operator==(const Handle& handle) const noexcept { + bool operator==(const Handle& handle) const noexcept + { return handle.generation_ == generation_ && handle.id_ == id_; } bool operator!=(const Handle& handle) const noexcept { return !(handle == *this); } @@ -100,17 +111,20 @@ inline bool operator==(const Handle& lhs, const std::nullptr_t&) noexcept // Non-member equality of base Handle to derived Handle template , bool> = true> -inline bool operator==(const Handle& lhs, const Handle& rhs) noexcept { +inline bool operator==(const Handle& lhs, const Handle& rhs) noexcept +{ return lhs.generation() == rhs.generation() && lhs.id() == rhs.id(); } template , bool> = true> -inline bool operator!=(const Handle& lhs, const Handle& rhs) noexcept { +inline bool operator!=(const Handle& lhs, const Handle& rhs) noexcept +{ return !(lhs == rhs); } template -class HandlePool { +class HandlePool +{ std::atomic_uint32_t current_id_ {0}; std::atomic_uint32_t current_gen_ {1}; @@ -124,7 +138,8 @@ public: /// @brief Create a new unique Handle in the current generation. /// @return the new Handle. - Handle create() noexcept { + Handle create() noexcept + { const uint32_t id = current_id_.fetch_add(1); SRB2_ASSERT(id != UINT32_MAX); const uint32_t gen = current_gen_.load(); @@ -132,7 +147,8 @@ public: } /// @brief Increment the generation. All handles created after this will belong to a new generation. - void generation() noexcept { + void generation() noexcept + { const uint32_t old_gen = current_gen_.fetch_add(1); SRB2_ASSERT(old_gen != UINT32_MAX); } @@ -150,6 +166,7 @@ class SlabIterator SlabIterator(size_t index, const Slab>* slab) : index_(index), slab_(slab) {} friend Slab>; + public: SlabIterator() = default; SlabIterator(const SlabIterator&) = default; @@ -158,10 +175,7 @@ public: SlabIterator& operator=(const SlabIterator&) = default; SlabIterator& operator=(SlabIterator&&) = default; - T& operator*() const noexcept - { - return *slab_->vec_[index_].item.get(); - } + T& operator*() const noexcept { return *slab_->vec_[index_].item.get(); } SlabIterator& operator++() noexcept { @@ -187,20 +201,16 @@ public: return SlabIterator {index_ + 1, slab_}; } - bool operator==(const SlabIterator& rhs) const noexcept - { - return slab_ == rhs.slab_ && index_ == rhs.index_; - } + bool operator==(const SlabIterator& rhs) const noexcept { return slab_ == rhs.slab_ && index_ == rhs.index_; } - bool operator!=(const SlabIterator& rhs) const noexcept - { - return !(*this == rhs); - } + bool operator!=(const SlabIterator& rhs) const noexcept { return !(*this == rhs); } }; template -class Slab { - struct SlabStorage { +class Slab +{ + struct SlabStorage + { std::unique_ptr item; uint32_t gen; }; @@ -210,34 +220,42 @@ class Slab { friend SlabIterator; friend SlabIterator; + public: Slab() = default; Slab(const Slab&) = delete; Slab& operator=(const Slab&) = delete; - Handle insert(std::unique_ptr&& value) { + Handle insert(std::unique_ptr&& value) + { uint32_t ret_id = 0; - if (!free_list_.empty()) { + if (!free_list_.empty()) + { ret_id = free_list_.back(); free_list_.pop_back(); SlabStorage& storage = vec_[ret_id]; storage.item = std::move(value); storage.gen = gen_; - } else { + } + else + { ret_id = vec_.size(); vec_.push_back(SlabStorage {std::move(value), gen_}); } return Handle(ret_id, gen_); } - std::unique_ptr remove(Handle handle) { + std::unique_ptr remove(Handle handle) + { uint32_t handle_id = handle.id(); uint32_t handle_gen = handle.generation(); - if (handle_id >= vec_.size()) { + if (handle_id >= vec_.size()) + { return nullptr; } SlabStorage& storage = vec_[handle_id]; - if (storage.gen > handle_gen) { + if (storage.gen > handle_gen) + { return nullptr; } std::unique_ptr ret = std::move(storage.item); @@ -251,14 +269,17 @@ public: return ret; } - bool is_valid(Handle handle) { + bool is_valid(Handle handle) + { uint32_t handle_id = handle.id(); uint32_t handle_gen = handle.generation(); - if (handle_id >= vec_.size()) { + if (handle_id >= vec_.size()) + { return false; } SlabStorage& storage = vec_[handle_id]; - if (storage.gen > handle_gen) { + if (storage.gen > handle_gen) + { return false; } return true; @@ -275,39 +296,31 @@ public: } } - T& operator[](Handle handle) { + T& operator[](Handle handle) + { SRB2_ASSERT(is_valid(handle)); return *vec_[handle.id()].item; } - SlabIterator begin() - { - return SlabIterator {0, this}; - } + SlabIterator begin() { return SlabIterator {0, this}; } - SlabIterator end() - { - return SlabIterator {vec_.size(), this}; - } + SlabIterator end() { return SlabIterator {vec_.size(), this}; } - SlabIterator cbegin() const - { - return SlabIterator {0, this}; - } + SlabIterator cbegin() const { return SlabIterator {0, this}; } - SlabIterator cend() const - { - return SlabIterator {vec_.size(), this}; - } + SlabIterator cend() const { return SlabIterator {vec_.size(), this}; } }; } // namespace srb2::rhi -namespace std { +namespace std +{ template -struct hash> { - std::size_t operator()(const srb2::rhi::Handle& e) const { +struct hash> +{ + std::size_t operator()(const srb2::rhi::Handle& e) const + { return std::hash()(e.generation()) ^ (std::hash()(e.id()) << 1); } }; diff --git a/src/rhi/rhi.cpp b/src/rhi/rhi.cpp index c5fd0b973..c63282b95 100644 --- a/src/rhi/rhi.cpp +++ b/src/rhi/rhi.cpp @@ -9,38 +9,28 @@ using namespace srb2::rhi; Rhi::~Rhi() = default; const ProgramRequirements srb2::rhi::kProgramRequirementsUnshaded = { - ProgramVertexInputRequirements {{ - ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, - ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, - ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false} - }}, - ProgramUniformRequirements {{ - {{UniformName::kProjection}}, - {{UniformName::kModelView, UniformName::kTexCoord0Transform}} - }}, - ProgramSamplerRequirements {{ - ProgramSamplerInput {SamplerName::kSampler0, true} - }} -}; + ProgramVertexInputRequirements { + {ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, + ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, + ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false}}}, + ProgramUniformRequirements { + {{{UniformName::kProjection}}, {{UniformName::kModelView, UniformName::kTexCoord0Transform}}}}, + ProgramSamplerRequirements {{ProgramSamplerInput {SamplerName::kSampler0, true}}}}; const ProgramRequirements srb2::rhi::kProgramRequirementsUnshadedPaletted = { - ProgramVertexInputRequirements {{ - ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, - ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, - ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false} - }}, - ProgramUniformRequirements {{ - {{UniformName::kProjection}}, - {{UniformName::kModelView, UniformName::kTexCoord0Transform}} - }}, - ProgramSamplerRequirements {{ - ProgramSamplerInput {SamplerName::kSampler0, true}, - ProgramSamplerInput {SamplerName::kSampler1, true} - }} -}; + ProgramVertexInputRequirements { + {ProgramVertexInput {VertexAttributeName::kPosition, VertexAttributeFormat::kFloat3, true}, + ProgramVertexInput {VertexAttributeName::kTexCoord0, VertexAttributeFormat::kFloat2, false}, + ProgramVertexInput {VertexAttributeName::kColor, VertexAttributeFormat::kFloat4, false}}}, + ProgramUniformRequirements { + {{{UniformName::kProjection}}, {{UniformName::kModelView, UniformName::kTexCoord0Transform}}}}, + ProgramSamplerRequirements { + {ProgramSamplerInput {SamplerName::kSampler0, true}, ProgramSamplerInput {SamplerName::kSampler1, true}}}}; -const ProgramRequirements& rhi::program_requirements_for_program(PipelineProgram program) noexcept { - switch (program) { +const ProgramRequirements& rhi::program_requirements_for_program(PipelineProgram program) noexcept +{ + switch (program) + { case PipelineProgram::kUnshaded: return kProgramRequirementsUnshaded; case PipelineProgram::kUnshadedPaletted: diff --git a/src/rhi/rhi.hpp b/src/rhi/rhi.hpp index 1da54fbf0..a44423aee 100644 --- a/src/rhi/rhi.hpp +++ b/src/rhi/rhi.hpp @@ -12,28 +12,41 @@ #include "../core/static_vec.hpp" #include "handle.hpp" -namespace srb2::rhi { +namespace srb2::rhi +{ -struct Buffer {}; +struct Buffer +{ +}; -struct Texture {}; +struct Texture +{ +}; -struct Pipeline {}; +struct Pipeline +{ +}; -struct RenderPass {}; +struct RenderPass +{ +}; -struct Renderbuffer {}; +struct Renderbuffer +{ +}; using TextureOrRenderbuffer = std::variant, Handle>; -enum class VertexAttributeFormat { +enum class VertexAttributeFormat +{ kFloat, kFloat2, kFloat3, kFloat4 }; -enum class UniformFormat { +enum class UniformFormat +{ kFloat, kFloat2, kFloat3, @@ -47,20 +60,23 @@ enum class UniformFormat { kMat4 }; -enum class PixelFormat { +enum class PixelFormat +{ kR8, kRGBA8, kDepth16, kStencil8 }; -enum class TextureFormat { +enum class TextureFormat +{ kLuminance, kRGB, kRGBA }; -enum class CompareFunc { +enum class CompareFunc +{ kNever, kLess, kEqual, @@ -71,7 +87,8 @@ enum class CompareFunc { kAlways }; -enum class BlendFactor { +enum class BlendFactor +{ kZero, kOne, kSource, @@ -89,13 +106,15 @@ enum class BlendFactor { kSourceAlphaSaturated }; -enum class BlendFunction { +enum class BlendFunction +{ kAdd, kSubtract, kReverseSubtract }; -enum class PrimitiveType { +enum class PrimitiveType +{ kPoints, kLines, kLineStrip, @@ -104,44 +123,52 @@ enum class PrimitiveType { kTriangleFan }; -enum class CullMode { +enum class CullMode +{ kNone, kFront, kBack }; -enum class FaceWinding { +enum class FaceWinding +{ kCounterClockwise, kClockwise }; -enum class AttachmentLoadOp { +enum class AttachmentLoadOp +{ kLoad, kClear, kDontCare }; -enum class AttachmentStoreOp { +enum class AttachmentStoreOp +{ kStore, kDontCare }; -enum class PipelineProgram { +enum class PipelineProgram +{ kUnshaded, kUnshadedPaletted }; -enum class BufferType { +enum class BufferType +{ kVertexBuffer, kIndexBuffer }; -enum class BufferUsage { +enum class BufferUsage +{ kImmutable, kDynamic }; -enum class VertexAttributeName { +enum class VertexAttributeName +{ kPosition, kNormal, kTexCoord0, @@ -149,28 +176,32 @@ enum class VertexAttributeName { kColor }; -enum class UniformName { +enum class UniformName +{ kTime, kModelView, kProjection, kTexCoord0Transform }; -enum class SamplerName { +enum class SamplerName +{ kSampler0, kSampler1, kSampler2, kSampler3 }; -struct Color { +struct Color +{ float r; float g; float b; float a; }; -struct Rect { +struct Rect +{ int32_t x; int32_t y; uint32_t w; @@ -180,35 +211,42 @@ struct Rect { constexpr const size_t kMaxVertexAttributes = 8; constexpr const size_t kMaxSamplers = 4; -struct ProgramVertexInput { +struct ProgramVertexInput +{ VertexAttributeName name; VertexAttributeFormat type; bool required; }; -struct ProgramUniformInput { +struct ProgramUniformInput +{ UniformName name; bool required; }; -struct ProgramSamplerInput { +struct ProgramSamplerInput +{ SamplerName name; bool required; }; -struct ProgramVertexInputRequirements { +struct ProgramVertexInputRequirements +{ srb2::StaticVec attributes; }; -struct ProgramUniformRequirements { +struct ProgramUniformRequirements +{ srb2::StaticVec, 4> uniform_groups; }; -struct ProgramSamplerRequirements { +struct ProgramSamplerRequirements +{ std::array, kMaxSamplers> samplers; }; -struct ProgramRequirements { +struct ProgramRequirements +{ ProgramVertexInputRequirements vertex_input; ProgramUniformRequirements uniforms; ProgramSamplerRequirements samplers; @@ -221,7 +259,8 @@ const ProgramRequirements& program_requirements_for_program(PipelineProgram prog inline constexpr const VertexAttributeFormat vertex_attribute_format(VertexAttributeName name) noexcept { - switch (name) { + switch (name) + { case VertexAttributeName::kPosition: return VertexAttributeFormat::kFloat3; case VertexAttributeName::kNormal: @@ -239,7 +278,8 @@ inline constexpr const VertexAttributeFormat vertex_attribute_format(VertexAttri inline constexpr const UniformFormat uniform_format(UniformName name) noexcept { - switch (name) { + switch (name) + { case UniformName::kTime: return UniformFormat::kFloat; case UniformName::kModelView: @@ -253,11 +293,13 @@ inline constexpr const UniformFormat uniform_format(UniformName name) noexcept } } -struct VertexBufferLayoutDesc { +struct VertexBufferLayoutDesc +{ uint32_t stride; }; -struct VertexAttributeLayoutDesc { +struct VertexAttributeLayoutDesc +{ VertexAttributeName name; uint32_t buffer_index; uint32_t offset; @@ -265,27 +307,32 @@ struct VertexAttributeLayoutDesc { // constexpr const size_t kMaxVertexBufferBindings = 4; -struct VertexInputDesc { +struct VertexInputDesc +{ std::vector buffer_layouts; std::vector attr_layouts; }; -struct UniformInputDesc { +struct UniformInputDesc +{ srb2::StaticVec, 4> enabled_uniforms; }; -struct SamplerInputDesc { +struct SamplerInputDesc +{ std::vector enabled_samplers; }; -struct ColorMask { +struct ColorMask +{ bool r; bool g; bool b; bool a; }; -struct BlendDesc { +struct BlendDesc +{ BlendFactor source_factor_color; BlendFactor dest_factor_color; BlendFunction color_function; @@ -294,19 +341,22 @@ struct BlendDesc { BlendFunction alpha_function; }; -struct PipelineDepthAttachmentDesc { +struct PipelineDepthAttachmentDesc +{ PixelFormat format; CompareFunc func; bool write; }; -struct PipelineColorAttachmentDesc { +struct PipelineColorAttachmentDesc +{ PixelFormat format; std::optional blend; ColorMask color_mask; }; -struct PipelineDesc { +struct PipelineDesc +{ PipelineProgram program; VertexInputDesc vertex_input; UniformInputDesc uniform_input; @@ -320,32 +370,37 @@ struct PipelineDesc { Color blend_color; }; -struct RenderPassDesc { +struct RenderPassDesc +{ std::optional depth_format; PixelFormat color_format; AttachmentLoadOp load_op; AttachmentStoreOp store_op; }; -struct RenderbufferDesc { +struct RenderbufferDesc +{ PixelFormat format; uint32_t width; uint32_t height; }; -struct TextureDesc { +struct TextureDesc +{ TextureFormat format; uint32_t width; uint32_t height; }; -struct BufferDesc { +struct BufferDesc +{ uint32_t size; BufferType type; BufferUsage usage; }; -struct RenderPassBeginInfo { +struct RenderPassBeginInfo +{ Handle render_pass; TextureOrRenderbuffer color_attachment; std::optional depth_attachment; @@ -367,8 +422,7 @@ using UniformVariant = std::variant< std::array, 2>, std::array, 3>, - std::array, 4> ->; + std::array, 4>>; inline constexpr UniformFormat uniform_variant_format(const UniformVariant& variant) { @@ -382,40 +436,62 @@ inline constexpr UniformFormat uniform_variant_format(const UniformVariant& vari UniformFormat operator()(const std::array&) const noexcept { return UniformFormat::kInt2; } UniformFormat operator()(const std::array&) const noexcept { return UniformFormat::kInt3; } UniformFormat operator()(const std::array&) const noexcept { return UniformFormat::kInt4; } - UniformFormat operator()(const std::array, 2>&) const noexcept { return UniformFormat::kMat2; } - UniformFormat operator()(const std::array, 3>&) const noexcept { return UniformFormat::kMat3; } - UniformFormat operator()(const std::array, 4>&) const noexcept { return UniformFormat::kMat4; } + UniformFormat operator()(const std::array, 2>&) const noexcept + { + return UniformFormat::kMat2; + } + UniformFormat operator()(const std::array, 3>&) const noexcept + { + return UniformFormat::kMat3; + } + UniformFormat operator()(const std::array, 4>&) const noexcept + { + return UniformFormat::kMat4; + } }; - return std::visit(Visitor{}, variant); + return std::visit(Visitor {}, variant); } -struct VertexAttributeBufferBinding { +struct VertexAttributeBufferBinding +{ uint32_t attribute_index; Handle vertex_buffer; }; -struct TextureBinding { +struct TextureBinding +{ SamplerName name; Handle texture; }; -struct CreateUniformSetInfo { +struct CreateUniformSetInfo +{ tcb::span uniforms; }; -struct CreateBindingSetInfo { +struct CreateBindingSetInfo +{ tcb::span vertex_buffers; tcb::span sampler_textures; }; -struct UniformSet {}; -struct BindingSet {}; +struct UniformSet +{ +}; +struct BindingSet +{ +}; -struct TransferContext {}; -struct GraphicsContext {}; +struct TransferContext +{ +}; +struct GraphicsContext +{ +}; /// @brief An active handle to a rendering device. -struct Rhi { +struct Rhi +{ virtual ~Rhi(); virtual Handle create_render_pass(const RenderPassDesc& desc) = 0; @@ -434,10 +510,22 @@ struct Rhi { virtual void end_transfer(Handle handle) = 0; // Transfer Context functions - virtual void update_buffer_contents(Handle ctx, Handle buffer, uint32_t offset, tcb::span data) = 0; - virtual void update_texture(Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data) = 0; + virtual void update_buffer_contents( + Handle ctx, + Handle buffer, + uint32_t offset, + tcb::span data + ) = 0; + virtual void update_texture( + Handle ctx, + Handle texture, + Rect region, + srb2::rhi::PixelFormat data_format, + tcb::span data + ) = 0; virtual Handle create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) = 0; - virtual Handle create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) = 0; + virtual Handle + create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) = 0; virtual Handle begin_graphics() = 0; virtual void end_graphics(Handle ctx) = 0; diff --git a/src/sdl/rhi_gl3_core_platform.cpp b/src/sdl/rhi_gl3_core_platform.cpp index e6971873d..d8c0cde33 100644 --- a/src/sdl/rhi_gl3_core_platform.cpp +++ b/src/sdl/rhi_gl3_core_platform.cpp @@ -11,17 +11,20 @@ using namespace srb2::rhi; SdlGlCorePlatform::~SdlGlCorePlatform() = default; -void SdlGlCorePlatform::present() { +void SdlGlCorePlatform::present() +{ SRB2_ASSERT(window != nullptr); SRB2_ASSERT(SDL_GetWindowID(window) != 0); SDL_GL_SwapWindow(window); } -std::tuple SdlGlCorePlatform::find_shader_sources(rhi::PipelineProgram program) { +std::tuple SdlGlCorePlatform::find_shader_sources(rhi::PipelineProgram program) +{ const char* vertex_lump_name = nullptr; const char* fragment_lump_name = nullptr; - switch (program) { + switch (program) + { case rhi::PipelineProgram::kUnshaded: vertex_lump_name = "rhi_glcore_vertex_unshaded"; fragment_lump_name = "rhi_glcore_fragment_unshaded"; @@ -47,7 +50,8 @@ std::tuple SdlGlCorePlatform::find_shader_sources(rhi: return std::make_tuple(std::move(vertex_shader), std::move(fragment_shader)); } -rhi::Rect SdlGlCorePlatform::get_default_framebuffer_dimensions() { +rhi::Rect SdlGlCorePlatform::get_default_framebuffer_dimensions() +{ SRB2_ASSERT(window != nullptr); int w; int h; diff --git a/src/sdl/rhi_gl3_core_platform.hpp b/src/sdl/rhi_gl3_core_platform.hpp index 0683a428b..0c0f6f4f3 100644 --- a/src/sdl/rhi_gl3_core_platform.hpp +++ b/src/sdl/rhi_gl3_core_platform.hpp @@ -1,14 +1,16 @@ #ifndef __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ #define __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ -#include "../rhi/rhi.hpp" #include "../rhi/gl3_core/gl3_core_rhi.hpp" +#include "../rhi/rhi.hpp" #include -namespace srb2::rhi { +namespace srb2::rhi +{ -struct SdlGlCorePlatform final : public GlCorePlatform { +struct SdlGlCorePlatform final : public GlCorePlatform +{ SDL_Window* window = nullptr; virtual ~SdlGlCorePlatform(); diff --git a/src/sdl/rhi_gles2_platform.cpp b/src/sdl/rhi_gles2_platform.cpp index d9d8546e5..d91a3d2bf 100644 --- a/src/sdl/rhi_gles2_platform.cpp +++ b/src/sdl/rhi_gles2_platform.cpp @@ -11,17 +11,20 @@ using namespace srb2::rhi; SdlGles2Platform::~SdlGles2Platform() = default; -void SdlGles2Platform::present() { +void SdlGles2Platform::present() +{ SRB2_ASSERT(window != nullptr); SRB2_ASSERT(SDL_GetWindowID(window) != 0); SDL_GL_SwapWindow(window); } -std::tuple SdlGles2Platform::find_shader_sources(rhi::PipelineProgram program) { +std::tuple SdlGles2Platform::find_shader_sources(rhi::PipelineProgram program) +{ const char* vertex_lump_name = nullptr; const char* fragment_lump_name = nullptr; - switch (program) { + switch (program) + { case rhi::PipelineProgram::kUnshaded: vertex_lump_name = "rhi_glsles_vertex_unshaded"; fragment_lump_name = "rhi_glsles_fragment_unshaded"; @@ -47,7 +50,8 @@ std::tuple SdlGles2Platform::find_shader_sources(rhi:: return std::make_tuple(std::move(vertex_shader), std::move(fragment_shader)); } -rhi::Rect SdlGles2Platform::get_default_framebuffer_dimensions() { +rhi::Rect SdlGles2Platform::get_default_framebuffer_dimensions() +{ SRB2_ASSERT(window != nullptr); int w; int h; diff --git a/src/sdl/rhi_gles2_platform.hpp b/src/sdl/rhi_gles2_platform.hpp index 0476931d0..19970d8f1 100644 --- a/src/sdl/rhi_gles2_platform.hpp +++ b/src/sdl/rhi_gles2_platform.hpp @@ -1,14 +1,16 @@ #ifndef __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ #define __SRB2_SDL_RHI_GLES2_PLATFORM_HPP__ -#include "../rhi/rhi.hpp" #include "../rhi/gles2/gles2_rhi.hpp" +#include "../rhi/rhi.hpp" #include -namespace srb2::rhi { +namespace srb2::rhi +{ -struct SdlGles2Platform final : public Gles2Platform { +struct SdlGles2Platform final : public Gles2Platform +{ SDL_Window* window = nullptr; virtual ~SdlGles2Platform();