Line data Source code
1 : /* Copyright (C) 2023 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #ifndef INCLUDED_VERTEXARRAY
19 : #define INCLUDED_VERTEXARRAY
20 :
21 : #include "renderer/backend/Format.h"
22 : #include "renderer/backend/IBuffer.h"
23 : #include "renderer/backend/IDeviceCommandContext.h"
24 : #include "renderer/VertexBufferManager.h"
25 :
26 : #include <vector>
27 :
28 : // Iterator
29 : template<typename T>
30 : class VertexArrayIterator
31 : {
32 : public:
33 : typedef T Type;
34 :
35 : public:
36 0 : VertexArrayIterator() :
37 0 : m_Data(0), m_Stride(0)
38 : {
39 0 : }
40 :
41 6 : VertexArrayIterator(char* data, size_t stride) :
42 6 : m_Data(data), m_Stride(stride)
43 : {
44 6 : }
45 :
46 36864 : VertexArrayIterator(const VertexArrayIterator& rhs) :
47 36864 : m_Data(rhs.m_Data), m_Stride(rhs.m_Stride)
48 : {
49 36864 : }
50 :
51 0 : VertexArrayIterator& operator=(const VertexArrayIterator& rhs)
52 : {
53 0 : m_Data = rhs.m_Data;
54 0 : m_Stride = rhs.m_Stride;
55 0 : return *this;
56 : }
57 :
58 : // Accessors
59 36864 : T& operator*() const { return *(T*)m_Data; }
60 0 : T* operator->() const { return (T*)m_Data; }
61 0 : T& operator[](size_t idx) const { return *(T*)(m_Data + idx*m_Stride); }
62 :
63 : // Walking
64 0 : VertexArrayIterator& operator++()
65 : {
66 0 : m_Data += m_Stride;
67 0 : return *this;
68 : }
69 36864 : VertexArrayIterator operator++(int)
70 : {
71 36864 : VertexArrayIterator tmp = *this;
72 36864 : m_Data += m_Stride;
73 36864 : return tmp;
74 : }
75 : VertexArrayIterator& operator--()
76 : {
77 : m_Data -= m_Stride;
78 : return *this;
79 : }
80 : VertexArrayIterator operator--(int)
81 : {
82 : VertexArrayIterator tmp = *this;
83 : m_Data -= m_Stride;
84 : return tmp;
85 : }
86 :
87 : VertexArrayIterator& operator+=(ssize_t rhs)
88 : {
89 : m_Data += rhs*m_Stride;
90 : return *this;
91 : }
92 : VertexArrayIterator& operator-=(ssize_t rhs)
93 : {
94 : m_Data -= rhs*m_Stride;
95 : return *this;
96 : }
97 :
98 : VertexArrayIterator operator+(ssize_t rhs) const
99 : {
100 : VertexArrayIterator tmp = *this;
101 : tmp.m_Data += rhs*m_Stride;
102 : return tmp;
103 : }
104 : VertexArrayIterator operator-(ssize_t rhs) const
105 : {
106 : VertexArrayIterator tmp = *this;
107 : tmp.m_Data -= rhs*m_Stride;
108 : return tmp;
109 : }
110 :
111 : // Accessors for raw buffer data, for performance-critical code
112 0 : char* GetData() const
113 : {
114 0 : return m_Data;
115 : }
116 0 : size_t GetStride() const
117 : {
118 0 : return m_Stride;
119 : }
120 :
121 : private:
122 : char* m_Data;
123 : size_t m_Stride;
124 : };
125 :
126 :
127 : // Manage a vertex array with a runtime-determined set of attributes.
128 : //
129 : // Purpose: Different rendering paths sometimes require different sets of
130 : // attributes (e.g. normal vector vs. color data), which is difficult to
131 : // support with hardcoded vertex structures.
132 : // This class chooses the vertex layout at runtime, based on the attributes
133 : // that are actually needed.
134 : //
135 : // Note that this class will not allocate any backend resources until one
136 : // of the Upload functions is called.
137 : class VertexArray
138 : {
139 : public:
140 : struct Attribute
141 : {
142 : Renderer::Backend::Format format = Renderer::Backend::Format::UNDEFINED;
143 :
144 : // Offset (in bytes) into a vertex structure (filled in by Layout())
145 : uint32_t offset = 0;
146 :
147 : VertexArray* vertexArray = nullptr;
148 :
149 36 : Attribute() {}
150 :
151 : // Get an iterator over the backing store for the given attribute that
152 : // initially points at the first vertex.
153 : // Supported types T: CVector3D, CVector4D, float[2], SColor4ub,
154 : // u16, u16[2], u8[4], short, short[2].
155 : // This function verifies at runtime that the requested type T matches
156 : // the attribute definition passed to AddAttribute().
157 : template<typename T>
158 : VertexArrayIterator<T> GetIterator() const;
159 : };
160 :
161 : public:
162 : VertexArray(
163 : const Renderer::Backend::IBuffer::Type type, const bool dynamic);
164 : ~VertexArray();
165 :
166 : // Set the number of vertices stored in the array
167 : void SetNumberOfVertices(const size_t numberOfVertices);
168 : // Add vertex attributes
169 : void AddAttribute(Attribute* attr);
170 :
171 0 : size_t GetNumberOfVertices() const { return m_NumberOfVertices; }
172 6 : uint32_t GetStride() const { return m_Stride; }
173 :
174 : // Layout the vertex array format and create backing buffer in RAM.
175 : // You must call Layout() after changing the number of vertices or
176 : // attributes.
177 : // All vertex data is lost when a vertex array is re-layouted.
178 : void Layout();
179 : // (Re-)Upload the attributes of the vertex array from the backing store to
180 : // the underlying buffer.
181 : void Upload();
182 : // Make this vertex array's data available for the next series of calls to Bind
183 : void PrepareForRendering();
184 :
185 : void UploadIfNeeded(Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
186 :
187 : // If you know for certain that you'll never have to change the data again,
188 : // call this to free some memory.
189 : void FreeBackingStore();
190 :
191 0 : Renderer::Backend::IBuffer* GetBuffer() { return m_VB ? m_VB->m_Owner->GetBuffer() : nullptr; }
192 :
193 0 : uint32_t GetOffset() const { return m_VB ? m_VB->m_Index : 0; }
194 :
195 : private:
196 : void Free();
197 :
198 : template<typename T>
199 6 : VertexArrayIterator<T> MakeIterator(const Attribute* attr)
200 : {
201 6 : ENSURE(attr->format != Renderer::Backend::Format::UNDEFINED);
202 6 : return VertexArrayIterator<T>(m_BackingStore + attr->offset, m_Stride);
203 : }
204 :
205 : Renderer::Backend::IBuffer::Type m_Type;
206 : bool m_Dynamic;
207 : size_t m_NumberOfVertices;
208 : std::vector<Attribute*> m_Attributes;
209 :
210 : CVertexBufferManager::Handle m_VB;
211 : uint32_t m_Stride;
212 : char* m_BackingStore; // 16-byte aligned, to allow fast SSE access
213 : };
214 :
215 : /**
216 : * A VertexArray that is specialised to handle 16-bit array indices.
217 : * Call UploadIfNeeded() before use in Draw/DrawIndexed.
218 : */
219 6 : class VertexIndexArray : public VertexArray
220 : {
221 : public:
222 : VertexIndexArray(const bool dynamic);
223 :
224 : /// Gets the iterator over the (only) attribute in this array, i.e. a u16.
225 : VertexArrayIterator<u16> GetIterator() const;
226 :
227 : private:
228 : Attribute m_Attr;
229 : };
230 :
231 : #endif // INCLUDED_VERTEXARRAY
|