From 8a8cce8ef4ee28b3572a72958b8b407759f9f826 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 17 Nov 2021 15:39:01 +0200 Subject: [PATCH] Add support for padding in vertex formats Vulkan requires attributes to be correctly aligned, so depending on the combination of types padding may be necessary. It's better to make it explicit so support for raw mesh data files can be added in the future. --- .../backends/opengl/vertexsetup_backend.cpp | 63 ++++++++++--------- source/builders/vertexarraybuilder.cpp | 10 +-- source/core/vertexformat.cpp | 3 +- source/core/vertexformat.h | 7 +++ source/core/vertexsetup.cpp | 2 +- 5 files changed, 49 insertions(+), 36 deletions(-) diff --git a/source/backends/opengl/vertexsetup_backend.cpp b/source/backends/opengl/vertexsetup_backend.cpp index acd14f48..d45481f9 100644 --- a/source/backends/opengl/vertexsetup_backend.cpp +++ b/source/backends/opengl/vertexsetup_backend.cpp @@ -87,27 +87,30 @@ void OpenGLVertexSetup::update_vertex_array(const VertexArray &array, unsigned b for(VertexAttribute a: fmt) { unsigned sem = get_attribute_semantic(a); - bool integer = is_integer_attribute(a); - GLenum type = get_gl_type(get_attribute_source_type(a)); - unsigned cc = get_attribute_component_count(a); - if(direct) - { - if(integer) - glVertexArrayAttribIFormat(id, sem, cc, type, offset); - else - glVertexArrayAttribFormat(id, sem, cc, type, true, offset); - glVertexArrayAttribBinding(id, sem, binding); - glEnableVertexArrayAttrib(id, sem); - } - else + if(!is_padding(a)) { - if(integer) - glVertexAttribIPointer(sem, cc, type, stride, reinterpret_cast(offset)); + bool integer = is_integer_attribute(a); + GLenum type = get_gl_type(get_attribute_source_type(a)); + unsigned cc = get_attribute_component_count(a); + if(direct) + { + if(integer) + glVertexArrayAttribIFormat(id, sem, cc, type, offset); + else + glVertexArrayAttribFormat(id, sem, cc, type, true, offset); + glVertexArrayAttribBinding(id, sem, binding); + glEnableVertexArrayAttrib(id, sem); + } else - glVertexAttribPointer(sem, cc, type, true, stride, reinterpret_cast(offset)); - if(ARB_instanced_arrays) - glVertexAttribDivisor(sem, divisor); - glEnableVertexAttribArray(sem); + { + if(integer) + glVertexAttribIPointer(sem, cc, type, stride, reinterpret_cast(offset)); + else + glVertexAttribPointer(sem, cc, type, true, stride, reinterpret_cast(offset)); + if(ARB_instanced_arrays) + glVertexAttribDivisor(sem, divisor); + glEnableVertexAttribArray(sem); + } } offset += get_attribute_size(a); } @@ -130,17 +133,19 @@ void OpenGLVertexSetup::unload() glBindBuffer(GL_ARRAY_BUFFER, 0); for(VertexAttribute a: static_cast(this)->vertex_format) - { - unsigned sem = get_attribute_semantic(a); - glDisableVertexAttribArray(sem); - glVertexAttribPointer(sem, 1, GL_FLOAT, false, 0, 0); - } + if(!is_padding(a)) + { + unsigned sem = get_attribute_semantic(a); + glDisableVertexAttribArray(sem); + glVertexAttribPointer(sem, 1, GL_FLOAT, false, 0, 0); + } for(VertexAttribute a: static_cast(this)->inst_format) - { - unsigned sem = get_attribute_semantic(a); - glDisableVertexAttribArray(sem); - glVertexAttribPointer(sem, 1, GL_FLOAT, false, 0, 0); - } + if(!is_padding(a)) + { + unsigned sem = get_attribute_semantic(a); + glDisableVertexAttribArray(sem); + glVertexAttribPointer(sem, 1, GL_FLOAT, false, 0, 0); + } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } diff --git a/source/builders/vertexarraybuilder.cpp b/source/builders/vertexarraybuilder.cpp index c9a1f3bc..00ff0012 100644 --- a/source/builders/vertexarraybuilder.cpp +++ b/source/builders/vertexarraybuilder.cpp @@ -16,12 +16,12 @@ void VertexArrayBuilder::vertex_(const Vector4 &vtx) for(VertexAttribute a: array.get_format()) { unsigned sem = get_attribute_semantic(a); - bool integer = is_integer_attribute(a); - DataType type = get_attribute_source_type(a); - unsigned cc = get_attribute_component_count(a); - - if(sem(ptr, value, !integer, cc); diff --git a/source/core/vertexformat.cpp b/source/core/vertexformat.cpp index ff043f7d..3db7542f 100644 --- a/source/core/vertexformat.cpp +++ b/source/core/vertexformat.cpp @@ -188,7 +188,8 @@ void operator>>(const LexicalConverter &conv, VertexAttribute &a) convert_attribute(str, "GROUP", 1, 4, a, GROUP1) || convert_attribute(str, "WEIGHT", 1, 4, a, WEIGHT1) || convert_attribute(str, "TEXCOORD", 1, 4, a, TEXCOORD1) || - convert_attribute(str, "GENERIC", 1, 4, a, GENERIC1)) + convert_attribute(str, "GENERIC", 1, 4, a, GENERIC1) || + convert_attribute(str, "PADDING", 1, 4, a, PADDING1)) return; } catch(...) diff --git a/source/core/vertexformat.h b/source/core/vertexformat.h index 64c89e13..fba206e4 100644 --- a/source/core/vertexformat.h +++ b/source/core/vertexformat.h @@ -61,6 +61,10 @@ enum VertexAttribute: std::uint16_t GENERIC_I2 = 0x28CA, GENERIC_I3 = 0x28CB, GENERIC_I4 = 0x28CC, + PADDING1 = 0xF811, + PADDING2 = 0xF812, + PADDING3 = 0xF813, + PADDING4 = 0xF814, RAW_ATTRIB1 = 0xFDC1, RAW_ATTRIB2 = 0xFDC2, RAW_ATTRIB3 = 0xFDC3, @@ -134,6 +138,9 @@ inline unsigned get_attribute_size(VertexAttribute a) inline bool is_integer_attribute(VertexAttribute a) { return a&8; } +inline bool is_padding(VertexAttribute a) +{ return get_attribute_semantic(a)==get_attribute_semantic(PADDING1); } + void operator>>(const LexicalConverter &, VertexAttribute &); } // namespace GL diff --git a/source/core/vertexsetup.cpp b/source/core/vertexsetup.cpp index 61bf032c..2994916e 100644 --- a/source/core/vertexsetup.cpp +++ b/source/core/vertexsetup.cpp @@ -73,7 +73,7 @@ bool VertexSetup::verify_format(const VertexFormat &fmt) return false; static unsigned max_attribs = Device::get_current().get_info().limits.max_vertex_attributes; - return all_of(fmt.begin(), fmt.end(), [](VertexAttribute a){ return get_attribute_semantic(a)