@@ -88,9 +88,9 @@ Renderer::Renderer(IVideoDriver* _driver, IAssetManager* _assetManager, scene::I
88
88
}
89
89
{
90
90
#ifndef DISABLE_NEE
91
- constexpr auto additionalGlobalDescriptorCount = 6u ;
91
+ constexpr auto additionalGlobalDescriptorCount = 5u ;
92
92
#else
93
- constexpr auto additionalGlobalDescriptorCount = 4u ;
93
+ constexpr auto additionalGlobalDescriptorCount = 3u ;
94
94
#endif
95
95
IGPUDescriptorSetLayout::SBinding bindings[additionalGlobalDescriptorCount];
96
96
fillIotaDescriptorBindingDeclarations (bindings,ISpecializedShader::ESS_COMPUTE|ISpecializedShader::ESS_VERTEX|ISpecializedShader::ESS_FRAGMENT,additionalGlobalDescriptorCount,asset::EDT_STORAGE_BUFFER);
@@ -209,7 +209,7 @@ Renderer::InitializationData Renderer::initSceneObjects(const SAssetBundle& mesh
209
209
info.buffer .offset = 0u ;
210
210
info.desc = std::move (buf);
211
211
};
212
- constexpr uint32_t writeBound = 4u ;
212
+ constexpr uint32_t writeBound = 3u ;
213
213
IGPUDescriptorSet::SWriteDescriptorSet writes[writeBound];
214
214
auto recordSSBOWrite = [](IGPUDescriptorSet::SWriteDescriptorSet& write, IGPUDescriptorSet::SDescriptorInfo* infos, uint32_t binding, uint32_t count=1u ) -> void
215
215
{
@@ -250,15 +250,17 @@ Renderer::InitializationData Renderer::initSceneObjects(const SAssetBundle& mesh
250
250
251
251
constexpr uint8_t kIndicesPerTriangle = 3u ;
252
252
constexpr uint16_t minIndicesBatch = minTrisBatch*kIndicesPerTriangle ;
253
-
253
+
254
254
CPUMeshPacker::AllocationParams allocParams;
255
255
allocParams.vertexBuffSupportedByteSize = 1u <<31u ;
256
256
allocParams.vertexBufferMinAllocByteSize = minTrisBatch*minVertexSize;
257
257
allocParams.indexBuffSupportedCnt = (allocParams.vertexBuffSupportedByteSize /allocParams.vertexBufferMinAllocByteSize )*minIndicesBatch;
258
258
allocParams.indexBufferMinAllocCnt = minIndicesBatch;
259
259
allocParams.MDIDataBuffSupportedCnt = allocParams.indexBuffSupportedCnt /minIndicesBatch;
260
260
allocParams.MDIDataBuffMinAllocCnt = 1u ; // so structs from different meshbuffers are adjacent in memory
261
-
261
+
262
+ constexpr auto combinedNormalUVAttributeIx = 1 ;
263
+
262
264
auto cpump = core::make_smart_refctd_ptr<CCPUMeshPackerV2<>>(allocParams,minTrisBatch,maxTrisBatch);
263
265
uint32_t mdiBoundMax=0u ,batchInstanceBoundTotal=0u ;
264
266
core::vector<CPUMeshPacker::ReservedAllocationMeshBuffers> allocData;
@@ -274,7 +276,39 @@ Renderer::InitializationData Renderer::initSceneObjects(const SAssetBundle& mesh
274
276
assert (!meshBuffers.empty ());
275
277
const uint32_t instanceCount = (*meshBuffers.begin ())->getInstanceCount ();
276
278
for (auto mbIt=meshBuffers.begin (); mbIt!=meshBuffers.end (); mbIt++)
277
- assert ((*mbIt)->getInstanceCount ()==instanceCount);
279
+ {
280
+ auto meshBuffer = *mbIt;
281
+ assert (meshBuffer->getInstanceCount ()==instanceCount);
282
+ // We'll disable certain attributes to ensure we only copy position, normal and uv attribute
283
+ SVertexInputParams& vertexInput = meshBuffer->getPipeline ()->getVertexInputParams ();
284
+ // but we'll pack normals and UVs together to save one SSBO binding (and quantize UVs to half floats)
285
+ constexpr auto freeBinding = 15u ;
286
+ vertexInput.attributes [combinedNormalUVAttributeIx].binding = freeBinding;
287
+ vertexInput.attributes [combinedNormalUVAttributeIx].format = EF_R32G32_UINT;
288
+ vertexInput.attributes [combinedNormalUVAttributeIx].relativeOffset = 0u ;
289
+ vertexInput.enabledBindingFlags |= 0x1u <<freeBinding;
290
+ vertexInput.bindings [freeBinding].inputRate = EVIR_PER_VERTEX;
291
+ vertexInput.bindings [freeBinding].stride = 0u ;
292
+ auto newBuff = core::make_smart_refctd_ptr<ICPUBuffer>(sizeof (uvec2)*IMeshManipulator::upperBoundVertexID (meshBuffer));
293
+ auto * dst = reinterpret_cast <uvec2*>(newBuff->getPointer ());
294
+ meshBuffer->setVertexBufferBinding ({0u ,newBuff},freeBinding);
295
+ // copy and pack data
296
+ const uint8_t * nmlSrc = meshBuffer->getAttribPointer (meshBuffer->getNormalAttributeIx ());
297
+ const auto stride = meshBuffer->getAttribStride (combinedNormalUVAttributeIx);
298
+ for (auto i=0u ; i<meshBuffer->getIndexCount (); i++)
299
+ {
300
+ const auto ix = meshBuffer->getIndexValue (i);
301
+ if (nmlSrc)
302
+ dst[ix].x = *reinterpret_cast <const uint32_t *>(nmlSrc+ix*stride);
303
+ else
304
+ dst[ix].x = 0xdeadbeefu ; // should warn about getting a mesh with no normals
305
+ core::vectorSIMDf uv;
306
+ meshBuffer->getAttribute (uv,2u ,ix);
307
+ reinterpret_cast <uint16_t *>(&dst[ix].y )[0 ] = core::Float16Compressor::compress (uv.x );
308
+ reinterpret_cast <uint16_t *>(&dst[ix].y )[1 ] = core::Float16Compressor::compress (uv.y );
309
+ }
310
+ vertexInput.enabledAttribFlags = (0x1u <<combinedNormalUVAttributeIx)|0b1 ;
311
+ }
278
312
279
313
const uint32_t mdiBound = cpump->calcMDIStructMaxCount (meshBuffers.begin (),meshBuffers.end ());
280
314
mdiBoundMax = core::max (mdiBound,mdiBoundMax);
@@ -356,22 +390,20 @@ Renderer::InitializationData Renderer::initSceneObjects(const SAssetBundle& mesh
356
390
indexCount/kIndicesPerTriangle
357
391
);
358
392
359
- const auto normalAttrID = mb->getNormalAttributeIx ();
360
393
const auto thisShapeInstancesBeginIx = rrInstances.size ();
361
394
const auto & batchAABB = mb->getBoundingBox ();// TODO: replace with batch AABB
362
395
for (auto auxIt=instanceAuxData.begin (); auxIt!=instanceAuxData.end (); auxIt++)
363
396
{
364
- constexpr auto UVAttributeIx = 2 ;
365
397
const auto batchInstanceGUID = cullData.size ();
366
398
367
399
const auto instanceID = std::distance (instanceAuxData.begin (),auxIt);
368
400
*newInstanceData = mbInstanceData[instanceID];
369
401
assert (instanceData.begin ()[instanceID].worldTform ==newInstanceData->tform );
370
- newInstanceData->padding0 = reinterpret_cast < const uint32_t &>(cdotIt-> attribInfo [posAttrID]) ;
371
- newInstanceData->padding1 = reinterpret_cast <const uint32_t &>(cdotIt->attribInfo [normalAttrID ]);
402
+ newInstanceData->padding0 = firstIndex ;
403
+ newInstanceData->padding1 = reinterpret_cast <const uint32_t &>(cdotIt->attribInfo [posAttrID ]);
372
404
newInstanceData->determinantSignBit = core::bitfieldInsert (
373
405
newInstanceData->determinantSignBit ,
374
- reinterpret_cast <const uint32_t &>(cdotIt->attribInfo [UVAttributeIx ]),
406
+ reinterpret_cast <const uint32_t &>(cdotIt->attribInfo [combinedNormalUVAttributeIx ]),
375
407
0u ,31u
376
408
);
377
409
if (frontFaceIsCCW) // compensate for Nabla's default camera being left handed
@@ -446,7 +478,7 @@ Renderer::InitializationData Renderer::initSceneObjects(const SAssetBundle& mesh
446
478
recordInfoBuffer (infos[i],core::smart_refctd_ptr (dataStore.vertexBuffer ));
447
479
recordSSBOWrite (writes[i],infos+i,i);
448
480
}
449
- recordInfoBuffer (infos[2 ],core::smart_refctd_ptr (m_indexBuffer));
481
+ recordInfoBuffer (infos[1 ],core::smart_refctd_ptr (m_indexBuffer));
450
482
451
483
setDstSetOnAllWrites (m_additionalGlobalDS.get ());
452
484
m_driver->updateDescriptorSets (writeBound,writes,0u ,nullptr );
@@ -866,7 +898,7 @@ void Renderer::init(const SAssetBundle& meshes, core::smart_refctd_ptr<ICPUBuffe
866
898
createFilledBufferAndSetUpInfoFromVector (infos+0 ,initData.lightCDF );
867
899
createFilledBufferAndSetUpInfoFromVector (infos+1 ,initData.lights );
868
900
869
- setDstSetAndDescTypesOnWrites (m_additionalGlobalDS.get (),writes,infos,{EDT_STORAGE_BUFFER,EDT_STORAGE_BUFFER},4u );
901
+ setDstSetAndDescTypesOnWrites (m_additionalGlobalDS.get (),writes,infos,{EDT_STORAGE_BUFFER,EDT_STORAGE_BUFFER},3u );
870
902
}
871
903
m_driver->updateDescriptorSets (descriptorUpdateCounts[0 ],writes,0u ,nullptr );
872
904
#endif
0 commit comments