Refactor SortOrder to use int8 instead of int16 due to performance reasons (more efficent sort keys packing in rendering)
This commit is contained in:
@@ -186,7 +186,7 @@ BoundingBox Model::GetBox(int32 lodIndex) const
|
||||
return LODs[lodIndex].GetBox();
|
||||
}
|
||||
|
||||
void Model::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, int16 sortOrder) const
|
||||
void Model::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, int8 sortOrder) const
|
||||
{
|
||||
if (!CanBeRendered())
|
||||
return;
|
||||
|
||||
@@ -182,7 +182,7 @@ public:
|
||||
/// <param name="flags">The object static flags.</param>
|
||||
/// <param name="receiveDecals">True if rendered geometry can receive decals, otherwise false.</param>
|
||||
/// <param name="sortOrder">Object sorting key.</param>
|
||||
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, int16 sortOrder = 0) const;
|
||||
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, int8 sortOrder = 0) const;
|
||||
|
||||
/// <summary>
|
||||
/// Draws the model.
|
||||
|
||||
@@ -385,7 +385,7 @@ void Mesh::Render(GPUContext* context) const
|
||||
context->DrawIndexedInstanced(_triangles * 3, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, DrawPass drawModes, float perInstanceRandom, int16 sortOrder) const
|
||||
void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, DrawPass drawModes, float perInstanceRandom, int8 sortOrder) const
|
||||
{
|
||||
if (!material || !material->IsSurface() || !IsInitialized())
|
||||
return;
|
||||
|
||||
@@ -287,7 +287,7 @@ public:
|
||||
/// <param name="drawModes">The draw passes to use for rendering this object.</param>
|
||||
/// <param name="perInstanceRandom">The random per-instance value (normalized to range 0-1).</param>
|
||||
/// <param name="sortOrder">Object sorting key.</param>
|
||||
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int16 sortOrder = 0) const;
|
||||
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int8 sortOrder = 0) const;
|
||||
|
||||
/// <summary>
|
||||
/// Draws the mesh.
|
||||
|
||||
@@ -240,6 +240,6 @@ public:
|
||||
/// <summary>
|
||||
/// The object sorting key.
|
||||
/// </summary>
|
||||
int16 SortOrder;
|
||||
int8 SortOrder;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
/// <param name="drawModes">The draw passes to use for rendering this object.</param>
|
||||
/// <param name="perInstanceRandom">The random per-instance value (normalized to range 0-1).</param>
|
||||
/// <param name="sortOrder">Object sorting key.</param>
|
||||
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int16 sortOrder = 0) const
|
||||
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int8 sortOrder = 0) const
|
||||
{
|
||||
for (int32 i = 0; i < Meshes.Count(); i++)
|
||||
Meshes.Get()[i].Draw(renderContext, material, world, flags, receiveDecals, drawModes, perInstanceRandom, sortOrder);
|
||||
|
||||
@@ -150,10 +150,10 @@ public:
|
||||
DrawPass DrawModes = DrawPass::Default;
|
||||
|
||||
/// <summary>
|
||||
/// The object sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be use to control transparency drawing.
|
||||
/// The object sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be used to control transparency drawing.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorDisplay(\"Skinned Model\"), EditorOrder(110), DefaultValue(0)")
|
||||
int16 SortOrder = 0;
|
||||
int8 SortOrder = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The shadows casting mode.
|
||||
|
||||
@@ -92,7 +92,7 @@ int32 StaticModel::GetSortOrder() const
|
||||
|
||||
void StaticModel::SetSortOrder(int32 value)
|
||||
{
|
||||
_sortOrder = (int16)Math::Clamp<int32>(value, MIN_int16, MAX_int16);
|
||||
_sortOrder = (int8)Math::Clamp<int32>(value, MIN_int8, MAX_int8);
|
||||
}
|
||||
|
||||
bool StaticModel::HasLightmap() const
|
||||
|
||||
@@ -22,7 +22,7 @@ private:
|
||||
char _forcedLod;
|
||||
bool _vertexColorsDirty;
|
||||
byte _vertexColorsCount;
|
||||
int16 _sortOrder;
|
||||
int8 _sortOrder;
|
||||
Array<Color32> _vertexColorsData[MODEL_MAX_LODS];
|
||||
GPUBuffer* _vertexColorsBuffer[MODEL_MAX_LODS];
|
||||
Model* _residencyChangedModel = nullptr;
|
||||
@@ -97,13 +97,13 @@ public:
|
||||
API_PROPERTY() void SetForcedLOD(int32 value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the model sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be use to control transparency drawing.
|
||||
/// Gets the model sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be used to control transparency drawing.
|
||||
/// </summary>
|
||||
API_PROPERTY(Attributes="EditorOrder(60), DefaultValue(0), EditorDisplay(\"Model\")")
|
||||
int32 GetSortOrder() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the model sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be use to control transparency drawing.
|
||||
/// Sets the model sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be used to control transparency drawing.
|
||||
/// </summary>
|
||||
API_PROPERTY() void SetSortOrder(int32 value);
|
||||
|
||||
|
||||
@@ -255,10 +255,10 @@ public:
|
||||
DrawPass DrawModes = DrawPass::Default;
|
||||
|
||||
/// <summary>
|
||||
/// The object sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be use to control transparency drawing.
|
||||
/// The object sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be used to control transparency drawing.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorDisplay(\"Particle Effect\"), EditorOrder(80), DefaultValue(0)")
|
||||
int16 SortOrder = 0;
|
||||
int8 SortOrder = 0;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -161,7 +161,7 @@ void Particles::OnEffectDestroy(ParticleEffect* effect)
|
||||
|
||||
typedef Array<int32, FixedAllocation<PARTICLE_EMITTER_MAX_MODULES>> RenderModulesIndices;
|
||||
|
||||
void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCall& drawCall, DrawPass drawModes, StaticFlags staticFlags, ParticleEmitterInstance& emitterData, const RenderModulesIndices& renderModulesIndices, int16 sortOrder)
|
||||
void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCall& drawCall, DrawPass drawModes, StaticFlags staticFlags, ParticleEmitterInstance& emitterData, const RenderModulesIndices& renderModulesIndices, int8 sortOrder)
|
||||
{
|
||||
// Skip if CPU buffer is empty
|
||||
if (buffer->CPU.Count == 0)
|
||||
@@ -598,7 +598,7 @@ void CleanupGPUParticlesSorting()
|
||||
GPUParticlesSorting = nullptr;
|
||||
}
|
||||
|
||||
void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCall& drawCall, DrawPass drawModes, StaticFlags staticFlags, ParticleEmitterInstance& emitterData, const RenderModulesIndices& renderModulesIndices, int16 sortOrder)
|
||||
void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCall& drawCall, DrawPass drawModes, StaticFlags staticFlags, ParticleEmitterInstance& emitterData, const RenderModulesIndices& renderModulesIndices, int8 sortOrder)
|
||||
{
|
||||
const auto context = GPUDevice::Instance->GetMainContext();
|
||||
auto emitter = buffer->Emitter;
|
||||
@@ -921,7 +921,7 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
|
||||
worldDeterminantSigns[0] = Math::FloatSelect(worlds[0].RotDeterminant(), 1, -1);
|
||||
worldDeterminantSigns[1] = Math::FloatSelect(worlds[1].RotDeterminant(), 1, -1);
|
||||
const StaticFlags staticFlags = effect->GetStaticFlags();
|
||||
const int16 sortOrder = effect->SortOrder;
|
||||
const int8 sortOrder = effect->SortOrder;
|
||||
|
||||
// Draw lights
|
||||
for (int32 emitterIndex = 0; emitterIndex < effect->Instance.Emitters.Count(); emitterIndex++)
|
||||
|
||||
@@ -449,14 +449,16 @@ struct PackedSortKey
|
||||
|
||||
struct
|
||||
{
|
||||
// Sorting order: By Sort Order -> By Material -> By Geometry -> By Distance
|
||||
uint32 DistanceKey;
|
||||
uint8 DrawKey;
|
||||
uint16 BatchKey;
|
||||
uint16 SortKey;
|
||||
uint8 SortKey;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
FORCE_INLINE void CalculateSortKey(const RenderContext& renderContext, DrawCall& drawCall, int16 sortOrder)
|
||||
FORCE_INLINE void CalculateSortKey(const RenderContext& renderContext, DrawCall& drawCall, int8 sortOrder)
|
||||
{
|
||||
const Float3 planeNormal = renderContext.View.Direction;
|
||||
const float planePoint = -Float3::Dot(planeNormal, renderContext.View.Position);
|
||||
@@ -464,20 +466,33 @@ FORCE_INLINE void CalculateSortKey(const RenderContext& renderContext, DrawCall&
|
||||
PackedSortKey key;
|
||||
key.DistanceKey = RenderTools::ComputeDistanceSortKey(distance);
|
||||
uint32 batchKey = GetHash(drawCall.Material);
|
||||
batchKey = (batchKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[0]);
|
||||
batchKey = (batchKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[1]);
|
||||
batchKey = (batchKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[2]);
|
||||
batchKey = (batchKey * 397) ^ GetHash(drawCall.Geometry.IndexBuffer);
|
||||
IMaterial::InstancingHandler handler;
|
||||
if (drawCall.Material->CanUseInstancing(handler))
|
||||
handler.GetHash(drawCall, batchKey);
|
||||
batchKey += (int32)(471 * drawCall.WorldDeterminantSign);
|
||||
key.SortKey = (uint16)(sortOrder - MIN_int16);
|
||||
key.BatchKey = (uint16)batchKey;
|
||||
uint32 drawKey = (uint32)(471 * drawCall.WorldDeterminantSign);
|
||||
drawKey = (drawKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[0]);
|
||||
drawKey = (drawKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[1]);
|
||||
drawKey = (drawKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[2]);
|
||||
drawKey = (drawKey * 397) ^ GetHash(drawCall.Geometry.IndexBuffer);
|
||||
key.DrawKey = (uint8)drawKey;
|
||||
key.SortKey = (uint8)(sortOrder - MIN_int8);
|
||||
drawCall.SortKey = key.Data;
|
||||
}
|
||||
|
||||
void RenderList::AddDrawCall(const RenderContext& renderContext, DrawPass drawModes, StaticFlags staticFlags, DrawCall& drawCall, bool receivesDecals, int16 sortOrder)
|
||||
FORCE_INLINE bool CanBatchDrawCalls(const DrawCall& a, const DrawCall& b, DrawPass pass)
|
||||
{
|
||||
IMaterial::InstancingHandler handlerA, handlerB;
|
||||
return a.Material->CanUseInstancing(handlerA) &&
|
||||
b.Material->CanUseInstancing(handlerB) &&
|
||||
a.InstanceCount != 0 &&
|
||||
b.InstanceCount != 0 &&
|
||||
handlerA.CanBatch == handlerB.CanBatch &&
|
||||
handlerA.CanBatch(a, b, pass) &&
|
||||
a.WorldDeterminantSign * b.WorldDeterminantSign > 0;
|
||||
}
|
||||
|
||||
void RenderList::AddDrawCall(const RenderContext& renderContext, DrawPass drawModes, StaticFlags staticFlags, DrawCall& drawCall, bool receivesDecals, int8 sortOrder)
|
||||
{
|
||||
#if ENABLE_ASSERTION_LOW_LAYERS
|
||||
// Ensure that draw modes are non-empty and in conjunction with material draw modes
|
||||
@@ -515,7 +530,7 @@ void RenderList::AddDrawCall(const RenderContext& renderContext, DrawPass drawMo
|
||||
}
|
||||
}
|
||||
|
||||
void RenderList::AddDrawCall(const RenderContextBatch& renderContextBatch, DrawPass drawModes, StaticFlags staticFlags, ShadowsCastingMode shadowsMode, const BoundingSphere& bounds, DrawCall& drawCall, bool receivesDecals, int16 sortOrder)
|
||||
void RenderList::AddDrawCall(const RenderContextBatch& renderContextBatch, DrawPass drawModes, StaticFlags staticFlags, ShadowsCastingMode shadowsMode, const BoundingSphere& bounds, DrawCall& drawCall, bool receivesDecals, int8 sortOrder)
|
||||
{
|
||||
#if ENABLE_ASSERTION_LOW_LAYERS
|
||||
// Ensure that draw modes are non-empty and in conjunction with material draw modes
|
||||
@@ -571,19 +586,8 @@ void RenderList::AddDrawCall(const RenderContextBatch& renderContextBatch, DrawP
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
FORCE_INLINE bool CanBatchWith(const DrawCall& a, const DrawCall& b, DrawPass pass)
|
||||
{
|
||||
IMaterial::InstancingHandler handlerA, handlerB;
|
||||
return a.Material->CanUseInstancing(handlerA) &&
|
||||
b.Material->CanUseInstancing(handlerB) &&
|
||||
Platform::MemoryCompare(&a.Geometry, &b.Geometry, sizeof(a.Geometry)) == 0 &&
|
||||
a.InstanceCount != 0 &&
|
||||
b.InstanceCount != 0 &&
|
||||
handlerA.CanBatch == handlerB.CanBatch &&
|
||||
handlerA.CanBatch(a, b, pass) &&
|
||||
a.WorldDeterminantSign * b.WorldDeterminantSign > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,11 +643,11 @@ void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseD
|
||||
int32 batchSize = 1;
|
||||
int32 instanceCount = drawCall.InstanceCount;
|
||||
|
||||
// Check the following draw calls to merge them (using instancing)
|
||||
// Check the following draw calls sequence to merge them
|
||||
for (int32 j = i + 1; j < listSize; j++)
|
||||
{
|
||||
const DrawCall& other = drawCallsData[listData[j]];
|
||||
if (!CanBatchWith(drawCall, other, pass))
|
||||
if (!CanBatchDrawCalls(drawCall, other, pass))
|
||||
break;
|
||||
batchSize++;
|
||||
instanceCount += other.InstanceCount;
|
||||
@@ -949,9 +953,7 @@ bool SurfaceDrawCallHandler::CanBatch(const DrawCall& a, const DrawCall& b, Draw
|
||||
{
|
||||
// TODO: find reason why batching static meshes with lightmap causes problems with sampling in shader (flickering when meshes in batch order gets changes due to async draw calls collection)
|
||||
if (a.Surface.Lightmap == nullptr && b.Surface.Lightmap == nullptr &&
|
||||
//return a.Surface.Lightmap == b.Surface.Lightmap &&
|
||||
a.Surface.Skinning == nullptr &&
|
||||
b.Surface.Skinning == nullptr)
|
||||
a.Surface.Skinning == nullptr && b.Surface.Skinning == nullptr)
|
||||
{
|
||||
if (a.Material != b.Material)
|
||||
{
|
||||
|
||||
@@ -502,7 +502,7 @@ public:
|
||||
/// <param name="drawCall">The draw call data.</param>
|
||||
/// <param name="receivesDecals">True if the rendered mesh can receive decals.</param>
|
||||
/// <param name="sortOrder">Object sorting key.</param>
|
||||
void AddDrawCall(const RenderContext& renderContext, DrawPass drawModes, StaticFlags staticFlags, DrawCall& drawCall, bool receivesDecals = true, int16 sortOrder = 0);
|
||||
void AddDrawCall(const RenderContext& renderContext, DrawPass drawModes, StaticFlags staticFlags, DrawCall& drawCall, bool receivesDecals = true, int8 sortOrder = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the draw call to the draw lists and references it in other render contexts. Performs additional per-context frustum culling.
|
||||
@@ -515,7 +515,7 @@ public:
|
||||
/// <param name="drawCall">The draw call data.</param>
|
||||
/// <param name="receivesDecals">True if the rendered mesh can receive decals.</param>
|
||||
/// <param name="sortOrder">Object sorting key.</param>
|
||||
void AddDrawCall(const RenderContextBatch& renderContextBatch, DrawPass drawModes, StaticFlags staticFlags, ShadowsCastingMode shadowsMode, const BoundingSphere& bounds, DrawCall& drawCall, bool receivesDecals = true, int16 sortOrder = 0);
|
||||
void AddDrawCall(const RenderContextBatch& renderContextBatch, DrawPass drawModes, StaticFlags staticFlags, ShadowsCastingMode shadowsMode, const BoundingSphere& bounds, DrawCall& drawCall, bool receivesDecals = true, int8 sortOrder = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Sorts the collected draw calls list.
|
||||
|
||||
@@ -85,10 +85,10 @@ public:
|
||||
DrawPass DrawModes = DrawPass::Default;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the object sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be use to control transparency drawing.
|
||||
/// Gets the object sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be used to control transparency drawing.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(60), DefaultValue(0), EditorDisplay(\"Sprite\")")
|
||||
int16 SortOrder = 0;
|
||||
int8 SortOrder = 0;
|
||||
|
||||
private:
|
||||
void OnMaterialLoaded();
|
||||
|
||||
@@ -111,10 +111,10 @@ public:
|
||||
ShadowsCastingMode ShadowsMode = ShadowsCastingMode::All;
|
||||
|
||||
/// <summary>
|
||||
/// The object sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be use to control transparency drawing.
|
||||
/// The object sort order key used when sorting drawable objects during rendering. Use lower values to draw object before others, higher values are rendered later (on top). Can be used to control transparency drawing.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(85), DefaultValue(0), EditorDisplay(\"Text\")")
|
||||
int16 SortOrder = 0;
|
||||
int8 SortOrder = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the layout options. Layout is defined in local space of the object (on XY plane).
|
||||
|
||||
Reference in New Issue
Block a user