1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_ParticleShape.cpp
4
5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Revision: 25788 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nn/gx.h>
19
20 #include <nw/gfx/gfx_ParticleShape.h>
21 #include <nw/gfx/gfx_ISceneVisitor.h>
22 #include <nw/gfx/res/gfx_ResVertex.h>
23
24 #include <nw/ut/ut_ResUtil.h>
25 #include <nw/ut/ut_ResDictionary.h>
26 #include <nw/ut/ut_Foreach.h>
27
28 namespace nw
29 {
30 namespace gfx
31 {
32
33 NW_UT_RUNTIME_TYPEINFO_DEFINITION(ParticleShape, SceneObject);
34
35 static const int MAX_ATTRIBUTES_NUM = 12;
36
37 //----------------------------------------
38 static void
SetupParticleVertexAttributeCommand(ParticleShape * shape,ParticleSet * particleSet,ParticleBuffer bufferSide)39 SetupParticleVertexAttributeCommand(
40 ParticleShape* shape,
41 ParticleSet* particleSet,
42 ParticleBuffer bufferSide)
43 {
44 ParticleCollection* collection = particleSet->GetParticleCollection();
45
46 enum
47 {
48 REG_VTX_SHADER_ATTR_NUM = 0x2b9, // [3:0] 頂点属性数 - 1
49 REG_VTX_SHADER_ATTR_NUM_2 = 0x242, // [3:0] 頂点族整数 - 1
50 REG_VTX_MAP_0 = 0x2bb, // [31:0] 入力レジスタのインデックス
51 REG_VTX_MAP_1 = 0x2bc, // [15:0] 入力レジスタのインデックス
52 REG_VTX_STREAM_BASE = 0x200, // [28:1] 頂点アレイのベースアドレス
53 REG_VTX_ARRAY_OFFSET = 0x203, // [27:0] ロードアレイ0のアドレスオフセット
54 REG_VTX_PARAM_INDEX = 0x232, // [3:0] 頂点シェーダの入力番号指定
55 REG_GEOM_MAP_0 = 0x28b, // [31:0] 入力レジスタのインデックス
56 REG_GEOM_MAP_1 = 0x28c // [15:0] 入力レジスタのインデックス
57 };
58
59 u32 baseAddr = nngxGetPhysicalAddr(nn::gx::GetVramStartAddr(nn::gx::MEM_VRAMA));
60
61 s32 vtxAttrNum = shape->GetVertexAttributesCount();
62
63 u32* command = reinterpret_cast<u32*>(shape->m_CommandCache[bufferSide]);
64
65 const u32 HEADER_VTX_SHADER_ATTR_NUM = internal::MakeCommandHeader(REG_VTX_SHADER_ATTR_NUM, 1, false, 0xb);
66 const u32 HEADER_VTX_SHADER_ATTR_NUM_2 = internal::MakeCommandHeader(REG_VTX_SHADER_ATTR_NUM_2, 1, false, 0x1);
67 const u32 HEADER_VTX_MAP_0 = internal::MakeCommandHeader(REG_VTX_MAP_0, 2, true, 0xF);
68
69
70 command[0] = (vtxAttrNum - 1) | 0xa0000000;
71 command[1] = HEADER_VTX_SHADER_ATTR_NUM;
72
73 command[2] = (vtxAttrNum - 1);
74 command[3] = HEADER_VTX_SHADER_ATTR_NUM_2;
75
76 command[4] = 0;
77 command[5] = HEADER_VTX_MAP_0;
78 command[6] = 0;
79 command[7] = 0;
80
81 NW_ASSERT((baseAddr & 0x0f) == 0);
82 command[8] = baseAddr >> 3;
83 command[9] = internal::MakeCommandHeader(REG_VTX_STREAM_BASE, 3 + vtxAttrNum * 3, true, 0xF);
84 command[10] = 0;
85 command[11] = static_cast<u32>(vtxAttrNum - 1) << 28;
86
87 u32* inputTable = &command[4];
88 u32* inputFormat = &command[10];
89 u32* vertexParamMask = &command[11];
90
91 int inputIndex = 0; // 内部頂点属性番号
92 u32 commandIndex = 12;
93
94 u32 usedFlag = 0;
95
96 // 頂点ストリームを番号の若い順に設定
97 for (s32 i = 0; i < shape->GetVertexAttributesCount(); ++i)
98 {
99 if (shape->IsVertexStream(i))
100 {
101 s32 usage = shape->GetVertexAttributeUsage(i);
102 NW_ASSERT(0 <= usage && usage < 12);
103 inputTable[ (inputIndex / 8) * 2 ] |= (usage & 0xF) << (4 * (inputIndex % 8));
104 usedFlag |= 0x1 << usage;
105
106 u32 format = shape->GetVertexAttributeFormatType(i);
107 u32 dimension = shape->GetVertexAttributeDimension(i);
108
109 inputFormat[ inputIndex / 8 ] |= internal::CommandCacheHelper::GetVertexFormat(dimension, format) << ((inputIndex % 8) * 4);
110
111 // ロードアレイの設定
112 u8* streamPtr = shape->GetVertexStreamPtr(i, bufferSide);
113 NW_NULL_ASSERT(streamPtr);
114 u32 bufferAddr = nngxGetPhysicalAddr(reinterpret_cast<uptr>(streamPtr));
115
116 shape->SetVertexAttributeCommandPtr(i, bufferSide, &command[commandIndex]);
117
118 // このクラスでは interleave 形式には対応しないので、(0番目の要素 == 内部頂点属性 index 番目)
119 NW_ASSERT((bufferAddr - baseAddr) < 0x10000000);
120 command[commandIndex++] = bufferAddr - baseAddr;
121 command[commandIndex++] = inputIndex;
122 command[commandIndex++] = (internal::CommandCacheHelper::GetVertexSize(dimension, format) << 16) + (1 << 28);
123
124 ++inputIndex;
125 }
126 }
127
128 // パラメータの分を設定
129 for (s32 i = inputIndex; i < vtxAttrNum; ++i)
130 {
131 command[commandIndex++] = 0;
132 command[commandIndex++] = 0;
133 command[commandIndex++] = 0;
134 }
135
136 // 64bit単位になるようにパディング
137 if ((commandIndex & 1) == 1)
138 {
139 command[commandIndex++] = 0;
140 }
141
142 // 頂点ストリームの後に頂点パラメータを設定。
143 for (s32 i = 0; i < shape->GetVertexAttributesCount(); ++i)
144 {
145 if (!shape->IsVertexStream(i))
146 {
147 s32 usage = shape->GetVertexAttributeUsage(i);
148 NW_ASSERT(0 <= usage && usage < 12);
149 inputTable[ (inputIndex / 8) * 2 ] |= (usage & 0xF) << (4 * (inputIndex % 8));
150 usedFlag |= 0x1 << usage;
151
152 // 頂点パラメータの場合の処理
153
154 u32 data[4] = { 0, 0, 0, 0 };
155
156 int count = shape->GetVertexAttributeDimension(i);
157 f32* fdata = shape->GetVertexParameter(i);
158
159 for (int j = 0; j < count; ++j)
160 {
161 data[j] = ut::Float24::Float32ToBits24(fdata[j]);
162 }
163
164 const u32 HEADER_VTX_PARAM_INDEX = internal::MakeCommandHeader(REG_VTX_PARAM_INDEX, 4, true, 0xF);
165
166 shape->SetVertexAttributeCommandPtr(i, bufferSide, &command[commandIndex + 2]);
167
168 command[commandIndex] = inputIndex;
169 command[commandIndex + 1] = HEADER_VTX_PARAM_INDEX;
170 command[commandIndex + 2] = (data[3] << 8) | (data[2] >> 16);
171 command[commandIndex + 3] = (data[2] << 16) | (data[1] >> 8);
172 command[commandIndex + 4] = (data[1] << 24) | (data[0]);
173 command[commandIndex + 5] = 0;
174
175 vertexParamMask[0] |= 1 << (16 + inputIndex);
176
177 ++inputIndex;
178 commandIndex += 6;
179 }
180 }
181
182 const u32 HEADER_GEOM_MAP_0 = internal::MakeCommandHeader(REG_GEOM_MAP_0, 2, true, 0xF);
183
184 command[commandIndex + 0] = 0x76543210;
185 command[commandIndex + 1] = HEADER_GEOM_MAP_0;
186 command[commandIndex + 2] = 0xfedcba98;
187 command[commandIndex + 3] = 0;
188 commandIndex += 4;
189
190 shape->m_CommandCacheSize[bufferSide] = commandIndex * sizeof(u32);
191 }
192
193
194 //----------------------------------------
195 static void
SetupDeactivateParticleVertexAttributeCommand(ParticleShape * shape)196 SetupDeactivateParticleVertexAttributeCommand(
197 ParticleShape* shape)
198 {
199 enum
200 {
201 REG_VTX_ARRAY_OFFSET = 0x203, // [27:0] ロードアレイ0のアドレスオフセット
202 REG_VTX_PARAM_INDEX = 0x232 // [3:0] 頂点シェーダの入力番号指定
203 };
204
205 s32 vtxAttrNum = shape->GetVertexAttributesCount();
206
207 u32* command = reinterpret_cast<u32*>(shape->m_DeactivateVertexCommandCache);
208
209 shape->m_DeactivateVertexCommandCache = command;
210
211 int inputIndex = 0; // 内部頂点属性番号
212 u32 commandIndex = 0;
213
214 // 頂点ストリームを番号の若い順に設定
215 for (s32 i = 0; i < vtxAttrNum; ++i)
216 {
217 if (shape->IsVertexStream(i))
218 {
219 // ロードアレイの無効化
220 // このクラスでは interleave 形式には対応しないので、(0番目の要素 == 内部頂点属性 index 番目)
221 command[commandIndex++] = 0;
222 command[commandIndex++] = internal::MakeCommandHeader(REG_VTX_ARRAY_OFFSET + 2 + 3 * inputIndex, 1, false, 0xF);
223
224 ++inputIndex;
225 }
226 }
227
228 const u32 HEADER_VTX_PARAM_INDEX = internal::MakeCommandHeader(REG_VTX_PARAM_INDEX, 4, true, 0xF);
229
230 // (0,0,0,0) の固定属性を設定
231 for ( int i = 0; i < inputIndex; ++i )
232 {
233 command[commandIndex++] = i;
234 command[commandIndex++] = HEADER_VTX_PARAM_INDEX;
235 command[commandIndex++] = 0;
236 command[commandIndex++] = 0;
237 command[commandIndex++] = 0;
238 command[commandIndex++] = 0;
239 }
240
241 shape->m_DeactivateVertexCommandCacheSize = commandIndex * sizeof(u32);
242
243 NW_ASSERT( shape->m_DeactivateVertexCommandCacheSize <= sizeof(u32) * (MAX_ATTRIBUTES_NUM * 8) );
244 }
245
246 static const int PrimitiveCommandSize = 26;
247
248 //----------------------------------------
249 static void
CreatePrimitiveCommandCache(ParticleShape * shape,ResParticleSet resParticleSet)250 CreatePrimitiveCommandCache(
251 ParticleShape* shape,
252 ResParticleSet resParticleSet)
253 {
254 enum
255 {
256 REG_VERTEX_UNIFORM_BOOL = 0x2b0,
257
258 REG_ELEMENTS_MODE = 0x229, // [23:16]にはバイトイネーブルでアクセスしてはいけない。
259 REG_ELEMENTS_MODE_2 = 0x253, // [31:16]にはバイトイネーブルでアクセスしてはいけない。
260 REG_ELEMENTS_MODE_3 = 0x25e, // [31:16]にはバイトイネーブルでアクセスしてはいけない。
261 REG_TRIANGLE_INDEX_RESET = 0x25f,
262 REG_DRAW_READY = 0x245,
263 REG_DRAW_KICK = 0x22f,
264 REG_VERTEX_CACHE_CLEAR = 0x231,
265 REG_COLOR_DEPTH_CACHE_CLEAR = 0x110,
266 REG_COLOR_DEPTH_CACHE_FLUSH = 0x111
267 };
268
269 u32* command = reinterpret_cast<u32*>(shape->m_PrimitiveCommandCache);
270
271 u32 commandIndex = 0;
272
273 s32 type;
274 switch (resParticleSet.GetParticleShapeBuilder().GetTypeInfo())
275 {
276 case ResParticleBillboardShapeBuilder::TYPE_INFO:
277 type = 0;
278 break;
279 case ResParticleWorldBillboardShapeBuilder::TYPE_INFO:
280 type = 8;
281 break;
282 case ResParticleYBillboardShapeBuilder::TYPE_INFO:
283 type = 2 | 1;
284 break;
285 case ResParticleXyPlaneShapeBuilder::TYPE_INFO:
286 type = 4 | 1;
287 break;
288 default:
289 NW_FATAL_ERROR("unknown shapebuilder type");
290 break;
291 }
292
293 const u32 HEADER_VERTEX_UNIFORM_BOOL = internal::MakeCommandHeader(REG_VERTEX_UNIFORM_BOOL, 5, true, 0xF);
294
295 const u32 HEADER_ELEMENTS_MODE = internal::MakeCommandHeader(REG_ELEMENTS_MODE, 1, false, 0x2);
296 const u32 HEADER_ELEMENTS_MODE_2 = internal::MakeCommandHeader(REG_ELEMENTS_MODE_2, 1, false, 0x2);
297 const u32 HEADER_ELEMENTS_MODE_3 = internal::MakeCommandHeader(REG_ELEMENTS_MODE_3, 1, false, 0x2);
298 const u32 HEADER_TRIANGLE_INDEX_RESET = internal::MakeCommandHeader(REG_TRIANGLE_INDEX_RESET, 1, false, 0xF);
299 const u32 HEADER_DRAW_READY = internal::MakeCommandHeader(REG_DRAW_READY, 1, false, 0xF);
300 const u32 HEADER_DRAW_KICK = internal::MakeCommandHeader(REG_DRAW_KICK, 1, false, 0xF);
301 const u32 HEADER_VERTEX_CACHE_CLEAR = internal::MakeCommandHeader(REG_VERTEX_CACHE_CLEAR, 1, false, 0xF);
302 const u32 HEADER_COLOR_DEPTH_CACHE_FLUSH = internal::MakeCommandHeader(REG_COLOR_DEPTH_CACHE_FLUSH, 1, false, 0xF);
303 const u32 HEADER_COLOR_DEPTH_CACHE_CLEAR = internal::MakeCommandHeader(REG_COLOR_DEPTH_CACHE_CLEAR, 1, false, 0xF);
304
305 command[commandIndex++] = 0x7fff0000 | (type << 1); // bit0は予約されているため、bit1から配置する
306 command[commandIndex++] = HEADER_VERTEX_UNIFORM_BOOL;
307 command[commandIndex++] = 0;
308 command[commandIndex++] = 0;
309 command[commandIndex++] = 0;
310 command[commandIndex++] = 0;
311
312 command[commandIndex++] = 0;
313 command[commandIndex++] = HEADER_ELEMENTS_MODE;
314 command[commandIndex++] = 0;
315 command[commandIndex++] = HEADER_ELEMENTS_MODE_2;
316 command[commandIndex++] = 3 << 8;
317 command[commandIndex++] = HEADER_ELEMENTS_MODE_3;
318 command[commandIndex++] = 1;
319 command[commandIndex++] = HEADER_TRIANGLE_INDEX_RESET;
320 command[commandIndex++] = 0;
321 command[commandIndex++] = HEADER_DRAW_READY;
322 command[commandIndex++] = 1;
323 command[commandIndex++] = HEADER_DRAW_KICK;
324 command[commandIndex++] = 1;
325 command[commandIndex++] = HEADER_DRAW_READY;
326 command[commandIndex++] = 1;
327 command[commandIndex++] = HEADER_VERTEX_CACHE_CLEAR;
328 command[commandIndex++] = 1;
329 command[commandIndex++] = HEADER_COLOR_DEPTH_CACHE_FLUSH;
330 command[commandIndex++] = 1;
331 command[commandIndex++] = HEADER_COLOR_DEPTH_CACHE_CLEAR;
332
333 NW_ASSERT(commandIndex == PrimitiveCommandSize);
334
335 shape->m_PrimitiveCommandCacheSize = commandIndex * sizeof(u32);
336 }
337
338 //----------------------------------------
339 void
CreateCommandCache(ParticleSet * particleSet)340 ParticleShape::CreateCommandCache(
341 ParticleSet* particleSet
342 )
343 {
344 for (int side = 0; side < 2; ++side)
345 {
346 SetupParticleVertexAttributeCommand(
347 this,
348 particleSet,
349 (ParticleBuffer)side);
350 }
351
352 SetupDeactivateParticleVertexAttributeCommand(this);
353
354 CreatePrimitiveCommandCache(
355 this,
356 particleSet->GetResParticleSet());
357 }
358
359 void
GetMemorySizeInternal(os::MemorySizeCalculator * pSize,int capacity)360 ParticleShape::GetMemorySizeInternal(
361 os::MemorySizeCalculator* pSize,
362 int capacity)
363 {
364 os::MemorySizeCalculator& size = *pSize;
365
366 const int streamSize = (capacity + internal::PARTICLE_SIMD_WIDTH_MAX) * sizeof(u16);
367 const int drawCommandCacheSize = sizeof(u32) * (12 + MAX_ATTRIBUTES_NUM * 6 + MAX_ATTRIBUTES_NUM * 4 + 4);
368 const int primitiveCommandCacheSize = sizeof(u32) * PrimitiveCommandSize;
369 const int deactivateVertexCommandCacheSize = sizeof(u32) * (MAX_ATTRIBUTES_NUM * 8);
370
371 int deviceMemorySize = 0;
372 if (size.GetAlignment() < 32)
373 {
374 deviceMemorySize += 32 - size.GetAlignment(); // 最悪値
375 }
376
377 deviceMemorySize = ut::RoundUp(deviceMemorySize, 32);
378 deviceMemorySize += streamSize;
379 deviceMemorySize = ut::RoundUp(deviceMemorySize, 32);
380 deviceMemorySize += streamSize;
381
382 int nodeMemorySize = sizeof(ParticleShape);
383 nodeMemorySize = ut::RoundUp(nodeMemorySize, 32);
384 nodeMemorySize += drawCommandCacheSize;
385 nodeMemorySize = ut::RoundUp(nodeMemorySize, 32);
386 nodeMemorySize += drawCommandCacheSize;
387 nodeMemorySize = ut::RoundUp(nodeMemorySize, 32);
388 nodeMemorySize += deactivateVertexCommandCacheSize;
389 nodeMemorySize = ut::RoundUp(nodeMemorySize, 32);
390 nodeMemorySize += primitiveCommandCacheSize;
391 nodeMemorySize = ut::RoundUp(nodeMemorySize, 32);
392
393 size.Add(nodeMemorySize, 32);
394 }
395
396 void
GetDeviceMemorySizeInternal(os::MemorySizeCalculator * pSize,int capacity)397 ParticleShape::GetDeviceMemorySizeInternal(
398 os::MemorySizeCalculator* pSize,
399 int capacity)
400 {
401 os::MemorySizeCalculator& size = *pSize;
402
403 const int streamSize = (capacity + internal::PARTICLE_SIMD_WIDTH_MAX) * sizeof(u16);
404 const int drawCommandCacheSize = sizeof(u32) * (12 + MAX_ATTRIBUTES_NUM * 6 + MAX_ATTRIBUTES_NUM * 4 + 4);
405 const int primitiveCommandCacheSize = sizeof(u32) * PrimitiveCommandSize;
406 const int deactivateVertexCommandCacheSize = sizeof(u32) * (MAX_ATTRIBUTES_NUM * 8);
407
408 int deviceMemorySize = 0;
409 if (size.GetAlignment() < 32)
410 {
411 deviceMemorySize += 32 - size.GetAlignment(); // 最悪値
412 }
413
414 deviceMemorySize = ut::RoundUp(deviceMemorySize, 32);
415 deviceMemorySize += streamSize;
416 deviceMemorySize = ut::RoundUp(deviceMemorySize, 32);
417 deviceMemorySize += streamSize;
418
419 size.Add(deviceMemorySize, 32);
420 }
421
422 //----------------------------------------
423 ParticleShape*
Create(ResSceneObject resource,int capacity,os::IAllocator * mainAllocator,os::IAllocator * deviceAllocator)424 ParticleShape::Create(
425 ResSceneObject resource,
426 int capacity,
427 os::IAllocator* mainAllocator,
428 os::IAllocator* deviceAllocator
429 )
430 {
431 NW_NULL_ASSERT(mainAllocator);
432 NW_NULL_ASSERT(deviceAllocator);
433
434 ResParticleShape resNode = ResDynamicCast<ResParticleShape>(resource);
435 NW_ASSERT(resNode.IsValid());
436
437 const int streamSize = (capacity + internal::PARTICLE_SIMD_WIDTH_MAX) * sizeof(u16);
438 const int drawCommandCacheSize = sizeof(u32) * (12 + MAX_ATTRIBUTES_NUM * 6 + MAX_ATTRIBUTES_NUM * 4 + 4);
439 const int primitiveCommandCacheSize = sizeof(u32) * PrimitiveCommandSize;
440 const int deactivateVertexCommandCacheSize = sizeof(u32) * (MAX_ATTRIBUTES_NUM * 8);
441
442 int deviceMemorySize = 0;
443 deviceMemorySize = ut::RoundUp(deviceMemorySize, 32);
444 deviceMemorySize += streamSize;
445 deviceMemorySize = ut::RoundUp(deviceMemorySize, 32);
446 deviceMemorySize += streamSize;
447
448 int nodeMemorySize = sizeof(ParticleShape);
449 nodeMemorySize = ut::RoundUp(nodeMemorySize, 32);
450 nodeMemorySize += drawCommandCacheSize;
451 nodeMemorySize = ut::RoundUp(nodeMemorySize, 32);
452 nodeMemorySize += drawCommandCacheSize;
453 nodeMemorySize = ut::RoundUp(nodeMemorySize, 32);
454 nodeMemorySize += deactivateVertexCommandCacheSize;
455 nodeMemorySize = ut::RoundUp(nodeMemorySize, 32);
456 nodeMemorySize += primitiveCommandCacheSize;
457 nodeMemorySize = ut::RoundUp(nodeMemorySize, 32);
458
459 u8* devicememory = reinterpret_cast<u8*>(deviceAllocator->Alloc(deviceMemorySize, 32));
460 if (devicememory == NULL)
461 {
462 return NULL;
463 }
464
465 u8* nodememory = reinterpret_cast<u8*>(mainAllocator->Alloc(nodeMemorySize, 32));
466 if (nodememory == NULL)
467 {
468 deviceAllocator->Free(devicememory);
469 return NULL;
470 }
471
472 ParticleShape* node = new(nodememory) ParticleShape(
473 capacity,
474 mainAllocator,
475 deviceAllocator,
476 devicememory,
477 resNode);
478 nodememory += sizeof(ParticleShape);
479
480 for (int i = 0; i < 2; ++i)
481 {
482 devicememory = reinterpret_cast<u8*>(ut::RoundUp(devicememory, 32));
483 node->m_PrimitiveBuffer[i] = devicememory;
484 devicememory += streamSize;
485
486 //std::memset(node->m_PrimitiveBuffer[i], 0, streamSize);
487
488 u32 baseAddr = nngxGetPhysicalAddr(nn::gx::GetVramStartAddr(nn::gx::MEM_VRAMA));
489 u32 bufferAddr = nngxGetPhysicalAddr(reinterpret_cast<uptr>(node->m_PrimitiveBuffer[i]));
490
491 NW_ASSERT((bufferAddr - baseAddr) < 0x10000000);
492 node->m_PrimitiveBufferOffset[i] = bufferAddr - baseAddr;
493 }
494
495 for (int side = 0; side < 2; ++side)
496 {
497 nodememory = reinterpret_cast<u8*>(ut::RoundUp(nodememory, 32));
498 node->m_CommandCache[side] = reinterpret_cast<u32*>(nodememory);
499 nodememory += drawCommandCacheSize;
500 }
501
502 nodememory = reinterpret_cast<u8*>(ut::RoundUp(nodememory, 32));
503 node->m_DeactivateVertexCommandCache = reinterpret_cast<u32*>(nodememory);
504 nodememory += deactivateVertexCommandCacheSize;
505
506 nodememory = reinterpret_cast<u8*>(ut::RoundUp(nodememory, 32));
507 node->m_PrimitiveCommandCache = reinterpret_cast<u32*>(nodememory);
508 nodememory += primitiveCommandCacheSize;
509
510 return node;
511 }
512
513 int
AddVertexStreamSize(u32 formatType,int dimension,int capacity,int prevSize)514 ParticleShape::AddVertexStreamSize(
515 u32 formatType,
516 int dimension,
517 int capacity,
518 int prevSize
519 )
520 {
521 int formatSize = 1;
522 switch (formatType)
523 {
524 case GL_FLOAT:
525 formatSize = 4;
526 break;
527 default:
528 NW_FATAL_ERROR("unsupported formatType");
529 }
530
531 int streamSize = (capacity + internal::PARTICLE_SIMD_WIDTH_MAX) * dimension * formatSize;
532
533 prevSize = ut::RoundUp(prevSize, 32);
534 prevSize += streamSize;
535 prevSize = ut::RoundUp(prevSize, 32);
536 prevSize += streamSize;
537
538 return prevSize + streamSize;
539 }
540
541 ParticleShape::VertexAttribute*
AddVertexStream(s32 usage,u32 formatType,int dimension,int capacity,u8 ** memory)542 ParticleShape::AddVertexStream(
543 s32 usage,
544 u32 formatType,
545 int dimension,
546 int capacity,
547 u8** memory
548 )
549 {
550 int formatSize = 1;
551 switch (formatType)
552 {
553 case GL_FLOAT:
554 formatSize = 4;
555 break;
556 default:
557 NW_FATAL_ERROR("unsupported formatType");
558 }
559
560 *memory = reinterpret_cast<u8*>(ut::RoundUp(*memory, 32));
561
562 int streamSize = (capacity + internal::PARTICLE_SIMD_WIDTH_MAX) * dimension * formatSize;
563 void* stream0 = *memory;
564 *memory += streamSize;
565
566 void* stream1 = *memory;
567 *memory += streamSize;
568
569 std::memset(stream0, 0, streamSize);
570 std::memset(stream1, 0, streamSize);
571
572 return this->AddVertexAttribute(
573 usage,
574 formatType,
575 dimension,
576 true,
577 reinterpret_cast<u8*>(stream0),
578 reinterpret_cast<u8*>(stream1));
579 }
580
581 int
AddVertexParamSize(u32 formatType,int dimension,int prevSize)582 ParticleShape::AddVertexParamSize(
583 u32 formatType,
584 int dimension,
585 int prevSize
586 )
587 {
588 int formatSize = 1;
589 switch (formatType)
590 {
591 case GL_FLOAT:
592 formatSize = 4;
593 break;
594 default:
595 NW_FATAL_ERROR("unsupported formatType");
596 }
597
598 prevSize = ut::RoundUp(prevSize, 32);
599
600 int streamSize = dimension * formatSize;
601
602 return prevSize + streamSize;
603 }
604
605 ParticleShape::VertexAttribute*
AddVertexParam(s32 usage,u32 formatType,int dimension,f32 * parameters,u8 ** memory)606 ParticleShape::AddVertexParam(
607 s32 usage,
608 u32 formatType,
609 int dimension,
610 f32* parameters,
611 u8** memory
612 )
613 {
614 NW_UNUSED_VARIABLE(parameters);
615
616 int formatSize = 1;
617 switch (formatType)
618 {
619 case GL_FLOAT:
620 formatSize = 4;
621 break;
622 default:
623 NW_FATAL_ERROR("unsupported formatType");
624 }
625
626 int streamSize = dimension * formatSize;
627 *memory = reinterpret_cast<u8*>(ut::RoundUp(*memory, 32));
628 void* stream = *memory;
629 *memory += streamSize;
630
631 std::memcpy(stream, parameters, streamSize);
632
633 return this->AddVertexAttribute(
634 usage,
635 formatType,
636 dimension,
637 false,
638 reinterpret_cast<u8*>(stream),
639 NULL);
640 }
641
642 //----------------------------------------
ParticleShape(int capacity,os::IAllocator * allocator,os::IAllocator * deviceAllocator,void * deviceMemory,ResParticleShape resObj)643 ParticleShape::ParticleShape(
644 int capacity,
645 os::IAllocator* allocator,
646 os::IAllocator* deviceAllocator,
647 void* deviceMemory,
648 ResParticleShape resObj)
649 : SceneObject(allocator, resObj),
650 m_Capacity(capacity),
651 m_BufferSide(false),
652 m_ResVertexAttributeDataCount(0),
653 m_DeviceAllocator(deviceAllocator),
654 m_DeviceMemory(deviceMemory)
655 {
656 m_PrimitiveBuffer[0] = NULL;
657 m_PrimitiveBuffer[1] = NULL;
658 m_PrimitiveBufferOffset[0] = 0;
659 m_PrimitiveBufferOffset[1] = 0;
660
661 for (int usage = 0; usage < PARTICLEUSAGE_COUNT; ++usage)
662 {
663 for (int side = 0; side < 2; ++side)
664 {
665 m_VertexAttribute[usage].m_Stream[side] = NULL;
666 m_VertexAttribute[usage].m_CommandPtr[side] = NULL;
667 }
668 }
669
670 for (int i = 0; i < 2; ++i)
671 {
672 m_CommandCache[i] = NULL;
673 m_CommandCacheSize[i] = 0;
674 }
675
676 m_DeactivateVertexCommandCache = NULL;
677 m_DeactivateVertexCommandCacheSize = 0;
678 m_PrimitiveCommandCache = NULL;
679 m_PrimitiveCommandCacheSize = 0;
680 }
681
682 //----------------------------------------
~ParticleShape()683 ParticleShape::~ParticleShape()
684 {
685 m_DeviceAllocator->Free(m_DeviceMemory);
686
687 for (int i = 0; i < 2; ++ i)
688 {
689 if (this->m_CommandCache[i] != NULL)
690 {
691 this->m_CommandCache[i] = NULL;
692 this->m_CommandCacheSize[i] = 0;
693 }
694 }
695
696 if (this->m_DeactivateVertexCommandCache != NULL)
697 {
698 this->m_DeactivateVertexCommandCache = NULL;
699 this->m_DeactivateVertexCommandCacheSize = 0;
700 }
701
702 if (this->m_PrimitiveCommandCache != NULL)
703 {
704 this->m_PrimitiveCommandCache = NULL;
705 this->m_PrimitiveCommandCacheSize = 0;
706 }
707 }
708
709 void
FlushBuffer()710 ParticleShape::FlushBuffer()
711 {
712 for (s32 i = 0; i < this->GetVertexAttributesCount(); ++i)
713 {
714 if (this->IsVertexStream(i))
715 {
716 nngxUpdateBuffer(
717 this->GetVertexStreamPtr(i, PARTICLE_BUFFER_FRONT),
718 this->GetVertexCapacity() * this->GetVertexAttributeDimension(i) * sizeof(f32));
719 }
720 }
721
722 nngxUpdateBuffer(
723 this->GetPrimitiveStreamPtr(PARTICLE_BUFFER_FRONT),
724 this->GetVertexCapacity() * sizeof(u16));
725 }
726
727 } // namespace gfx
728 } // namespace nw
729