diff --git a/Source/Engine/Content/Assets/Model.cpp b/Source/Engine/Content/Assets/Model.cpp index 9c7110692..c57b9c7be 100644 --- a/Source/Engine/Content/Assets/Model.cpp +++ b/Source/Engine/Content/Assets/Model.cpp @@ -722,6 +722,7 @@ bool Model::Init(const Span& meshesCountPerLod) { auto& lod = LODs[lodIndex]; lod._model = this; + lod._lodIndex = lodIndex; lod.ScreenSize = 1.0f; const int32 meshesCount = meshesCountPerLod[lodIndex]; if (meshesCount <= 0 || meshesCount > MODEL_MAX_MESHES) @@ -922,6 +923,7 @@ Asset::LoadResult Model::load() { auto& lod = LODs[lodIndex]; lod._model = this; + lod._lodIndex = lodIndex; // Screen Size stream->ReadFloat(&lod.ScreenSize); diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp index 7cbb5119d..5e5e3eae8 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -14,6 +14,9 @@ #include "Engine/Serialization/MemoryReadStream.h" #include "Engine/Threading/Task.h" #include "Engine/Threading/Threading.h" +#if USE_EDITOR +#include "Engine/Renderer/GBufferPass.h" +#endif #if USE_MONO #include #endif @@ -436,6 +439,11 @@ void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, cons drawCall.Surface.LODDitherFactor = 0.0f; drawCall.WorldDeterminantSign = Math::FloatSelect(world.RotDeterminant(), 1, -1); drawCall.PerInstanceRandom = perInstanceRandom; +#if USE_EDITOR + const ViewMode viewMode = renderContext.View.Mode; + if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::VertexColors) + GBufferPass::AddIndexBufferToModelLOD(_indexBuffer, &((Model*)_model)->LODs[_lodIndex]); +#endif // Push draw call to the render list renderContext.List->AddDrawCall(renderContext, drawModes, flags, drawCall, receiveDecals); @@ -497,6 +505,11 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float drawCall.Surface.LODDitherFactor = lodDitherFactor; drawCall.WorldDeterminantSign = Math::FloatSelect(drawCall.World.RotDeterminant(), 1, -1); drawCall.PerInstanceRandom = info.PerInstanceRandom; +#if USE_EDITOR + const ViewMode viewMode = renderContext.View.Mode; + if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::VertexColors) + GBufferPass::AddIndexBufferToModelLOD(_indexBuffer, &((Model*)_model)->LODs[_lodIndex]); +#endif // Push draw call to the render list renderContext.List->AddDrawCall(renderContext, drawModes, info.Flags, drawCall, entry.ReceiveDecals); @@ -552,6 +565,11 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in drawCall.Surface.LODDitherFactor = lodDitherFactor; drawCall.WorldDeterminantSign = Math::FloatSelect(drawCall.World.RotDeterminant(), 1, -1); drawCall.PerInstanceRandom = info.PerInstanceRandom; +#if USE_EDITOR + const ViewMode viewMode = renderContextBatch.GetMainContext().View.Mode; + if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::VertexColors) + GBufferPass::AddIndexBufferToModelLOD(_indexBuffer, &((Model*)_model)->LODs[_lodIndex]); +#endif // Push draw call to the render lists const auto shadowsMode = (ShadowsCastingMode)(entry.ShadowsMode & slot.ShadowsMode); diff --git a/Source/Engine/Graphics/Models/ModelLOD.h b/Source/Engine/Graphics/Models/ModelLOD.h index 1f44ae39f..9c4c852b4 100644 --- a/Source/Engine/Graphics/Models/ModelLOD.h +++ b/Source/Engine/Graphics/Models/ModelLOD.h @@ -17,6 +17,7 @@ API_CLASS(NoSpawn) class FLAXENGINE_API ModelLOD : public ScriptingObject friend Mesh; private: Model* _model = nullptr; + int32 _lodIndex = 0; uint32 _verticesCount; public: @@ -40,6 +41,14 @@ public: return Meshes.HasItems() && Meshes.Last().IsInitialized(); } + /// + /// Gets the model LOD index. + /// + API_PROPERTY() FORCE_INLINE int32 GetLODIndex() const + { + return _lodIndex; + } + /// /// Gets the vertex count for this model LOD level. /// diff --git a/Source/Engine/Renderer/Editor/LODPreview.cpp b/Source/Engine/Renderer/Editor/LODPreview.cpp index 612de21a8..eb4ce7b6a 100644 --- a/Source/Engine/Renderer/Editor/LODPreview.cpp +++ b/Source/Engine/Renderer/Editor/LODPreview.cpp @@ -10,6 +10,7 @@ #include "Engine/Graphics/RenderTask.h" #include "Engine/Renderer/DrawCall.h" #include "Engine/Renderer/RenderList.h" +#include "Engine/Renderer/GBufferPass.h" LODPreviewMaterialShader::LODPreviewMaterialShader() { @@ -47,26 +48,10 @@ void LODPreviewMaterialShader::Bind(BindParameters& params) // Find the LOD that produced this draw call int32 lodIndex = 0; auto& drawCall = *params.FirstDrawCall; - for (auto& e : Content::GetAssetsRaw()) + const ModelLOD* drawCallModelLod; + if (GBufferPass::IndexBufferToModelLOD.TryGet(drawCall.Geometry.IndexBuffer, drawCallModelLod)) { - auto model = ScriptingObject::Cast(e.Value); - if (!model) - continue; - bool found = false; - for (const auto& lod : model->LODs) - { - for (const auto& mesh : lod.Meshes) - { - if (mesh.GetIndexBuffer() == drawCall.Geometry.IndexBuffer) - { - lodIndex = mesh.GetLODIndex(); - found = true; - break; - } - } - } - if (found) - break; + lodIndex = drawCallModelLod->GetLODIndex(); } // Bind diff --git a/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp b/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp index 2e8232762..ebaa86e2b 100644 --- a/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp +++ b/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp @@ -7,6 +7,7 @@ #include "Engine/Content/Assets/Model.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUContext.h" +#include "Engine/Renderer/GBufferPass.h" #include "Engine/Graphics/GPUPipelineState.h" #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Graphics/Shaders/GPUConstantBuffer.h" @@ -125,7 +126,9 @@ void LightmapUVsDensityMaterialShader::Bind(BindParameters& params) float scaleInLightmap = 1.0f; if (params.RenderContext.Task) { - if (params.RenderContext.Task->ActorsSource & ActorsSources::CustomActors) + // Skip this lookup as it's too slow + + /*if (params.RenderContext.Task->ActorsSource & ActorsSources::CustomActors) { for (auto actor : params.RenderContext.Task->CustomActors) { @@ -142,33 +145,7 @@ void LightmapUVsDensityMaterialShader::Bind(BindParameters& params) if (drawCallActor) break; } - } - } - - // Find the model that produced this draw call - const Model* drawCallModel = nullptr; - const ModelLOD* drawCallModelLod = nullptr; - const Mesh* drawCallMesh = nullptr; - for (auto& e : Content::GetAssetsRaw()) - { - auto model = ScriptingObject::Cast(e.Value); - if (!model) - continue; - for (const auto& lod : model->LODs) - { - for (const auto& mesh : lod.Meshes) - { - if (mesh.GetIndexBuffer() == drawCall.Geometry.IndexBuffer) - { - drawCallModel = model; - drawCallModelLod = &lod; - drawCallMesh = &mesh; - break; - } - } - } - if (drawCallModel) - break; + }*/ } // Bind constants @@ -188,21 +165,19 @@ void LightmapUVsDensityMaterialShader::Bind(BindParameters& params) data.LightmapTexelsPerWorldUnit = ShadowsOfMordor::LightmapTexelsPerWorldUnit; data.LightmapSize = 1024.0f; data.LightmapArea = drawCall.Surface.LightmapUVsArea; - if (drawCallModel) + const ModelLOD* drawCallModelLod; + if (GBufferPass::IndexBufferToModelLOD.TryGet(drawCall.Geometry.IndexBuffer, drawCallModelLod)) { // Calculate current lightmap slot size for the object (matches the ShadowsOfMordor calculations when baking the lighting) float globalObjectsScale = 1.0f; int32 atlasSize = 1024; int32 chartsPadding = 3; - if (drawCallActor) + const Scene* drawCallScene = drawCallActor ? drawCallActor->GetScene() : (Level::Scenes.Count() != 0 ? Level::Scenes[0] : nullptr); + if (drawCallScene) { - const Scene* drawCallScene = drawCallActor->GetScene(); - if (drawCallScene) - { - globalObjectsScale = drawCallScene->Info.LightmapSettings.GlobalObjectsScale; - atlasSize = (int32)drawCallScene->Info.LightmapSettings.AtlasSize; - chartsPadding = drawCallScene->Info.LightmapSettings.ChartsPadding; - } + globalObjectsScale = drawCallScene->Info.LightmapSettings.GlobalObjectsScale; + atlasSize = (int32)drawCallScene->Info.LightmapSettings.AtlasSize; + chartsPadding = drawCallScene->Info.LightmapSettings.ChartsPadding; } BoundingBox box = drawCallModelLod->GetBox(drawCall.World); Float3 size = box.GetSize(); @@ -219,7 +194,7 @@ void LightmapUVsDensityMaterialShader::Bind(BindParameters& params) const int32 maximumChartSize = atlasSize - chartsPadding * 2; int32 width = Math::Clamp(Math::CeilToInt(scale), ShadowsOfMordor::LightmapMinChartSize, maximumChartSize); int32 height = Math::Clamp(Math::CeilToInt(scale), ShadowsOfMordor::LightmapMinChartSize, maximumChartSize); - float invSize = 1.0f / atlasSize; + float invSize = 1.0f / (float)atlasSize; data.LightmapArea = Rectangle(0, 0, width * invSize, height * invSize); data.LightmapSize = (float)atlasSize; } diff --git a/Source/Engine/Renderer/Editor/LightmapUVsDensity.h b/Source/Engine/Renderer/Editor/LightmapUVsDensity.h index 9c293ca57..99ece19a5 100644 --- a/Source/Engine/Renderer/Editor/LightmapUVsDensity.h +++ b/Source/Engine/Renderer/Editor/LightmapUVsDensity.h @@ -17,27 +17,23 @@ class GPUPipelineState; class LightmapUVsDensityMaterialShader : public IMaterial { private: - AssetReference _shader; AssetReference _gridTexture; GPUPipelineState* _ps = nullptr; MaterialInfo _info; public: - LightmapUVsDensityMaterialShader(); virtual ~LightmapUVsDensityMaterialShader() { } private: - #if COMPILE_WITH_DEV_ENV void OnShaderReloading(Asset* obj); #endif public: - // [IMaterial] const MaterialInfo& GetInfo() const override; GPUShader* GetShader() const override; diff --git a/Source/Engine/Renderer/Editor/MaterialComplexity.cpp b/Source/Engine/Renderer/Editor/MaterialComplexity.cpp index 569050f5e..4aa18beda 100644 --- a/Source/Engine/Renderer/Editor/MaterialComplexity.cpp +++ b/Source/Engine/Renderer/Editor/MaterialComplexity.cpp @@ -102,6 +102,8 @@ MaterialComplexityMaterialShader::MaterialComplexityMaterialShader() void MaterialComplexityMaterialShader::DebugOverrideDrawCallsMaterial(RenderContext& renderContext) { + PROFILE_CPU(); + // Cache 'ready' state for wrappers bool isReady[ARRAY_COUNT(_wrappers) + 1]; for (int32 i = 0; i < ARRAY_COUNT(_wrappers); i++) diff --git a/Source/Engine/Renderer/GBufferPass.cpp b/Source/Engine/Renderer/GBufferPass.cpp index 87ce7a432..2d5f6eadf 100644 --- a/Source/Engine/Renderer/GBufferPass.cpp +++ b/Source/Engine/Renderer/GBufferPass.cpp @@ -27,6 +27,11 @@ PACK_STRUCT(struct GBufferPassData{ int32 ViewMode; }); +#if USE_EDITOR +Dictionary GBufferPass::IndexBufferToModelLOD; +CriticalSection GBufferPass::Locker; +#endif + String GBufferPass::ToString() const { return TEXT("GBufferPass"); @@ -97,6 +102,7 @@ void GBufferPass::Dispose() SAFE_DELETE(_vertexColors); SAFE_DELETE(_lodPreview); SAFE_DELETE(_materialComplexity); + IndexBufferToModelLOD.SetCapacity(0); #endif } @@ -106,6 +112,7 @@ void DebugOverrideDrawCallsMaterial(const RenderContext& renderContext, IMateria { if (!material->IsReady()) return; + PROFILE_CPU(); IMaterial::InstancingHandler handler; const bool canUseInstancing = material->CanUseInstancing(handler); const auto drawModes = material->GetDrawModes(); @@ -318,6 +325,12 @@ GPUTextureView* GBufferPass::RenderSkybox(RenderContext& renderContext, GPUConte #if USE_EDITOR +void GBufferPass::PreOverrideDrawCalls(RenderContext& renderContext) +{ + // Clear cache before scene drawing + IndexBufferToModelLOD.Clear(); +} + void GBufferPass::OverrideDrawCalls(RenderContext& renderContext) { // Override draw calls material to use material debug shader diff --git a/Source/Engine/Renderer/GBufferPass.h b/Source/Engine/Renderer/GBufferPass.h index 81a65a108..61ed58a23 100644 --- a/Source/Engine/Renderer/GBufferPass.h +++ b/Source/Engine/Renderer/GBufferPass.h @@ -3,6 +3,9 @@ #pragma once #include "RendererPass.h" +#if USE_EDITOR +#include "Engine/Core/Collections/Dictionary.h" +#endif /// /// Rendering scene to the GBuffer @@ -46,6 +49,17 @@ public: GPUTextureView* RenderSkybox(RenderContext& renderContext, GPUContext* context); #if USE_EDITOR + // Temporary cache for faster debug previews drawing (used only during frame rendering). + static Dictionary IndexBufferToModelLOD; + static CriticalSection Locker; + + FORCE_INLINE static void AddIndexBufferToModelLOD(GPUBuffer* indexBuffer, const ModelLOD* modelLod) + { + Locker.Lock(); + IndexBufferToModelLOD[indexBuffer] = modelLod; + Locker.Unlock(); + } + void PreOverrideDrawCalls(RenderContext& renderContext); void OverrideDrawCalls(RenderContext& renderContext); void DrawMaterialComplexity(RenderContext& renderContext, GPUContext* context, GPUTextureView* lightBuffer); #endif diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp index 10fde8f51..0a2aefab5 100644 --- a/Source/Engine/Renderer/Renderer.cpp +++ b/Source/Engine/Renderer/Renderer.cpp @@ -347,6 +347,9 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont } if (drawShadows) ShadowsPass::Instance()->SetupShadows(renderContext, renderContextBatch); +#if USE_EDITOR + GBufferPass::Instance()->PreOverrideDrawCalls(renderContext); +#endif // Dispatch drawing (via JobSystem - multiple job batches for every scene) JobSystem::SetJobStartingOnDispatch(false);