Fix for index buffer

- Fix index data offset in Vulkan geometry buffer.
- Normalize vertex colors.
- Add support for drawing from a given index offset.
This commit is contained in:
Attila Uygun 2023-10-10 00:04:46 +02:00
parent 2823aa3197
commit 14b2d22fbd
5 changed files with 53 additions and 28 deletions

View File

@ -26,6 +26,9 @@ constexpr GLenum kGlDataType[eng::kDataType_Max] = {
GL_UNSIGNED_BYTE, GL_FLOAT, GL_INT,
GL_SHORT, GL_UNSIGNED_INT, GL_UNSIGNED_SHORT};
constexpr GLboolean kGlNormalize[eng::kDataType_Max] = {
GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE};
const std::string kAttributeNames[eng::kAttribType_Max] = {
"in_color", "in_normal", "in_position", "in_tex_coord"};
@ -132,11 +135,16 @@ void RendererOpenGL::DestroyGeometry(uint64_t resource_id) {
geometries_.erase(it);
}
void RendererOpenGL::Draw(uint64_t resource_id) {
void RendererOpenGL::Draw(uint64_t resource_id,
uint64_t num_indices,
uint64_t start_offset) {
auto it = geometries_.find(resource_id);
if (it == geometries_.end())
return;
if (num_indices == 0)
num_indices = it->second.num_indices;
// Set up the vertex data.
if (it->second.vertex_array_id)
glBindVertexArray(it->second.vertex_array_id);
@ -152,14 +160,14 @@ void RendererOpenGL::Draw(uint64_t resource_id) {
(const GLvoid*)e.vertex_offset);
}
if (it->second.num_indices > 0)
if (num_indices > 0)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, it->second.index_buffer_id);
}
// Draw the primitive.
if (it->second.num_indices > 0)
glDrawElements(it->second.primitive, it->second.num_indices,
it->second.index_type, NULL);
if (num_indices > 0)
glDrawElements(it->second.primitive, num_indices, it->second.index_type,
(void*)(intptr_t)(start_offset * sizeof(unsigned short)));
else
glDrawArrays(it->second.primitive, 0, it->second.num_vertices);
@ -446,7 +454,7 @@ bool RendererOpenGL::InitCommon() {
#if 0
LOG(0) << " extensions:";
for (auto& ext : extensions)
LOG(0) << " " << ext.c_str());
LOG(0) << " " << ext.c_str();
#endif
// Check for supported texture compression extensions.
@ -465,7 +473,8 @@ bool RendererOpenGL::InitCommon() {
extensions.find("GL_ATI_texture_compression_atitc") != extensions.end())
texture_compression_.atc = true;
if (extensions.find("GL_OES_vertex_array_object") != extensions.end()) {
if (extensions.find("GL_OES_vertex_array_object") != extensions.end() ||
extensions.find("GL_ARB_vertex_array_object") != extensions.end()) {
// This extension seems to be broken on older PowerVR drivers.
if (!strstr(renderer, "PowerVR SGX 53") &&
!strstr(renderer, "PowerVR SGX 54") &&
@ -555,8 +564,9 @@ bool RendererOpenGL::SetupVertexLayout(
if (use_vao) {
// This will be saved into the vertex array object.
glEnableVertexAttribArray(attribute_index);
glVertexAttribPointer(attribute_index, num_elements, type, GL_FALSE,
vertex_size, (const GLvoid*)vertex_offset);
glVertexAttribPointer(attribute_index, num_elements, type,
kGlNormalize[data_type], vertex_size,
(const GLvoid*)vertex_offset);
} else {
// Need to keep this information for when rendering.
GeometryOpenGL::Element element;

View File

@ -33,7 +33,9 @@ class RendererOpenGL final : public Renderer {
uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) final;
void DestroyGeometry(uint64_t resource_id) final;
void Draw(uint64_t resource_id) final;
void Draw(uint64_t resource_id,
uint64_t num_indices = 0,
uint64_t start_offset = 0) final;
uint64_t CreateTexture() final;
void UpdateTexture(uint64_t resource_id, std::unique_ptr<Image> image) final;

View File

@ -40,7 +40,9 @@ class Renderer {
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 Draw(uint64_t resource_id,
uint64_t num_indices = 0,
uint64_t start_offset = 0) = 0;
virtual uint64_t CreateTexture() = 0;
virtual void UpdateTexture(uint64_t resource_id,

View File

@ -155,10 +155,10 @@ constexpr VkPrimitiveTopology kVkPrimitiveType[eng::kPrimitive_Max] = {
constexpr VkFormat kVkDataType[eng::kDataType_Max][4] = {
{
VK_FORMAT_R8_UINT,
VK_FORMAT_R8G8_UINT,
VK_FORMAT_R8G8B8_UINT,
VK_FORMAT_R8G8B8A8_UINT,
VK_FORMAT_R8_UNORM,
VK_FORMAT_R8G8_UNORM,
VK_FORMAT_R8G8B8_UNORM,
VK_FORMAT_R8G8B8A8_UNORM,
},
{
VK_FORMAT_R32_SFLOAT,
@ -400,7 +400,8 @@ uint64_t RendererVulkan::CreateGeometry(std::unique_ptr<Mesh> mesh) {
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.index_type_size = mesh->GetIndexSize();
index_data_size = geometry.index_type_size * geometry.num_indices;
}
size_t data_size = vertex_data_size + index_data_size;
@ -414,10 +415,10 @@ uint64_t RendererVulkan::CreateGeometry(std::unique_ptr<Mesh> mesh) {
std::get<0>(geometry.buffer), 0,
mesh->GetVertices(), 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,
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,
mesh->GetIndices(), index_data_size));
}
task_runner_.PostTask(HERE,
@ -442,20 +443,27 @@ void RendererVulkan::DestroyGeometry(uint64_t resource_id) {
geometries_.erase(it);
}
void RendererVulkan::Draw(uint64_t resource_id) {
void RendererVulkan::Draw(uint64_t resource_id,
uint64_t num_indices,
uint64_t start_offset) {
auto it = geometries_.find(resource_id);
if (it == geometries_.end())
return;
uint64_t data_offset = start_offset * it->second.index_type_size;
if (num_indices == 0)
num_indices = it->second.num_indices;
VkDeviceSize offset = 0;
vkCmdBindVertexBuffers(frames_[current_frame_].draw_command_buffer, 0, 1,
&std::get<0>(it->second.buffer), &offset);
if (it->second.num_indices > 0) {
if (num_indices > 0) {
vkCmdBindIndexBuffer(frames_[current_frame_].draw_command_buffer,
std::get<0>(it->second.buffer),
it->second.indices_offset, it->second.index_type);
vkCmdDrawIndexed(frames_[current_frame_].draw_command_buffer,
it->second.num_indices, 1, 0, 0, 0);
it->second.index_data_offset + data_offset,
it->second.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);

View File

@ -35,7 +35,9 @@ class RendererVulkan final : public Renderer {
uint64_t CreateGeometry(std::unique_ptr<Mesh> mesh) final;
void DestroyGeometry(uint64_t resource_id) final;
void Draw(uint64_t resource_id) final;
void Draw(uint64_t resource_id,
uint64_t num_indices = 0,
uint64_t start_offset = 0) final;
uint64_t CreateTexture() final;
void UpdateTexture(uint64_t resource_id, std::unique_ptr<Image> image) final;
@ -101,7 +103,8 @@ class RendererVulkan final : public Renderer {
Buffer<VkBuffer> buffer;
uint32_t num_vertices = 0;
uint32_t num_indices = 0;
uint64_t indices_offset = 0;
uint64_t index_data_offset = 0;
uint64_t index_type_size = 0;
VkIndexType index_type = VK_INDEX_TYPE_UINT16;
};