Renderer code refactoring.

This commit is contained in:
Attila Uygun 2021-10-25 22:54:57 +02:00
parent 79d9d294e6
commit 042bffaff3
20 changed files with 569 additions and 594 deletions

View File

@ -81,7 +81,6 @@ add_library(kaliber SHARED
../../../src/engine/renderer/opengl/render_command.cc
../../../src/engine/renderer/opengl/renderer_opengl_android.cc
../../../src/engine/renderer/opengl/renderer_opengl.cc
../../../src/engine/renderer/render_resource.cc
../../../src/engine/renderer/renderer_types.cc
../../../src/engine/renderer/shader.cc
../../../src/engine/renderer/texture.cc

View File

@ -106,7 +106,6 @@ GLTEST_SRC := \
$(SRC_ROOT)/engine/renderer/opengl/render_command.cc \
$(SRC_ROOT)/engine/renderer/opengl/renderer_opengl_linux.cc \
$(SRC_ROOT)/engine/renderer/opengl/renderer_opengl.cc \
$(SRC_ROOT)/engine/renderer/render_resource.cc \
$(SRC_ROOT)/engine/renderer/renderer_types.cc \
$(SRC_ROOT)/engine/renderer/shader.cc \
$(SRC_ROOT)/engine/renderer/texture.cc \

View File

@ -8,7 +8,6 @@ source_set("engine") {
"audio/audio_base.cc",
"audio/audio_base.h",
"audio/audio_forward.h",
"audio/audio_sample.h",
"audio/audio.h",
"drawable.cc",
"drawable.h",
@ -29,9 +28,7 @@ source_set("engine") {
"persistent_data.h",
"platform/asset_file.cc",
"platform/asset_file.h",
"platform/platform_base.cc",
"platform/platform_base.h",
"platform/platform_forward.h",
"platform/platform.cc",
"platform/platform.h",
"renderer/geometry.cc",
"renderer/geometry.h",
@ -40,7 +37,6 @@ source_set("engine") {
"renderer/opengl/render_command.h",
"renderer/opengl/renderer_opengl.cc",
"renderer/opengl/renderer_opengl.h",
"renderer/render_resource.cc",
"renderer/render_resource.h",
"renderer/renderer_types.cc",
"renderer/renderer_types.h",

View File

@ -440,16 +440,13 @@ bool Engine::IsMobile() const {
return platform_->mobile_device();
}
std::unique_ptr<RenderResource> Engine::CreateRenderResourceInternal(
RenderResourceFactoryBase& factory) {
return renderer_->CreateResource(factory);
}
void Engine::ContextLost() {
CreateRenderResources();
for (auto& t : textures_)
for (auto& t : textures_) {
t.second.texture->Destroy();
RefreshImage(t.first);
}
game_->ContextLost();
}

View File

@ -11,7 +11,6 @@
#include "../base/vecmath.h"
#include "audio/audio_forward.h"
#include "persistent_data.h"
#include "renderer/render_resource.h"
class TextureCompressor;
@ -65,10 +64,7 @@ class Engine {
template <typename T>
std::unique_ptr<T> CreateRenderResource() {
RenderResourceFactory<T> factory;
std::unique_ptr<RenderResource> resource =
CreateRenderResourceInternal(factory);
return std::unique_ptr<T>(static_cast<T*>(resource.release()));
return std::unique_ptr<T>(static_cast<T*>(new T(renderer_)));
}
void SetImageSource(const std::string& asset_name,
@ -212,9 +208,6 @@ class Engine {
base::Random random_;
std::unique_ptr<RenderResource> CreateRenderResourceInternal(
RenderResourceFactoryBase& factory);
void ContextLost();
bool CreateRenderResources();

View File

@ -5,10 +5,7 @@
namespace eng {
Geometry::Geometry(unsigned resource_id,
std::shared_ptr<void> impl_data,
Renderer* renderer)
: RenderResource(resource_id, impl_data, renderer) {}
Geometry::Geometry(Renderer* renderer) : RenderResource(renderer) {}
Geometry::~Geometry() {
Destroy();
@ -16,22 +13,21 @@ Geometry::~Geometry() {
void Geometry::Create(std::unique_ptr<Mesh> mesh) {
Destroy();
valid_ = true;
vertex_description_ = mesh->vertex_description();
primitive_ = mesh->primitive();
renderer_->CreateGeometry(impl_data_, std::move(mesh));
resource_id_ = renderer_->CreateGeometry(std::move(mesh));
}
void Geometry::Destroy() {
if (valid_) {
renderer_->DestroyGeometry(impl_data_);
valid_ = false;
if (IsValid()) {
renderer_->DestroyGeometry(resource_id_);
resource_id_ = 0;
}
}
void Geometry::Draw() {
if (valid_)
renderer_->Draw(impl_data_);
if (IsValid())
renderer_->Draw(resource_id_);
}
} // namespace eng

View File

@ -14,14 +14,12 @@ class Mesh;
class Geometry : public RenderResource {
public:
Geometry(unsigned resource_id,
std::shared_ptr<void> impl_data,
Renderer* renderer);
~Geometry() override;
Geometry(Renderer* renderer);
~Geometry();
void Create(std::unique_ptr<Mesh> mesh);
void Destroy() override;
void Destroy();
void Draw();

View File

@ -15,6 +15,8 @@
namespace eng {
RENDER_COMMAND_IMPL(CmdPresent, false);
RENDER_COMMAND_IMPL(CmdInvalidateAllResources, true);
RENDER_COMMAND_IMPL(CmdCreateTexture, true);
RENDER_COMMAND_IMPL(CmdUpdateTexture, true);
RENDER_COMMAND_IMPL(CmdDestoryTexture, true);
RENDER_COMMAND_IMPL(CmdActivateTexture, false);

View File

@ -50,81 +50,88 @@ struct RenderCommand {
RENDER_COMMAND_BEGIN(CmdPresent)
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdInvalidateAllResources)
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdCreateTexture)
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdUpdateTexture)
std::unique_ptr<Image> image;
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdDestoryTexture)
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdActivateTexture)
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdCreateGeometry)
std::unique_ptr<Mesh> mesh;
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdDestroyGeometry)
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdDrawGeometry)
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdCreateShader)
std::unique_ptr<ShaderSource> source;
VertexDescripton vertex_description;
std::shared_ptr<void> impl_data;
uint64_t resource_id;
bool enable_depth_test;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdDestroyShader)
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdActivateShader)
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdSetUniformVec2)
std::string name;
base::Vector2f v;
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdSetUniformVec3)
std::string name;
base::Vector3f v;
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdSetUniformVec4)
std::string name;
base::Vector4f v;
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdSetUniformMat4)
std::string name;
base::Matrix4f m;
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdSetUniformInt)
std::string name;
int i;
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
RENDER_COMMAND_BEGIN(CmdSetUniformFloat)
std::string name;
float f;
std::shared_ptr<void> impl_data;
uint64_t resource_id;
RENDER_COMMAND_END
} // namespace eng

View File

@ -45,47 +45,54 @@ RendererOpenGL::RendererOpenGL() = default;
RendererOpenGL::~RendererOpenGL() = default;
void RendererOpenGL::CreateGeometry(std::shared_ptr<void> impl_data,
std::unique_ptr<Mesh> mesh) {
uint64_t RendererOpenGL::CreateGeometry(std::unique_ptr<Mesh> mesh) {
auto cmd = std::make_unique<CmdCreateGeometry>();
cmd->mesh = std::move(mesh);
cmd->impl_data = impl_data;
cmd->resource_id = ++last_resource_id_;
EnqueueCommand(std::move(cmd));
return last_resource_id_;
}
void RendererOpenGL::DestroyGeometry(std::shared_ptr<void> impl_data) {
void RendererOpenGL::DestroyGeometry(uint64_t resource_id) {
auto cmd = std::make_unique<CmdDestroyGeometry>();
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
void RendererOpenGL::Draw(std::shared_ptr<void> impl_data) {
void RendererOpenGL::Draw(uint64_t resource_id) {
auto cmd = std::make_unique<CmdDrawGeometry>();
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
void RendererOpenGL::UpdateTexture(std::shared_ptr<void> impl_data,
uint64_t RendererOpenGL::CreateTexture() {
auto cmd = std::make_unique<CmdCreateTexture>();
cmd->resource_id = ++last_resource_id_;
EnqueueCommand(std::move(cmd));
return last_resource_id_;
}
void RendererOpenGL::UpdateTexture(uint64_t resource_id,
std::unique_ptr<Image> image) {
auto cmd = std::make_unique<CmdUpdateTexture>();
cmd->image = std::move(image);
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
void RendererOpenGL::DestroyTexture(std::shared_ptr<void> impl_data) {
void RendererOpenGL::DestroyTexture(uint64_t resource_id) {
auto cmd = std::make_unique<CmdDestoryTexture>();
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
void RendererOpenGL::ActivateTexture(std::shared_ptr<void> impl_data) {
void RendererOpenGL::ActivateTexture(uint64_t resource_id) {
auto cmd = std::make_unique<CmdActivateTexture>();
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
void RendererOpenGL::CreateShader(std::shared_ptr<void> impl_data,
uint64_t RendererOpenGL::CreateShader(
std::unique_ptr<ShaderSource> source,
const VertexDescripton& vertex_description,
Primitive primitive,
@ -93,80 +100,81 @@ void RendererOpenGL::CreateShader(std::shared_ptr<void> impl_data,
auto cmd = std::make_unique<CmdCreateShader>();
cmd->source = std::move(source);
cmd->vertex_description = vertex_description;
cmd->impl_data = impl_data;
cmd->resource_id = ++last_resource_id_;
cmd->enable_depth_test = enable_depth_test;
EnqueueCommand(std::move(cmd));
return last_resource_id_;
}
void RendererOpenGL::DestroyShader(std::shared_ptr<void> impl_data) {
void RendererOpenGL::DestroyShader(uint64_t resource_id) {
auto cmd = std::make_unique<CmdDestroyShader>();
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
void RendererOpenGL::ActivateShader(std::shared_ptr<void> impl_data) {
void RendererOpenGL::ActivateShader(uint64_t resource_id) {
auto cmd = std::make_unique<CmdActivateShader>();
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
void RendererOpenGL::SetUniform(std::shared_ptr<void> impl_data,
void RendererOpenGL::SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector2f& val) {
auto cmd = std::make_unique<CmdSetUniformVec2>();
cmd->name = name;
cmd->v = val;
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
void RendererOpenGL::SetUniform(std::shared_ptr<void> impl_data,
void RendererOpenGL::SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector3f& val) {
auto cmd = std::make_unique<CmdSetUniformVec3>();
cmd->name = name;
cmd->v = val;
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
void RendererOpenGL::SetUniform(std::shared_ptr<void> impl_data,
void RendererOpenGL::SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector4f& val) {
auto cmd = std::make_unique<CmdSetUniformVec4>();
cmd->name = name;
cmd->v = val;
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
void RendererOpenGL::SetUniform(std::shared_ptr<void> impl_data,
void RendererOpenGL::SetUniform(uint64_t resource_id,
const std::string& name,
const base::Matrix4f& val) {
auto cmd = std::make_unique<CmdSetUniformMat4>();
cmd->name = name;
cmd->m = val;
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
void RendererOpenGL::SetUniform(std::shared_ptr<void> impl_data,
void RendererOpenGL::SetUniform(uint64_t resource_id,
const std::string& name,
float val) {
auto cmd = std::make_unique<CmdSetUniformFloat>();
cmd->name = name;
cmd->f = val;
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
void RendererOpenGL::SetUniform(std::shared_ptr<void> impl_data,
void RendererOpenGL::SetUniform(uint64_t resource_id,
const std::string& name,
int val) {
auto cmd = std::make_unique<CmdSetUniformInt>();
cmd->name = name;
cmd->i = val;
cmd->impl_data = impl_data;
cmd->resource_id = resource_id;
EnqueueCommand(std::move(cmd));
}
@ -182,47 +190,21 @@ void RendererOpenGL::ContextLost() {
LOG << "Context lost.";
#ifdef THREADED_RENDERING
{
std::unique_lock<std::mutex> scoped_lock(mutex_);
global_commands_.clear();
draw_commands_[0].clear();
draw_commands_[1].clear();
}
main_thread_task_runner_->PostTask(
HERE, std::bind(&RendererOpenGL::InvalidateAllResources, this));
DestroyAllResources();
main_thread_task_runner_->PostTask(HERE, context_lost_cb_);
#else
InvalidateAllResources();
DestroyAllResources();
context_lost_cb_();
#endif // THREADED_RENDERING
}
std::unique_ptr<RenderResource> RendererOpenGL::CreateResource(
RenderResourceFactoryBase& factory) {
static unsigned last_id = 0;
// Set implementation specific data. This data will be sent with render
// commands to the render thread and sould not be used in any other thread.
std::shared_ptr<void> impl_data;
if (factory.IsTypeOf<Geometry>())
impl_data = std::make_shared<GeometryOpenGL>();
else if (factory.IsTypeOf<Shader>())
impl_data = std::make_shared<ShaderOpenGL>();
else if (factory.IsTypeOf<Texture>())
impl_data = std::make_shared<TextureOpenGL>();
else
NOTREACHED << "- Unknown resource type.";
unsigned resource_id = ++last_id;
auto resource = factory.Create(resource_id, impl_data, this);
resources_[resource_id] = resource.get();
return resource;
}
void RendererOpenGL::ReleaseResource(unsigned resource_id) {
auto it = resources_.find(resource_id);
if (it != resources_.end())
resources_.erase(it);
}
size_t RendererOpenGL::GetAndResetFPS() {
int ret = fps_;
fps_ = 0;
@ -309,9 +291,37 @@ bool RendererOpenGL::InitCommon() {
return true;
}
void RendererOpenGL::InvalidateAllResources() {
for (auto& r : resources_)
r.second->Destroy();
void RendererOpenGL::DestroyAllResources() {
std::vector<uint64_t> resource_ids;
for (auto& r : geometries_)
resource_ids.push_back(r.first);
for (auto& r : resource_ids) {
auto cmd = std::make_unique<CmdDestroyGeometry>();
cmd->resource_id = r;
ProcessCommand(cmd.get());
}
resource_ids.clear();
for (auto& r : shaders_)
resource_ids.push_back(r.first);
for (auto& r : resource_ids) {
auto cmd = std::make_unique<CmdDestroyShader>();
cmd->resource_id = r;
ProcessCommand(cmd.get());
}
resource_ids.clear();
for (auto& r : textures_)
resource_ids.push_back(r.first);
for (auto& r : resource_ids) {
auto cmd = std::make_unique<CmdDestoryTexture>();
cmd->resource_id = r;
ProcessCommand(cmd.get());
}
DCHECK(geometries_.size() == 0);
DCHECK(shaders_.size() == 0);
DCHECK(textures_.size() == 0);
}
bool RendererOpenGL::StartRenderThread() {
@ -425,6 +435,9 @@ void RendererOpenGL::ProcessCommand(RenderCommand* cmd) {
case CmdPresent::CMD_ID:
HandleCmdPresent(cmd);
break;
case CmdCreateTexture::CMD_ID:
HandleCmdCreateTexture(cmd);
break;
case CmdUpdateTexture::CMD_ID:
HandleCmdUpdateTexture(cmd);
break;
@ -475,18 +488,29 @@ void RendererOpenGL::ProcessCommand(RenderCommand* cmd) {
}
}
void RendererOpenGL::HandleCmdUpdateTexture(RenderCommand* cmd) {
auto* c = static_cast<CmdUpdateTexture*>(cmd);
auto impl_data = reinterpret_cast<TextureOpenGL*>(c->impl_data.get());
bool new_texture = impl_data->id == 0;
void RendererOpenGL::HandleCmdCreateTexture(RenderCommand* cmd) {
auto* c = static_cast<CmdCreateTexture*>(cmd);
GLuint gl_id = 0;
if (new_texture)
glGenTextures(1, &gl_id);
else
gl_id = impl_data->id;
glBindTexture(GL_TEXTURE_2D, gl_id);
BindTexture(gl_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
textures_.insert({c->resource_id, {gl_id}});
}
void RendererOpenGL::HandleCmdUpdateTexture(RenderCommand* cmd) {
auto* c = static_cast<CmdUpdateTexture*>(cmd);
auto it = textures_.find(c->resource_id);
if (it == textures_.end())
return;
BindTexture(it->second.id);
if (c->image->IsCompressed()) {
GLenum format = 0;
switch (c->image->GetFormat()) {
@ -515,8 +539,8 @@ void RendererOpenGL::HandleCmdUpdateTexture(RenderCommand* cmd) {
c->image->GetHeight(), 0, c->image->GetSize(),
c->image->GetBuffer());
// Sometimes the first glCompressedTexImage2D call after context-lost
// generates GL_INVALID_VALUE.
// On some devices the first glCompressedTexImage2D call after context-lost
// returns GL_INVALID_VALUE for some reason.
GLenum err = glGetError();
if (err == GL_INVALID_VALUE) {
glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, c->image->GetWidth(),
@ -532,40 +556,30 @@ void RendererOpenGL::HandleCmdUpdateTexture(RenderCommand* cmd) {
c->image->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
c->image->GetBuffer());
}
if (new_texture) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
*impl_data = {gl_id};
}
}
void RendererOpenGL::HandleCmdDestoryTexture(RenderCommand* cmd) {
auto* c = static_cast<CmdDestoryTexture*>(cmd);
auto impl_data = reinterpret_cast<TextureOpenGL*>(c->impl_data.get());
if (impl_data->id > 0) {
glDeleteTextures(1, &(impl_data->id));
*impl_data = {};
}
auto it = textures_.find(c->resource_id);
if (it == textures_.end())
return;
glDeleteTextures(1, &(it->second.id));
textures_.erase(it);
}
void RendererOpenGL::HandleCmdActivateTexture(RenderCommand* cmd) {
auto* c = static_cast<CmdActivateTexture*>(cmd);
auto impl_data = reinterpret_cast<TextureOpenGL*>(c->impl_data.get());
if (impl_data->id > 0 && impl_data->id != active_texture_id_) {
glBindTexture(GL_TEXTURE_2D, impl_data->id);
active_texture_id_ = impl_data->id;
auto it = textures_.find(c->resource_id);
if (it == textures_.end()) {
return;
}
BindTexture(it->second.id);
}
void RendererOpenGL::HandleCmdCreateGeometry(RenderCommand* cmd) {
auto* c = static_cast<CmdCreateGeometry*>(cmd);
auto impl_data = reinterpret_cast<GeometryOpenGL*>(c->impl_data.get());
if (impl_data->vertex_buffer_id > 0)
return;
// Verify that we have a valid layout and get the total byte size per vertex.
GLuint vertex_size = c->mesh->GetVertexSize();
@ -613,7 +627,7 @@ void RendererOpenGL::HandleCmdCreateGeometry(RenderCommand* cmd) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
*impl_data = {(GLsizei)c->mesh->num_vertices(),
geometries_[c->resource_id] = {(GLsizei)c->mesh->num_vertices(),
(GLsizei)c->mesh->num_indices(),
kGlPrimitive[c->mesh->primitive()],
kGlDataType[c->mesh->index_description()],
@ -626,58 +640,58 @@ void RendererOpenGL::HandleCmdCreateGeometry(RenderCommand* cmd) {
void RendererOpenGL::HandleCmdDestroyGeometry(RenderCommand* cmd) {
auto* c = static_cast<CmdDestroyGeometry*>(cmd);
auto impl_data = reinterpret_cast<GeometryOpenGL*>(c->impl_data.get());
if (impl_data->vertex_buffer_id == 0)
auto it = geometries_.find(c->resource_id);
if (it == geometries_.end())
return;
if (impl_data->index_buffer_id)
glDeleteBuffers(1, &(impl_data->index_buffer_id));
if (impl_data->vertex_buffer_id)
glDeleteBuffers(1, &(impl_data->vertex_buffer_id));
if (impl_data->vertex_array_id)
glDeleteVertexArrays(1, &(impl_data->vertex_array_id));
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));
*impl_data = {};
geometries_.erase(it);
}
void RendererOpenGL::HandleCmdDrawGeometry(RenderCommand* cmd) {
auto* c = static_cast<CmdDrawGeometry*>(cmd);
auto impl_data = reinterpret_cast<GeometryOpenGL*>(c->impl_data.get());
if (impl_data->vertex_buffer_id == 0)
auto it = geometries_.find(c->resource_id);
if (it == geometries_.end())
return;
// Set up the vertex data.
if (impl_data->vertex_array_id)
glBindVertexArray(impl_data->vertex_array_id);
if (it->second.vertex_array_id)
glBindVertexArray(it->second.vertex_array_id);
else {
glBindBuffer(GL_ARRAY_BUFFER, impl_data->vertex_buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, it->second.vertex_buffer_id);
for (GLuint attribute_index = 0;
attribute_index < (GLuint)impl_data->vertex_layout.size();
attribute_index < (GLuint)it->second.vertex_layout.size();
++attribute_index) {
GeometryOpenGL::Element& e = impl_data->vertex_layout[attribute_index];
GeometryOpenGL::Element& e = it->second.vertex_layout[attribute_index];
glEnableVertexAttribArray(attribute_index);
glVertexAttribPointer(attribute_index, e.num_elements, e.type, GL_FALSE,
impl_data->vertex_size,
it->second.vertex_size,
(const GLvoid*)e.vertex_offset);
}
if (impl_data->num_indices > 0)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, impl_data->index_buffer_id);
if (it->second.num_indices > 0)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, it->second.index_buffer_id);
}
// Draw the primitive.
if (impl_data->num_indices > 0)
glDrawElements(impl_data->primitive, impl_data->num_indices,
impl_data->index_type, NULL);
if (it->second.num_indices > 0)
glDrawElements(it->second.primitive, it->second.num_indices,
it->second.index_type, NULL);
else
glDrawArrays(impl_data->primitive, 0, impl_data->num_vertices);
glDrawArrays(it->second.primitive, 0, it->second.num_vertices);
// Clean up states.
if (impl_data->vertex_array_id)
if (it->second.vertex_array_id)
glBindVertexArray(0);
else {
for (GLuint attribute_index = 0;
attribute_index < (GLuint)impl_data->vertex_layout.size();
attribute_index < (GLuint)it->second.vertex_layout.size();
++attribute_index)
glDisableVertexAttribArray(attribute_index);
@ -688,9 +702,6 @@ void RendererOpenGL::HandleCmdDrawGeometry(RenderCommand* cmd) {
void RendererOpenGL::HandleCmdCreateShader(RenderCommand* cmd) {
auto* c = static_cast<CmdCreateShader*>(cmd);
auto impl_data = reinterpret_cast<ShaderOpenGL*>(c->impl_data.get());
if (impl_data->id > 0)
return;
GLuint vertex_shader =
CreateShader(c->source->GetVertexSource(), GL_VERTEX_SHADER);
@ -728,25 +739,29 @@ void RendererOpenGL::HandleCmdCreateShader(RenderCommand* cmd) {
}
}
*impl_data = {id, {}, c->enable_depth_test};
shaders_[c->resource_id] = {id, {}, c->enable_depth_test};
}
void RendererOpenGL::HandleCmdDestroyShader(RenderCommand* cmd) {
auto* c = static_cast<CmdDestroyShader*>(cmd);
auto impl_data = reinterpret_cast<ShaderOpenGL*>(c->impl_data.get());
if (impl_data->id > 0) {
glDeleteProgram(impl_data->id);
*impl_data = {};
}
auto it = shaders_.find(c->resource_id);
if (it == shaders_.end())
return;
glDeleteProgram(it->second.id);
shaders_.erase(it);
}
void RendererOpenGL::HandleCmdActivateShader(RenderCommand* cmd) {
auto* c = static_cast<CmdActivateShader*>(cmd);
auto impl_data = reinterpret_cast<ShaderOpenGL*>(c->impl_data.get());
if (impl_data->id > 0 && impl_data->id != active_shader_id_) {
glUseProgram(impl_data->id);
active_shader_id_ = impl_data->id;
if (impl_data->enable_depth_test)
auto it = shaders_.find(c->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)
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
@ -755,68 +770,75 @@ void RendererOpenGL::HandleCmdActivateShader(RenderCommand* cmd) {
void RendererOpenGL::HandleCmdSetUniformVec2(RenderCommand* cmd) {
auto* c = static_cast<CmdSetUniformVec2*>(cmd);
auto impl_data = reinterpret_cast<ShaderOpenGL*>(c->impl_data.get());
if (impl_data->id > 0) {
GLint index =
GetUniformLocation(impl_data->id, c->name, impl_data->uniforms);
auto it = shaders_.find(c->resource_id);
if (it == shaders_.end())
return;
GLint index = GetUniformLocation(it->second.id, c->name, it->second.uniforms);
if (index >= 0)
glUniform2fv(index, 1, c->v.GetData());
}
}
void RendererOpenGL::HandleCmdSetUniformVec3(RenderCommand* cmd) {
auto* c = static_cast<CmdSetUniformVec3*>(cmd);
auto impl_data = reinterpret_cast<ShaderOpenGL*>(c->impl_data.get());
if (impl_data->id > 0) {
GLint index =
GetUniformLocation(impl_data->id, c->name, impl_data->uniforms);
auto it = shaders_.find(c->resource_id);
if (it == shaders_.end())
return;
GLint index = GetUniformLocation(it->second.id, c->name, it->second.uniforms);
if (index >= 0)
glUniform3fv(index, 1, c->v.GetData());
}
}
void RendererOpenGL::HandleCmdSetUniformVec4(RenderCommand* cmd) {
auto* c = static_cast<CmdSetUniformVec4*>(cmd);
auto impl_data = reinterpret_cast<ShaderOpenGL*>(c->impl_data.get());
if (impl_data->id > 0) {
GLint index =
GetUniformLocation(impl_data->id, c->name, impl_data->uniforms);
auto it = shaders_.find(c->resource_id);
if (it == shaders_.end())
return;
GLint index = GetUniformLocation(it->second.id, c->name, it->second.uniforms);
if (index >= 0)
glUniform4fv(index, 1, c->v.GetData());
}
}
void RendererOpenGL::HandleCmdSetUniformMat4(RenderCommand* cmd) {
auto* c = static_cast<CmdSetUniformMat4*>(cmd);
auto impl_data = reinterpret_cast<ShaderOpenGL*>(c->impl_data.get());
if (impl_data->id > 0) {
GLint index =
GetUniformLocation(impl_data->id, c->name, impl_data->uniforms);
auto it = shaders_.find(c->resource_id);
if (it == shaders_.end())
return;
GLint index = GetUniformLocation(it->second.id, c->name, it->second.uniforms);
if (index >= 0)
glUniformMatrix4fv(index, 1, GL_FALSE, c->m.GetData());
}
}
void RendererOpenGL::HandleCmdSetUniformFloat(RenderCommand* cmd) {
auto* c = static_cast<CmdSetUniformFloat*>(cmd);
auto impl_data = reinterpret_cast<ShaderOpenGL*>(c->impl_data.get());
if (impl_data->id > 0) {
GLint index =
GetUniformLocation(impl_data->id, c->name, impl_data->uniforms);
auto it = shaders_.find(c->resource_id);
if (it == shaders_.end())
return;
GLint index = GetUniformLocation(it->second.id, c->name, it->second.uniforms);
if (index >= 0)
glUniform1f(index, c->f);
}
}
void RendererOpenGL::HandleCmdSetUniformInt(RenderCommand* cmd) {
auto* c = static_cast<CmdSetUniformInt*>(cmd);
auto impl_data = reinterpret_cast<ShaderOpenGL*>(c->impl_data.get());
if (impl_data->id > 0) {
GLint index =
GetUniformLocation(impl_data->id, c->name, impl_data->uniforms);
auto it = shaders_.find(c->resource_id);
if (it == shaders_.end())
return;
GLint index = GetUniformLocation(it->second.id, c->name, it->second.uniforms);
if (index >= 0)
glUniform1i(index, c->i);
}
void RendererOpenGL::BindTexture(GLuint id) {
if (id != active_texture_id_) {
glBindTexture(GL_TEXTURE_2D, id);
active_texture_id_ = id;
}
}
bool RendererOpenGL::SetupVertexLayout(

View File

@ -20,7 +20,6 @@
#include "opengl.h"
#include "../render_resource.h"
#include "../renderer.h"
#if defined(__ANDROID__)
@ -50,51 +49,46 @@ class RendererOpenGL : public Renderer {
void Shutdown() override;
void CreateGeometry(std::shared_ptr<void> impl_data,
std::unique_ptr<Mesh> mesh) override;
void DestroyGeometry(std::shared_ptr<void> impl_data) override;
void Draw(std::shared_ptr<void> impl_data) override;
uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) override;
void DestroyGeometry(uint64_t resource_id) override;
void Draw(uint64_t resource_id) override;
void UpdateTexture(std::shared_ptr<void> impl_data,
uint64_t CreateTexture() override;
void UpdateTexture(uint64_t resource_id,
std::unique_ptr<Image> image) override;
void DestroyTexture(std::shared_ptr<void> impl_data) override;
void ActivateTexture(std::shared_ptr<void> impl_data) override;
void DestroyTexture(uint64_t resource_id) override;
void ActivateTexture(uint64_t resource_id) override;
void CreateShader(std::shared_ptr<void> impl_data,
std::unique_ptr<ShaderSource> source,
uint64_t CreateShader(std::unique_ptr<ShaderSource> source,
const VertexDescripton& vertex_description,
Primitive primitive,
bool enable_depth_test) override;
void DestroyShader(std::shared_ptr<void> impl_data) override;
void ActivateShader(std::shared_ptr<void> impl_data) override;
void DestroyShader(uint64_t resource_id) override;
void ActivateShader(uint64_t resource_id) override;
void SetUniform(std::shared_ptr<void> impl_data,
void SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector2f& val) override;
void SetUniform(std::shared_ptr<void> impl_data,
void SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector3f& val) override;
void SetUniform(std::shared_ptr<void> impl_data,
void SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector4f& val) override;
void SetUniform(std::shared_ptr<void> impl_data,
void SetUniform(uint64_t resource_id,
const std::string& name,
const base::Matrix4f& val) override;
void SetUniform(std::shared_ptr<void> impl_data,
void SetUniform(uint64_t resource_id,
const std::string& name,
float val) override;
void SetUniform(std::shared_ptr<void> impl_data,
void SetUniform(uint64_t resource_id,
const std::string& name,
int val) override;
void UploadUniforms(std::shared_ptr<void> impl_data) override {}
void UploadUniforms(uint64_t resource_id) override {}
void PrepareForDrawing() override {}
void Present() override;
std::unique_ptr<RenderResource> CreateResource(
RenderResourceFactoryBase& factory) override;
void ReleaseResource(unsigned resource_id) override;
size_t GetAndResetFPS() override;
#if defined(__linux__) && !defined(__ANDROID__)
@ -130,14 +124,17 @@ class RendererOpenGL : public Renderer {
GLuint id = 0;
};
std::unordered_map<uint64_t, GeometryOpenGL> geometries_;
std::unordered_map<uint64_t, ShaderOpenGL> shaders_;
std::unordered_map<uint64_t, TextureOpenGL> textures_;
uint64_t last_resource_id_ = 0;
GLuint active_shader_id_ = 0;
GLuint active_texture_id_ = 0;
bool vertex_array_objects_ = false;
bool npot_ = false;
std::unordered_map<unsigned, RenderResource*> resources_;
#ifdef THREADED_RENDERING
// Global commands are independent from frames and guaranteed to be processed.
std::deque<std::unique_ptr<RenderCommand>> global_commands_;
@ -172,7 +169,7 @@ class RendererOpenGL : public Renderer {
void ContextLost();
void InvalidateAllResources();
void DestroyAllResources();
bool StartRenderThread();
void TerminateRenderThread();
@ -185,6 +182,7 @@ class RendererOpenGL : public Renderer {
void ProcessCommand(RenderCommand* cmd);
void HandleCmdPresent(RenderCommand* cmd);
void HandleCmdCreateTexture(RenderCommand* cmd);
void HandleCmdUpdateTexture(RenderCommand* cmd);
void HandleCmdDestoryTexture(RenderCommand* cmd);
void HandleCmdActivateTexture(RenderCommand* cmd);
@ -201,6 +199,7 @@ class RendererOpenGL : public Renderer {
void HandleCmdSetUniformFloat(RenderCommand* cmd);
void HandleCmdSetUniformInt(RenderCommand* cmd);
void BindTexture(GLuint id);
bool SetupVertexLayout(const VertexDescripton& vd,
GLuint vertex_size,
bool use_vao,

View File

@ -1,16 +0,0 @@
#include "render_resource.h"
#include "renderer.h"
namespace eng {
RenderResource::RenderResource(unsigned resource_id,
std::shared_ptr<void> impl_data,
Renderer* renderer)
: resource_id_(resource_id), impl_data_(impl_data), renderer_(renderer) {}
RenderResource::~RenderResource() {
renderer_->ReleaseResource(resource_id_);
}
} // namespace eng

View File

@ -1,10 +1,7 @@
#ifndef RENDER_RESOURCE_H
#define RENDER_RESOURCE_H
#include <array>
#include <memory>
#include <typeindex>
#include <typeinfo>
#include <cstdint>
namespace eng {
@ -12,60 +9,22 @@ class Renderer;
class RenderResource {
public:
RenderResource(unsigned resource_id,
std::shared_ptr<void> impl_data,
Renderer* renderer);
virtual ~RenderResource();
RenderResource(Renderer* renderer) : renderer_(renderer){};
virtual void Destroy() = 0;
bool IsValid() const { return resource_id_ != 0; }
bool IsValid() const { return valid_; }
std::shared_ptr<void> impl_data() { return impl_data_; }
uint64_t resource_id() { return resource_id_; }
protected:
unsigned resource_id_ = 0;
std::shared_ptr<void> impl_data_; // For use in render thread only.
bool valid_ = false;
uint64_t resource_id_ = 0;
Renderer* renderer_ = nullptr;
~RenderResource() = default;
RenderResource(const RenderResource&) = delete;
RenderResource& operator=(const RenderResource&) = delete;
};
class RenderResourceFactoryBase {
public:
RenderResourceFactoryBase(std::type_index resource_type)
: resource_type_(resource_type) {}
virtual ~RenderResourceFactoryBase() = default;
virtual std::unique_ptr<eng::RenderResource>
Create(unsigned id, std::shared_ptr<void> impl_data, Renderer* renderer) = 0;
template <typename T>
bool IsTypeOf() const {
return resource_type_ == std::type_index(typeid(T));
}
private:
std::type_index resource_type_;
};
template <typename T>
class RenderResourceFactory : public RenderResourceFactoryBase {
public:
RenderResourceFactory()
: RenderResourceFactoryBase(std::type_index(typeid(T))) {}
~RenderResourceFactory() override = default;
std::unique_ptr<eng::RenderResource> Create(unsigned id,
std::shared_ptr<void> impl_data,
Renderer* renderer) override {
return std::make_unique<T>(id, impl_data, renderer);
}
};
} // namespace eng
#endif // RENDER_RESOURCE_H

View File

@ -40,51 +40,46 @@ class Renderer {
virtual void Shutdown() = 0;
virtual void CreateGeometry(std::shared_ptr<void> impl_data,
std::unique_ptr<Mesh> mesh) = 0;
virtual void DestroyGeometry(std::shared_ptr<void> impl_data) = 0;
virtual void Draw(std::shared_ptr<void> impl_data) = 0;
virtual uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) = 0;
virtual void DestroyGeometry(uint64_t resource_id) = 0;
virtual void Draw(uint64_t resource_id) = 0;
virtual void UpdateTexture(std::shared_ptr<void> impl_data,
virtual uint64_t CreateTexture() = 0;
virtual void UpdateTexture(uint64_t resource_id,
std::unique_ptr<Image> image) = 0;
virtual void DestroyTexture(std::shared_ptr<void> impl_data) = 0;
virtual void ActivateTexture(std::shared_ptr<void> impl_data) = 0;
virtual void DestroyTexture(uint64_t resource_id) = 0;
virtual void ActivateTexture(uint64_t resource_id) = 0;
virtual void CreateShader(std::shared_ptr<void> impl_data,
std::unique_ptr<ShaderSource> source,
virtual uint64_t CreateShader(std::unique_ptr<ShaderSource> source,
const VertexDescripton& vertex_description,
Primitive primitive,
bool enable_depth_test) = 0;
virtual void DestroyShader(std::shared_ptr<void> impl_data) = 0;
virtual void ActivateShader(std::shared_ptr<void> impl_data) = 0;
virtual void DestroyShader(uint64_t resource_id) = 0;
virtual void ActivateShader(uint64_t resource_id) = 0;
virtual void SetUniform(std::shared_ptr<void> impl_data,
virtual void SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector2f& val) = 0;
virtual void SetUniform(std::shared_ptr<void> impl_data,
virtual void SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector3f& val) = 0;
virtual void SetUniform(std::shared_ptr<void> impl_data,
virtual void SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector4f& val) = 0;
virtual void SetUniform(std::shared_ptr<void> impl_data,
virtual void SetUniform(uint64_t resource_id,
const std::string& name,
const base::Matrix4f& val) = 0;
virtual void SetUniform(std::shared_ptr<void> impl_data,
virtual void SetUniform(uint64_t resource_id,
const std::string& name,
float val) = 0;
virtual void SetUniform(std::shared_ptr<void> impl_data,
virtual void SetUniform(uint64_t resource_id,
const std::string& name,
int val) = 0;
virtual void UploadUniforms(std::shared_ptr<void> impl_data) = 0;
virtual void UploadUniforms(uint64_t resource_id) = 0;
virtual void PrepareForDrawing() = 0;
virtual void Present() = 0;
virtual std::unique_ptr<RenderResource> CreateResource(
RenderResourceFactoryBase& factory) = 0;
virtual void ReleaseResource(unsigned resource_id) = 0;
bool SupportsETC1() const { return texture_compression_.etc1; }
bool SupportsDXT1() const {
return texture_compression_.dxt1 || texture_compression_.s3tc;

View File

@ -7,10 +7,7 @@ using namespace base;
namespace eng {
Shader::Shader(unsigned resource_id,
std::shared_ptr<void> impl_data,
Renderer* renderer)
: RenderResource(resource_id, impl_data, renderer) {}
Shader::Shader(Renderer* renderer) : RenderResource(renderer) {}
Shader::~Shader() {
Destroy();
@ -21,56 +18,55 @@ void Shader::Create(std::unique_ptr<ShaderSource> source,
Primitive primitive,
bool enable_depth_test) {
Destroy();
valid_ = true;
renderer_->CreateShader(impl_data_, std::move(source), vd, primitive,
resource_id_ = renderer_->CreateShader(std::move(source), vd, primitive,
enable_depth_test);
}
void Shader::Destroy() {
if (valid_) {
renderer_->DestroyShader(impl_data_);
valid_ = false;
if (IsValid()) {
renderer_->DestroyShader(resource_id_);
resource_id_ = 0;
}
}
void Shader::Activate() {
if (valid_)
renderer_->ActivateShader(impl_data_);
if (IsValid())
renderer_->ActivateShader(resource_id_);
}
void Shader::SetUniform(const std::string& name, const Vector2f& v) {
if (valid_)
renderer_->SetUniform(impl_data_, name, v);
if (IsValid())
renderer_->SetUniform(resource_id_, name, v);
}
void Shader::SetUniform(const std::string& name, const Vector3f& v) {
if (valid_)
renderer_->SetUniform(impl_data_, name, v);
if (IsValid())
renderer_->SetUniform(resource_id_, name, v);
}
void Shader::SetUniform(const std::string& name, const Vector4f& v) {
if (valid_)
renderer_->SetUniform(impl_data_, name, v);
if (IsValid())
renderer_->SetUniform(resource_id_, name, v);
}
void Shader::SetUniform(const std::string& name, const Matrix4f& m) {
if (valid_)
renderer_->SetUniform(impl_data_, name, m);
if (IsValid())
renderer_->SetUniform(resource_id_, name, m);
}
void Shader::SetUniform(const std::string& name, float f) {
if (valid_)
renderer_->SetUniform(impl_data_, name, f);
if (IsValid())
renderer_->SetUniform(resource_id_, name, f);
}
void Shader::SetUniform(const std::string& name, int i) {
if (valid_)
renderer_->SetUniform(impl_data_, name, i);
if (IsValid())
renderer_->SetUniform(resource_id_, name, i);
}
void Shader::UploadUniforms() {
if (valid_)
renderer_->UploadUniforms(impl_data_);
if (IsValid())
renderer_->UploadUniforms(resource_id_);
}
} // namespace eng

View File

@ -15,17 +15,15 @@ class ShaderSource;
class Shader : public RenderResource {
public:
Shader(unsigned resource_id,
std::shared_ptr<void> impl_data,
Renderer* renderer);
~Shader() override;
Shader(Renderer* renderer);
~Shader();
void Create(std::unique_ptr<ShaderSource> source,
const VertexDescripton& vd,
Primitive primitive,
bool enable_depth_test);
void Destroy() override;
void Destroy();
void Activate();

View File

@ -6,33 +6,31 @@
namespace eng {
Texture::Texture(unsigned resource_id,
std::shared_ptr<void> impl_data,
Renderer* renderer)
: RenderResource(resource_id, impl_data, renderer) {}
Texture::Texture(Renderer* renderer) : RenderResource(renderer) {}
Texture::~Texture() {
Destroy();
}
void Texture::Update(std::unique_ptr<Image> image) {
valid_ = true;
if (!IsValid())
resource_id_ = renderer_->CreateTexture();
width_ = image->GetWidth();
height_ = image->GetHeight();
renderer_->UpdateTexture(impl_data_, std::move(image));
renderer_->UpdateTexture(resource_id_, std::move(image));
}
void Texture::Destroy() {
if (valid_) {
renderer_->DestroyTexture(impl_data_);
valid_ = false;
if (IsValid()) {
renderer_->DestroyTexture(resource_id_);
resource_id_ = 0;
DLOG << "Texture destroyed. resource_id: " << resource_id_;
}
}
void Texture::Activate() {
if (valid_)
renderer_->ActivateTexture(impl_data_);
if (IsValid())
renderer_->ActivateTexture(resource_id_);
}
} // namespace eng

View File

@ -13,15 +13,12 @@ class Renderer;
class Texture : public RenderResource {
public:
Texture(unsigned resource_id,
std::shared_ptr<void> impl_data,
Renderer* renderer);
~Texture() override;
Texture(Renderer* renderer);
~Texture();
// Uploads image.
void Update(std::unique_ptr<Image> image);
void Destroy() override;
void Destroy();
void Activate();

View File

@ -259,39 +259,39 @@ RendererVulkan::RendererVulkan() = default;
RendererVulkan::~RendererVulkan() = default;
void RendererVulkan::CreateGeometry(std::shared_ptr<void> impl_data,
std::unique_ptr<Mesh> mesh) {
auto geometry = reinterpret_cast<GeometryVulkan*>(impl_data.get());
geometry->num_vertices = mesh->num_vertices();
size_t vertex_data_size = mesh->GetVertexSize() * geometry->num_vertices;
uint64_t RendererVulkan::CreateGeometry(std::unique_ptr<Mesh> mesh) {
auto& geometry = geometries_[++last_resource_id_] = {};
geometry.num_vertices = mesh->num_vertices();
size_t vertex_data_size = mesh->GetVertexSize() * geometry.num_vertices;
size_t index_data_size = 0;
if (mesh->GetIndices()) {
geometry->num_indices = mesh->num_indices();
geometry->index_type = GetIndexType(mesh->index_description());
index_data_size = mesh->GetIndexSize() * geometry->num_indices;
geometry.num_indices = mesh->num_indices();
geometry.index_type = GetIndexType(mesh->index_description());
index_data_size = mesh->GetIndexSize() * geometry.num_indices;
}
size_t data_size = vertex_data_size + index_data_size;
AllocateBuffer(geometry->buffer, data_size,
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);
task_runner_.PostTask(HERE, std::bind(&RendererVulkan::UpdateBuffer, this,
std::get<0>(geometry->buffer), 0,
std::get<0>(geometry.buffer), 0,
mesh->GetVertices(), vertex_data_size));
if (geometry->num_indices > 0) {
geometry->indices_offset = vertex_data_size;
if (geometry.num_indices > 0) {
geometry.indices_offset = vertex_data_size;
task_runner_.PostTask(
HERE, std::bind(&RendererVulkan::UpdateBuffer, this,
std::get<0>(geometry->buffer), geometry->indices_offset,
std::get<0>(geometry.buffer), geometry.indices_offset,
mesh->GetIndices(), index_data_size));
}
task_runner_.PostTask(HERE,
std::bind(&RendererVulkan::BufferMemoryBarrier, this,
std::get<0>(geometry->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,
@ -301,70 +301,87 @@ void RendererVulkan::CreateGeometry(std::shared_ptr<void> impl_data,
std::unique_ptr<Mesh> own(mesh);
});
semaphore_.Release();
return last_resource_id_;
}
void RendererVulkan::DestroyGeometry(std::shared_ptr<void> impl_data) {
auto geometry = reinterpret_cast<GeometryVulkan*>(impl_data.get());
FreeBuffer(std::move(geometry->buffer));
geometry = {};
void RendererVulkan::DestroyGeometry(uint64_t resource_id) {
auto it = geometries_.find(resource_id);
if (it == geometries_.end())
return;
FreeBuffer(std::move(it->second.buffer));
geometries_.erase(it);
}
void RendererVulkan::Draw(std::shared_ptr<void> impl_data) {
auto geometry = reinterpret_cast<GeometryVulkan*>(impl_data.get());
void RendererVulkan::Draw(uint64_t resource_id) {
auto it = geometries_.find(resource_id);
if (it == geometries_.end())
return;
VkDeviceSize offset = 0;
vkCmdBindVertexBuffers(frames_[current_frame_].draw_command_buffer, 0, 1,
&std::get<0>(geometry->buffer), &offset);
if (geometry->num_indices > 0) {
&std::get<0>(it->second.buffer), &offset);
if (it->second.num_indices > 0) {
vkCmdBindIndexBuffer(frames_[current_frame_].draw_command_buffer,
std::get<0>(geometry->buffer),
geometry->indices_offset, geometry->index_type);
std::get<0>(it->second.buffer),
it->second.indices_offset, it->second.index_type);
vkCmdDrawIndexed(frames_[current_frame_].draw_command_buffer,
geometry->num_indices, 1, 0, 0, 0);
it->second.num_indices, 1, 0, 0, 0);
} else {
vkCmdDraw(frames_[current_frame_].draw_command_buffer,
geometry->num_vertices, 1, 0, 0);
it->second.num_vertices, 1, 0, 0);
}
}
void RendererVulkan::UpdateTexture(std::shared_ptr<void> impl_data,
uint64_t RendererVulkan::CreateTexture() {
textures_.insert({++last_resource_id_, {}});
return last_resource_id_;
}
void RendererVulkan::UpdateTexture(uint64_t resource_id,
std::unique_ptr<Image> image) {
auto texture = reinterpret_cast<TextureVulkan*>(impl_data.get());
auto it = textures_.find(resource_id);
if (it == textures_.end())
return;
VkImageLayout old_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkFormat format = GetImageFormat(image->GetFormat());
if (texture->view != VK_NULL_HANDLE &&
(texture->width != image->GetWidth() ||
texture->height != image->GetHeight())) {
if (it->second.view != VK_NULL_HANDLE &&
(it->second.width != image->GetWidth() ||
it->second.height != image->GetHeight())) {
// Size mismatch. Recreate the texture.
FreeTexture(std::move(texture->image), texture->view,
std::move(texture->desc_set));
*texture = {};
FreeTexture(std::move(it->second.image), it->second.view,
std::move(it->second.desc_set));
it->second = {};
}
if (texture->view == VK_NULL_HANDLE) {
CreateTexture(texture->image, texture->view, texture->desc_set, format,
image->GetWidth(), image->GetHeight(),
if (it->second.view == VK_NULL_HANDLE) {
CreateTexture(it->second.image, it->second.view, it->second.desc_set,
format, image->GetWidth(), image->GetHeight(),
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VMA_MEMORY_USAGE_GPU_ONLY);
old_layout = VK_IMAGE_LAYOUT_UNDEFINED;
texture->width = image->GetWidth();
texture->height = image->GetHeight();
it->second.width = image->GetWidth();
it->second.height = image->GetHeight();
}
task_runner_.PostTask(
HERE,
std::bind(&RendererVulkan::ImageMemoryBarrier, this,
std::get<0>(texture->image),
std::get<0>(it->second.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>(texture->image), format, image->GetBuffer(),
std::get<0>(it->second.image), format, image->GetBuffer(),
image->GetWidth(), image->GetHeight()));
task_runner_.PostTask(
HERE, std::bind(&RendererVulkan::ImageMemoryBarrier, this,
std::get<0>(texture->image), VK_ACCESS_TRANSFER_WRITE_BIT,
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,
@ -378,26 +395,30 @@ void RendererVulkan::UpdateTexture(std::shared_ptr<void> impl_data,
semaphore_.Release();
}
void RendererVulkan::DestroyTexture(std::shared_ptr<void> impl_data) {
auto texture = reinterpret_cast<TextureVulkan*>(impl_data.get());
FreeTexture(std::move(texture->image), texture->view,
std::move(texture->desc_set));
*texture = {};
void RendererVulkan::DestroyTexture(uint64_t resource_id) {
auto it = textures_.find(resource_id);
if (it == textures_.end())
return;
FreeTexture(std::move(it->second.image), it->second.view,
std::move(it->second.desc_set));
textures_.erase(it);
}
void RendererVulkan::ActivateTexture(std::shared_ptr<void> impl_data) {
auto texture = reinterpret_cast<TextureVulkan*>(impl_data.get());
void RendererVulkan::ActivateTexture(uint64_t resource_id) {
auto it = textures_.find(resource_id);
if (it == textures_.end())
return;
// Keep as pengind and bind later in ActivateShader.
penging_descriptor_sets_[/*TODO*/ 0] = std::get<0>(texture->desc_set);
penging_descriptor_sets_[/*TODO*/ 0] = std::get<0>(it->second.desc_set);
}
void RendererVulkan::CreateShader(std::shared_ptr<void> impl_data,
uint64_t RendererVulkan::CreateShader(
std::unique_ptr<ShaderSource> source,
const VertexDescripton& vertex_description,
Primitive primitive,
bool enable_depth_test) {
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
auto it = spirv_cache_.find(source->name());
if (it == spirv_cache_.end()) {
std::array<std::vector<uint8_t>, 2> spirv;
@ -426,7 +447,7 @@ void RendererVulkan::CreateShader(std::shared_ptr<void> impl_data,
if (vkCreateShaderModule(device_, &shader_module_info, nullptr,
&vert_shader_module) != VK_SUCCESS) {
DLOG << "vkCreateShaderModule failed!";
return;
return 0;
}
}
@ -441,12 +462,14 @@ void RendererVulkan::CreateShader(std::shared_ptr<void> impl_data,
if (vkCreateShaderModule(device_, &shader_module_info, nullptr,
&frag_shader_module) != VK_SUCCESS) {
DLOG << "vkCreateShaderModule failed!";
return;
return 0;
}
}
auto& shader = shaders_[++last_resource_id_] = {};
if (!CreatePipelineLayout(shader, spirv_vertex, spirv_fragment))
return;
DLOG << "Failed to create pipeline layout!";
VkPipelineShaderStageCreateInfo vert_shader_stage_info{};
vert_shader_stage_info.sType =
@ -567,97 +590,125 @@ void RendererVulkan::CreateShader(std::shared_ptr<void> impl_data,
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 = shader.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, &shader.pipeline) != VK_SUCCESS)
DLOG << "failed to create graphics pipeline.";
vkDestroyShaderModule(device_, frag_shader_module, nullptr);
vkDestroyShaderModule(device_, vert_shader_module, nullptr);
return last_resource_id_;
}
void RendererVulkan::DestroyShader(std::shared_ptr<void> impl_data) {
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
void RendererVulkan::DestroyShader(uint64_t resource_id) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
frames_[current_frame_].pipelines_to_destroy.push_back(
std::make_tuple(shader->pipeline, shader->pipeline_layout));
*shader = {};
std::make_tuple(it->second.pipeline, it->second.pipeline_layout));
shaders_.erase(it);
}
void RendererVulkan::ActivateShader(std::shared_ptr<void> impl_data) {
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
if (active_pipeline_ != shader->pipeline) {
active_pipeline_ = shader->pipeline;
void RendererVulkan::ActivateShader(uint64_t resource_id) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
if (active_pipeline_ != it->second.pipeline) {
active_pipeline_ = it->second.pipeline;
vkCmdBindPipeline(frames_[current_frame_].draw_command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS, shader->pipeline);
VK_PIPELINE_BIND_POINT_GRAPHICS, it->second.pipeline);
}
for (int i = 0; i < shader->desc_set_count; ++i) {
for (int i = 0; i < it->second.desc_set_count; ++i) {
if (active_descriptor_sets_[i] != penging_descriptor_sets_[i]) {
active_descriptor_sets_[i] = penging_descriptor_sets_[i];
vkCmdBindDescriptorSets(frames_[current_frame_].draw_command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
shader->pipeline_layout, 0, 1,
it->second.pipeline_layout, 0, 1,
&active_descriptor_sets_[i], 0, nullptr);
break;
}
}
}
void RendererVulkan::SetUniform(std::shared_ptr<void> impl_data,
void RendererVulkan::SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector2f& val) {
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
SetUniformInternal(shader, name, val);
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
SetUniformInternal(it->second, name, val);
}
void RendererVulkan::SetUniform(std::shared_ptr<void> impl_data,
void RendererVulkan::SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector3f& val) {
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
SetUniformInternal(shader, name, val);
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
SetUniformInternal(it->second, name, val);
}
void RendererVulkan::SetUniform(std::shared_ptr<void> impl_data,
void RendererVulkan::SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector4f& val) {
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
SetUniformInternal(shader, name, val);
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
SetUniformInternal(it->second, name, val);
}
void RendererVulkan::SetUniform(std::shared_ptr<void> impl_data,
void RendererVulkan::SetUniform(uint64_t resource_id,
const std::string& name,
const base::Matrix4f& val) {
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
SetUniformInternal(shader, name, val);
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
SetUniformInternal(it->second, name, val);
}
void RendererVulkan::SetUniform(std::shared_ptr<void> impl_data,
void RendererVulkan::SetUniform(uint64_t resource_id,
const std::string& name,
float val) {
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
SetUniformInternal(shader, name, val);
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
SetUniformInternal(it->second, name, val);
}
void RendererVulkan::SetUniform(std::shared_ptr<void> impl_data,
void RendererVulkan::SetUniform(uint64_t resource_id,
const std::string& name,
int val) {
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
for (auto& sampler_name : shader->sampler_uniform_names) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
for (auto& sampler_name : it->second.sampler_uniform_names) {
if (name == sampler_name)
return;
}
SetUniformInternal(shader, name, val);
SetUniformInternal(it->second, name, val);
}
void RendererVulkan::UploadUniforms(std::shared_ptr<void> impl_data) {
auto shader = reinterpret_cast<ShaderVulkan*>(impl_data.get());
void RendererVulkan::UploadUniforms(uint64_t resource_id) {
auto it = shaders_.find(resource_id);
if (it == shaders_.end())
return;
vkCmdPushConstants(
frames_[current_frame_].draw_command_buffer, shader->pipeline_layout,
frames_[current_frame_].draw_command_buffer, it->second.pipeline_layout,
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0,
shader->push_constants_size, shader->push_constants.get());
it->second.push_constants_size, it->second.push_constants.get());
}
void RendererVulkan::PrepareForDrawing() {
@ -818,7 +869,7 @@ void RendererVulkan::Shutdown() {
return;
LOG << "Shutting down renderer.";
InvalidateAllResources();
DestroyAllResources();
quit_.store(true, std::memory_order_relaxed);
semaphore_.Release();
@ -1520,7 +1571,7 @@ void RendererVulkan::ImageMemoryBarrier(VkImage image,
}
bool RendererVulkan::CreatePipelineLayout(
ShaderVulkan* shader,
ShaderVulkan& shader,
const std::vector<uint8_t>& spirv_vertex,
const std::vector<uint8_t>& spirv_fragment) {
SpvReflectShaderModule module_vertex;
@ -1608,14 +1659,14 @@ bool RendererVulkan::CreatePipelineLayout(
break;
}
shader->sampler_uniform_names.push_back(binding.name);
shader->desc_set_count++;
shader.sampler_uniform_names.push_back(binding.name);
shader.desc_set_count++;
}
}
if (active_descriptor_sets_.size() < shader->desc_set_count) {
active_descriptor_sets_.resize(shader->desc_set_count);
penging_descriptor_sets_.resize(shader->desc_set_count);
if (active_descriptor_sets_.size() < shader.desc_set_count) {
active_descriptor_sets_.resize(shader.desc_set_count);
penging_descriptor_sets_.resize(shader.desc_set_count);
}
// Parse push constants.
@ -1679,10 +1730,10 @@ bool RendererVulkan::CreatePipelineLayout(
break;
}
shader->push_constants_size = pconstants_vertex[0]->size;
shader->push_constants =
std::make_unique<char[]>(shader->push_constants_size);
memset(shader->push_constants.get(), 0, shader->push_constants_size);
shader.push_constants_size = pconstants_vertex[0]->size;
shader.push_constants =
std::make_unique<char[]>(shader.push_constants_size);
memset(shader.push_constants.get(), 0, shader.push_constants_size);
size_t offset = 0;
for (uint32_t j = 0; j < pconstants_vertex[0]->member_count; j++) {
@ -1691,7 +1742,7 @@ bool RendererVulkan::CreatePipelineLayout(
<< " padded_size: "
<< pconstants_vertex[0]->members[j].padded_size;
shader->variables[pconstants_vertex[0]->members[j].name] = {
shader.variables[pconstants_vertex[0]->members[j].name] = {
pconstants_vertex[0]->members[j].size, offset};
offset += pconstants_vertex[0]->members[j].padded_size;
}
@ -1716,11 +1767,11 @@ bool RendererVulkan::CreatePipelineLayout(
}
VkPushConstantRange push_constant_range;
if (shader->push_constants_size) {
if (shader.push_constants_size) {
push_constant_range.stageFlags =
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
push_constant_range.offset = 0;
push_constant_range.size = shader->push_constants_size;
push_constant_range.size = shader.push_constants_size;
pipeline_layout_create_info.pushConstantRangeCount = 1;
pipeline_layout_create_info.pPushConstantRanges = &push_constant_range;
@ -1730,7 +1781,7 @@ bool RendererVulkan::CreatePipelineLayout(
}
if (vkCreatePipelineLayout(device_, &pipeline_layout_create_info, nullptr,
&shader->pipeline_layout) != VK_SUCCESS) {
&shader.pipeline_layout) != VK_SUCCESS) {
DLOG << "Failed to create pipeline layout!";
break;
}
@ -1855,11 +1906,11 @@ void RendererVulkan::SetupThreadMain(int preallocate) {
}
template <typename T>
bool RendererVulkan::SetUniformInternal(ShaderVulkan* shader,
bool RendererVulkan::SetUniformInternal(ShaderVulkan& shader,
const std::string& name,
T val) {
auto it = shader->variables.find(name);
if (it == shader->variables.end()) {
auto it = shader.variables.find(name);
if (it == shader.variables.end()) {
DLOG << "No variable found with name " << name;
return false;
}
@ -1868,8 +1919,7 @@ bool RendererVulkan::SetUniformInternal(ShaderVulkan* shader,
return false;
}
auto* dst =
reinterpret_cast<T*>(shader->push_constants.get() + it->second[1]);
auto* dst = reinterpret_cast<T*>(shader.push_constants.get() + it->second[1]);
*dst = val;
return true;
}
@ -1881,39 +1931,32 @@ bool RendererVulkan::IsFormatSupported(VkFormat format) {
return properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
}
std::unique_ptr<RenderResource> RendererVulkan::CreateResource(
RenderResourceFactoryBase& factory) {
static unsigned last_id = 0;
std::shared_ptr<void> impl_data;
if (factory.IsTypeOf<Geometry>())
impl_data = std::make_shared<GeometryVulkan>();
else if (factory.IsTypeOf<Shader>())
impl_data = std::make_shared<ShaderVulkan>();
else if (factory.IsTypeOf<Texture>())
impl_data = std::make_shared<TextureVulkan>();
else
NOTREACHED << "- Unknown resource type.";
unsigned resource_id = ++last_id;
auto resource = factory.Create(resource_id, impl_data, this);
resources_[resource_id] = resource.get();
return resource;
}
void RendererVulkan::ReleaseResource(unsigned resource_id) {
auto it = resources_.find(resource_id);
if (it != resources_.end())
resources_.erase(it);
}
size_t RendererVulkan::GetAndResetFPS() {
return context_.GetAndResetFPS();
}
void RendererVulkan::InvalidateAllResources() {
for (auto& r : resources_)
r.second->Destroy();
void RendererVulkan::DestroyAllResources() {
std::vector<uint64_t> resource_ids;
for (auto& r : geometries_)
resource_ids.push_back(r.first);
for (auto& r : resource_ids)
DestroyGeometry(r);
resource_ids.clear();
for (auto& r : shaders_)
resource_ids.push_back(r.first);
for (auto& r : resource_ids)
DestroyShader(r);
resource_ids.clear();
for (auto& r : textures_)
resource_ids.push_back(r.first);
for (auto& r : resource_ids)
DestroyTexture(r);
DCHECK(geometries_.size() == 0);
DCHECK(shaders_.size() == 0);
DCHECK(textures_.size() == 0);
}
} // namespace eng

View File

@ -13,7 +13,6 @@
#include "../../../base/semaphore.h"
#include "../../../base/task_runner.h"
#include "../../../third_party/vma/vk_mem_alloc.h"
#include "../render_resource.h"
#include "../renderer.h"
namespace eng {
@ -33,51 +32,46 @@ class RendererVulkan : public Renderer {
void Shutdown() override;
void CreateGeometry(std::shared_ptr<void> impl_data,
std::unique_ptr<Mesh> mesh) override;
void DestroyGeometry(std::shared_ptr<void> impl_data) override;
void Draw(std::shared_ptr<void> impl_data) override;
uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) override;
void DestroyGeometry(uint64_t resource_id) override;
void Draw(uint64_t resource_id) override;
void UpdateTexture(std::shared_ptr<void> impl_data,
uint64_t CreateTexture() override;
void UpdateTexture(uint64_t resource_id,
std::unique_ptr<Image> image) override;
void DestroyTexture(std::shared_ptr<void> impl_data) override;
void ActivateTexture(std::shared_ptr<void> impl_data) override;
void DestroyTexture(uint64_t resource_id) override;
void ActivateTexture(uint64_t resource_id) override;
void CreateShader(std::shared_ptr<void> impl_data,
std::unique_ptr<ShaderSource> source,
uint64_t CreateShader(std::unique_ptr<ShaderSource> source,
const VertexDescripton& vertex_description,
Primitive primitive,
bool enable_depth_test) override;
void DestroyShader(std::shared_ptr<void> impl_data) override;
void ActivateShader(std::shared_ptr<void> impl_data) override;
void DestroyShader(uint64_t resource_id) override;
void ActivateShader(uint64_t resource_id) override;
void SetUniform(std::shared_ptr<void> impl_data,
void SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector2f& val) override;
void SetUniform(std::shared_ptr<void> impl_data,
void SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector3f& val) override;
void SetUniform(std::shared_ptr<void> impl_data,
void SetUniform(uint64_t resource_id,
const std::string& name,
const base::Vector4f& val) override;
void SetUniform(std::shared_ptr<void> impl_data,
void SetUniform(uint64_t resource_id,
const std::string& name,
const base::Matrix4f& val) override;
void SetUniform(std::shared_ptr<void> impl_data,
void SetUniform(uint64_t resource_id,
const std::string& name,
float val) override;
void SetUniform(std::shared_ptr<void> impl_data,
void SetUniform(uint64_t resource_id,
const std::string& name,
int val) override;
void UploadUniforms(std::shared_ptr<void> impl_data) override;
void UploadUniforms(uint64_t resource_id) override;
void PrepareForDrawing() override;
void Present() override;
std::unique_ptr<RenderResource> CreateResource(
RenderResourceFactoryBase& factory) override;
void ReleaseResource(unsigned resource_id) override;
size_t GetAndResetFPS() override;
#if defined(__linux__) && !defined(__ANDROID__)
@ -155,6 +149,11 @@ class RendererVulkan : 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;
VulkanContext context_;
VmaAllocator allocator_ = nullptr;
@ -179,8 +178,6 @@ class RendererVulkan : public Renderer {
VkSampler sampler_ = VK_NULL_HANDLE;
std::unordered_map<unsigned, RenderResource*> resources_;
std::thread setup_thread_;
base::TaskRunner task_runner_;
base::Semaphore semaphore_;
@ -250,7 +247,7 @@ class RendererVulkan : public Renderer {
VkImageLayout old_layout,
VkImageLayout new_layout);
bool CreatePipelineLayout(ShaderVulkan* shader,
bool CreatePipelineLayout(ShaderVulkan& shader,
const std::vector<uint8_t>& spirv_vertex,
const std::vector<uint8_t>& spirv_fragment);
@ -262,11 +259,11 @@ class RendererVulkan : public Renderer {
void SetupThreadMain(int preallocate);
template <typename T>
bool SetUniformInternal(ShaderVulkan* shader, const std::string& name, T val);
bool SetUniformInternal(ShaderVulkan& shader, const std::string& name, T val);
bool IsFormatSupported(VkFormat format);
void InvalidateAllResources();
void DestroyAllResources();
};
} // namespace eng