std::shared_ptr<void> resource

This commit is contained in:
Attila Uygun 2023-11-07 12:18:07 +01:00
parent 14958d00ff
commit 8144057bff
5 changed files with 342 additions and 397 deletions

View File

@ -71,23 +71,25 @@ void RendererOpenGL::ResetScissor() {
glDisable(GL_SCISSOR_TEST);
}
uint64_t RendererOpenGL::CreateGeometry(std::unique_ptr<Mesh> mesh) {
std::shared_ptr<void> RendererOpenGL::CreateGeometry(
std::unique_ptr<Mesh> mesh) {
auto id = CreateGeometry(mesh->primitive(), mesh->vertex_description(),
mesh->index_description());
if (id != kInvalidId)
if (id)
UpdateGeometry(id, mesh->num_vertices(), mesh->GetVertices(),
mesh->num_indices(), mesh->GetIndices());
return id;
}
uint64_t RendererOpenGL::CreateGeometry(Primitive primitive,
VertexDescription vertex_description,
DataType index_description) {
std::shared_ptr<void> RendererOpenGL::CreateGeometry(
Primitive primitive,
VertexDescription vertex_description,
DataType index_description) {
// Verify that we have a valid layout and get the total byte size per vertex.
GLuint vertex_size = GetVertexSize(vertex_description);
if (!vertex_size) {
LOG(0) << "Invalid vertex layout";
return kInvalidId;
return nullptr;
}
GLuint vertex_array_id = 0;
@ -107,7 +109,7 @@ uint64_t RendererOpenGL::CreateGeometry(Primitive primitive,
if (!SetupVertexLayout(vertex_description, vertex_size, vertex_array_objects_,
vertex_layout)) {
LOG(0) << "Invalid vertex layout";
return kInvalidId;
return nullptr;
}
// Create the index buffer.
@ -126,106 +128,102 @@ uint64_t RendererOpenGL::CreateGeometry(Primitive primitive,
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
uint64_t resource_id = ++last_resource_id_;
geometries_[resource_id] = {0,
0,
kGlPrimitive[primitive],
kGlDataType[index_description],
vertex_layout,
vertex_size,
vertex_array_id,
vertex_buffer_id,
(GLuint)GetIndexSize(index_description),
index_buffer_id};
return resource_id;
auto it =
geometries_.insert(geometries_.end(), std::make_shared<GeometryOpenGL>());
**it = {it,
0,
0,
kGlPrimitive[primitive],
kGlDataType[index_description],
vertex_layout,
vertex_size,
vertex_array_id,
vertex_buffer_id,
(GLuint)GetIndexSize(index_description),
index_buffer_id};
return *it;
}
void RendererOpenGL::UpdateGeometry(uint64_t resource_id,
void RendererOpenGL::UpdateGeometry(std::shared_ptr<void> resource,
size_t num_vertices,
const void* vertices,
size_t num_indices,
const void* indices) {
auto it = geometries_.find(resource_id);
if (it == geometries_.end())
return;
auto geometry = std::static_pointer_cast<GeometryOpenGL>(resource);
// Go with GL_STATIC_DRAW for the first update.
GLenum usage = it->second.num_vertices > 0 ? GL_STREAM_DRAW : GL_STATIC_DRAW;
GLenum usage = geometry->num_vertices > 0 ? GL_STREAM_DRAW : GL_STATIC_DRAW;
// Upload the vertex data.
glBindBuffer(GL_ARRAY_BUFFER, it->second.vertex_buffer_id);
glBufferData(GL_ARRAY_BUFFER, num_vertices * it->second.vertex_size, vertices,
glBindBuffer(GL_ARRAY_BUFFER, geometry->vertex_buffer_id);
glBufferData(GL_ARRAY_BUFFER, num_vertices * geometry->vertex_size, vertices,
usage);
glBindBuffer(GL_ARRAY_BUFFER, 0);
it->second.num_vertices = (GLsizei)num_vertices;
geometry->num_vertices = (GLsizei)num_vertices;
// Upload the index data.
if (it->second.index_buffer_id) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, it->second.index_buffer_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_indices * it->second.index_size,
if (geometry->index_buffer_id) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->index_buffer_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_indices * geometry->index_size,
indices, usage);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
it->second.num_indices = (GLsizei)num_indices;
geometry->num_indices = (GLsizei)num_indices;
}
}
void RendererOpenGL::DestroyGeometry(uint64_t resource_id) {
auto it = geometries_.find(resource_id);
if (it == geometries_.end())
return;
void RendererOpenGL::DestroyGeometry(std::shared_ptr<void> resource) {
auto geometry = std::static_pointer_cast<GeometryOpenGL>(resource);
if (it->second.index_buffer_id)
glDeleteBuffers(1, &(it->second.index_buffer_id));
if (it->second.vertex_buffer_id)
glDeleteBuffers(1, &(it->second.vertex_buffer_id));
if (it->second.vertex_array_id)
glDeleteVertexArrays(1, &(it->second.vertex_array_id));
if (geometry->index_buffer_id)
glDeleteBuffers(1, &(geometry->index_buffer_id));
if (geometry->vertex_buffer_id)
glDeleteBuffers(1, &(geometry->vertex_buffer_id));
if (geometry->vertex_array_id)
glDeleteVertexArrays(1, &(geometry->vertex_array_id));
geometries_.erase(it);
geometries_.erase(geometry->it);
}
void RendererOpenGL::Draw(uint64_t resource_id,
void RendererOpenGL::Draw(std::shared_ptr<void> resource,
size_t num_indices,
size_t start_offset) {
auto it = geometries_.find(resource_id);
if (it == geometries_.end())
return;
auto geometry = std::static_pointer_cast<GeometryOpenGL>(resource);
if (num_indices == 0)
num_indices = it->second.num_indices;
num_indices = geometry->num_indices;
// Set up the vertex data.
if (it->second.vertex_array_id) {
glBindVertexArray(it->second.vertex_array_id);
if (geometry->vertex_array_id) {
glBindVertexArray(geometry->vertex_array_id);
} else {
glBindBuffer(GL_ARRAY_BUFFER, it->second.vertex_buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, geometry->vertex_buffer_id);
for (GLuint attribute_index = 0;
attribute_index < (GLuint)it->second.vertex_layout.size();
attribute_index < (GLuint)geometry->vertex_layout.size();
++attribute_index) {
GeometryOpenGL::Element& e = it->second.vertex_layout[attribute_index];
GeometryOpenGL::Element& e = geometry->vertex_layout[attribute_index];
glEnableVertexAttribArray(attribute_index);
glVertexAttribPointer(attribute_index, e.num_elements, e.type, GL_TRUE,
it->second.vertex_size,
geometry->vertex_size,
(const GLvoid*)e.vertex_offset);
}
if (num_indices > 0)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, it->second.index_buffer_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->index_buffer_id);
}
// Draw the primitive.
if (num_indices > 0)
glDrawElements(it->second.primitive, num_indices, it->second.index_type,
glDrawElements(geometry->primitive, num_indices, geometry->index_type,
(void*)(intptr_t)(start_offset * sizeof(unsigned short)));
else
glDrawArrays(it->second.primitive, 0, it->second.num_vertices);
glDrawArrays(geometry->primitive, 0, geometry->num_vertices);
// Clean up states.
if (it->second.vertex_array_id)
if (geometry->vertex_array_id)
glBindVertexArray(0);
else {
for (GLuint attribute_index = 0;
attribute_index < (GLuint)it->second.vertex_layout.size();
attribute_index < (GLuint)geometry->vertex_layout.size();
++attribute_index)
glDisableVertexAttribArray(attribute_index);
@ -234,7 +232,7 @@ void RendererOpenGL::Draw(uint64_t resource_id,
}
}
uint64_t RendererOpenGL::CreateTexture() {
std::shared_ptr<void> RendererOpenGL::CreateTexture() {
GLuint gl_id = 0;
glGenTextures(1, &gl_id);
glBindTexture(GL_TEXTURE_2D, gl_id);
@ -244,28 +242,27 @@ uint64_t RendererOpenGL::CreateTexture() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
uint64_t resource_id = ++last_resource_id_;
textures_[resource_id] = gl_id;
return resource_id;
auto it =
textures_.insert(textures_.end(), std::make_shared<TextureOpenGL>());
**it = {it, gl_id};
return *it;
}
void RendererOpenGL::UpdateTexture(uint64_t resource_id,
void RendererOpenGL::UpdateTexture(std::shared_ptr<void> resource,
std::unique_ptr<Image> image) {
UpdateTexture(resource_id, image->GetWidth(), image->GetHeight(),
UpdateTexture(resource, image->GetWidth(), image->GetHeight(),
image->GetFormat(), image->GetSize(), image->GetBuffer());
}
void RendererOpenGL::UpdateTexture(uint64_t resource_id,
void RendererOpenGL::UpdateTexture(std::shared_ptr<void> resource,
int width,
int height,
ImageFormat format,
size_t data_size,
uint8_t* image_data) {
auto it = textures_.find(resource_id);
if (it == textures_.end())
return;
auto texture = std::static_pointer_cast<TextureOpenGL>(resource);
glBindTexture(GL_TEXTURE_2D, it->second);
glBindTexture(GL_TEXTURE_2D, texture->id);
if (IsCompressedFormat(format)) {
GLenum gl_format = 0;
switch (format) {
@ -311,35 +308,28 @@ void RendererOpenGL::UpdateTexture(uint64_t resource_id,
}
}
void RendererOpenGL::DestroyTexture(uint64_t resource_id) {
auto it = textures_.find(resource_id);
if (it == textures_.end())
return;
glDeleteTextures(1, &(it->second));
textures_.erase(it);
void RendererOpenGL::DestroyTexture(std::shared_ptr<void> resource) {
auto texture = std::static_pointer_cast<TextureOpenGL>(resource);
glDeleteTextures(1, &(texture->id));
textures_.erase(texture->it);
}
void RendererOpenGL::ActivateTexture(uint64_t resource_id,
void RendererOpenGL::ActivateTexture(std::shared_ptr<void> resource,
size_t texture_unit) {
if (texture_unit >= kMaxTextureUnits) {
DLOG(0) << "Invalid texture unit " << texture_unit;
return;
}
auto it = textures_.find(resource_id);
if (it == textures_.end()) {
return;
}
if (it->second != active_texture_id_[texture_unit]) {
auto texture = std::static_pointer_cast<TextureOpenGL>(resource);
if (texture->id != active_texture_id_[texture_unit]) {
glActiveTexture(GL_TEXTURE0 + texture_unit);
glBindTexture(GL_TEXTURE_2D, it->second);
active_texture_id_[texture_unit] = it->second;
glBindTexture(GL_TEXTURE_2D, texture->id);
active_texture_id_[texture_unit] = texture->id;
}
}
uint64_t RendererOpenGL::CreateShader(
std::shared_ptr<void> RendererOpenGL::CreateShader(
std::unique_ptr<ShaderSource> source,
const VertexDescription& vertex_description,
Primitive primitive,
@ -382,103 +372,79 @@ uint64_t RendererOpenGL::CreateShader(
}
}
uint64_t resource_id = ++last_resource_id_;
shaders_[resource_id] = {id, {}, enable_depth_test};
return resource_id;
auto it = shaders_.insert(shaders_.end(), std::make_shared<ShaderOpenGL>());
**it = {it, id, {}, enable_depth_test};
return *it;
}
void RendererOpenGL::DestroyShader(uint64_t resource_id) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
glDeleteProgram(it->second.id);
shaders_.erase(it);
void RendererOpenGL::DestroyShader(std::shared_ptr<void> resource) {
auto shader = std::static_pointer_cast<ShaderOpenGL>(resource);
glDeleteProgram(shader->id);
shaders_.erase(shader->it);
}
void RendererOpenGL::ActivateShader(uint64_t resource_id) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
if (it->second.id != active_shader_id_) {
glUseProgram(it->second.id);
active_shader_id_ = it->second.id;
if (it->second.enable_depth_test)
void RendererOpenGL::ActivateShader(std::shared_ptr<void> resource) {
auto shader = std::static_pointer_cast<ShaderOpenGL>(resource);
if (shader->id != active_shader_id_) {
glUseProgram(shader->id);
active_shader_id_ = shader->id;
if (shader->enable_depth_test)
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
}
}
void RendererOpenGL::SetUniform(uint64_t resource_id,
void RendererOpenGL::SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector2f& val) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
GLint index = GetUniformLocation(it->second.id, name, it->second.uniforms);
auto shader = std::static_pointer_cast<ShaderOpenGL>(resource);
GLint index = GetUniformLocation(shader->id, name, shader->uniforms);
if (index >= 0)
glUniform2fv(index, 1, val.GetData());
}
void RendererOpenGL::SetUniform(uint64_t resource_id,
void RendererOpenGL::SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector3f& val) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
GLint index = GetUniformLocation(it->second.id, name, it->second.uniforms);
auto shader = std::static_pointer_cast<ShaderOpenGL>(resource);
GLint index = GetUniformLocation(shader->id, name, shader->uniforms);
if (index >= 0)
glUniform3fv(index, 1, val.GetData());
}
void RendererOpenGL::SetUniform(uint64_t resource_id,
void RendererOpenGL::SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector4f& val) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
GLint index = GetUniformLocation(it->second.id, name, it->second.uniforms);
auto shader = std::static_pointer_cast<ShaderOpenGL>(resource);
GLint index = GetUniformLocation(shader->id, name, shader->uniforms);
if (index >= 0)
glUniform4fv(index, 1, val.GetData());
}
void RendererOpenGL::SetUniform(uint64_t resource_id,
void RendererOpenGL::SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Matrix4f& val) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
GLint index = GetUniformLocation(it->second.id, name, it->second.uniforms);
auto shader = std::static_pointer_cast<ShaderOpenGL>(resource);
GLint index = GetUniformLocation(shader->id, name, shader->uniforms);
if (index >= 0)
glUniformMatrix4fv(index, 1, GL_FALSE, val.GetData());
}
void RendererOpenGL::SetUniform(uint64_t resource_id,
void RendererOpenGL::SetUniform(std::shared_ptr<void> resource,
const std::string& name,
float val) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
GLint index = GetUniformLocation(it->second.id, name, it->second.uniforms);
auto shader = std::static_pointer_cast<ShaderOpenGL>(resource);
GLint index = GetUniformLocation(shader->id, name, shader->uniforms);
if (index >= 0)
glUniform1f(index, val);
}
void RendererOpenGL::SetUniform(uint64_t resource_id,
void RendererOpenGL::SetUniform(std::shared_ptr<void> resource,
const std::string& name,
int val) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
GLint index = GetUniformLocation(it->second.id, name, it->second.uniforms);
auto shader = std::static_pointer_cast<ShaderOpenGL>(resource);
GLint index = GetUniformLocation(shader->id, name, shader->uniforms);
if (index >= 0)
glUniform1i(index, val);
}

View File

@ -2,9 +2,9 @@
#define ENGINE_RENDERER_OPENGL_RENDERER_OPENGL_H
#include <array>
#include <list>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
@ -38,56 +38,62 @@ class RendererOpenGL final : public Renderer {
void SetScissor(int x, int y, int width, int height) final;
void ResetScissor() final;
uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) final;
uint64_t CreateGeometry(Primitive primitive,
VertexDescription vertex_description,
DataType index_description = kDataType_Invalid) final;
void UpdateGeometry(uint64_t resource_id,
std::shared_ptr<void> CreateGeometry(std::unique_ptr<Mesh> mesh) final;
std::shared_ptr<void> CreateGeometry(
Primitive primitive,
VertexDescription vertex_description,
DataType index_description = kDataType_Invalid) final;
void UpdateGeometry(std::shared_ptr<void> resource,
size_t num_vertices,
const void* vertices,
size_t num_indices,
const void* indices) final;
void DestroyGeometry(uint64_t resource_id) final;
void Draw(uint64_t resource_id,
void DestroyGeometry(std::shared_ptr<void> resource) final;
void Draw(std::shared_ptr<void> resource,
size_t num_indices = 0,
size_t start_offset = 0) final;
uint64_t CreateTexture() final;
void UpdateTexture(uint64_t resource_id, std::unique_ptr<Image> image) final;
void UpdateTexture(uint64_t resource_id,
std::shared_ptr<void> CreateTexture() final;
void UpdateTexture(std::shared_ptr<void> resource,
std::unique_ptr<Image> image) final;
void UpdateTexture(std::shared_ptr<void> resource,
int width,
int height,
ImageFormat format,
size_t data_size,
uint8_t* image_data) final;
void DestroyTexture(uint64_t resource_id) final;
void ActivateTexture(uint64_t resource_id, size_t texture_unit) final;
void DestroyTexture(std::shared_ptr<void> resource) final;
void ActivateTexture(std::shared_ptr<void> resource,
size_t texture_unit) final;
uint64_t CreateShader(std::unique_ptr<ShaderSource> source,
const VertexDescription& vertex_description,
Primitive primitive,
bool enable_depth_test) final;
void DestroyShader(uint64_t resource_id) final;
void ActivateShader(uint64_t resource_id) final;
std::shared_ptr<void> CreateShader(
std::unique_ptr<ShaderSource> source,
const VertexDescription& vertex_description,
Primitive primitive,
bool enable_depth_test) final;
void DestroyShader(std::shared_ptr<void> resource) final;
void ActivateShader(std::shared_ptr<void> resource) final;
void SetUniform(uint64_t resource_id,
void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector2f& val) final;
void SetUniform(uint64_t resource_id,
void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector3f& val) final;
void SetUniform(uint64_t resource_id,
void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector4f& val) final;
void SetUniform(uint64_t resource_id,
void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Matrix4f& val) final;
void SetUniform(uint64_t resource_id,
void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
float val) final;
void SetUniform(uint64_t resource_id, const std::string& name, int val) final;
void UploadUniforms(uint64_t resource_id) final {}
void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
int val) final;
void UploadUniforms(std::shared_ptr<void> resource) final {}
void PrepareForDrawing() final;
void Present() final;
@ -106,6 +112,7 @@ class RendererOpenGL final : public Renderer {
size_t vertex_offset;
};
std::list<std::shared_ptr<GeometryOpenGL>>::iterator it;
GLsizei num_vertices = 0;
GLsizei num_indices = 0;
GLenum primitive = 0;
@ -119,6 +126,7 @@ class RendererOpenGL final : public Renderer {
};
struct ShaderOpenGL {
std::list<std::shared_ptr<ShaderOpenGL>>::iterator it;
GLuint id = 0;
std::vector<std::pair<size_t, // Uniform name hash
GLuint // Uniform index
@ -127,10 +135,14 @@ class RendererOpenGL final : public Renderer {
bool enable_depth_test = false;
};
std::unordered_map<uint64_t, GeometryOpenGL> geometries_;
std::unordered_map<uint64_t, ShaderOpenGL> shaders_;
std::unordered_map<uint64_t, GLuint> textures_;
uint64_t last_resource_id_ = 0;
struct TextureOpenGL {
std::list<std::shared_ptr<TextureOpenGL>>::iterator it;
GLuint id = 0;
};
std::list<std::shared_ptr<GeometryOpenGL>> geometries_;
std::list<std::shared_ptr<ShaderOpenGL>> shaders_;
std::list<std::shared_ptr<TextureOpenGL>> textures_;
GLuint active_shader_id_ = 0;
std::array<GLuint, kMaxTextureUnits> active_texture_id_ = {};

View File

@ -45,59 +45,61 @@ class Renderer {
virtual void SetScissor(int x, int y, int width, int height) = 0;
virtual void ResetScissor() = 0;
virtual uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) = 0;
virtual uint64_t CreateGeometry(
virtual std::shared_ptr<void> CreateGeometry(std::unique_ptr<Mesh> mesh) = 0;
virtual std::shared_ptr<void> CreateGeometry(
Primitive primitive,
VertexDescription vertex_description,
DataType index_description = kDataType_Invalid) = 0;
virtual void UpdateGeometry(uint64_t resource_id,
virtual void UpdateGeometry(std::shared_ptr<void> resource,
size_t num_vertices,
const void* vertices,
size_t num_indices,
const void* indices) = 0;
virtual void DestroyGeometry(uint64_t resource_id) = 0;
virtual void Draw(uint64_t resource_id,
virtual void DestroyGeometry(std::shared_ptr<void> resource) = 0;
virtual void Draw(std::shared_ptr<void> resource,
size_t num_indices = 0,
size_t start_offset = 0) = 0;
virtual uint64_t CreateTexture() = 0;
virtual void UpdateTexture(uint64_t resource_id,
virtual std::shared_ptr<void> CreateTexture() = 0;
virtual void UpdateTexture(std::shared_ptr<void> resource,
std::unique_ptr<Image> image) = 0;
virtual void UpdateTexture(uint64_t resource_id,
virtual void UpdateTexture(std::shared_ptr<void> resource,
int width,
int height,
ImageFormat format,
size_t data_size,
uint8_t* image_data) = 0;
virtual void DestroyTexture(uint64_t resource_id) = 0;
virtual void ActivateTexture(uint64_t resource_id, size_t texture_unit) = 0;
virtual void DestroyTexture(std::shared_ptr<void> resource) = 0;
virtual void ActivateTexture(std::shared_ptr<void> resource,
size_t texture_unit) = 0;
virtual uint64_t CreateShader(std::unique_ptr<ShaderSource> source,
const VertexDescription& vertex_description,
Primitive primitive,
bool enable_depth_test) = 0;
virtual void DestroyShader(uint64_t resource_id) = 0;
virtual void ActivateShader(uint64_t resource_id) = 0;
virtual std::shared_ptr<void> CreateShader(
std::unique_ptr<ShaderSource> source,
const VertexDescription& vertex_description,
Primitive primitive,
bool enable_depth_test) = 0;
virtual void DestroyShader(std::shared_ptr<void> resource) = 0;
virtual void ActivateShader(std::shared_ptr<void> resource) = 0;
virtual void SetUniform(uint64_t resource_id,
virtual void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector2f& val) = 0;
virtual void SetUniform(uint64_t resource_id,
virtual void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector3f& val) = 0;
virtual void SetUniform(uint64_t resource_id,
virtual void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector4f& val) = 0;
virtual void SetUniform(uint64_t resource_id,
virtual void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Matrix4f& val) = 0;
virtual void SetUniform(uint64_t resource_id,
virtual void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
float val) = 0;
virtual void SetUniform(uint64_t resource_id,
virtual void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
int val) = 0;
virtual void UploadUniforms(uint64_t resource_id) = 0;
virtual void UploadUniforms(std::shared_ptr<void> resource) = 0;
virtual void PrepareForDrawing() = 0;
virtual void Present() = 0;

View File

@ -442,10 +442,11 @@ void RendererVulkan::ResetScissor() {
vkCmdSetScissor(frames_[current_frame_].draw_command_buffer, 0, 1, &scissor);
}
uint64_t RendererVulkan::CreateGeometry(std::unique_ptr<Mesh> mesh) {
std::shared_ptr<void> RendererVulkan::CreateGeometry(
std::unique_ptr<Mesh> mesh) {
auto id = CreateGeometry(mesh->primitive(), mesh->vertex_description(),
mesh->index_description());
if (id != kInvalidId)
if (id)
UpdateGeometry(id, mesh->num_vertices(), mesh->GetVertices(),
mesh->num_indices(), mesh->GetIndices());
task_runner_.Delete(HERE, std::move(mesh));
@ -453,61 +454,61 @@ uint64_t RendererVulkan::CreateGeometry(std::unique_ptr<Mesh> mesh) {
return id;
}
uint64_t RendererVulkan::CreateGeometry(Primitive primitive,
VertexDescription vertex_description,
DataType index_description) {
auto& geometry = geometries_[++last_resource_id_] = {};
geometry.vertex_size = GetVertexSize(vertex_description);
geometry.index_type = GetIndexType(index_description);
geometry.index_type_size = GetIndexSize(index_description);
return last_resource_id_;
std::shared_ptr<void> RendererVulkan::CreateGeometry(
Primitive primitive,
VertexDescription vertex_description,
DataType index_description) {
auto it =
geometries_.insert(geometries_.end(), std::make_shared<GeometryVulkan>());
(*it)->vertex_size = GetVertexSize(vertex_description);
(*it)->index_type = GetIndexType(index_description);
(*it)->index_type_size = GetIndexSize(index_description);
return *it;
}
void RendererVulkan::UpdateGeometry(uint64_t resource_id,
void RendererVulkan::UpdateGeometry(std::shared_ptr<void> resource,
size_t num_vertices,
const void* vertices,
size_t num_indices,
const void* indices) {
auto it = geometries_.find(resource_id);
if (it == geometries_.end())
return;
auto geometry = std::static_pointer_cast<GeometryVulkan>(resource);
it->second.num_vertices = num_vertices;
size_t vertex_data_size = it->second.vertex_size * it->second.num_vertices;
geometry->num_vertices = num_vertices;
size_t vertex_data_size = geometry->vertex_size * geometry->num_vertices;
size_t index_data_size = 0;
if (indices) {
DCHECK(it->second.index_type != VK_INDEX_TYPE_NONE_KHR);
it->second.num_indices = num_indices;
index_data_size = it->second.index_type_size * it->second.num_indices;
DCHECK(geometry->index_type != VK_INDEX_TYPE_NONE_KHR);
geometry->num_indices = num_indices;
index_data_size = geometry->index_type_size * geometry->num_indices;
}
size_t data_size = vertex_data_size + index_data_size;
if (it->second.buffer_size < data_size) {
if (geometry->buffer_size < data_size) {
DLOG(1) << __func__ << "Reallocate buffer " << data_size;
if (it->second.buffer_size > 0)
FreeBuffer(std::move(it->second.buffer));
AllocateBuffer(it->second.buffer, data_size,
if (geometry->buffer_size > 0)
FreeBuffer(std::move(geometry->buffer));
AllocateBuffer(geometry->buffer, data_size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VMA_MEMORY_USAGE_GPU_ONLY);
it->second.buffer_size = data_size;
geometry->buffer_size = data_size;
}
task_runner_.PostTask(HERE, std::bind(&RendererVulkan::UpdateBuffer, this,
std::get<0>(it->second.buffer), 0,
std::get<0>(geometry->buffer), 0,
vertices, vertex_data_size));
if (it->second.num_indices > 0) {
it->second.index_data_offset = vertex_data_size;
task_runner_.PostTask(HERE, std::bind(&RendererVulkan::UpdateBuffer, this,
std::get<0>(it->second.buffer),
it->second.index_data_offset, indices,
index_data_size));
if (geometry->num_indices > 0) {
geometry->index_data_offset = vertex_data_size;
task_runner_.PostTask(
HERE, std::bind(&RendererVulkan::UpdateBuffer, this,
std::get<0>(geometry->buffer),
geometry->index_data_offset, indices, index_data_size));
}
task_runner_.PostTask(HERE,
std::bind(&RendererVulkan::BufferMemoryBarrier, this,
std::get<0>(it->second.buffer), 0, data_size,
std::get<0>(geometry->buffer), 0, data_size,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
@ -515,143 +516,125 @@ void RendererVulkan::UpdateGeometry(uint64_t resource_id,
semaphore_.release();
}
void RendererVulkan::DestroyGeometry(uint64_t resource_id) {
auto it = geometries_.find(resource_id);
if (it == geometries_.end())
return;
FreeBuffer(std::move(it->second.buffer));
void RendererVulkan::DestroyGeometry(std::shared_ptr<void> resource) {
auto geometry = std::static_pointer_cast<GeometryVulkan>(resource);
FreeBuffer(std::move(geometry->buffer));
geometries_.erase(it);
}
void RendererVulkan::Draw(uint64_t resource_id,
void RendererVulkan::Draw(std::shared_ptr<void> resource,
size_t num_indices,
size_t start_offset) {
auto it = geometries_.find(resource_id);
if (it == geometries_.end())
return;
auto geometry = std::static_pointer_cast<GeometryVulkan>(resource);
uint64_t data_offset = start_offset * it->second.index_type_size;
uint64_t data_offset = start_offset * geometry->index_type_size;
if (num_indices == 0)
num_indices = it->second.num_indices;
num_indices = geometry->num_indices;
VkDeviceSize offset = 0;
vkCmdBindVertexBuffers(frames_[current_frame_].draw_command_buffer, 0, 1,
&std::get<0>(it->second.buffer), &offset);
&std::get<0>(geometry->buffer), &offset);
if (num_indices > 0) {
vkCmdBindIndexBuffer(frames_[current_frame_].draw_command_buffer,
std::get<0>(it->second.buffer),
it->second.index_data_offset + data_offset,
it->second.index_type);
std::get<0>(geometry->buffer),
geometry->index_data_offset + data_offset,
geometry->index_type);
vkCmdDrawIndexed(frames_[current_frame_].draw_command_buffer, num_indices,
1, 0, 0, 0);
} else {
vkCmdDraw(frames_[current_frame_].draw_command_buffer,
it->second.num_vertices, 1, 0, 0);
geometry->num_vertices, 1, 0, 0);
}
}
uint64_t RendererVulkan::CreateTexture() {
textures_.insert({++last_resource_id_, {}});
return last_resource_id_;
std::shared_ptr<void> RendererVulkan::CreateTexture() {
auto it =
textures_.insert(textures_.end(), std::make_shared<TextureVulkan>());
(*it)->it = it;
return *it;
}
void RendererVulkan::UpdateTexture(uint64_t resource_id,
void RendererVulkan::UpdateTexture(std::shared_ptr<void> resource,
std::unique_ptr<Image> image) {
UpdateTexture(resource_id, image->GetWidth(), image->GetHeight(),
UpdateTexture(resource, image->GetWidth(), image->GetHeight(),
image->GetFormat(), image->GetSize(), image->GetBuffer());
task_runner_.Delete(HERE, std::move(image));
semaphore_.release();
}
void RendererVulkan::UpdateTexture(uint64_t resource_id,
void RendererVulkan::UpdateTexture(std::shared_ptr<void> resource,
int width,
int height,
ImageFormat format,
size_t data_size,
uint8_t* image_data) {
auto it = textures_.find(resource_id);
if (it == textures_.end())
return;
auto texture = std::static_pointer_cast<TextureVulkan>(resource);
VkImageLayout old_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkFormat vk_format = GetImageFormat(format);
if (it->second.view != VK_NULL_HANDLE &&
(it->second.width != width || it->second.height != height)) {
if (texture->view != VK_NULL_HANDLE &&
(texture->width != width || texture->height != height)) {
// Size mismatch. Recreate the texture.
FreeImage(std::move(it->second.image), it->second.view,
std::move(it->second.desc_set));
FreeImage(std::move(texture->image), texture->view,
std::move(texture->desc_set));
it->second = {};
}
if (it->second.view == VK_NULL_HANDLE) {
AllocateImage(it->second.image, it->second.view, it->second.desc_set,
vk_format, width, height,
if (texture->view == VK_NULL_HANDLE) {
AllocateImage(texture->image, texture->view, texture->desc_set, vk_format,
width, height,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VMA_MEMORY_USAGE_GPU_ONLY);
old_layout = VK_IMAGE_LAYOUT_UNDEFINED;
it->second.width = width;
it->second.height = height;
texture->width = width;
texture->height = height;
}
task_runner_.PostTask(
HERE,
std::bind(&RendererVulkan::ImageMemoryBarrier, this,
std::get<0>(it->second.image),
std::get<0>(texture->image),
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT,
old_layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL));
task_runner_.PostTask(HERE, std::bind(&RendererVulkan::UpdateImage, this,
std::get<0>(it->second.image),
vk_format, image_data, width, height));
std::get<0>(texture->image), vk_format,
image_data, width, height));
task_runner_.PostTask(
HERE,
std::bind(&RendererVulkan::ImageMemoryBarrier, this,
std::get<0>(it->second.image), VK_ACCESS_TRANSFER_WRITE_BIT,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
HERE, std::bind(&RendererVulkan::ImageMemoryBarrier, this,
std::get<0>(texture->image), VK_ACCESS_TRANSFER_WRITE_BIT,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
semaphore_.release();
}
void RendererVulkan::DestroyTexture(uint64_t resource_id) {
auto it = textures_.find(resource_id);
if (it == textures_.end())
return;
FreeImage(std::move(it->second.image), it->second.view,
std::move(it->second.desc_set));
textures_.erase(it);
void RendererVulkan::DestroyTexture(std::shared_ptr<void> resource) {
auto texture = std::static_pointer_cast<TextureVulkan>(resource);
FreeImage(std::move(texture->image), texture->view,
std::move(texture->desc_set));
textures_.erase(texture->it);
}
void RendererVulkan::ActivateTexture(uint64_t resource_id,
void RendererVulkan::ActivateTexture(std::shared_ptr<void> resource,
size_t texture_unit) {
auto it = textures_.find(resource_id);
if (it == textures_.end())
return;
if (active_descriptor_sets_[texture_unit] !=
std::get<0>(it->second.desc_set)) {
active_descriptor_sets_[texture_unit] = std::get<0>(it->second.desc_set);
if (active_shader_id_ != kInvalidId) {
auto active_shader = shaders_.find(active_shader_id_);
if (active_shader != shaders_.end() &&
active_shader->second.desc_set_count > texture_unit) {
vkCmdBindDescriptorSets(
frames_[current_frame_].draw_command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
active_shader->second.pipeline_layout, texture_unit, 1,
&active_descriptor_sets_[texture_unit], 0, nullptr);
}
auto texture = std::static_pointer_cast<TextureVulkan>(resource);
if (active_descriptor_sets_[texture_unit] != std::get<0>(texture->desc_set)) {
active_descriptor_sets_[texture_unit] = std::get<0>(texture->desc_set);
if (active_shader_ && active_shader_->desc_set_count > texture_unit) {
vkCmdBindDescriptorSets(
frames_[current_frame_].draw_command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS, active_shader_->pipeline_layout,
texture_unit, 1, &active_descriptor_sets_[texture_unit], 0, nullptr);
}
}
}
uint64_t RendererVulkan::CreateShader(
std::shared_ptr<void> RendererVulkan::CreateShader(
std::unique_ptr<ShaderSource> source,
const VertexDescription& vertex_description,
Primitive primitive,
@ -703,9 +686,9 @@ uint64_t RendererVulkan::CreateShader(
}
}
auto& shader = shaders_[++last_resource_id_] = {};
auto it = shaders_.insert(shaders_.end(), std::make_shared<ShaderVulkan>());
if (!CreatePipelineLayout(shader, spirv_vertex, spirv_fragment))
if (!CreatePipelineLayout(**it, spirv_vertex, spirv_fragment))
DLOG(0) << "Failed to create pipeline layout!";
VkPipelineShaderStageCreateInfo vert_shader_stage_info{};
@ -827,124 +810,97 @@ uint64_t RendererVulkan::CreateShader(
pipeline_info.pColorBlendState = &color_blending;
pipeline_info.pDepthStencilState = &depth_stencil;
pipeline_info.pDynamicState = &dynamic_state_create_info;
pipeline_info.layout = shader.pipeline_layout;
pipeline_info.layout = (*it)->pipeline_layout;
pipeline_info.renderPass = context_.GetRenderPass();
pipeline_info.subpass = 0;
pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
if (vkCreateGraphicsPipelines(device_, VK_NULL_HANDLE, 1, &pipeline_info,
nullptr, &shader.pipeline) != VK_SUCCESS)
nullptr, &(*it)->pipeline) != VK_SUCCESS)
DLOG(0) << "failed to create graphics pipeline.";
vkDestroyShaderModule(device_, frag_shader_module, nullptr);
vkDestroyShaderModule(device_, vert_shader_module, nullptr);
return last_resource_id_;
return *it;
}
void RendererVulkan::DestroyShader(uint64_t resource_id) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
void RendererVulkan::DestroyShader(std::shared_ptr<void> resource) {
auto shader = std::static_pointer_cast<ShaderVulkan>(resource);
frames_[current_frame_].pipelines_to_destroy.push_back(
std::make_tuple(it->second.pipeline, it->second.pipeline_layout));
shaders_.erase(it);
std::make_tuple(shader->pipeline, shader->pipeline_layout));
shaders_.erase(shader->it);
}
void RendererVulkan::ActivateShader(uint64_t resource_id) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
if (active_shader_id_ != resource_id) {
active_shader_id_ = resource_id;
void RendererVulkan::ActivateShader(std::shared_ptr<void> resource) {
auto shader = std::static_pointer_cast<ShaderVulkan>(resource);
if (active_shader_ != resource) {
active_shader_ = std::static_pointer_cast<ShaderVulkan>(resource);
vkCmdBindPipeline(frames_[current_frame_].draw_command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS, it->second.pipeline);
VK_PIPELINE_BIND_POINT_GRAPHICS, shader->pipeline);
for (size_t i = 0; i < it->second.desc_set_count; ++i) {
for (size_t i = 0; i < shader->desc_set_count; ++i) {
if (active_descriptor_sets_[i] != VK_NULL_HANDLE) {
vkCmdBindDescriptorSets(frames_[current_frame_].draw_command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
it->second.pipeline_layout, i, 1,
shader->pipeline_layout, i, 1,
&active_descriptor_sets_[i], 0, nullptr);
}
}
}
}
void RendererVulkan::SetUniform(uint64_t resource_id,
void RendererVulkan::SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector2f& val) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
SetUniformInternal(it->second, name, val);
auto shader = std::static_pointer_cast<ShaderVulkan>(resource);
SetUniformInternal(*shader, name, val);
}
void RendererVulkan::SetUniform(uint64_t resource_id,
void RendererVulkan::SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector3f& val) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
SetUniformInternal(it->second, name, val);
auto shader = std::static_pointer_cast<ShaderVulkan>(resource);
SetUniformInternal(*shader, name, val);
}
void RendererVulkan::SetUniform(uint64_t resource_id,
void RendererVulkan::SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector4f& val) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
SetUniformInternal(it->second, name, val);
auto shader = std::static_pointer_cast<ShaderVulkan>(resource);
SetUniformInternal(*shader, name, val);
}
void RendererVulkan::SetUniform(uint64_t resource_id,
void RendererVulkan::SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Matrix4f& val) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
SetUniformInternal(it->second, name, val);
auto shader = std::static_pointer_cast<ShaderVulkan>(resource);
SetUniformInternal(*shader, name, val);
}
void RendererVulkan::SetUniform(uint64_t resource_id,
void RendererVulkan::SetUniform(std::shared_ptr<void> resource,
const std::string& name,
float val) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
SetUniformInternal(it->second, name, val);
auto shader = std::static_pointer_cast<ShaderVulkan>(resource);
SetUniformInternal(*shader, name, val);
}
void RendererVulkan::SetUniform(uint64_t resource_id,
void RendererVulkan::SetUniform(std::shared_ptr<void> resource,
const std::string& name,
int val) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
for (auto& sampler_name : it->second.sampler_uniform_names) {
auto shader = std::static_pointer_cast<ShaderVulkan>(resource);
for (auto& sampler_name : shader->sampler_uniform_names) {
if (name == sampler_name)
return;
}
SetUniformInternal(it->second, name, val);
SetUniformInternal(*shader, name, val);
}
void RendererVulkan::UploadUniforms(uint64_t resource_id) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
void RendererVulkan::UploadUniforms(std::shared_ptr<void> resource) {
auto shader = std::static_pointer_cast<ShaderVulkan>(resource);
vkCmdPushConstants(
frames_[current_frame_].draw_command_buffer, it->second.pipeline_layout,
frames_[current_frame_].draw_command_buffer, shader->pipeline_layout,
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0,
it->second.push_constants_size, it->second.push_constants.get());
shader->push_constants_size, shader->push_constants.get());
}
void RendererVulkan::PrepareForDrawing() {
@ -2112,7 +2068,7 @@ void RendererVulkan::SwapBuffers() {
context_.SwapBuffers();
current_frame_ = (current_frame_ + 1) % frames_.size();
active_shader_id_ = kInvalidId;
active_shader_ = nullptr;
for (auto& ds : active_descriptor_sets_)
ds = VK_NULL_HANDLE;

View File

@ -2,6 +2,7 @@
#define ENGINE_RENDERER_VULKAN_RENDERER_VULKAN_H
#include <atomic>
#include <list>
#include <memory>
#include <semaphore>
#include <string>
@ -39,55 +40,61 @@ class RendererVulkan final : public Renderer {
void SetScissor(int x, int y, int width, int height) final;
void ResetScissor() final;
uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) final;
uint64_t CreateGeometry(Primitive primitive,
VertexDescription vertex_description,
DataType index_description = kDataType_Invalid) final;
void UpdateGeometry(uint64_t resource_id,
std::shared_ptr<void> CreateGeometry(std::unique_ptr<Mesh> mesh) final;
std::shared_ptr<void> CreateGeometry(
Primitive primitive,
VertexDescription vertex_description,
DataType index_description = kDataType_Invalid) final;
void UpdateGeometry(std::shared_ptr<void> resource,
size_t num_vertices,
const void* vertices,
size_t num_indices,
const void* indices) final;
void DestroyGeometry(uint64_t resource_id) final;
void Draw(uint64_t resource_id,
void DestroyGeometry(std::shared_ptr<void> resource) final;
void Draw(std::shared_ptr<void> resource,
size_t num_indices = 0,
size_t start_offset = 0) final;
uint64_t CreateTexture() final;
void UpdateTexture(uint64_t resource_id, std::unique_ptr<Image> image) final;
void UpdateTexture(uint64_t resource_id,
std::shared_ptr<void> CreateTexture() final;
void UpdateTexture(std::shared_ptr<void> resource,
std::unique_ptr<Image> image) final;
void UpdateTexture(std::shared_ptr<void> resource,
int width,
int height,
ImageFormat format,
size_t data_size,
uint8_t* image_data) final;
void DestroyTexture(uint64_t resource_id) final;
void ActivateTexture(uint64_t resource_id, size_t texture_unit) final;
void DestroyTexture(std::shared_ptr<void> resource) final;
void ActivateTexture(std::shared_ptr<void> resource,
size_t texture_unit) final;
uint64_t CreateShader(std::unique_ptr<ShaderSource> source,
const VertexDescription& vertex_description,
Primitive primitive,
bool enable_depth_test) final;
void DestroyShader(uint64_t resource_id) final;
void ActivateShader(uint64_t resource_id) final;
std::shared_ptr<void> CreateShader(
std::unique_ptr<ShaderSource> source,
const VertexDescription& vertex_description,
Primitive primitive,
bool enable_depth_test) final;
void DestroyShader(std::shared_ptr<void> resource) final;
void ActivateShader(std::shared_ptr<void> resource) final;
void SetUniform(uint64_t resource_id,
void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector2f& val) final;
void SetUniform(uint64_t resource_id,
void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector3f& val) final;
void SetUniform(uint64_t resource_id,
void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Vector4f& val) final;
void SetUniform(uint64_t resource_id,
void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
const base::Matrix4f& val) final;
void SetUniform(uint64_t resource_id,
void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
float val) final;
void SetUniform(uint64_t resource_id, const std::string& name, int val) final;
void UploadUniforms(uint64_t resource_id) final;
void SetUniform(std::shared_ptr<void> resource,
const std::string& name,
int val) final;
void UploadUniforms(std::shared_ptr<void> resource) final;
void PrepareForDrawing() final;
void Present() final;
@ -120,6 +127,7 @@ class RendererVulkan final : public Renderer {
spirv_cache_;
struct GeometryVulkan {
std::list<std::shared_ptr<GeometryVulkan>>::iterator it;
Buffer<VkBuffer> buffer;
size_t buffer_size = 0;
uint32_t num_vertices = 0;
@ -131,6 +139,7 @@ class RendererVulkan final : public Renderer {
};
struct ShaderVulkan {
std::list<std::shared_ptr<ShaderVulkan>>::iterator it;
std::vector<std::tuple<size_t, // Variable name hash
size_t, // Variable size
size_t // Push constant offset
@ -145,6 +154,7 @@ class RendererVulkan final : public Renderer {
};
struct TextureVulkan {
std::list<std::shared_ptr<TextureVulkan>>::iterator it;
Buffer<VkImage> image;
VkImageView view = VK_NULL_HANDLE;
DescSet desc_set = {};
@ -176,10 +186,9 @@ class RendererVulkan final : public Renderer {
VmaAllocationInfo alloc_info;
};
std::unordered_map<uint64_t, GeometryVulkan> geometries_;
std::unordered_map<uint64_t, ShaderVulkan> shaders_;
std::unordered_map<uint64_t, TextureVulkan> textures_;
uint64_t last_resource_id_ = 0;
std::list<std::shared_ptr<GeometryVulkan>> geometries_;
std::list<std::shared_ptr<ShaderVulkan>> shaders_;
std::list<std::shared_ptr<TextureVulkan>> textures_;
bool context_lost_ = false;
@ -198,7 +207,7 @@ class RendererVulkan final : public Renderer {
uint64_t max_staging_buffer_size_ = 16 * 1024 * 1024;
bool staging_buffer_used_ = false;
uint64_t active_shader_id_ = 0;
std::shared_ptr<ShaderVulkan> active_shader_ = 0;
std::vector<std::unique_ptr<DescPool>> desc_pools_;
VkDescriptorSetLayout descriptor_set_layout_ = VK_NULL_HANDLE;