[SM91] Update to Spidermonkey 91.1.3 APIs
[0ad.git] / source / renderer / VertexArray.cpp
blobe4aef539bd21a45489fe98d1fa739efbd04f77a5
1 /* Copyright (C) 2023 Wildfire Games.
2 * This file is part of 0 A.D.
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.
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.
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/>.
18 #include "precompiled.h"
20 #include "lib/alignment.h"
21 #include "lib/sysdep/rtl.h"
22 #include "maths/Vector3D.h"
23 #include "maths/Vector4D.h"
24 #include "ps/CLogger.h"
25 #include "graphics/Color.h"
26 #include "graphics/SColor.h"
27 #include "renderer/VertexArray.h"
28 #include "renderer/VertexBuffer.h"
29 #include "renderer/VertexBufferManager.h"
31 namespace
34 uint32_t GetAttributeSize(const Renderer::Backend::Format format)
36 switch (format)
38 case Renderer::Backend::Format::R8G8B8A8_UNORM: FALLTHROUGH;
39 case Renderer::Backend::Format::R8G8B8A8_UINT:
40 return sizeof(u8) * 4;
41 case Renderer::Backend::Format::A8_UNORM:
42 return sizeof(u8);
43 case Renderer::Backend::Format::R16_UNORM: FALLTHROUGH;
44 case Renderer::Backend::Format::R16_UINT: FALLTHROUGH;
45 case Renderer::Backend::Format::R16_SINT:
46 return sizeof(u16);
47 case Renderer::Backend::Format::R16G16_UNORM: FALLTHROUGH;
48 case Renderer::Backend::Format::R16G16_UINT: FALLTHROUGH;
49 case Renderer::Backend::Format::R16G16_SINT:
50 return sizeof(u16) * 2;
51 case Renderer::Backend::Format::R32_SFLOAT:
52 return sizeof(float);
53 case Renderer::Backend::Format::R32G32_SFLOAT:
54 return sizeof(float) * 2;
55 case Renderer::Backend::Format::R32G32B32_SFLOAT:
56 return sizeof(float) * 3;
57 case Renderer::Backend::Format::R32G32B32A32_SFLOAT:
58 return sizeof(float) * 4;
59 default:
60 break;
62 return 0;
65 } // anonymous namespace
67 VertexArray::VertexArray(
68 const Renderer::Backend::IBuffer::Type type, const bool dynamic)
69 : m_Type(type), m_Dynamic(dynamic)
71 m_NumberOfVertices = 0;
73 m_BackingStore = 0;
74 m_Stride = 0;
77 VertexArray::~VertexArray()
79 Free();
82 // Free all resources on destruction or when a layout parameter changes
83 void VertexArray::Free()
85 rtl_FreeAligned(m_BackingStore);
86 m_BackingStore = 0;
88 m_VB.Reset();
91 // Set the number of vertices stored in the array
92 void VertexArray::SetNumberOfVertices(const size_t numberOfVertices)
94 if (numberOfVertices == m_NumberOfVertices)
95 return;
97 Free();
98 m_NumberOfVertices = numberOfVertices;
101 // Add vertex attributes like Position, Normal, UV
102 void VertexArray::AddAttribute(Attribute* attr)
104 // Attribute is supported is its size is greater than zero.
105 ENSURE(GetAttributeSize(attr->format) > 0 && "Unsupported attribute.");
107 attr->vertexArray = this;
108 m_Attributes.push_back(attr);
110 Free();
113 // Template specialization for GetIterator().
114 // We can put this into the source file because only a fixed set of types
115 // is supported for type safety.
116 template<>
117 VertexArrayIterator<CVector3D> VertexArray::Attribute::GetIterator<CVector3D>() const
119 ENSURE(vertexArray);
120 ENSURE(
121 format == Renderer::Backend::Format::R32G32B32_SFLOAT ||
122 format == Renderer::Backend::Format::R32G32B32A32_SFLOAT);
124 return vertexArray->MakeIterator<CVector3D>(this);
127 template<>
128 VertexArrayIterator<CVector4D> VertexArray::Attribute::GetIterator<CVector4D>() const
130 ENSURE(vertexArray);
131 ENSURE(format == Renderer::Backend::Format::R32G32B32A32_SFLOAT);
133 return vertexArray->MakeIterator<CVector4D>(this);
136 template<>
137 VertexArrayIterator<float[2]> VertexArray::Attribute::GetIterator<float[2]>() const
139 ENSURE(vertexArray);
140 ENSURE(format == Renderer::Backend::Format::R32G32_SFLOAT);
142 return vertexArray->MakeIterator<float[2]>(this);
145 template<>
146 VertexArrayIterator<SColor4ub> VertexArray::Attribute::GetIterator<SColor4ub>() const
148 ENSURE(vertexArray);
149 ENSURE(
150 format == Renderer::Backend::Format::R8G8B8A8_UNORM ||
151 format == Renderer::Backend::Format::R8G8B8A8_UINT);
153 return vertexArray->MakeIterator<SColor4ub>(this);
156 template<>
157 VertexArrayIterator<u16> VertexArray::Attribute::GetIterator<u16>() const
159 ENSURE(vertexArray);
160 ENSURE(format == Renderer::Backend::Format::R16_UINT);
162 return vertexArray->MakeIterator<u16>(this);
165 template<>
166 VertexArrayIterator<u16[2]> VertexArray::Attribute::GetIterator<u16[2]>() const
168 ENSURE(vertexArray);
169 ENSURE(format == Renderer::Backend::Format::R16G16_UINT);
171 return vertexArray->MakeIterator<u16[2]>(this);
174 template<>
175 VertexArrayIterator<u8> VertexArray::Attribute::GetIterator<u8>() const
177 ENSURE(vertexArray);
178 ENSURE(format == Renderer::Backend::Format::A8_UNORM);
180 return vertexArray->MakeIterator<u8>(this);
183 template<>
184 VertexArrayIterator<u8[4]> VertexArray::Attribute::GetIterator<u8[4]>() const
186 ENSURE(vertexArray);
187 ENSURE(
188 format == Renderer::Backend::Format::R8G8B8A8_UNORM ||
189 format == Renderer::Backend::Format::R8G8B8A8_UINT);
191 return vertexArray->MakeIterator<u8[4]>(this);
194 template<>
195 VertexArrayIterator<short> VertexArray::Attribute::GetIterator<short>() const
197 ENSURE(vertexArray);
198 ENSURE(format == Renderer::Backend::Format::R16_SINT);
200 return vertexArray->MakeIterator<short>(this);
203 template<>
204 VertexArrayIterator<short[2]> VertexArray::Attribute::GetIterator<short[2]>() const
206 ENSURE(vertexArray);
207 ENSURE(format == Renderer::Backend::Format::R16G16_SINT);
209 return vertexArray->MakeIterator<short[2]>(this);
212 static uint32_t RoundStride(uint32_t stride)
214 if (stride <= 0)
215 return 0;
216 if (stride <= 4)
217 return 4;
218 if (stride <= 8)
219 return 8;
220 if (stride <= 16)
221 return 16;
223 return Align<32>(stride);
226 // Re-layout by assigning offsets on a first-come first-serve basis,
227 // then round up to a reasonable stride.
228 // Backing store is also created here, backend buffers are created on upload.
229 void VertexArray::Layout()
231 Free();
233 m_Stride = 0;
235 for (ssize_t idx = m_Attributes.size()-1; idx >= 0; --idx)
237 Attribute* attr = m_Attributes[idx];
238 if (attr->format == Renderer::Backend::Format::UNDEFINED)
239 continue;
241 const uint32_t attrSize = GetAttributeSize(attr->format);
242 ENSURE(attrSize > 0);
244 attr->offset = m_Stride;
246 m_Stride += attrSize;
248 if (m_Type == Renderer::Backend::IBuffer::Type::VERTEX)
249 m_Stride = Align<4>(m_Stride);
252 if (m_Type == Renderer::Backend::IBuffer::Type::VERTEX)
253 m_Stride = RoundStride(m_Stride);
255 if (m_Stride)
256 m_BackingStore = (char*)rtl_AllocateAligned(m_Stride * m_NumberOfVertices, 16);
259 void VertexArray::PrepareForRendering()
261 m_VB->m_Owner->PrepareForRendering(m_VB.Get());
264 // (Re-)Upload the attributes.
265 // Create the backend buffer if necessary.
266 void VertexArray::Upload()
268 ENSURE(m_BackingStore);
270 if (!m_VB)
272 m_VB = g_VBMan.AllocateChunk(
273 m_Stride, m_NumberOfVertices, m_Type, m_Dynamic, m_BackingStore);
276 if (!m_VB)
278 LOGERROR("Failed to allocate backend buffer for vertex array");
279 return;
282 m_VB->m_Owner->UpdateChunkVertices(m_VB.Get(), m_BackingStore);
285 void VertexArray::UploadIfNeeded(
286 Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
288 m_VB->m_Owner->UploadIfNeeded(deviceCommandContext);
291 // Free the backing store to save some memory
292 void VertexArray::FreeBackingStore()
294 // In streaming modes, the backing store must be retained
295 ENSURE(!CVertexBuffer::UseStreaming(m_Dynamic));
297 rtl_FreeAligned(m_BackingStore);
298 m_BackingStore = 0;
301 VertexIndexArray::VertexIndexArray(const bool dynamic) :
302 VertexArray(Renderer::Backend::IBuffer::Type::INDEX, dynamic)
304 m_Attr.format = Renderer::Backend::Format::R16_UINT;
305 AddAttribute(&m_Attr);
308 VertexArrayIterator<u16> VertexIndexArray::GetIterator() const
310 return m_Attr.GetIterator<u16>();