From d40673bd28c4b4524d3642b949d9d109dc6f9f24 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 4 Aug 2021 20:58:42 +0300 Subject: [PATCH] Only allow VertexArray's format to be set once Also affects related classes like VertexSetup and Mesh. This will make state management with Vulkan easier. --- source/core/mesh.cpp | 38 ++++++++--- source/core/mesh.h | 6 +- source/core/vertexarray.cpp | 17 ++++- source/core/vertexarray.h | 10 ++- source/core/vertexsetup.cpp | 110 +++++++++++++++----------------- source/core/vertexsetup.h | 14 ++-- source/render/instancearray.cpp | 3 +- 7 files changed, 115 insertions(+), 83 deletions(-) diff --git a/source/core/mesh.cpp b/source/core/mesh.cpp index f63b3293..ea14d590 100644 --- a/source/core/mesh.cpp +++ b/source/core/mesh.cpp @@ -14,16 +14,15 @@ using namespace std; namespace Msp { namespace GL { -Mesh::Mesh(ResourceManager *rm): - vertices(VERTEX3) +Mesh::Mesh(ResourceManager *rm) { init(rm); } -Mesh::Mesh(const VertexFormat &f, ResourceManager *rm): - vertices(f) +Mesh::Mesh(const VertexFormat &f, ResourceManager *rm) { init(rm); + storage(f); } void Mesh::init(ResourceManager *rm) @@ -46,6 +45,15 @@ Mesh::~Mesh() delete ibuf; } +void Mesh::storage(const VertexFormat &fmt) +{ + if(!vertices.get_format().empty()) + throw invalid_operation("Mesh::storage"); + + vertices.set_format(fmt); + vtx_setup.set_format(fmt); +} + void Mesh::clear() { vertices.clear(); @@ -99,6 +107,8 @@ unsigned Mesh::get_n_vertices() const float *Mesh::modify_vertex(unsigned i) { + if(vertices.get_format().empty()) + throw invalid_operation("Mesh::modify_vertex"); return vertices.modify(i); } @@ -243,11 +253,13 @@ Mesh::Loader::Loader(Mesh &m, bool g): allow_gl_calls(g) { add("batch", &Loader::batch); + add("storage", &Loader::storage); add("vertices", &Loader::vertices); + add("vertices", &Loader::vertices_with_format); add("winding", &Loader::winding); } -void Mesh::Loader::vertices(const vector &a) +void Mesh::Loader::storage(const vector &a) { if(a.empty()) throw invalid_argument("No vertex attributes"); @@ -255,13 +267,20 @@ void Mesh::Loader::vertices(const vector &a) VertexFormat fmt; for(vector::const_iterator i=a.begin(); i!=a.end(); ++i) fmt = (fmt, *i); - obj.vertices.reset(fmt); + obj.storage(fmt); +} + +void Mesh::Loader::vertices() +{ load_sub(obj.vertices); if(allow_gl_calls) - { obj.check_buffers(VERTEX_BUFFER); - obj.vtx_setup.refresh(); - } +} + +void Mesh::Loader::vertices_with_format(const vector &a) +{ + storage(a); + vertices(); } void Mesh::Loader::batch(PrimitiveType p) @@ -315,7 +334,6 @@ bool Mesh::AsyncLoader::process() else if(phase==1) { mesh.resize_buffers(); - mesh.vtx_setup.refresh(); vertex_updater = mesh.vertices.refresh_async(); if(!mesh.batches.empty()) index_updater = mesh.batches.front().refresh_async(); diff --git a/source/core/mesh.h b/source/core/mesh.h index acf2910c..66516267 100644 --- a/source/core/mesh.h +++ b/source/core/mesh.h @@ -32,7 +32,9 @@ public: public: Loader(Mesh &, bool = true); private: - void vertices(const std::vector &); + void storage(const std::vector &); + void vertices(); + void vertices_with_format(const std::vector &); void batch(PrimitiveType); void winding(FaceWinding); }; @@ -79,6 +81,8 @@ private: public: ~Mesh(); + void storage(const VertexFormat &); + void clear(); private: void check_buffers(unsigned); diff --git a/source/core/vertexarray.cpp b/source/core/vertexarray.cpp index 347e4259..2bb6a667 100644 --- a/source/core/vertexarray.cpp +++ b/source/core/vertexarray.cpp @@ -11,14 +11,19 @@ using namespace std; namespace Msp { namespace GL { +VertexArray::VertexArray(): + stride(0) +{ } + VertexArray::VertexArray(const VertexFormat &f) { - reset(f); + set_format(f); } -void VertexArray::reset(const VertexFormat &f) +void VertexArray::set_format(const VertexFormat &f) { - clear(); + if(!format.empty()) + throw invalid_operation("VertexArray::set_format"); format = f; stride = format.stride(); } @@ -30,11 +35,15 @@ void VertexArray::clear() void VertexArray::reserve(unsigned n) { + if(format.empty()) + throw invalid_operation("VertexArray::reserve"); data.reserve(n*stride); } float *VertexArray::append() { + if(format.empty()) + throw invalid_operation("VertexArray::append"); data.insert(data.end(), stride, 0.0f); update_offset(); dirty = true; @@ -43,6 +52,8 @@ float *VertexArray::append() float *VertexArray::modify(unsigned i) { + if(format.empty()) + throw invalid_operation("VertexArray::modify"); dirty = true; return &data[0]+i*stride; } diff --git a/source/core/vertexarray.h b/source/core/vertexarray.h index 95a6ec2f..4c2a028f 100644 --- a/source/core/vertexarray.h +++ b/source/core/vertexarray.h @@ -43,10 +43,16 @@ private: VertexArray(const VertexArray &); VertexArray &operator=(const VertexArray &); public: + VertexArray(); + + /// Construct a VertexArray and set its format. VertexArray(const VertexFormat &); - /// Resets the VertexArray to a different format. All data is cleared. - void reset(const VertexFormat &); + /// Deprecated. Use set_format. + DEPRECATED void reset(const VertexFormat &f) { set_format(f); } + + /// Sets the format of the VertexArray. + void set_format(const VertexFormat &); const VertexFormat &get_format() const { return format; } diff --git a/source/core/vertexsetup.cpp b/source/core/vertexsetup.cpp index d9e9d095..da79e7f6 100644 --- a/source/core/vertexsetup.cpp +++ b/source/core/vertexsetup.cpp @@ -38,29 +38,53 @@ VertexSetup::~VertexSetup() glDeleteVertexArrays(1, &id); } +void VertexSetup::set_format(const VertexFormat &vfmt) +{ + if(!verify_format(vfmt)) + throw invalid_argument("VertexSetup::set_format"); + if(!vertex_format.empty()) + throw invalid_operation("VertexSetup::set_format"); + + vertex_format = vfmt; +} + +void VertexSetup::set_format_instanced(const VertexFormat &vfmt, const VertexFormat &ifmt) +{ + if(!verify_format(vfmt) || !verify_format(ifmt)) + throw invalid_argument("VertexSetup::set_format"); + if(!vertex_format.empty()) + throw invalid_operation("VertexSetup::set_format"); + + vertex_format = vfmt; + inst_format = ifmt; +} + void VertexSetup::set_vertex_array(const VertexArray &a) { - if(!verify_array(a)) + if(vertex_format.empty()) + throw invalid_operation("VertexSetup::set_vertex_array"); + if(a.get_format()!=vertex_format) + throw incompatible_data("VertexSetup::set_vertex_array"); + if(!a.get_buffer()) throw invalid_argument("VertexSetup::set_vertex_array"); vertex_array = &a; - update(get_update_mask(VERTEX_ARRAY, vertex_format, *vertex_array)); - vertex_format = vertex_array->get_format(); + update(VERTEX_ARRAY); } -void VertexSetup::set_instance_array(const VertexArray *a) +void VertexSetup::set_instance_array(const VertexArray &a) { - if(a) - { - if(!verify_array(*a)) - throw invalid_argument("VertexSetup::set_instance_array"); + if(inst_format.empty()) + throw invalid_operation("VertexSetup::set_instance_array"); + if(a.get_format()!=inst_format) + throw incompatible_data("VertexSetup::set_instance_array"); + if(!a.get_buffer()) + throw invalid_argument("VertexSetup::set_instance_array"); - static Require req(ARB_instanced_arrays); - } + static Require req(ARB_instanced_arrays); - inst_array = a; - update(get_update_mask(INSTANCE_ARRAY, inst_format, *inst_array)); - inst_format = inst_array->get_format(); + inst_array = &a; + update(INSTANCE_ARRAY); } void VertexSetup::set_index_buffer(const Buffer &ibuf) @@ -69,25 +93,15 @@ void VertexSetup::set_index_buffer(const Buffer &ibuf) update(INDEX_BUFFER); } -void VertexSetup::refresh() +bool VertexSetup::verify_format(const VertexFormat &fmt) { - if(vertex_array && vertex_array->get_format()!=vertex_format) - set_vertex_array(*vertex_array); - - if(inst_array && inst_array->get_format()!=inst_format) - set_instance_array(inst_array); -} - -bool VertexSetup::verify_array(const VertexArray &array) -{ - if(!array.get_buffer()) + if(fmt.empty()) return false; static int max_attribs = -1; if(max_attribs<0) max_attribs = get_i(GL_MAX_VERTEX_ATTRIBS); - const VertexFormat &fmt = array.get_format(); for(const unsigned char *a=fmt.begin(); a!=fmt.end(); ++a) if(static_cast(get_attribute_semantic(*a))>=max_attribs) return false; @@ -95,20 +109,6 @@ bool VertexSetup::verify_array(const VertexArray &array) return true; } -unsigned VertexSetup::get_attribs(const VertexFormat &fmt) -{ - unsigned mask = 0; - for(const unsigned char *a=fmt.begin(); a!=fmt.end(); ++a) - mask |= 1<>ATTRIB_SHIFT; am; ++i, am>>=1) - if(am&1) - { - if(direct) - glDisableVertexArrayAttrib(id, i); - else - glDisableVertexAttribArray(i); - } - } - if(mask&VERTEX_ARRAY) update_vertex_array(*vertex_array, 0, 0, direct); @@ -223,13 +211,19 @@ void VertexSetup::unload() BindRestore _bind(*this); Buffer::unbind_from(ARRAY_BUFFER); - unsigned mask = get_attribs(vertex_format)|get_attribs(inst_format); - for(unsigned i=0; mask; ++i, mask>>=1) - if(mask&1) - { - glDisableVertexAttribArray(i); - glVertexAttribPointer(i, 1, GL_FLOAT, false, 0, 0); - } + for(const unsigned char *a=vertex_format.begin(); a!=vertex_format.end(); ++a) + { + unsigned sem = get_attribute_semantic(*a); + glDisableVertexAttribArray(sem); + glVertexAttribPointer(sem, 1, GL_FLOAT, false, 0, 0); + } + for(const unsigned char *a=inst_format.begin(); a!=inst_format.end(); ++a) + { + unsigned sem = get_attribute_semantic(*a); + glDisableVertexAttribArray(sem); + glVertexAttribPointer(sem, 1, GL_FLOAT, false, 0, 0); + } + glBindBuffer(ELEMENT_ARRAY_BUFFER, 0); } diff --git a/source/core/vertexsetup.h b/source/core/vertexsetup.h index 51183af5..3b18006a 100644 --- a/source/core/vertexsetup.h +++ b/source/core/vertexsetup.h @@ -20,9 +20,7 @@ private: { VERTEX_ARRAY = 1, INSTANCE_ARRAY = 2, - INDEX_BUFFER = 4, - UNUSED_ATTRIBS = 8, - ATTRIB_SHIFT = 4 + INDEX_BUFFER = 4 }; unsigned id; @@ -37,18 +35,18 @@ public: VertexSetup(); ~VertexSetup(); + void set_format(const VertexFormat &); + void set_format_instanced(const VertexFormat &, const VertexFormat &); + void set_vertex_array(const VertexArray &); - void set_instance_array(const VertexArray *); + void set_instance_array(const VertexArray &); void set_index_buffer(const Buffer &); - void refresh(); const VertexArray *get_vertex_array() const { return vertex_array; } const VertexArray *get_instance_array() const { return inst_array; } const Buffer *get_index_buffer() const { return index_buffer; } private: - static bool verify_array(const VertexArray &); - static unsigned get_attribs(const VertexFormat &); - static unsigned get_update_mask(unsigned, const VertexFormat &, const VertexArray &); + static bool verify_format(const VertexFormat &); void update(unsigned) const; void update_vertex_array(const VertexArray &, unsigned, unsigned, bool) const; diff --git a/source/render/instancearray.cpp b/source/render/instancearray.cpp index 231bebe1..5854906f 100644 --- a/source/render/instancearray.cpp +++ b/source/render/instancearray.cpp @@ -52,9 +52,10 @@ InstanceArray::InstanceArray(const Object &o): instance_data->use_buffer(instance_buffer); vtx_setup = new VertexSetup; + vtx_setup->set_format_instanced(object.get_mesh()->get_vertices().get_format(), fmt); vtx_setup->set_vertex_array(object.get_mesh()->get_vertices()); vtx_setup->set_index_buffer(*object.get_mesh()->get_index_buffer()); - vtx_setup->set_instance_array(instance_data); + vtx_setup->set_instance_array(*instance_data); } else static Require req(ARB_vertex_shader); -- 2.43.0