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