Add Renderer::UpdateGeometry()

Also add its implementations in Vulkan and OpenGL renderers. Use it in
ImguiBackend instead of recreating geometry buffers every frame.
This commit is contained in:
Attila Uygun 2023-10-31 21:40:07 +01:00
parent a02d1ba71e
commit a17039d87b
10 changed files with 249 additions and 61 deletions

View File

@ -139,28 +139,16 @@ bool Mesh::Load(const std::string& file_name) {
} }
} }
} }
// TODO: Load indices
return true; return true;
} }
size_t Mesh::GetVertexSize() const { size_t Mesh::GetVertexSize() const {
unsigned int size = 0; return eng::GetVertexSize(vertex_description_);
for (auto& attr : vertex_description_) {
size += std::get<2>(attr) * std::get<3>(attr);
}
return size;
} }
size_t Mesh::GetIndexSize() const { size_t Mesh::GetIndexSize() const {
switch (index_description_) { return eng::GetIndexSize(index_description_);
case kDataType_Byte:
return sizeof(char);
case kDataType_UShort:
return sizeof(unsigned short);
case kDataType_UInt:
return sizeof(unsigned int);
default:
return 0;
}
} }
} // namespace eng } // namespace eng

View File

@ -144,6 +144,105 @@ void Engine::Update(float delta_time) {
if (stats_visible_) if (stats_visible_)
ShowStats(); ShowStats();
ImGui::ShowDemoWindow();
#if 0
// ImVec2 center = ImGui::GetMainViewport()->GetCenter();
// ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always, ImVec2(0, 0));
static ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings;
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
ImGui::Begin("Stats", nullptr, window_flags);
static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
// // PushStyleCompact();
// ImGuiStyle& style = ImGui::GetStyle();
// ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(style.FramePadding.x, (float)(int)(style.FramePadding.y * 0.60f)));
// ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x, (float)(int)(style.ItemSpacing.y * 0.60f)));
// ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
// // PopStyleCompact();
// ImGui::PopStyleVar(2);
// When using ScrollX or ScrollY we need to specify a size for our table container!
// Otherwise by default the table will fit all available space, like a BeginChild() call.
// ImVec2 outer_size = ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 8);
if (ImGui::BeginTable("table_scrolly", 3, flags))
{
ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible
ImGui::TableSetupColumn("One", ImGuiTableColumnFlags_None);
ImGui::TableSetupColumn("Two", ImGuiTableColumnFlags_None);
ImGui::TableSetupColumn("Three", ImGuiTableColumnFlags_None);
ImGui::TableHeadersRow();
// Demonstrate using clipper for large vertical lists
ImGuiListClipper clipper;
clipper.Begin(1000);
while (clipper.Step())
{
for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++)
{
ImGui::TableNextRow();
// ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap;
for (int column = 0; column < 3; column++)
{
char buf[32];
sprintf(buf, "Hello %d,%d", column, row);
ImGui::TableSetColumnIndex(column);
ImGui::Selectable(buf, false, ImGuiSelectableFlags_SpanAllColumns);
// ImGui::Text("Hello %d,%d", column, row);
}
// static int row_bg_target = 1;
// static int row_bg_type = 1;
// if (ImGui::TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered) {
// ImU32 row_bg_color = ImGui::GetColorU32(row_bg_type == 1 ? ImVec4(0.7f, 0.3f, 0.3f, 0.65f) : ImVec4(0.2f + row * 0.1f, 0.2f, 0.2f, 0.65f)); // Flat or Gradient?
// ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0 + row_bg_target, row_bg_color);
// // ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, IM_COL32(0, 100, 0, 255));
// }
}
}
ImGui::EndTable();
}
ImGui::End();
#else
{
bool show_app_fullscreen = false;
static bool use_work_area = true;
static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings;
// We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.)
// Based on your use case you may want one or the other.
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos);
ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size);
if (ImGui::Begin("Example: Fullscreen window", &show_app_fullscreen, flags))
{
ImGui::Checkbox("Use work area instead of main area", &use_work_area);
ImGui::SameLine();
// HelpMarker("Main Area = entire viewport,\nWork Area = entire viewport minus sections used by the main menu bars, task bars etc.\n\nEnable the main-menu bar in Examples menu to see the difference.");
ImGui::CheckboxFlags("ImGuiWindowFlags_NoBackground", &flags, ImGuiWindowFlags_NoBackground);
ImGui::CheckboxFlags("ImGuiWindowFlags_NoDecoration", &flags, ImGuiWindowFlags_NoDecoration);
ImGui::Indent();
ImGui::CheckboxFlags("ImGuiWindowFlags_NoTitleBar", &flags, ImGuiWindowFlags_NoTitleBar);
ImGui::CheckboxFlags("ImGuiWindowFlags_NoCollapse", &flags, ImGuiWindowFlags_NoCollapse);
ImGui::CheckboxFlags("ImGuiWindowFlags_NoScrollbar", &flags, ImGuiWindowFlags_NoScrollbar);
ImGui::Unindent();
if (ImGui::Button("Close this window"))
show_app_fullscreen = false;
}
ImGui::End();
}
#endif
imgui_backend_.Render(); imgui_backend_.Render();
} }

View File

@ -68,6 +68,9 @@ void ImguiBackend::Initialize() {
} }
void ImguiBackend::Shutdown() { void ImguiBackend::Shutdown() {
for (auto& id : geometries_)
renderer_->DestroyGeometry(id);
geometries_.clear();
ImGui::DestroyContext(); ImGui::DestroyContext();
shader_.reset(); shader_.reset();
} }
@ -75,6 +78,7 @@ void ImguiBackend::Shutdown() {
void ImguiBackend::CreateRenderResources(Renderer* renderer) { void ImguiBackend::CreateRenderResources(Renderer* renderer) {
renderer_ = renderer; renderer_ = renderer;
shader_->SetRenderer(renderer); shader_->SetRenderer(renderer);
geometries_.clear();
auto source = std::make_unique<ShaderSource>(); auto source = std::make_unique<ShaderSource>();
if (source->Load("engine/imgui.glsl")) { if (source->Load("engine/imgui.glsl")) {
@ -115,10 +119,6 @@ std::unique_ptr<InputEvent> ImguiBackend::OnInputEvent(
} }
void ImguiBackend::NewFrame(float delta_time) { void ImguiBackend::NewFrame(float delta_time) {
for (auto& id : geometries_)
renderer_->DestroyGeometry(id);
geometries_.clear();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.DisplaySize = ImVec2((float)renderer_->GetScreenWidth(), io.DisplaySize = ImVec2((float)renderer_->GetScreenWidth(),
(float)renderer_->GetScreenHeight()); (float)renderer_->GetScreenHeight());
@ -129,7 +129,8 @@ void ImguiBackend::NewFrame(float delta_time) {
void ImguiBackend::Render() { void ImguiBackend::Render() {
ImGui::Render(); ImGui::Render();
ImDrawData* draw_data = ImGui::GetDrawData(); ImDrawData* draw_data = ImGui::GetDrawData();
geometries_.resize(draw_data->CmdListsCount); if (geometries_.size() < draw_data->CmdListsCount)
geometries_.resize(draw_data->CmdListsCount, 0);
for (int n = 0; n < draw_data->CmdListsCount; n++) { for (int n = 0; n < draw_data->CmdListsCount; n++) {
const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n];
auto mesh = std::make_unique<Mesh>(); auto mesh = std::make_unique<Mesh>();
@ -137,7 +138,11 @@ void ImguiBackend::Render() {
cmd_list->VtxBuffer.Size, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size, cmd_list->VtxBuffer.Data,
kDataType_UShort, cmd_list->IdxBuffer.Size, kDataType_UShort, cmd_list->IdxBuffer.Size,
cmd_list->IdxBuffer.Data); cmd_list->IdxBuffer.Data);
geometries_[n] = renderer_->CreateGeometry(std::move(mesh)); if (geometries_[n] == 0)
geometries_[n] = renderer_->CreateGeometry(mesh->primitive(),
mesh->vertex_description(),
mesh->index_description());
renderer_->UpdateGeometry(geometries_[n], std::move(mesh));
} }
} }

View File

@ -72,11 +72,21 @@ void RendererOpenGL::ResetScissor() {
} }
uint64_t RendererOpenGL::CreateGeometry(std::unique_ptr<Mesh> mesh) { uint64_t RendererOpenGL::CreateGeometry(std::unique_ptr<Mesh> mesh) {
auto id = CreateGeometry(mesh->primitive(), mesh->vertex_description(),
mesh->index_description());
if (id != kInvalidId)
UpdateGeometry(id, std::move(mesh));
return id;
}
uint64_t 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. // Verify that we have a valid layout and get the total byte size per vertex.
GLuint vertex_size = mesh->GetVertexSize(); GLuint vertex_size = GetVertexSize(vertex_description);
if (!vertex_size) { if (!vertex_size) {
LOG(0) << "Invalid vertex layout"; LOG(0) << "Invalid vertex layout";
return 0; return kInvalidId;
} }
GLuint vertex_array_id = 0; GLuint vertex_array_id = 0;
@ -85,30 +95,25 @@ uint64_t RendererOpenGL::CreateGeometry(std::unique_ptr<Mesh> mesh) {
glBindVertexArray(vertex_array_id); glBindVertexArray(vertex_array_id);
} }
// Create the vertex buffer and upload the data. // Create the vertex buffer.
GLuint vertex_buffer_id = 0; GLuint vertex_buffer_id = 0;
glGenBuffers(1, &vertex_buffer_id); glGenBuffers(1, &vertex_buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id); glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id);
glBufferData(GL_ARRAY_BUFFER, mesh->num_vertices() * vertex_size,
mesh->GetVertices(), GL_STATIC_DRAW);
// Make sure the vertex format is understood and the attribute pointers are // Make sure the vertex format is understood and the attribute pointers are
// set up. // set up.
std::vector<GeometryOpenGL::Element> vertex_layout; std::vector<GeometryOpenGL::Element> vertex_layout;
if (!SetupVertexLayout(mesh->vertex_description(), vertex_size, if (!SetupVertexLayout(vertex_description, vertex_size, vertex_array_objects_,
vertex_array_objects_, vertex_layout)) { vertex_layout)) {
LOG(0) << "Invalid vertex layout"; LOG(0) << "Invalid vertex layout";
return 0; return kInvalidId;
} }
// Create the index buffer and upload the data. // Create the index buffer.
GLuint index_buffer_id = 0; GLuint index_buffer_id = 0;
if (mesh->GetIndices()) { if (index_description != kDataType_Invalid) {
glGenBuffers(1, &index_buffer_id); glGenBuffers(1, &index_buffer_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_id); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
mesh->num_indices() * mesh->GetIndexSize(), mesh->GetIndices(),
GL_STATIC_DRAW);
} }
if (vertex_array_id) { if (vertex_array_id) {
@ -121,10 +126,10 @@ uint64_t RendererOpenGL::CreateGeometry(std::unique_ptr<Mesh> mesh) {
} }
uint64_t resource_id = ++last_resource_id_; uint64_t resource_id = ++last_resource_id_;
geometries_[resource_id] = {(GLsizei)mesh->num_vertices(), geometries_[resource_id] = {0,
(GLsizei)mesh->num_indices(), 0,
kGlPrimitive[mesh->primitive()], kGlPrimitive[primitive],
kGlDataType[mesh->index_description()], kGlDataType[index_description],
vertex_layout, vertex_layout,
vertex_size, vertex_size,
vertex_array_id, vertex_array_id,
@ -133,6 +138,31 @@ uint64_t RendererOpenGL::CreateGeometry(std::unique_ptr<Mesh> mesh) {
return resource_id; return resource_id;
} }
void RendererOpenGL::UpdateGeometry(uint64_t resource_id,
std::unique_ptr<Mesh> mesh) {
auto it = geometries_.find(resource_id);
if (it == geometries_.end())
return;
// Go with GL_STATIC_DRAW for the first update.
GLenum usage = it->second.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, mesh->num_vertices() * it->second.vertex_size,
mesh->GetVertices(), usage);
it->second.num_vertices = (GLsizei)mesh->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,
mesh->num_indices() * mesh->GetIndexSize(), mesh->GetIndices(),
usage);
it->second.num_indices = (GLsizei)mesh->num_indices();
}
}
void RendererOpenGL::DestroyGeometry(uint64_t resource_id) { void RendererOpenGL::DestroyGeometry(uint64_t resource_id) {
auto it = geometries_.find(resource_id); auto it = geometries_.find(resource_id);
if (it == geometries_.end()) if (it == geometries_.end())

View File

@ -39,6 +39,10 @@ class RendererOpenGL final : public Renderer {
void ResetScissor() final; void ResetScissor() final;
uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) final; uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) final;
uint64_t CreateGeometry(Primitive primitive,
VertexDescription vertex_description,
DataType index_description = kDataType_Invalid) final;
void UpdateGeometry(uint64_t resource_id, std::unique_ptr<Mesh> mesh) final;
void DestroyGeometry(uint64_t resource_id) final; void DestroyGeometry(uint64_t resource_id) final;
void Draw(uint64_t resource_id, void Draw(uint64_t resource_id,
uint64_t num_indices = 0, uint64_t num_indices = 0,

View File

@ -46,6 +46,12 @@ class Renderer {
virtual void ResetScissor() = 0; virtual void ResetScissor() = 0;
virtual uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) = 0; virtual uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) = 0;
virtual uint64_t CreateGeometry(
Primitive primitive,
VertexDescription vertex_description,
DataType index_description = kDataType_Invalid) = 0;
virtual void UpdateGeometry(uint64_t resource_id,
std::unique_ptr<Mesh> mesh) = 0;
virtual void DestroyGeometry(uint64_t resource_id) = 0; virtual void DestroyGeometry(uint64_t resource_id) = 0;
virtual void Draw(uint64_t resource_id, virtual void Draw(uint64_t resource_id,
uint64_t num_indices = 0, uint64_t num_indices = 0,

View File

@ -14,6 +14,27 @@ const char kLayoutDelimiter[] = ";/ \t";
namespace eng { namespace eng {
size_t GetVertexSize(const VertexDescription& vertex_description) {
size_t size = 0;
for (auto& attr : vertex_description) {
size += std::get<2>(attr) * std::get<3>(attr);
}
return size;
}
size_t GetIndexSize(DataType index_description) {
switch (index_description) {
case kDataType_Byte:
return sizeof(char);
case kDataType_UShort:
return sizeof(unsigned short);
case kDataType_UInt:
return sizeof(unsigned int);
default:
return 0;
}
}
bool ParseVertexDescription(const std::string& vd_str, VertexDescription& out) { bool ParseVertexDescription(const std::string& vd_str, VertexDescription& out) {
// Parse the description. // Parse the description.
char buffer[32]; char buffer[32];

View File

@ -41,6 +41,9 @@ using DataTypeSize = size_t;
using VertexDescription = using VertexDescription =
std::vector<std::tuple<AttribType, DataType, ElementCount, DataTypeSize>>; std::vector<std::tuple<AttribType, DataType, ElementCount, DataTypeSize>>;
size_t GetVertexSize(const VertexDescription& vertex_description);
size_t GetIndexSize(DataType index_description);
bool ParseVertexDescription(const std::string& vd_str, VertexDescription& out); bool ParseVertexDescription(const std::string& vd_str, VertexDescription& out);
} // namespace eng } // namespace eng

View File

@ -307,6 +307,8 @@ VertexInputDescription GetVertexInputDescription(
VkIndexType GetIndexType(eng::DataType data_type) { VkIndexType GetIndexType(eng::DataType data_type) {
switch (data_type) { switch (data_type) {
case eng::kDataType_Invalid:
return VK_INDEX_TYPE_NONE_KHR;
case eng::kDataType_UInt: case eng::kDataType_UInt:
return VK_INDEX_TYPE_UINT32; return VK_INDEX_TYPE_UINT32;
case eng::kDataType_UShort: case eng::kDataType_UShort:
@ -315,7 +317,7 @@ VkIndexType GetIndexType(eng::DataType data_type) {
break; break;
} }
NOTREACHED() << "Invalid index type: " << data_type; NOTREACHED() << "Invalid index type: " << data_type;
return VK_INDEX_TYPE_UINT16; return VK_INDEX_TYPE_NONE_KHR;
} }
VkFormat GetImageFormat(eng::Image::Format format) { VkFormat GetImageFormat(eng::Image::Format format) {
@ -442,47 +444,71 @@ void RendererVulkan::ResetScissor() {
} }
uint64_t RendererVulkan::CreateGeometry(std::unique_ptr<Mesh> mesh) { uint64_t RendererVulkan::CreateGeometry(std::unique_ptr<Mesh> mesh) {
auto& geometry = geometries_[++last_resource_id_] = {}; auto id = CreateGeometry(mesh->primitive(), mesh->vertex_description(),
mesh->index_description());
if (id != kInvalidId)
UpdateGeometry(id, std::move(mesh));
return id;
}
geometry.num_vertices = mesh->num_vertices(); uint64_t RendererVulkan::CreateGeometry(Primitive primitive,
size_t vertex_data_size = mesh->GetVertexSize() * geometry.num_vertices; 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_;
}
void RendererVulkan::UpdateGeometry(uint64_t resource_id,
std::unique_ptr<Mesh> mesh) {
auto it = geometries_.find(resource_id);
if (it == geometries_.end())
return;
it->second.num_vertices = mesh->num_vertices();
size_t vertex_data_size = it->second.vertex_size * it->second.num_vertices;
size_t index_data_size = 0; size_t index_data_size = 0;
if (mesh->GetIndices()) { if (mesh->GetIndices()) {
geometry.num_indices = mesh->num_indices(); DCHECK(it->second.index_type != VK_INDEX_TYPE_NONE_KHR);
geometry.index_type = GetIndexType(mesh->index_description()); it->second.num_indices = mesh->num_indices();
geometry.index_type_size = mesh->GetIndexSize(); index_data_size = it->second.index_type_size * it->second.num_indices;
index_data_size = geometry.index_type_size * geometry.num_indices;
} }
size_t data_size = vertex_data_size + index_data_size;
AllocateBuffer(geometry.buffer, data_size, size_t data_size = vertex_data_size + index_data_size;
if (it->second.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,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VMA_MEMORY_USAGE_GPU_ONLY); VMA_MEMORY_USAGE_GPU_ONLY);
it->second.buffer_size = data_size;
}
task_runner_.PostTask(HERE, std::bind(&RendererVulkan::UpdateBuffer, this, task_runner_.PostTask(HERE, std::bind(&RendererVulkan::UpdateBuffer, this,
std::get<0>(geometry.buffer), 0, std::get<0>(it->second.buffer), 0,
mesh->GetVertices(), vertex_data_size)); mesh->GetVertices(), vertex_data_size));
if (geometry.num_indices > 0) { if (it->second.num_indices > 0) {
geometry.index_data_offset = vertex_data_size; it->second.index_data_offset = vertex_data_size;
task_runner_.PostTask(HERE, std::bind(&RendererVulkan::UpdateBuffer, this, task_runner_.PostTask(HERE, std::bind(&RendererVulkan::UpdateBuffer, this,
std::get<0>(geometry.buffer), std::get<0>(it->second.buffer),
geometry.index_data_offset, it->second.index_data_offset,
mesh->GetIndices(), index_data_size)); mesh->GetIndices(), index_data_size));
} }
task_runner_.PostTask(HERE, task_runner_.PostTask(HERE,
std::bind(&RendererVulkan::BufferMemoryBarrier, this, std::bind(&RendererVulkan::BufferMemoryBarrier, this,
std::get<0>(geometry.buffer), 0, data_size, std::get<0>(it->second.buffer), 0, data_size,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT)); VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT));
task_runner_.Delete(HERE, std::move(mesh)); task_runner_.Delete(HERE, std::move(mesh));
semaphore_.release(); semaphore_.release();
return last_resource_id_;
} }
void RendererVulkan::DestroyGeometry(uint64_t resource_id) { void RendererVulkan::DestroyGeometry(uint64_t resource_id) {

View File

@ -40,6 +40,10 @@ class RendererVulkan final : public Renderer {
void ResetScissor() final; void ResetScissor() final;
uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) final; uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) final;
uint64_t CreateGeometry(Primitive primitive,
VertexDescription vertex_description,
DataType index_description = kDataType_Invalid) final;
void UpdateGeometry(uint64_t resource_id, std::unique_ptr<Mesh> mesh) final;
void DestroyGeometry(uint64_t resource_id) final; void DestroyGeometry(uint64_t resource_id) final;
void Draw(uint64_t resource_id, void Draw(uint64_t resource_id,
uint64_t num_indices = 0, uint64_t num_indices = 0,
@ -107,11 +111,13 @@ class RendererVulkan final : public Renderer {
struct GeometryVulkan { struct GeometryVulkan {
Buffer<VkBuffer> buffer; Buffer<VkBuffer> buffer;
size_t buffer_size = 0;
uint32_t num_vertices = 0; uint32_t num_vertices = 0;
uint32_t num_indices = 0; uint32_t num_indices = 0;
size_t vertex_size = 0;
uint64_t index_data_offset = 0; uint64_t index_data_offset = 0;
uint64_t index_type_size = 0; uint64_t index_type_size = 0;
VkIndexType index_type = VK_INDEX_TYPE_UINT16; VkIndexType index_type = VK_INDEX_TYPE_NONE_KHR;
}; };
struct ShaderVulkan { struct ShaderVulkan {