Refactor draw calls drawing to use single objects buffer and better materials batching

This commit is contained in:
Wojtek Figat
2024-07-02 00:52:22 +02:00
parent 78f3248ac9
commit 08ef7c93ea
35 changed files with 491 additions and 442 deletions

View File

@@ -3,7 +3,6 @@
#include "DeferredMaterialShader.h"
#include "MaterialShaderFeatures.h"
#include "MaterialParams.h"
#include "Engine/Core/Math/Matrix3x4.h"
#include "Engine/Graphics/RenderBuffers.h"
#include "Engine/Graphics/RenderView.h"
#include "Engine/Renderer/DrawCall.h"
@@ -17,16 +16,6 @@
#include "Engine/Graphics/GPULimits.h"
#include "Engine/Graphics/RenderTask.h"
PACK_STRUCT(struct DeferredMaterialShaderData {
Matrix3x4 WorldMatrix;
Matrix3x4 PrevWorldMatrix;
Float2 Dummy0;
float LODDitherFactor;
float PerInstanceRandom;
Float3 GeometrySize;
float WorldDeterminantSign;
});
DrawPass DeferredMaterialShader::GetDrawModes() const
{
return DrawPass::Depth | DrawPass::GBuffer | DrawPass::GlobalSurfaceAtlas | DrawPass::MotionVectors | DrawPass::QuadOverdraw;
@@ -39,22 +28,17 @@ bool DeferredMaterialShader::CanUseLightmap() const
bool DeferredMaterialShader::CanUseInstancing(InstancingHandler& handler) const
{
handler = { SurfaceDrawCallHandler::GetHash, SurfaceDrawCallHandler::CanBatch, SurfaceDrawCallHandler::WriteDrawCall, };
handler = { SurfaceDrawCallHandler::GetHash, SurfaceDrawCallHandler::CanBatch, };
return true;
}
void DeferredMaterialShader::Bind(BindParameters& params)
{
//PROFILE_CPU();
// Prepare
auto context = params.GPUContext;
auto& view = params.RenderContext.View;
auto& drawCall = *params.FirstDrawCall;
auto& drawCall = *params.DrawCall;
Span<byte> cb(_cbData.Get(), _cbData.Count());
ASSERT_LOW_LAYER(cb.Length() >= sizeof(DeferredMaterialShaderData));
auto materialData = reinterpret_cast<DeferredMaterialShaderData*>(cb.Get());
cb = Span<byte>(cb.Get() + sizeof(DeferredMaterialShaderData), cb.Length() - sizeof(DeferredMaterialShaderData));
int32 srv = 2;
int32 srv = 3;
// Setup features
const bool useLightmap = _info.BlendMode == MaterialBlendMode::Opaque && LightmapFeature::Bind(params, cb, srv);
@@ -68,28 +52,19 @@ void DeferredMaterialShader::Bind(BindParameters& params)
bindMeta.CanSampleDepth = false;
bindMeta.CanSampleGBuffer = false;
MaterialParams::Bind(params.ParamsLink, bindMeta);
context->BindSR(0, params.ObjectBuffer);
// Setup material constants
{
materialData->WorldMatrix.SetMatrixTranspose(drawCall.World);
materialData->PrevWorldMatrix.SetMatrixTranspose(drawCall.Surface.PrevWorld);
materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign;
materialData->LODDitherFactor = drawCall.Surface.LODDitherFactor;
materialData->PerInstanceRandom = drawCall.PerInstanceRandom;
materialData->GeometrySize = drawCall.Surface.GeometrySize;
}
// Check if is using mesh skinning
// Check if using mesh skinning
const bool useSkinning = drawCall.Surface.Skinning != nullptr;
bool perBoneMotionBlur = false;
if (useSkinning)
{
// Bind skinning buffer
ASSERT(drawCall.Surface.Skinning->IsReady());
context->BindSR(0, drawCall.Surface.Skinning->BoneMatrices->View());
context->BindSR(1, drawCall.Surface.Skinning->BoneMatrices->View());
if (drawCall.Surface.Skinning->PrevBoneMatrices && drawCall.Surface.Skinning->PrevBoneMatrices->IsAllocated())
{
context->BindSR(1, drawCall.Surface.Skinning->PrevBoneMatrices->View());
context->BindSR(2, drawCall.Surface.Skinning->PrevBoneMatrices->View());
perBoneMotionBlur = true;
}
}
@@ -116,8 +91,8 @@ void DeferredMaterialShader::Bind(BindParameters& params)
else
cullMode = CullMode::Normal;
}
ASSERT_LOW_LAYER(!(useSkinning && params.DrawCallsCount > 1)); // No support for instancing skinned meshes
const auto cache = params.DrawCallsCount == 1 ? &_cache : &_cacheInstanced;
ASSERT_LOW_LAYER(!(useSkinning && params.Instanced)); // No support for instancing skinned meshes
const auto cache = params.Instanced ? &_cacheInstanced : &_cache;
PipelineStateCache* psCache = cache->GetPS(view.Pass, useLightmap, useSkinning, perBoneMotionBlur);
ASSERT(psCache);
GPUPipelineState* state = psCache->GetPS(cullMode, wireframe);