Skip to content

Commit 8b4ccb9

Browse files
committed
Merge material system surfaces
Impoves VS lane usage.
1 parent 3079161 commit 8b4ccb9

3 files changed

Lines changed: 127 additions & 48 deletions

File tree

src/engine/renderer/GeometryOptimiser.cpp

Lines changed: 119 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2727

2828
#include "GeometryOptimiser.h"
2929

30+
#include "ShadeCommon.h"
31+
3032
static int LeafSurfaceCompare( const void* a, const void* b ) {
3133
bspSurface_t* aa, * bb;
3234

@@ -419,33 +421,10 @@ void MergeDuplicateVertices( bspSurface_t** rendererSurfaces, int numSurfaces, s
419421
Log::Notice( "Merged %i vertices into %i in %i ms", numVerticesIn, numVerticesOut, Sys::Milliseconds() - start );
420422
}
421423

422-
/* static void ProcessMaterialSurface( MaterialSurface& surface, std::vector<MaterialSurface>& materialSurfaces,
423-
std::vector<MaterialSurface>& processedMaterialSurfaces,
424-
srfVert_t* verts, glIndex_t* indices ) {
425-
if ( surface.count == MAX_MATERIAL_SURFACE_TRIS ) {
426-
materialSurfaces.emplace_back( surface );
427-
}
428-
429-
while ( surface.count > MAX_MATERIAL_SURFACE_TRIS ) {
430-
MaterialSurface srf = surface;
431-
432-
srf.count = MAX_MATERIAL_SURFACE_TRIS;
433-
surface.count -= MAX_MATERIAL_SURFACE_TRIS;
434-
surface.firstIndex += MAX_MATERIAL_SURFACE_TRIS;
435-
436-
processedMaterialSurfaces.push_back( srf );
437-
}
438-
} */
439-
440424
std::vector<MaterialSurface> OptimiseMapGeometryMaterial(bspSurface_t** rendererSurfaces, int numSurfaces ) {
441425
std::vector<MaterialSurface> materialSurfaces;
442426
materialSurfaces.reserve( numSurfaces );
443427

444-
std::vector<MaterialSurface> processedMaterialSurfaces;
445-
processedMaterialSurfaces.reserve( numSurfaces );
446-
447-
// std::unordered_map<TriEdge, TriIndex> triEdges;
448-
449428
vec3_t worldBounds[2] = {};
450429
materialSystem.buildOneShader = false;
451430
for ( int i = 0; i < numSurfaces; i++ ) {
@@ -482,13 +461,128 @@ std::vector<MaterialSurface> OptimiseMapGeometryMaterial(bspSurface_t** renderer
482461

483462
materialSurfaces.emplace_back( srf );
484463
}
485-
486464
materialSystem.buildOneShader = true;
487465

466+
/* GenerateWorldMaterialsBuffer() must be called before the surface merging loop, because it will compare the UBO offsets,
467+
which are set by this call */
488468
materialSystem.GenerateWorldMaterialsBuffer();
469+
470+
std::vector<MaterialSurface> processedMaterialSurfaces;
471+
processedMaterialSurfaces.reserve( numSurfaces );
472+
for ( uint32_t i = 0; i < materialSurfaces.size(); i++ ) {
473+
MaterialSurface* surface = &materialSurfaces[i];
474+
475+
if ( surface->merged ) {
476+
continue;
477+
}
478+
479+
uint32_t lastIndex = surface->firstIndex + surface->count;
480+
for ( uint32_t j = i + 1; j < materialSurfaces.size(); j++ ) {
481+
MaterialSurface* surface2 = &materialSurfaces[j];
482+
483+
if ( surface2->merged ) {
484+
continue;
485+
}
486+
487+
if ( surface->stages != surface2->stages ) {
488+
continue;
489+
}
490+
491+
if ( surface->count + surface2->count > MAX_MATERIAL_SURFACE_INDEXES ) {
492+
continue;
493+
}
494+
495+
vec3_t mins;
496+
vec3_t maxs;
497+
ClearBounds( mins, maxs );
498+
for ( uint32_t k = 0; k < surface->count; k++ ) {
499+
AddPointToBounds( vertices[idxs[k + surface->firstIndex]].xyz, mins, maxs );
500+
}
501+
502+
for ( uint32_t k = 0; k < surface2->count; k++ ) {
503+
AddPointToBounds( vertices[indices[k + surface2->firstIndex]].xyz, mins, maxs );
504+
}
505+
506+
vec3_t origin;
507+
float radius;
508+
SphereFromBounds( mins, maxs, origin, &radius );
509+
510+
// Check both against a mul and add increase, so we can reasonably merge both large and small surfaces
511+
if ( radius > surface->radius * MAX_MATERIAL_SURFACE_RADIUS_INCREASE
512+
&& radius > surface->radius + MAX_MATERIAL_SURFACE_RADIUS_INCREASE_ADD ) {
513+
continue;
514+
}
515+
516+
bool skip = false;
517+
for ( uint8_t stage = 0; stage < surface->stages; stage++ ) {
518+
if( ( surface->materialPackIDs[stage] != surface2->materialPackIDs[stage] )
519+
|| ( surface->materialIDs[stage] != surface2->materialIDs[stage] ) ) {
520+
skip = true;
521+
break;
522+
}
523+
524+
shaderStage_t* pStage = surface->shaderStages[stage];
525+
pStage = pStage->materialRemappedStage ? pStage->materialRemappedStage : pStage;
526+
527+
const uint32_t surfaceMaterialID =
528+
pStage->materialOffset + pStage->variantOffsets[surface->shaderVariant[stage]];
529+
530+
pStage = surface2->shaderStages[stage];
531+
pStage = pStage->materialRemappedStage ? pStage->materialRemappedStage : pStage;
532+
533+
const uint32_t surfaceMaterialID2 =
534+
pStage->materialOffset + pStage->variantOffsets[surface2->shaderVariant[stage]];
535+
536+
if ( surfaceMaterialID != surfaceMaterialID2 ) {
537+
skip = true;
538+
break;
539+
}
540+
541+
uint32_t texData = surface->texDataDynamic[stage]
542+
? ( surface->texDataIDs[stage] + materialSystem.GetTexDataSize() ) << TEX_BUNDLE_BITS
543+
: surface->texDataIDs[stage] << TEX_BUNDLE_BITS;
544+
texData |= ( HasLightMap( surface ) ? GetLightMapNum( surface ) : 255 ) << LIGHTMAP_BITS;
545+
546+
uint32_t texData2 = surface2->texDataDynamic[stage]
547+
? ( surface2->texDataIDs[stage] + materialSystem.GetTexDataSize() ) << TEX_BUNDLE_BITS
548+
: surface2->texDataIDs[stage] << TEX_BUNDLE_BITS;
549+
texData2 |= ( HasLightMap( surface2 ) ? GetLightMapNum( surface2 ) : 255 ) << LIGHTMAP_BITS;
550+
551+
if( texData != texData2 ) {
552+
skip = true;
553+
break;
554+
}
555+
}
556+
557+
if ( skip ) {
558+
continue;
559+
}
560+
561+
if ( surface2->firstIndex == lastIndex ) {
562+
surface->count += surface2->count;
563+
lastIndex += surface2->count;
564+
565+
VectorCopy( origin, surface->origin );
566+
surface->radius = radius;
567+
568+
surface2->merged = true;
569+
}
570+
571+
if ( surface->count >= MAX_MATERIAL_SURFACE_INDEXES ) {
572+
break;
573+
}
574+
}
575+
}
576+
577+
for( MaterialSurface& srf : materialSurfaces ) {
578+
if ( !srf.merged ) {
579+
processedMaterialSurfaces.push_back( srf );
580+
}
581+
}
582+
489583
materialSystem.GeneratePortalBoundingSpheres();
490584
materialSystem.SetWorldBounds( worldBounds );
491-
materialSystem.GenerateWorldCommandBuffer( materialSurfaces );
585+
materialSystem.GenerateWorldCommandBuffer( processedMaterialSurfaces );
492586

493587
return materialSurfaces;
494588
}

src/engine/renderer/GeometryOptimiser.h

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,29 +42,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4242
static const uint32_t MAX_MATERIAL_SURFACE_TRIS = 64;
4343
static const uint32_t MAX_MATERIAL_SURFACE_INDEXES = 3 * MAX_MATERIAL_SURFACE_TRIS;
4444
static const uint32_t MAX_MATERIAL_SURFACE_DISTANCE = 256;
45-
46-
struct TriEdge {
47-
enum State : uint32_t {
48-
MERGEABLE_TRUE = BIT( 27 ),
49-
MERGEABLE_FALSE = BIT( 28 ),
50-
MERGEABLE_NOT_PROCESSED = BIT( 29 ),
51-
NONE = BIT( 30 )
52-
};
53-
54-
uint32_t index1;
55-
uint32_t index2;
56-
};
57-
58-
struct TriEdgeHasher {
59-
size_t operator()( const TriEdge& triEdge ) {
60-
return std::hash<uint32_t>{} ( triEdge.index1 ) ^ ( std::hash<uint32_t>{} ( triEdge.index2 ) << 16 );
61-
}
62-
};
63-
64-
struct TriIndex {
65-
int tri1 = -1;
66-
int tri2 = -1;
67-
};
45+
static const float MAX_MATERIAL_SURFACE_RADIUS_INCREASE = 2.0f;
46+
static const float MAX_MATERIAL_SURFACE_RADIUS_INCREASE_ADD = 256.0f; // 8 meters
6847

6948
struct MapVertHasher {
7049
size_t operator()( const srfVert_t& vert ) const {

src/engine/renderer/Material.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ struct MaterialSurface {
9494
srfVert_t* verts;
9595
srfTriangle_t* tris;
9696

97+
bool merged = false;
98+
9799
uint32_t materialPackIDs[MAX_SHADER_STAGES];
98100
uint32_t materialIDs[MAX_SHADER_STAGES];
99101

@@ -382,6 +384,10 @@ class MaterialSystem {
382384
void InitGLBuffers();
383385
void FreeGLBuffers();
384386

387+
uint32_t GetTexDataSize() const {
388+
return texData.size();
389+
}
390+
385391
void AddStageTextures( MaterialSurface* surface, shader_t* shader, shaderStage_t* pStage, const uint32_t stage, Material* material );
386392
void AddStage( MaterialSurface* surface, shaderStage_t* pStage, uint32_t stage,
387393
const bool mayUseVertexOverbright, const bool vertexLit, const bool fullbright );

0 commit comments

Comments
 (0)