hwr: Store T in Slab directly

This commit is contained in:
Eidolon 2023-01-14 20:27:56 -06:00
parent ccc10eadd0
commit 095aa635b0
3 changed files with 123 additions and 142 deletions

View file

@ -11,9 +11,7 @@
#include <glad/gl.h>
using namespace srb2;
using srb2::rhi::GlCorePlatform;
using srb2::rhi::GlCoreRhi;
using namespace rhi;
#if 1
#define GL_ASSERT \
@ -31,13 +29,6 @@ using srb2::rhi::GlCoreRhi;
namespace
{
template <typename D, typename B>
std::unique_ptr<D, std::default_delete<D>> static_unique_ptr_cast(std::unique_ptr<B, std::default_delete<B>> ptr)
{
D* derived = static_cast<D*>(ptr.release());
return std::unique_ptr<D, std::default_delete<D>>(derived, std::default_delete<D>());
}
constexpr GLenum map_pixel_format(rhi::PixelFormat format)
{
switch (format)
@ -399,69 +390,6 @@ constexpr GLenum map_uniform_format(rhi::UniformFormat format)
}
}
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
{
GLuint buffer;
rhi::BufferDesc desc;
GlCoreBuffer(GLuint buffer, const rhi::BufferDesc& desc) noexcept : buffer(buffer), desc(desc) {}
};
struct GlCoreRenderPass : public rhi::RenderPass
{
rhi::RenderPassDesc desc;
explicit GlCoreRenderPass(const rhi::RenderPassDesc& desc) noexcept : desc(desc) {}
};
struct GlCoreRenderbuffer : public rhi::Renderbuffer
{
GLuint renderbuffer;
explicit GlCoreRenderbuffer(GLuint renderbuffer) noexcept : renderbuffer(renderbuffer) {}
};
struct GlCoreUniformSet : public rhi::UniformSet
{
std::vector<rhi::UniformVariant> uniforms;
};
struct GlCoreBindingSet : public rhi::BindingSet
{
GLuint vao;
std::unordered_map<rhi::SamplerName, GLuint> textures {4};
};
struct GlCorePipeline : public rhi::Pipeline
{
GLuint vertex_shader = 0;
GLuint fragment_shader = 0;
GLuint program = 0;
std::unordered_map<rhi::VertexAttributeName, GLuint> attrib_locations {2};
std::unordered_map<rhi::UniformName, GLuint> uniform_locations {2};
std::unordered_map<rhi::SamplerName, GLuint> sampler_locations {2};
rhi::PipelineDesc desc;
};
struct GlCoreGraphicsContext : public rhi::GraphicsContext
{
};
struct GlCoreTransferContext : public rhi::TransferContext
{
};
struct GlCoreActiveUniform
{
GLenum type;
GLuint location;
};
} // namespace
GlCorePlatform::~GlCorePlatform() = default;
@ -479,15 +407,16 @@ rhi::Handle<rhi::RenderPass> GlCoreRhi::create_render_pass(const rhi::RenderPass
SRB2_ASSERT(graphics_context_active_ == false);
// GL has no formal render pass object
return render_pass_slab_.insert(std::make_unique<GlCoreRenderPass>(desc));
GlCoreRenderPass pass;
pass.desc = desc;
return render_pass_slab_.insert(std::move(pass));
}
void GlCoreRhi::destroy_render_pass(rhi::Handle<rhi::RenderPass> handle)
{
SRB2_ASSERT(graphics_context_active_ == false);
std::unique_ptr<rhi::RenderPass> buffer = render_pass_slab_.remove(handle);
std::unique_ptr<GlCoreRenderPass> casted(static_cast<GlCoreRenderPass*>(buffer.release()));
render_pass_slab_.remove(handle);
}
rhi::Handle<rhi::Texture> GlCoreRhi::create_texture(const rhi::TextureDesc& desc)
@ -513,7 +442,10 @@ rhi::Handle<rhi::Texture> GlCoreRhi::create_texture(const rhi::TextureDesc& desc
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<GlCoreTexture>(name, desc));
GlCoreTexture texture;
texture.texture = name;
texture.desc = desc;
return texture_slab_.insert(std::move(texture));
}
void GlCoreRhi::destroy_texture(rhi::Handle<rhi::Texture> handle)
@ -521,8 +453,8 @@ void GlCoreRhi::destroy_texture(rhi::Handle<rhi::Texture> handle)
SRB2_ASSERT(graphics_context_active_ == false);
SRB2_ASSERT(texture_slab_.is_valid(handle) == true);
std::unique_ptr<GlCoreTexture> casted = static_unique_ptr_cast<GlCoreTexture>(texture_slab_.remove(handle));
GLuint name = casted->texture;
GlCoreTexture casted = texture_slab_.remove(handle);
GLuint name = casted.texture;
disposal_.push_back([this, name] { gl_->DeleteTextures(1, &name); });
}
@ -544,7 +476,7 @@ void GlCoreRhi::update_texture(
}
SRB2_ASSERT(texture_slab_.is_valid(texture) == true);
auto& t = *static_cast<GlCoreTexture*>(&texture_slab_[texture]);
auto& t = texture_slab_[texture];
GLenum format = GL_RGBA;
GLenum type = GL_UNSIGNED_BYTE;
@ -593,7 +525,10 @@ rhi::Handle<rhi::Buffer> GlCoreRhi::create_buffer(const rhi::BufferDesc& desc)
gl_->BufferData(target, desc.size, nullptr, usage);
GL_ASSERT
return buffer_slab_.insert(std::make_unique<GlCoreBuffer>(name, desc));
GlCoreBuffer buffer;
buffer.buffer = name;
buffer.desc = desc;
return buffer_slab_.insert(std::move(buffer));
}
void GlCoreRhi::destroy_buffer(rhi::Handle<rhi::Buffer> handle)
@ -602,8 +537,8 @@ void GlCoreRhi::destroy_buffer(rhi::Handle<rhi::Buffer> handle)
SRB2_ASSERT(buffer_slab_.is_valid(handle) == true);
SRB2_ASSERT(graphics_context_active_ == false);
std::unique_ptr<GlCoreBuffer> casted = static_unique_ptr_cast<GlCoreBuffer>(buffer_slab_.remove(handle));
GLuint name = casted->buffer;
GlCoreBuffer casted = buffer_slab_.remove(handle);
GLuint name = casted.buffer;
disposal_.push_back([this, name] { gl_->DeleteBuffers(1, &name); });
}
@ -625,7 +560,7 @@ void GlCoreRhi::update_buffer_contents(
}
SRB2_ASSERT(buffer_slab_.is_valid(handle) == true);
auto& b = *static_cast<GlCoreBuffer*>(&buffer_slab_[handle]);
auto& b = buffer_slab_[handle];
SRB2_ASSERT(offset < b.desc.size && offset + data.size() <= b.desc.size);
@ -660,7 +595,7 @@ GlCoreRhi::create_uniform_set(rhi::Handle<rhi::TransferContext> ctx, const rhi::
uniform_set.uniforms.push_back(uniform);
}
return uniform_set_slab_.insert(std::make_unique<GlCoreUniformSet>(std::move(uniform_set)));
return uniform_set_slab_.insert(std::move(uniform_set));
}
rhi::Handle<rhi::BindingSet> GlCoreRhi::create_binding_set(
@ -674,7 +609,7 @@ rhi::Handle<rhi::BindingSet> GlCoreRhi::create_binding_set(
SRB2_ASSERT(ctx.generation() == transfer_context_generation_);
SRB2_ASSERT(pipeline_slab_.is_valid(pipeline) == true);
auto& pl = *static_cast<GlCorePipeline*>(&pipeline_slab_[pipeline]);
auto& pl = pipeline_slab_[pipeline];
SRB2_ASSERT(info.vertex_buffers.size() == pl.desc.vertex_input.buffer_layouts.size());
@ -689,8 +624,7 @@ rhi::Handle<rhi::BindingSet> GlCoreRhi::create_binding_set(
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<GlCoreBuffer*>(&buffer_slab_[info.vertex_buffers[attr_layout.buffer_index].vertex_buffer]);
auto& buf = 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];
@ -728,11 +662,11 @@ rhi::Handle<rhi::BindingSet> GlCoreRhi::create_binding_set(
SRB2_ASSERT(binding.name == sampler_name);
SRB2_ASSERT(texture_slab_.is_valid(binding.texture));
auto& tx = *static_cast<GlCoreTexture*>(&texture_slab_[binding.texture]);
auto& tx = texture_slab_[binding.texture];
binding_set.textures.insert({sampler_name, tx.texture});
}
return binding_set_slab_.insert(std::make_unique<GlCoreBindingSet>(std::move(binding_set)));
return binding_set_slab_.insert(std::move(binding_set));
}
rhi::Handle<rhi::Renderbuffer> GlCoreRhi::create_renderbuffer(const rhi::RenderbufferDesc& desc)
@ -748,7 +682,9 @@ rhi::Handle<rhi::Renderbuffer> GlCoreRhi::create_renderbuffer(const rhi::Renderb
gl_->RenderbufferStorage(GL_RENDERBUFFER, map_pixel_format(desc.format), desc.width, desc.height);
GL_ASSERT
return renderbuffer_slab_.insert(std::make_unique<GlCoreRenderbuffer>(GlCoreRenderbuffer {name}));
GlCoreRenderbuffer rb;
rb.renderbuffer = name;
return renderbuffer_slab_.insert(std::move(rb));
}
void GlCoreRhi::destroy_renderbuffer(rhi::Handle<rhi::Renderbuffer> handle)
@ -756,9 +692,8 @@ void GlCoreRhi::destroy_renderbuffer(rhi::Handle<rhi::Renderbuffer> handle)
SRB2_ASSERT(graphics_context_active_ == false);
SRB2_ASSERT(renderbuffer_slab_.is_valid(handle) == true);
std::unique_ptr<GlCoreRenderbuffer> casted =
static_unique_ptr_cast<GlCoreRenderbuffer>(renderbuffer_slab_.remove(handle));
GLuint name = casted->renderbuffer;
GlCoreRenderbuffer casted = renderbuffer_slab_.remove(handle);
GLuint name = casted.renderbuffer;
disposal_.push_back([this, name] { gl_->DeleteRenderbuffers(1, &name); });
}
@ -1031,7 +966,7 @@ rhi::Handle<rhi::Pipeline> GlCoreRhi::create_pipeline(const PipelineDesc& desc)
pipeline.fragment_shader = fragment;
pipeline.program = program;
return pipeline_slab_.insert(std::make_unique<GlCorePipeline>(std::move(pipeline)));
return pipeline_slab_.insert(std::move(pipeline));
}
void GlCoreRhi::destroy_pipeline(rhi::Handle<rhi::Pipeline> handle)
@ -1039,10 +974,10 @@ void GlCoreRhi::destroy_pipeline(rhi::Handle<rhi::Pipeline> handle)
SRB2_ASSERT(graphics_context_active_ == false);
SRB2_ASSERT(pipeline_slab_.is_valid(handle) == true);
std::unique_ptr<GlCorePipeline> casted = static_unique_ptr_cast<GlCorePipeline>(pipeline_slab_.remove(handle));
GLuint vertex_shader = casted->vertex_shader;
GLuint fragment_shader = casted->fragment_shader;
GLuint program = casted->program;
GlCorePipeline casted = pipeline_slab_.remove(handle);
GLuint vertex_shader = casted.vertex_shader;
GLuint fragment_shader = casted.fragment_shader;
GLuint program = casted.program;
disposal_.push_back([this, fragment_shader] { gl_->DeleteShader(fragment_shader); });
disposal_.push_back([this, vertex_shader] { gl_->DeleteShader(vertex_shader); });
@ -1126,7 +1061,7 @@ void GlCoreRhi::begin_render_pass(Handle<GraphicsContext> ctx, const RenderPassB
SRB2_ASSERT(current_render_pass_.has_value() == false);
SRB2_ASSERT(render_pass_slab_.is_valid(info.render_pass) == true);
auto& rp = *static_cast<GlCoreRenderPass*>(&render_pass_slab_[info.render_pass]);
auto& rp = render_pass_slab_[info.render_pass];
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});
@ -1150,14 +1085,14 @@ void GlCoreRhi::begin_render_pass(Handle<GraphicsContext> ctx, const RenderPassB
[&, this](const Handle<Texture>& handle)
{
SRB2_ASSERT(texture_slab_.is_valid(handle));
auto& texture = *static_cast<GlCoreTexture*>(&texture_slab_[handle]);
auto& texture = texture_slab_[handle];
gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.texture, 0);
GL_ASSERT
},
[&, this](const Handle<Renderbuffer>& handle)
{
SRB2_ASSERT(renderbuffer_slab_.is_valid(handle));
auto& renderbuffer = *static_cast<GlCoreRenderbuffer*>(&renderbuffer_slab_[handle]);
auto& renderbuffer = renderbuffer_slab_[handle];
gl_->FramebufferRenderbuffer(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
@ -1206,7 +1141,7 @@ void GlCoreRhi::bind_pipeline(Handle<GraphicsContext> ctx, Handle<Pipeline> pipe
SRB2_ASSERT(current_render_pass_.has_value() == true);
SRB2_ASSERT(pipeline_slab_.is_valid(pipeline) == true);
auto& pl = *static_cast<GlCorePipeline*>(&pipeline_slab_[pipeline]);
auto& pl = pipeline_slab_[pipeline];
auto& desc = pl.desc;
gl_->UseProgram(pl.program);
@ -1288,10 +1223,10 @@ void GlCoreRhi::bind_uniform_set(Handle<GraphicsContext> ctx, uint32_t slot, Han
SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true);
SRB2_ASSERT(pipeline_slab_.is_valid(*current_pipeline_));
auto& pl = *static_cast<GlCorePipeline*>(&pipeline_slab_[*current_pipeline_]);
auto& pl = pipeline_slab_[*current_pipeline_];
SRB2_ASSERT(uniform_set_slab_.is_valid(set));
auto& us = *static_cast<GlCoreUniformSet*>(&uniform_set_slab_[set]);
auto& us = uniform_set_slab_[set];
auto& uniform_input = pl.desc.uniform_input;
SRB2_ASSERT(slot < uniform_input.enabled_uniforms.size());
@ -1384,10 +1319,10 @@ void GlCoreRhi::bind_binding_set(Handle<GraphicsContext> ctx, Handle<BindingSet>
SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true);
SRB2_ASSERT(pipeline_slab_.is_valid(*current_pipeline_));
auto& pl = *static_cast<GlCorePipeline*>(&pipeline_slab_[*current_pipeline_]);
auto& pl = pipeline_slab_[*current_pipeline_];
SRB2_ASSERT(binding_set_slab_.is_valid(set));
auto& bs = *static_cast<GlCoreBindingSet*>(&binding_set_slab_[set]);
auto& bs = binding_set_slab_[set];
SRB2_ASSERT(bs.textures.size() == pl.desc.sampler_input.enabled_samplers.size());
@ -1441,7 +1376,7 @@ void GlCoreRhi::bind_index_buffer(Handle<GraphicsContext> ctx, Handle<Buffer> bu
SRB2_ASSERT(current_render_pass_.has_value() == true && current_pipeline_.has_value() == true);
SRB2_ASSERT(buffer_slab_.is_valid(buffer));
auto& ib = *static_cast<GlCoreBuffer*>(&buffer_slab_[buffer]);
auto& ib = buffer_slab_[buffer];
SRB2_ASSERT(ib.desc.type == rhi::BufferType::kIndexBuffer);

View file

@ -73,19 +73,77 @@ struct GlCorePlatform
virtual Rect get_default_framebuffer_dimensions() = 0;
};
struct GlCoreTexture : public rhi::Texture
{
uint32_t texture;
rhi::TextureDesc desc;
};
struct GlCoreBuffer : public rhi::Buffer
{
uint32_t buffer;
rhi::BufferDesc desc;
};
struct GlCoreRenderPass : public rhi::RenderPass
{
rhi::RenderPassDesc desc;
};
struct GlCoreRenderbuffer : public rhi::Renderbuffer
{
uint32_t renderbuffer;
};
struct GlCoreUniformSet : public rhi::UniformSet
{
std::vector<rhi::UniformVariant> uniforms;
};
struct GlCoreBindingSet : public rhi::BindingSet
{
uint32_t vao;
std::unordered_map<rhi::SamplerName, uint32_t> textures {4};
};
struct GlCorePipeline : public rhi::Pipeline
{
uint32_t vertex_shader = 0;
uint32_t fragment_shader = 0;
uint32_t program = 0;
std::unordered_map<rhi::VertexAttributeName, uint32_t> attrib_locations {2};
std::unordered_map<rhi::UniformName, uint32_t> uniform_locations {2};
std::unordered_map<rhi::SamplerName, uint32_t> sampler_locations {2};
rhi::PipelineDesc desc;
};
struct GlCoreGraphicsContext : public rhi::GraphicsContext
{
};
struct GlCoreTransferContext : public rhi::TransferContext
{
};
struct GlCoreActiveUniform
{
uint32_t type;
uint32_t location;
};
class GlCoreRhi final : public Rhi
{
std::unique_ptr<GlCorePlatform> platform_;
std::unique_ptr<GladGLContext> gl_;
Slab<RenderPass> render_pass_slab_;
Slab<Texture> texture_slab_;
Slab<Buffer> buffer_slab_;
Slab<Renderbuffer> renderbuffer_slab_;
Slab<Pipeline> pipeline_slab_;
Slab<UniformSet> uniform_set_slab_;
Slab<BindingSet> binding_set_slab_;
Slab<GlCoreRenderPass> render_pass_slab_;
Slab<GlCoreTexture> texture_slab_;
Slab<GlCoreBuffer> buffer_slab_;
Slab<GlCoreRenderbuffer> renderbuffer_slab_;
Slab<GlCorePipeline> pipeline_slab_;
Slab<GlCoreUniformSet> uniform_set_slab_;
Slab<GlCoreBindingSet> binding_set_slab_;
std::unordered_map<GlCoreFramebufferKey, uint32_t> framebuffers_ {16};

View file

@ -52,17 +52,10 @@ public:
// Conversions from Handles of derived type U to base type T
template <typename U, typename std::enable_if_t<std::is_base_of_v<T, U>, bool> = true>
Handle(const Handle<U>& rhs) noexcept : id_(rhs.id_), generation_(rhs.generation_)
Handle(const Handle<U>& rhs) noexcept : id_(rhs.id()), generation_(rhs.generation())
{
}
template <typename U, typename std::enable_if_t<std::is_base_of_v<T, U>, bool> = true>
Handle(Handle<U>&& rhs) noexcept
{
id_ = std::exchange(rhs.id_, 0);
generation_ = std::exchange(rhs.generation_, 0);
}
template <typename U, typename std::enable_if_t<std::is_base_of_v<T, U>, bool> = true>
Handle& operator=(const Handle<U>& rhs) noexcept
{
@ -70,14 +63,6 @@ public:
generation_ = rhs.generation_;
}
template <typename U, typename std::enable_if_t<std::is_base_of_v<T, U>, bool> = true>
Handle& operator=(Handle<U>&& rhs) noexcept
{
id_ = std::exchange(rhs.id_, 0);
generation_ = std::exchange(rhs.generation_, 0);
return *this;
}
uint32_t id() const noexcept { return id_; }
uint32_t generation() const noexcept { return generation_; }
@ -175,7 +160,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; }
SlabIterator& operator++() noexcept
{
@ -211,7 +196,7 @@ class Slab
{
struct SlabStorage
{
std::unique_ptr<T> item;
T item;
uint32_t gen;
};
std::vector<SlabStorage> vec_;
@ -226,7 +211,7 @@ public:
Slab(const Slab&) = delete;
Slab& operator=(const Slab&) = delete;
Handle<T> insert(std::unique_ptr<T>&& value)
Handle<T> insert(T&& value)
{
uint32_t ret_id = 0;
if (!free_list_.empty())
@ -245,21 +230,22 @@ public:
return Handle<T>(ret_id, gen_);
}
std::unique_ptr<T> remove(Handle<T> handle)
template <typename U, typename std::enable_if_t<std::is_base_of_v<U, T>, bool> = true>
T remove(Handle<U> handle)
{
uint32_t handle_id = handle.id();
uint32_t handle_gen = handle.generation();
if (handle_id >= vec_.size())
{
return nullptr;
return T();
}
SlabStorage& storage = vec_[handle_id];
if (storage.gen > handle_gen)
{
return nullptr;
return T();
}
std::unique_ptr<T> ret = std::move(storage.item);
storage.item = nullptr;
T ret = std::move(storage.item);
storage.item = T();
free_list_.push_back(handle_id);
gen_ += 1;
if (gen_ == 0)
@ -269,7 +255,8 @@ public:
return ret;
}
bool is_valid(Handle<T> handle)
template <typename U, typename std::enable_if_t<std::is_base_of_v<U, T>, bool> = true>
bool is_valid(Handle<U> handle)
{
uint32_t handle_id = handle.id();
uint32_t handle_gen = handle.generation();
@ -296,10 +283,11 @@ public:
}
}
T& operator[](Handle<T> handle)
template <typename U, typename std::enable_if_t<std::is_base_of_v<U, T>, bool> = true>
T& operator[](Handle<U> handle)
{
SRB2_ASSERT(is_valid(handle));
return *vec_[handle.id()].item;
return vec_[handle.id()].item;
}
SlabIterator<T> begin() { return SlabIterator<T> {0, this}; }