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 "ForwardMaterialShader.h"
#include "MaterialShaderFeatures.h"
#include "MaterialParams.h"
#include "Engine/Core/Math/Matrix3x4.h"
#include "Engine/Graphics/GPUContext.h"
#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Graphics/GPULimits.h"
@@ -18,16 +17,6 @@
#include "Engine/Renderer/Lightmaps.h"
#endif
PACK_STRUCT(struct ForwardMaterialShaderData {
Matrix3x4 WorldMatrix;
Matrix3x4 PrevWorldMatrix;
Float2 Dummy0;
float LODDitherFactor;
float PerInstanceRandom;
Float3 GeometrySize;
float WorldDeterminantSign;
});
DrawPass ForwardMaterialShader::GetDrawModes() const
{
return _drawModes;
@@ -35,7 +24,7 @@ DrawPass ForwardMaterialShader::GetDrawModes() const
bool ForwardMaterialShader::CanUseInstancing(InstancingHandler& handler) const
{
handler = { SurfaceDrawCallHandler::GetHash, SurfaceDrawCallHandler::CanBatch, SurfaceDrawCallHandler::WriteDrawCall, };
handler = { SurfaceDrawCallHandler::GetHash, SurfaceDrawCallHandler::CanBatch, };
return true;
}
@@ -44,12 +33,9 @@ void ForwardMaterialShader::Bind(BindParameters& params)
// 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(ForwardMaterialShaderData));
auto materialData = reinterpret_cast<ForwardMaterialShaderData*>(cb.Get());
cb = Span<byte>(cb.Get() + sizeof(ForwardMaterialShaderData), cb.Length() - sizeof(ForwardMaterialShaderData));
int32 srv = 2;
int32 srv = 3;
// Setup features
if ((_info.FeaturesFlags & MaterialFeaturesFlags::GlobalIllumination) != MaterialFeaturesFlags::None)
@@ -65,24 +51,15 @@ void ForwardMaterialShader::Bind(BindParameters& params)
bindMeta.CanSampleDepth = GPUDevice::Instance->Limits.HasReadOnlyDepth;
bindMeta.CanSampleGBuffer = true;
MaterialParams::Bind(params.ParamsLink, bindMeta);
context->BindSR(0, params.ObjectBuffer);
// Check if is using mesh skinning
// Check if using mesh skinning
const bool useSkinning = drawCall.Surface.Skinning != nullptr;
if (useSkinning)
{
// Bind skinning buffer
ASSERT(drawCall.Surface.Skinning->IsReady());
context->BindSR(0, drawCall.Surface.Skinning->BoneMatrices->View());
}
// 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;
context->BindSR(1, drawCall.Surface.Skinning->BoneMatrices->View());
}
// Bind constants
@@ -107,8 +84,8 @@ void ForwardMaterialShader::Bind(BindParameters& params)
else
cullMode = CullMode::Normal;
}
ASSERT_LOW_LAYER(!(useSkinning && params.DrawCallsCount > 1)); // No support for instancing skinned meshes
const auto cacheObj = params.DrawCallsCount == 1 ? &_cache : &_cacheInstanced;
ASSERT_LOW_LAYER(!(useSkinning && params.Instanced)); // No support for instancing skinned meshes
const auto cacheObj = params.Instanced ? &_cacheInstanced : &_cache;
PipelineStateCache* psCache = cacheObj->GetPS(view.Pass, useSkinning);
ASSERT(psCache);
GPUPipelineState* state = psCache->GetPS(cullMode, wireframe);