mirror of https://github.com/auygun/kaliber.git
std::shared_ptr<void> resource
This commit is contained in:
parent
14958d00ff
commit
8144057bff
|
@ -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,
|
||||
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,8 +128,10 @@ uint64_t RendererOpenGL::CreateGeometry(Primitive primitive,
|
|||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
uint64_t resource_id = ++last_resource_id_;
|
||||
geometries_[resource_id] = {0,
|
||||
auto it =
|
||||
geometries_.insert(geometries_.end(), std::make_shared<GeometryOpenGL>());
|
||||
**it = {it,
|
||||
0,
|
||||
0,
|
||||
kGlPrimitive[primitive],
|
||||
kGlDataType[index_description],
|
||||
|
@ -137,95 +141,89 @@ uint64_t RendererOpenGL::CreateGeometry(Primitive primitive,
|
|||
vertex_buffer_id,
|
||||
(GLuint)GetIndexSize(index_description),
|
||||
index_buffer_id};
|
||||
return resource_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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
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(uint64_t resource_id,
|
||||
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,
|
||||
std::shared_ptr<void> 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;
|
||||
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_ = {};
|
||||
|
|
|
@ -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,
|
||||
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(uint64_t resource_id) = 0;
|
||||
virtual void ActivateShader(uint64_t resource_id) = 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;
|
||||
|
|
|
@ -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,
|
||||
std::shared_ptr<void> 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_;
|
||||
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,100 +516,94 @@ 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,
|
||||
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,
|
||||
|
@ -618,40 +613,28 @@ void RendererVulkan::UpdateTexture(uint64_t resource_id,
|
|||
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) {
|
||||
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->second.pipeline_layout, texture_unit, 1,
|
||||
&active_descriptor_sets_[texture_unit], 0, nullptr);
|
||||
}
|
||||
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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
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(uint64_t resource_id,
|
||||
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,
|
||||
std::shared_ptr<void> 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;
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue