Hi! I’m stuck on a display bug since several weeks now. I defines offsets with reference vertices and indices positions of first vertices/indices mesh on the buffers, depending on the visible mesh and the lod level, and my compute shader which generate draw commands of visible meshes, like this :
#version 460 GL_EXT_debug_printf : enable MAX_BONE_INFLUENCE 4 MAX_BONES 100 NB_PRIMITIVE_TYPES 6 MAX_FRAMES_IN_FLIGHT 2/Boîtes englobantes des objets/const uint opaqueMask = 1 << 0;const uint transparentMask = 1 << 1;const uint rtPipeline = 2 << 1;const uint rasterPipeline = 3 << 1;struct AABB {vec4 center;vec4 size;};/Objets/struct Object {AABB globalBounds;int id; int type;int subMeshesOffset;int modelDataOffset; int nbSubMeshes;int renderingType; };struct LODLevel {uint index_offset;uint index_count;int mesheltOffset;int meshletCount;};/subMesh/struct SubMesh {AABB globalBounds;int vertexOffset;int indexOffset;int primitiveType;int materialId;int nbVertices;int nbIndexes;int lodOffset;int id;int lodLevel;int objectId;int meshletOffset;int meshletCount;};/Matrices/struct ModelData {mat4 modelMatrix;mat4 shadowProjMatrix;mat4 borderMatrices;};/Matériaux/struct MaterialData {uint diffuseTextureIndex;uint specularTextureIndex;uint normalTextureIndex;uint metalnessTextureIndex;uint roughnessTextureIndex;uint aoTextureIndex;uint emissiveTextureIndex;uint materialType;uint taskOffset;uint nbVertices;uint nbIndexes;int instanceGroupId;uint vertsInstanceSet;uint materialId;uint nbBuffers;uint opaque;uint pipelineType;};struct IndirectElementsDrawCommand {uint index_count;uint instance_count;uint first_index; // cf parametre offset de glDrawElements()uint vertex_base;uint instance_base;};/objets en entrée./layout(push_constant) uniform PushConstant {uint currentFrame;uint opaqueMask;} pc;layout (set = 0, binding = 0) buffer ObjectTypesSSBO {int types;} objectTypes[MAX_FRAMES_IN_FLIGHT];layout (std430, set = 0, binding = 1) buffer inputObjectSSBO {Object objects;} inputObjectBuffer;/SubMeshes en entrée./layout (std430, set = 0, binding = 2) buffer inputSubmeshesSSBO {SubMesh subMeshes;} inputSubmeshesBuffer;/matrices en entrée./layout (std430, set = 0, binding = 3) buffer inputModelDataSSBO {ModelData modelData;} inputModelData;/matériaux en entrée./layout (std430, set = 0, binding = 4) buffer inputMaterialDataSSBO {MaterialData materialData;} inputMaterialData[NB_PRIMITIVE_TYPESMAX_FRAMES_IN_FLIGHT];/matériaux en sortie./layout (std430, set = 0, binding = 5) buffer outputMaterialDataSSBO {MaterialData materialData[];} outputMaterialData[NB_PRIMITIVE_TYPESMAX_FRAMES_IN_FLIGHT];/matrices des objets visibles pour les instances en sortie./layout (std430, set = 0, binding = 6) buffer outputModelDataSSBO {ModelData modelData;} outputModelData[NB_PRIMITIVE_TYPESMAX_FRAMES_IN_FLIGHT];/Matrices des objets visible en sortie pour les non instances/layout (std430, set = 0, binding = 7) buffer outputObjectDataSSBO {SubMesh meshData[];} outputMeshesData[NB_PRIMITIVE_TYPESMAX_FRAMES_IN_FLIGHT];/position dans le buffer de matrices de sortie pour les instance/layout (std430, set = 0, binding = 8) buffer offsetInOutputModelDataSSBO {uint modelDataOffset;} offsetInOutputModelData[NB_PRIMITIVE_TYPESMAX_FRAMES_IN_FLIGHT];/position dans le buffer des matrices de sortie/layout (std430, set = 0, binding = 9) buffer offsetInOutputMeshDataSSBO {uint meshDataOffset;} offsetInOutputMeshData[NB_PRIMITIVE_TYPESMAX_FRAMES_IN_FLIGHT];/Nombre de commandes pour le rendu indirect./layout (std430, set = 0, binding = 10) buffer outputIndirectDrawCountSSBO {uint drawCount;} outputDrawCount[NB_PRIMITIVE_TYPESMAX_FRAMES_IN_FLIGHT];layout (std430, set = 0, binding = 11) buffer outputIndirectElementCommandSSBO {IndirectElementsDrawCommand indirectElementsDrawCommands[];} outputIndirectElementsDrawCommands[NB_PRIMITIVE_TYPESMAX_FRAMES_IN_FLIGHT];/position dans le buffer de commandes pour le rendu indirect./layout (std430, set = 0, binding = 12) buffer offsetInOutputElementsIndirectCommandSSBO {uint offsetIndirectElementsDrawCommand;} offsetInOutputIndirectElementsDrawCommand[NB_PRIMITIVE_TYPESMAX_FRAMES_IN_FLIGHT];/Buffer pour données de la frame/layout (std430, set = 0, binding = 13) buffer offsetOutputMaterialSSBO {uint materialOffset;} offsetInOutputMaterial[NB_PRIMITIVE_TYPESMAX_FRAMES_IN_FLIGHT];layout (std430, set = 0, binding = 14) buffer outputInstanceBaseSSBO {uint instanceBase;} outputInstanceBase[NB_PRIMITIVE_TYPESMAX_FRAMES_IN_FLIGHT];layout (std140, set = 0, binding = 15) uniform UniformBufferObject {AABB frustrum; uint nbObjectTypes;uint gridCellCount[5];ivec4 gridCellSize[5];ivec4 nbCellsPerRow[5];ivec4 gridSize[5];ivec4 gridPos[5];} ubo[MAX_FRAMES_IN_FLIGHT];layout (std430, set=0, binding = 16) buffer LodLevelBuffer {LODLevel lodLevel[];} lodLevelData;layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;bool intersects (AABB first, AABB second) {float hx1 = first.size.x * 0.5;float hy1 = first.size.y * 0.5;float hz1 = first.size.z * 0.5;float hx2 = second.size.x * 0.5;float hy2 = second.size.y * 0.5;float hz2 = second.size.z * 0.5;//Check the mins and max medians positions.float minX1 = first.center.x - hx1;float minX2 = second.center.x - hx2;float minY1 = first.center.y - hy1;float minY2 = second.center.y - hy2;float minZ1 = first.center.z - hz1;float minZ2 = second.center.z - hz2;float maxX1 = first.center.x + hx1;float maxX2 = second.center.x + hx2;float maxY1 = first.center.y + hy1;float maxY2 = second.center.y + hy2;float maxZ1 = first.center.z + hz1;float maxZ2 = second.center.z + hz2;//If the medians overlap, our two boxes intersects.for (int i = 0; i < 3; i++) {if (i == 0) {if (minX1 > maxX2 || maxX1 < minX2)return false;} else if (i == 1) {if (minY1 > maxY2 || maxY1 < minY2)return false;} else {if (minZ1 > maxZ2 || maxZ1 < minZ2)return false;}}return true;}void main() {//debugPrintfEXT("nb object types : %i, %i, %i",gl_GlobalInvocationID.x, gl_GlobalInvocationID.y, gl_GlobalInvocationID.z);Object object = inputObjectBuffer.objects[gl_GlobalInvocationID.x];uint materialId = gl_GlobalInvocationID.y;uint primitiveType = gl_GlobalInvocationID.z;//debugPrintfEXT("nb object types : %v3f, %v3f, %i",ubo[pc.currentFrame].frustrum.center, ubo[pc.currentFrame].frustrum.size, ubo[pc.currentFrame].nbObjectTypes);memoryBarrier();for (uint t = 0; t < ubo[pc.currentFrame].nbObjectTypes; t++) {//debugPrintfEXT("type : %i,%i", t, object.type );if (object.type == objectTypes[pc.currentFrame].types[t] && intersects(object.globalBounds, ubo[pc.currentFrame].frustrum)) {//debugPrintfEXT("Object in frustrum : %v3f %v3f", ubo[pc.currentFrame].frustrum.center, ubo[pc.currentFrame].frustrum.size);//debugPrintfEXT("nb sub meshes : %i", object.nbSubMeshes); //Regroupement des données par matériaux et par type de primitive. (Batching)for (uint s = 0; s < object.nbSubMeshes; s++) {SubMesh subMesh = inputSubmeshesBuffer.subMeshes[object.subMeshesOffset+s];MaterialData material = inputMaterialData[primitiveTypeMAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId];//debugPrintfEXT("opaque mask : %i %i", rasterPipeline, material.pipelineType);if ((pc.opaqueMask & material.opaque) != 0&& ((rasterPipeline & material.pipelineType) != 0) && subMesh.materialId == materialId && subMesh.primitiveType == primitiveType&& intersects(subMesh.globalBounds, ubo[pc.currentFrame].frustrum)) {//debugPrintfEXT("submesh in frustrum %i", s);float dist = distance(ubo[pc.currentFrame].frustrum.center, subMesh.globalBounds.center);float lodStep = 20.0;int lod = clamp(int(dist / lodStep), 0, 4);//debugPrintfEXT("primitiveType : %i", subMesh.primitiveType);//Vérifie si les sommets pour l'instance n'ont pas déjà été ajoutés. (Les instances sont regroupée par instanceGroupId dans matériaux)//Si le matériel est instancé.if (inputMaterialData[primitiveTypeMAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId].instanceGroupId != -1) {debugPrintfEXT("Instanced! %i", inputMaterialData[primitiveTypeMAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId].instanceGroupId); uint instanceBase = atomicAdd(outputInstanceBase[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].instanceBase, 1);
//Si la commande n'est pas encore ajoutée pour cette instance, on l'ajoute.
if(inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId].vertsInstanceSet == 0) {
inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId].vertsInstanceSet = 1;
uint indirectElementsDrawCommandOffset = atomicAdd(outputDrawCount[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].drawCount, 1);
inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId].taskOffset = indirectElementsDrawCommandOffset;
IndirectElementsDrawCommand indirectElementsDrawCommand;
indirectElementsDrawCommand.index_count = lodLevelData.lodLevel[subMesh.lodOffset+lod].index_count;
indirectElementsDrawCommand.first_index = subMesh.indexOffset + lodLevelData.lodLevel[subMesh.lodOffset+lod].index_offset;
/*indirectElementsDrawCommand.index_count = subMesh.nbIndexes;
indirectElementsDrawCommand.first_index = subMesh.indexOffset;*/
indirectElementsDrawCommand.instance_base = instanceBase;
indirectElementsDrawCommand.vertex_base = subMesh.vertexOffset;
outputIndirectElementsDrawCommands[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].indirectElementsDrawCommands[indirectElementsDrawCommandOffset] = indirectElementsDrawCommand;
MaterialData material = inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId];
material.materialId = materialId;
outputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[indirectElementsDrawCommandOffset] = material;
}
ModelData modelData = inputModelData.modelData[object.modelDataOffset];
outputModelData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].modelData[instanceBase] = modelData;
//nombre d'instances + 1.
uint indirectElementsDrawCommandOffset = inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId].taskOffset;
outputIndirectElementsDrawCommands[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].indirectElementsDrawCommands[indirectElementsDrawCommandOffset].instance_count++;
//Matériel non instancé.
} else {
uint indirectElementsDrawCommandOffset = atomicAdd(outputDrawCount[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].drawCount, 1);
uint instanceBase = atomicAdd(outputInstanceBase[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].instanceBase, 1);
uint offsetInOutputMeshData = atomicAdd(offsetInOutputMeshData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].meshDataOffset, 1);
//debugPrintfEXT("indexes! %i, draw count : %i", instanceBase, indirectElementsDrawCommandOffset );
IndirectElementsDrawCommand indirectElementsDrawCommand;
/*if (subMesh.id == 1590)
debugPrintfEXT("submesh id : %i, vertex offset : %i, nb vertices : %i", subMesh.id, subMesh.vertexOffset, subMesh.nbVertices);*/
/*if (subMesh.lodOffset + lod >= 215)
debugPrintfEXT("lodOffset=%d lod=%d\n", subMesh.lodOffset, lod);*/
indirectElementsDrawCommand.index_count = lodLevelData.lodLevel[subMesh.lodOffset+lod].index_count;
indirectElementsDrawCommand.first_index = subMesh.indexOffset + lodLevelData.lodLevel[subMesh.lodOffset+lod].index_offset;
/*indirectElementsDrawCommand.index_count = subMesh.nbIndexes;
indirectElementsDrawCommand.first_index = subMesh.indexOffset;*/
indirectElementsDrawCommand.instance_base = instanceBase;
indirectElementsDrawCommand.vertex_base = subMesh.vertexOffset;
indirectElementsDrawCommand.instance_count = 1;
//debugPrintfEXT("offsets : %i, %i, %i, %i", indirectElementsDrawCommand.first_index, indirectElementsDrawCommand.index_count, indirectElementsDrawCommand.instance_base, indirectElementsDrawCommand.vertex_base);
//debugPrintfEXT("lod infos : %i, %i",subMesh.lodLevel[lod].index_offset,subMesh.lodLevel[lod].index_count);
//debugPrintfEXT("instance base %i", instanceBase);
outputIndirectElementsDrawCommands[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].indirectElementsDrawCommands[indirectElementsDrawCommandOffset] = indirectElementsDrawCommand;
//debugPrintfEXT("indirect elements draw command offset : %i", indirectElementsDrawCommandOffset);
ModelData modelData = inputModelData.modelData[object.modelDataOffset];
//debugPrintfEXT("model data matrix : %v4f\n%v4f\n%v4f\n%v4f", modelData.modelMatrix[0], modelData.modelMatrix[1], modelData.modelMatrix[2], modelData.modelMatrix[3]);
//debugPrintfEXT("object data offset : %i",objectDataOffset);
outputModelData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].modelData[instanceBase] = modelData;
//debugPrintfEXT("offset model : %i", instanceBase);
MaterialData material = inputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[materialId];
//material.materialId = materialId;
//debugPrintfEXT("culling shader draw id : %i, material id : %i", indirectElementsDrawCommandOffset, materialId);
/*if (subMesh.materialId == 1)
debugPrintfEXT("sm id : %i, diffuse tex id : %i", subMesh.id, material.diffuseTextureIndex);*/
outputMaterialData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].materialData[indirectElementsDrawCommandOffset] = material;
outputMeshesData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].meshData[offsetInOutputMeshData] = subMesh;
//debugPrintfEXT("material datas %v2f", material.uvScale);
//debugPrintfEXT("Output Model Matrix : %i\n%v4f\n%v4f\n%v4f\n%v4f",objectDataOffset,outputObjectData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].objectData[objectDataOffset].modelMatrix[0], outputObjectData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].objectData[objectDataOffset].modelMatrix[1], outputObjectData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].objectData[objectDataOffset].modelMatrix[2], outputObjectData[primitiveType*MAX_FRAMES_IN_FLIGHT+pc.currentFrame].objectData[objectDataOffset].modelMatrix[3]);
}
} /*else {
debugPrintfEXT("doesn't intersects");
} */
}
}
}
}
and my c++ code :
for (unsigned int j = 0; j < gameObjects[i]->getGameObject()->getSubMeshesCount(); j++) {
//std::cout<<"add subMesh : "<<j<<std::endl;
entity::SubMesh& subMesh = gameObjects\[i\]->getGameObject()->getSubMeshes()\[j\];
gameObjects\[i\]->getGameObject()->getSubMeshes()\[j\].vertexOffset = currentVertexOffset\[subMesh.getVertexArray().getPrimitiveType()\];
gameObjects\[i\]->getGameObject()->getSubMeshes()\[j\].indexOffset = currentIndexOffset\[subMesh.getVertexArray().getPrimitiveType()\];
SubMeshData subMeshData;
physic::BoundingBox subMeshGlobalBounds = subMesh.getVertexArray().getGlobalBounds(gameObjects\[i\]->getGameObject()->getTransform());
/\*if (!subMeshGlobalBounds.intersects(m_camera.getViewVolume())) {
std::cout<<"out of furstrum"<<std::endl;
}\*/
AABB subMeshAABB;
subMeshData.id = currentSubmeshesOffset;
float center\[4\], size\[4\];
subMeshGlobalBounds.getCenter().toVkVec(center);
subMeshGlobalBounds.getSize().toVkVec(size);
core::arrayCopy(center, subMeshAABB.center, 3);
core::arrayCopy(size, subMeshAABB.size, 3);
//std::cout<<"submesh offset : "<<currentSubmeshesOffset<<","<<gameObjects\[i\]->getSubMeshesCount()<<std::endl;
subMeshData.globalBounds = subMeshAABB;
unsigned int primitiveType = subMesh.getVertexArray().getPrimitiveType();
subMeshData.primitiveType = primitiveType;
subMeshData.vertexOffset = currentVertexOffset\[primitiveType\];
subMeshData.indexOffset = currentIndexOffset\[primitiveType\];
for (unsigned int m = 0; m < materials.size(); m++) {
//std::cout<<"j"<<" "<<gameObjects\[i\]->getMaterials().size()<<std::endl;
if (\*materials\[m\] == \*gameObjects\[i\]->getMaterials()\[j\]) {
/\*if (materials\[m\]->getTexture(entity::SubMesh::DIFFUSE) != nullptr && materials\[m\]->getTexture(entity::SubMesh::DIFFUSE)->getId() == 4) {
std::cout<<"ids : "<<subMeshData.id<<","<<gameObjects\[i\]->getMaterials()\[j\]->getId()<<","<<materialDatas\[gameObjects\[i\]->getMaterials()\[j\]->getId()\].diffuseTextureIndex<<std::endl;
system("PAUSE");
}\*/
//std::cout<<"reflectable "<<materials\[m\]->isReflectable()<<"refractable : "<<materials\[m\]->isRefractable()<<std::endl;
subMeshData.materialId = gameObjects\[i\]->getMaterials()\[j\]->getId();
/\*if (subMeshData.materialId > 0)
system("PAUSE");\*/
subMesh.materialId = gameObjects\[i\]->getMaterials()\[j\]->getId();
/\*if (materials\[m\]->isReflectable())
std::cout<<"material id : "<<subMeshData.materialId<<std::endl;
system("PAUSE");\*/
}
}
subMeshData.nbVertices = subMesh.getVertexArray().getVertexCount();
subMeshData.nbIndexes = subMesh.getVertexArray().getIndexCount();
subMeshData.objectId = i;
/\*if (subMeshData.id == 1590) {
std::cout<<"id : vertex offset : nbVertices : "<<subMeshData.id<<","<<subMeshData.vertexOffset<<","<<subMeshData.nbVertices<<std::endl;
system("PAUSE");
}\*/
//std::cout<<"vertices count : "<<subMesh.getVertexBuffer().getVertexCount()<<std::endl;
/\*int pause;
std::cin>>pause;\*/
//std::cout<<"index count : "<<subMesh.getVertexBuffer().getIndexCount()<<std::endl;
/\*std::cout<<"total vertex count : "<<vertices\[primitiveType\].getVertexCount()<<std::endl;
std::cout<<"total index count : "<<vertices\[primitiveType\].getIndexCount()<<std::endl;\*/
//std::cout<<"vertx offset, texture id : "<<currentVertexOffset\[primitiveType\]<<","<<subMeshData.materialId<<std::endl;
subMesh.getVertexArray().updateLods();
//std::cout<<"vertex offset : "<<currentVertexOffset\[primitiveType\]<<std::endl;
unsigned int baseVertex = currentVertexOffset\[primitiveType\];
//std::cout<<"base vertex : "<<subMeshData.vertexOffset <<"nb vertices : "<<subMeshData.nbVertices<<std::endl;
if (gameObjects\[i\]->getMaterials()\[j\]->getInstanceGroupId() == -1 || (gameObjects\[i\]->getMaterials()\[j\]->getInstanceGroupId() != -1 && !gameObjects\[i\]->getMaterials()\[j\]->materialSet)) {
gameObjects\[i\]->getMaterials()\[j\]->materialSet = true;
for (unsigned int v = 0; v < subMesh.getVertexArray().getVertexCount(); v++) {
//std::cout<<"add vertex : "<<subMesh.getVertexBuffer()\[v\].position<<std::endl;
/\*if (subMeshData.id == 2)
std::cout<<"position : "<<subMesh.getVertexArray()\[v\].position<<std::endl;\*/
vertices\[primitiveType\].append(subMesh.getVertexArray()\[v\]);
vertices\[primitiveType\]\[baseVertex+v\].drawableDataId = currentSubmeshesOffset;
//std::cout<<"drawable data id : "<<vertices\[primitiveType\]\[v\].drawableDataId<<std::endl;
currentVertexOffset\[primitiveType\]++;
}
for (unsigned int v = 0; v < subMesh.getVertexArray().getIndexCount(); v++) {
uint32_t idx = subMesh.getVertexArray().getIndex(v);
vertices\[primitiveType\].addIndex(idx);
/\*if (subMeshData.id == 2) {
std::cout<<"index : "<<subMesh.getVertexArray().getIndex(v)<<std::endl;
system("PAUSE");
}\*/
/\*if (v == 0)
std::cout<<"add index : "<<baseVertex<<","<<idx<<std::endl;\*/
currentIndexOffset\[primitiveType\]++;
}
/\*if (subMeshData.id == 2)
system("PAUSE");\*/
}
/\*std::cout<<"new total vertex count : "<<vertices\[primitiveType\].getVertexCount()<<std::endl;
std::cout<<"new total index count : "<<vertices\[primitiveType\].getIndexCount()<<std::endl;\*/
subMeshData.meshletOffset = meshletDatas.size();
std::array<entity::VertexArray::LODLevel, 5> lods = subMesh.getVertexArray().getLODs();
unsigned int currentSubmeshMeshletOffset = meshletDatas.size();
for (unsigned int l = 0; l < lods.size() && lods\[l\].indexCount > 0; l++) {
LODLevelData lodLevelData{};
lodLevelData.index_offset = lods\[l\].indexOffset;
lodLevelData.index_count = lods\[l\].indexCount; .... As this renderdocs capture's shows, for some mesh the gerometry of the bistro scene of lamberyard if totally incoherent. I don't know what's happening.
but some triangles of bistro scene from lamberyard are missing. (As you can see on this renderdoc capture)
For me it’s not how the nvidia driver should work.


