Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/renderer/ModelRenderer.cpp
/* Copyright (C) 2022 Wildfire Games. | /* Copyright (C) 2023 Wildfire Games. | ||||
* This file is part of 0 A.D. | * This file is part of 0 A.D. | ||||
* | * | ||||
* 0 A.D. is free software: you can redistribute it and/or modify | * 0 A.D. is free software: you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation, either version 2 of the License, or | * the Free Software Foundation, either version 2 of the License, or | ||||
* (at your option) any later version. | * (at your option) any later version. | ||||
* | * | ||||
* 0 A.D. is distributed in the hope that it will be useful, | * 0 A.D. is distributed in the hope that it will be useful, | ||||
Show All 15 Lines | |||||
#include "graphics/ShaderManager.h" | #include "graphics/ShaderManager.h" | ||||
#include "graphics/TextureManager.h" | #include "graphics/TextureManager.h" | ||||
#include "lib/allocators/DynamicArena.h" | #include "lib/allocators/DynamicArena.h" | ||||
#include "lib/allocators/STLAllocators.h" | #include "lib/allocators/STLAllocators.h" | ||||
#include "lib/hash.h" | #include "lib/hash.h" | ||||
#include "maths/Vector3D.h" | #include "maths/Vector3D.h" | ||||
#include "maths/Vector4D.h" | #include "maths/Vector4D.h" | ||||
#include "ps/CLogger.h" | #include "ps/CLogger.h" | ||||
#include "ps/containers/Span.h" | |||||
#include "ps/CStrInternStatic.h" | #include "ps/CStrInternStatic.h" | ||||
#include "ps/Profile.h" | #include "ps/Profile.h" | ||||
#include "renderer/MikktspaceWrap.h" | #include "renderer/MikktspaceWrap.h" | ||||
#include "renderer/ModelRenderer.h" | #include "renderer/ModelRenderer.h" | ||||
#include "renderer/ModelVertexRenderer.h" | #include "renderer/ModelVertexRenderer.h" | ||||
#include "renderer/Renderer.h" | #include "renderer/Renderer.h" | ||||
#include "renderer/RenderModifiers.h" | #include "renderer/RenderModifiers.h" | ||||
#include "renderer/SceneRenderer.h" | #include "renderer/SceneRenderer.h" | ||||
▲ Show 20 Lines • Show All 295 Lines • ▼ Show 20 Lines | size_t operator()(const SMRMaterialBucketKey& key) const | ||||
hash_combine(hash, key.defines.GetHash()); | hash_combine(hash, key.defines.GetHash()); | ||||
return hash; | return hash; | ||||
} | } | ||||
}; | }; | ||||
struct SMRTechBucket | struct SMRTechBucket | ||||
{ | { | ||||
CShaderTechniquePtr tech; | CShaderTechniquePtr tech; | ||||
CModel** models; | PS::span<CModel*> models; | ||||
size_t numModels; | |||||
// Model list is stored as pointers, not as a std::vector, | // Model list is stored as pointers, not as a std::vector, | ||||
// so that sorting lists of this struct is fast | // so that sorting lists of this struct is fast | ||||
}; | }; | ||||
struct SMRCompareTechBucket | struct SMRCompareTechBucket | ||||
{ | { | ||||
bool operator()(const SMRTechBucket& a, const SMRTechBucket& b) | bool operator()(const SMRTechBucket& a, const SMRTechBucket& b) | ||||
▲ Show 20 Lines • Show All 158 Lines • ▼ Show 20 Lines | for (MaterialBuckets_t::iterator it = materialBuckets.begin(); it != materialBuckets.end(); ++it) | ||||
{ | { | ||||
// Sort model list by modeldef+texture, for batching | // Sort model list by modeldef+texture, for batching | ||||
// TODO: This only sorts by base texture. While this is an OK approximation | // TODO: This only sorts by base texture. While this is an OK approximation | ||||
// for most cases (as related samplers are usually used together), it would be better | // for most cases (as related samplers are usually used together), it would be better | ||||
// to take all the samplers into account when sorting here. | // to take all the samplers into account when sorting here. | ||||
std::sort(it->second.begin(), it->second.end(), SMRBatchModel()); | std::sort(it->second.begin(), it->second.end(), SMRBatchModel()); | ||||
// Add a tech bucket pointing at this model list | // Add a tech bucket pointing at this model list | ||||
SMRTechBucket techBucket = { tech, &it->second[0], it->second.size() }; | SMRTechBucket techBucket{tech, it->second}; | ||||
techBuckets.push_back(techBucket); | techBuckets.push_back(techBucket); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
{ | { | ||||
PROFILE3("sorting tech buckets"); | PROFILE3("sorting tech buckets"); | ||||
// Sort by technique, for better batching | // Sort by technique, for better batching | ||||
Show All 27 Lines | if (!sortByDistItems.empty()) | ||||
for (size_t end = 0; end < sortByDistItems.size(); ++end) | for (size_t end = 0; end < sortByDistItems.size(); ++end) | ||||
{ | { | ||||
sortByDistModels.push_back(sortByDistItems[end].model); | sortByDistModels.push_back(sortByDistItems[end].model); | ||||
size_t techIdx = sortByDistItems[end].techIdx; | size_t techIdx = sortByDistItems[end].techIdx; | ||||
if (techIdx != currentTechIdx) | if (techIdx != currentTechIdx) | ||||
{ | { | ||||
// Start of a new run - push the old run into a new tech bucket | // Start of a new run - push the old run into a new tech bucket | ||||
SMRTechBucket techBucket = { sortByDistTechs[currentTechIdx], &sortByDistModels[start], end - start }; | SMRTechBucket techBucket{sortByDistTechs[currentTechIdx], | ||||
{sortByDistModels.data() + start, end - start}}; | |||||
techBuckets.push_back(techBucket); | techBuckets.push_back(techBucket); | ||||
start = end; | start = end; | ||||
currentTechIdx = techIdx; | currentTechIdx = techIdx; | ||||
} | } | ||||
} | } | ||||
// Add the tech bucket for the final run | // Add the tech bucket for the final run | ||||
SMRTechBucket techBucket = { sortByDistTechs[currentTechIdx], &sortByDistModels[start], sortByDistItems.size() - start }; | SMRTechBucket techBucket{sortByDistTechs[currentTechIdx], | ||||
{sortByDistModels.data() + start, sortByDistItems.size() - start}}; | |||||
techBuckets.push_back(techBucket); | techBuckets.push_back(techBucket); | ||||
} | } | ||||
} | } | ||||
const double time = g_Renderer.GetTimeManager().GetGlobalTime(); | const double time = g_Renderer.GetTimeManager().GetGlobalTime(); | ||||
{ | { | ||||
PROFILE3("rendering bucketed submissions"); | PROFILE3("rendering bucketed submissions"); | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | while (idxTechStart < techBuckets.size()) | ||||
texBindings.clear(); | texBindings.clear(); | ||||
texBindingNames.clear(); | texBindingNames.clear(); | ||||
CModelDef* currentModeldef = NULL; | CModelDef* currentModeldef = NULL; | ||||
CShaderUniforms currentStaticUniforms; | CShaderUniforms currentStaticUniforms; | ||||
for (size_t idx = idxTechStart; idx < idxTechEnd; ++idx) | for (size_t idx = idxTechStart; idx < idxTechEnd; ++idx) | ||||
{ | { | ||||
CModel** models = techBuckets[idx].models; | for (CModel* model : techBuckets[idx].models) | ||||
size_t numModels = techBuckets[idx].numModels; | |||||
for (size_t i = 0; i < numModels; ++i) | |||||
{ | { | ||||
CModel* model = models[i]; | |||||
if (flags && !(model->GetFlags() & flags)) | if (flags && !(model->GetFlags() & flags)) | ||||
continue; | continue; | ||||
const CMaterial::SamplersVector& samplers = model->GetMaterial().GetSamplers(); | const CMaterial::SamplersVector& samplers = model->GetMaterial().GetSamplers(); | ||||
size_t samplersNum = samplers.size(); | size_t samplersNum = samplers.size(); | ||||
// make sure the vectors are the right virtual sizes, and also | // make sure the vectors are the right virtual sizes, and also | ||||
// reallocate if there are more samplers than expected. | // reallocate if there are more samplers than expected. | ||||
▲ Show 20 Lines • Show All 117 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator