| 1084 | } |
| 1085 | |
| 1086 | void DrawEmitterGPU(RenderContextBatch& renderContextBatch, ParticleBuffer* buffer, DrawCall& drawCall, DrawPass drawModes, StaticFlags staticFlags, const BoundingSphere& bounds, uint32 renderModulesIndices, int8 sortOrder) |
| 1087 | { |
| 1088 | // Setup drawing data |
| 1089 | uint32 indirectArgsSize = 0; |
| 1090 | ParticleEmitter* emitter = buffer->Emitter; |
| 1091 | for (int32 moduleIndex = 0; moduleIndex < emitter->Graph.RenderModules.Count(); moduleIndex++) |
| 1092 | { |
| 1093 | if ((renderModulesIndices & (1u << moduleIndex)) == 0) |
| 1094 | continue; |
| 1095 | auto module = emitter->Graph.RenderModules.Get()[moduleIndex]; |
| 1096 | switch (module->TypeID) |
| 1097 | { |
| 1098 | // Sprite Rendering |
| 1099 | case 400: |
| 1100 | indirectArgsSize += sizeof(GPUDrawIndexedIndirectArgs); |
| 1101 | break; |
| 1102 | // Model Rendering |
| 1103 | case 403: |
| 1104 | { |
| 1105 | const auto model = (Model*)module->Assets[0].Get(); |
| 1106 | // TODO: model LOD picking for particles? |
| 1107 | int32 lodIndex = 0; |
| 1108 | ModelLOD& lod = model->LODs[lodIndex]; |
| 1109 | indirectArgsSize += sizeof(GPUDrawIndexedIndirectArgs) * lod.Meshes.Count(); |
| 1110 | break; |
| 1111 | } |
| 1112 | } |
| 1113 | } |
| 1114 | if (indirectArgsSize == 0) |
| 1115 | return; |
| 1116 | bool sorting = EmitterUseSorting(renderContextBatch, buffer, drawModes, bounds) && (buffer->GPU.ParticlesCountMax != 0 || buffer->GPU.SortedIndices); |
| 1117 | if (sorting && !buffer->GPU.SortedIndices) |
| 1118 | buffer->AllocateSortBuffer(); |
| 1119 | |
| 1120 | // When rendering in async, delay GPU particles drawing to be in sync by moving drawing into delayed callback post scene drawing to use GPUContext safely |
| 1121 | // Also, batch rendering all GPU emitters together for more efficient usage of GPU memory barriers and indirect arguments buffers allocation |
| 1122 | RenderContext::GPULocker.Lock(); |
| 1123 | if (GPUEmitterDraws.Count() == 0) |
| 1124 | { |
| 1125 | // The first emitter schedules the drawing of all batched draws |
| 1126 | renderContextBatch.GetMainContext().List->AddDelayedDraw([](GPUContext* context, RenderContextBatch& renderContextBatch, int32 renderContextIndex) |
| 1127 | { |
| 1128 | DrawEmittersGPU(context, renderContextBatch); |
| 1129 | }); |
| 1130 | } |
| 1131 | GPUEmitterDraws.Add({ buffer, drawCall, drawModes, staticFlags, bounds, renderModulesIndices, indirectArgsSize, sortOrder, sorting }); |
| 1132 | RenderContext::GPULocker.Unlock(); |
| 1133 | } |
| 1134 | |
| 1135 | #endif |
| 1136 |
no test coverage detected