diff --git a/Content/Editor/MaterialTemplates/Surface.shader b/Content/Editor/MaterialTemplates/Surface.shader
index 461aa714d..3b924ecf3 100644
--- a/Content/Editor/MaterialTemplates/Surface.shader
+++ b/Content/Editor/MaterialTemplates/Surface.shader
@@ -22,14 +22,12 @@ float3 ViewDir;
float TimeParam;
float4 ViewInfo;
float4 ScreenSize;
-float3 WorldInvScale;
-float WorldDeterminantSign;
float2 Dummy0;
float LODDitherFactor;
float PerInstanceRandom;
float4 TemporalAAJitter;
float3 GeometrySize;
-float Dummy1;
+float WorldDeterminantSign;
@1META_CB_END
// Shader resources
@@ -48,6 +46,9 @@ struct GeometryData
nointerpolation float3 InstanceOrigin : TEXCOORD5;
nointerpolation float2 InstanceParams : TEXCOORD6; // x-PerInstanceRandom, y-LODDitherFactor
float3 PrevWorldPosition : TEXCOORD7;
+ nointerpolation float3 InstanceTransform1 : TEXCOORD8;
+ nointerpolation float3 InstanceTransform2 : TEXCOORD9;
+ nointerpolation float3 InstanceTransform3 : TEXCOORD10;
};
// Interpolants passed from the vertex shader
@@ -92,11 +93,9 @@ struct MaterialInput
float3 PreSkinnedNormal;
float3 InstanceOrigin;
float2 InstanceParams;
-#if USE_INSTANCING
float3 InstanceTransform1;
float3 InstanceTransform2;
float3 InstanceTransform3;
-#endif
#if USE_CUSTOM_VERTEX_INTERPOLATORS
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT];
#endif
@@ -117,6 +116,9 @@ MaterialInput GetGeometryMaterialInput(GeometryData geometry)
output.TBN = CalcTangentBasis(geometry.WorldNormal, geometry.WorldTangent);
output.InstanceOrigin = geometry.InstanceOrigin;
output.InstanceParams = geometry.InstanceParams;
+ output.InstanceTransform1 = geometry.InstanceTransform1;
+ output.InstanceTransform2 = geometry.InstanceTransform2;
+ output.InstanceTransform3 = geometry.InstanceTransform3;
return output;
}
@@ -154,6 +156,9 @@ GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, flo
output.WorldTangent.xyz = normalize(output.WorldTangent.xyz);
output.InstanceOrigin = p0.InstanceOrigin;
output.InstanceParams = p0.InstanceParams;
+ output.InstanceTransform1 = p0.InstanceTransform1;
+ output.InstanceTransform2 = p0.InstanceTransform2;
+ output.InstanceTransform3 = p0.InstanceTransform3;
return output;
}
@@ -170,17 +175,19 @@ MaterialInput GetMaterialInput(PixelInput input)
return output;
}
-// Gets the local to world transform matrix (supports instancing)
-#if USE_INSTANCING
+// Gets the local to world transform matrix
#define GetInstanceTransform(input) float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f))
+
+// Extarcts the world matrix and instancce transform vector
+#if USE_INSTANCING
+#define CalculateInstanceTransform(input) float4x4 world = GetInstanceTransform(input); output.Geometry.InstanceTransform1 = input.InstanceTransform1.xyz; output.Geometry.InstanceTransform2 = input.InstanceTransform2.xyz; output.Geometry.InstanceTransform3 = input.InstanceTransform3.xyz;
#else
-#define GetInstanceTransform(input) WorldMatrix;
+#define CalculateInstanceTransform(input) float4x4 world = WorldMatrix; output.Geometry.InstanceTransform1 = world[0].xyz; output.Geometry.InstanceTransform2 = world[1].xyz; output.Geometry.InstanceTransform3 = world[2].xyz;
#endif
// Removes the scale vector from the local to world transformation matrix (supports instancing)
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
{
-#if USE_INSTANCING
// Extract per axis scales from localToWorld transform
float scaleX = length(localToWorld[0]);
float scaleY = length(localToWorld[1]);
@@ -189,9 +196,6 @@ float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
scaleX > 0.00001f ? 1.0f / scaleX : 0.0f,
scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
-#else
- float3 invScale = WorldInvScale;
-#endif
localToWorld[0] *= invScale.x;
localToWorld[1] *= invScale.y;
localToWorld[2] *= invScale.z;
@@ -333,7 +337,7 @@ VertexOutput VS(ModelInput input)
VertexOutput output;
// Compute world space vertex position
- float4x4 world = GetInstanceTransform(input);
+ CalculateInstanceTransform(input);
output.Geometry.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), PrevWorldMatrix).xyz;
@@ -372,11 +376,6 @@ VertexOutput VS(ModelInput input)
materialInput.SvPosition = output.Position;
materialInput.PreSkinnedPosition = input.Position.xyz;
materialInput.PreSkinnedNormal = tangentToLocal[2].xyz;
-#if USE_INSTANCING
- materialInput.InstanceTransform1 = input.InstanceTransform1.xyz;
- materialInput.InstanceTransform2 = input.InstanceTransform2.xyz;
- materialInput.InstanceTransform3 = input.InstanceTransform3.xyz;
-#endif
Material material = GetMaterialVS(materialInput);
#endif
@@ -411,7 +410,11 @@ META_VS_IN_ELEMENT(ATTRIBUTE,3, R32G32B32_FLOAT, 3, ALIGN, PER_INSTANCE, 1, US
META_VS_IN_ELEMENT(ATTRIBUTE,4, R16G16B16A16_FLOAT,3, ALIGN, PER_INSTANCE, 1, USE_INSTANCING)
float4 VS_Depth(ModelInput_PosOnly input) : SV_Position
{
+#if USE_INSTANCING
float4x4 world = GetInstanceTransform(input);
+#else
+ float4x4 world = WorldMatrix;
+#endif
float3 worldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
float4 position = mul(float4(worldPosition, 1), ViewProjectionMatrix);
return position;
@@ -515,7 +518,7 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
float3x3 tangentToLocal = SkinTangents(input, data);
// Compute world space vertex position
- float4x4 world = GetInstanceTransform(input);
+ CalculateInstanceTransform(input);
output.Geometry.WorldPosition = mul(float4(position, 1), world).xyz;
#if PER_BONE_MOTION_BLUR
float3 prevPosition = SkinPrevPosition(input);
diff --git a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
index 6fdac4f2d..9f03f81ca 100644
--- a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
@@ -30,14 +30,12 @@ PACK_STRUCT(struct DeferredMaterialShaderData {
float TimeParam;
Float4 ViewInfo;
Float4 ScreenSize;
- Float3 WorldInvScale;
- float WorldDeterminantSign;
Float2 Dummy0;
float LODDitherFactor;
float PerInstanceRandom;
Float4 TemporalAAJitter;
Float3 GeometrySize;
- float Dummy1;
+ float WorldDeterminantSign;
});
DrawPass DeferredMaterialShader::GetDrawModes() const
@@ -96,13 +94,6 @@ void DeferredMaterialShader::Bind(BindParameters& params)
materialData->TimeParam = params.TimeParam;
materialData->ViewInfo = view.ViewInfo;
materialData->ScreenSize = view.ScreenSize;
- const float scaleX = Float3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13).Length();
- const float scaleY = Float3(drawCall.World.M21, drawCall.World.M22, drawCall.World.M23).Length();
- const float scaleZ = Float3(drawCall.World.M31, drawCall.World.M32, drawCall.World.M33).Length();
- materialData->WorldInvScale = Float3(
- scaleX > 0.00001f ? 1.0f / scaleX : 0.0f,
- scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
- scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign;
materialData->LODDitherFactor = drawCall.Surface.LODDitherFactor;
materialData->PerInstanceRandom = drawCall.PerInstanceRandom;
diff --git a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp
index 6c28fa096..9897063d1 100644
--- a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp
+++ b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp
@@ -32,14 +32,12 @@ PACK_STRUCT(struct ForwardMaterialShaderData {
float TimeParam;
Float4 ViewInfo;
Float4 ScreenSize;
- Float3 WorldInvScale;
- float WorldDeterminantSign;
Float2 Dummy0;
float LODDitherFactor;
float PerInstanceRandom;
Float4 TemporalAAJitter;
Float3 GeometrySize;
- float Dummy1;
+ float WorldDeterminantSign;
});
DrawPass ForwardMaterialShader::GetDrawModes() const
@@ -104,13 +102,6 @@ void ForwardMaterialShader::Bind(BindParameters& params)
materialData->TimeParam = params.TimeParam;
materialData->ViewInfo = view.ViewInfo;
materialData->ScreenSize = view.ScreenSize;
- const float scaleX = Float3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13).Length();
- const float scaleY = Float3(drawCall.World.M21, drawCall.World.M22, drawCall.World.M23).Length();
- const float scaleZ = Float3(drawCall.World.M31, drawCall.World.M32, drawCall.World.M33).Length();
- materialData->WorldInvScale = Float3(
- scaleX > 0.00001f ? 1.0f / scaleX : 0.0f,
- scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
- scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign;
materialData->LODDitherFactor = drawCall.Surface.LODDitherFactor;
materialData->PerInstanceRandom = drawCall.PerInstanceRandom;
diff --git a/Source/Engine/Graphics/Materials/IMaterial.h b/Source/Engine/Graphics/Materials/IMaterial.h
index 061da5192..9c6eed0cf 100644
--- a/Source/Engine/Graphics/Materials/IMaterial.h
+++ b/Source/Engine/Graphics/Materials/IMaterial.h
@@ -117,7 +117,7 @@ public:
///
struct InstancingHandler
{
- void (*GetHash)(const DrawCall& drawCall, int32& batchKey);
+ void (*GetHash)(const DrawCall& drawCall, uint32& batchKey);
bool (*CanBatch)(const DrawCall& a, const DrawCall& b);
void (*WriteDrawCall)(struct InstanceData* instanceData, const DrawCall& drawCall);
};
diff --git a/Source/Engine/Graphics/Materials/MaterialShader.h b/Source/Engine/Graphics/Materials/MaterialShader.h
index 3c8bf37bf..c7249b2ab 100644
--- a/Source/Engine/Graphics/Materials/MaterialShader.h
+++ b/Source/Engine/Graphics/Materials/MaterialShader.h
@@ -10,7 +10,7 @@
///
/// Current materials shader version.
///
-#define MATERIAL_GRAPH_VERSION 156
+#define MATERIAL_GRAPH_VERSION 157
class Material;
class GPUShader;
diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp
index 14395cb84..1d0278b17 100644
--- a/Source/Engine/Renderer/RenderList.cpp
+++ b/Source/Engine/Renderer/RenderList.cpp
@@ -16,11 +16,6 @@
#include "Engine/Level/Scene/Lightmap.h"
#include "Engine/Level/Actors/PostFxVolume.h"
-// Amount of bits to use for draw calls batches hash key
-#define USE_BATCH_KEY_MASK 0
-#define BATCH_KEY_BITS 32
-#define BATCH_KEY_MASK ((1 << BATCH_KEY_BITS) - 1)
-
static_assert(sizeof(DrawCall) <= 280, "Too big draw call data size.");
static_assert(sizeof(DrawCall::Surface) >= sizeof(DrawCall::Terrain), "Wrong draw call data size.");
static_assert(sizeof(DrawCall::Surface) >= sizeof(DrawCall::Particle), "Wrong draw call data size.");
@@ -524,9 +519,10 @@ namespace
}
}
-void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseDistance, DrawCallsList& list, const DrawCall* drawCalls)
+void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseDistance, DrawCallsList& list, const RenderListBuffer& drawCalls)
{
PROFILE_CPU();
+ const auto* drawCallsData = drawCalls.Get();
const auto* listData = list.Indices.Get();
const int32 listSize = list.Indices.Count();
const Float3 planeNormal = renderContext.View.Direction;
@@ -544,10 +540,10 @@ void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseD
const uint32 sortKeyXor = reverseDistance ? MAX_uint32 : 0;
for (int32 i = 0; i < listSize; i++)
{
- const DrawCall& drawCall = drawCalls[listData[i]];
+ const DrawCall& drawCall = drawCallsData[listData[i]];
const float distance = Float3::Dot(planeNormal, drawCall.ObjectPosition) - planePoint;
const uint32 sortKey = RenderTools::ComputeDistanceSortKey(distance) ^ sortKeyXor;
- int32 batchKey = GetHash(drawCall.Geometry.IndexBuffer);
+ uint32 batchKey = GetHash(drawCall.Geometry.IndexBuffer);
batchKey = (batchKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[0]);
batchKey = (batchKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[1]);
batchKey = (batchKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[2]);
@@ -556,12 +552,7 @@ void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseD
if (drawCall.Material->CanUseInstancing(handler))
handler.GetHash(drawCall, batchKey);
batchKey += (int32)(471 * drawCall.WorldDeterminantSign);
-#if USE_BATCH_KEY_MASK
- const uint32 batchHashKey = (uint32)batchKey & BATCH_KEY_MASK;
-#else
- const uint32 batchHashKey = (uint32)batchKey;
-#endif
- sortedKeys[i] = (uint64)batchHashKey << 32 | (uint64)sortKey;
+ sortedKeys[i] = (uint64)batchKey << 32 | (uint64)sortKey;
}
// Sort draw calls indices
@@ -574,14 +565,14 @@ void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseD
list.Batches.Clear();
for (int32 i = 0; i < listSize;)
{
- const DrawCall& drawCall = drawCalls[listData[i]];
+ const DrawCall& drawCall = drawCallsData[listData[i]];
int32 batchSize = 1;
int32 instanceCount = drawCall.InstanceCount;
// Check the following draw calls to merge them (using instancing)
for (int32 j = i + 1; j < listSize; j++)
{
- const DrawCall& other = drawCalls[listData[j]];
+ const DrawCall& other = drawCallsData[listData[j]];
if (!CanBatchWith(drawCall, other))
break;
@@ -608,11 +599,12 @@ bool CanUseInstancing(DrawPass pass)
return pass == DrawPass::GBuffer || pass == DrawPass::Depth;
}
-void RenderList::ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsList& list, const DrawCall* drawCalls, GPUTextureView* input)
+void RenderList::ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsList& list, const RenderListBuffer& drawCalls, GPUTextureView* input)
{
if (list.IsEmpty())
return;
PROFILE_GPU_CPU("Drawing");
+ const auto* drawCallsData = drawCalls.Get();
const auto* listData = list.Indices.Get();
const auto* batchesData = list.Batches.Get();
const auto context = GPUDevice::Instance->GetMainContext();
@@ -655,10 +647,10 @@ void RenderList::ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsL
if (batch.BatchSize > 1)
{
IMaterial::InstancingHandler handler;
- drawCalls[listData[batch.StartIndex]].Material->CanUseInstancing(handler);
+ drawCallsData[listData[batch.StartIndex]].Material->CanUseInstancing(handler);
for (int32 j = 0; j < batch.BatchSize; j++)
{
- auto& drawCall = drawCalls[listData[batch.StartIndex + j]];
+ auto& drawCall = drawCallsData[listData[batch.StartIndex + j]];
handler.WriteDrawCall(instanceData, drawCall);
instanceData++;
}
@@ -691,7 +683,7 @@ DRAW:
for (int32 i = 0; i < list.Batches.Count(); i++)
{
auto& batch = batchesData[i];
- const DrawCall& drawCall = drawCalls[listData[batch.StartIndex]];
+ const DrawCall& drawCall = drawCallsData[listData[batch.StartIndex]];
int32 vbCount = 0;
while (vbCount < ARRAY_COUNT(drawCall.Geometry.VertexBuffers) && drawCall.Geometry.VertexBuffers[vbCount])
@@ -866,14 +858,16 @@ DRAW:
}
}
-void SurfaceDrawCallHandler::GetHash(const DrawCall& drawCall, int32& batchKey)
+void SurfaceDrawCallHandler::GetHash(const DrawCall& drawCall, uint32& batchKey)
{
batchKey = (batchKey * 397) ^ ::GetHash(drawCall.Surface.Lightmap);
}
bool SurfaceDrawCallHandler::CanBatch(const DrawCall& a, const DrawCall& b)
{
- return a.Surface.Lightmap == b.Surface.Lightmap &&
+ // 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)
+ return a.Surface.Lightmap == nullptr && b.Surface.Lightmap == nullptr &&
+ //return a.Surface.Lightmap == b.Surface.Lightmap &&
a.Surface.Skinning == nullptr &&
b.Surface.Skinning == nullptr;
}
diff --git a/Source/Engine/Renderer/RenderList.h b/Source/Engine/Renderer/RenderList.h
index 1363d5071..292adf278 100644
--- a/Source/Engine/Renderer/RenderList.h
+++ b/Source/Engine/Renderer/RenderList.h
@@ -504,7 +504,7 @@ public:
/// The collected draw calls list type.
API_FUNCTION() FORCE_INLINE void SortDrawCalls(API_PARAM(Ref) const RenderContext& renderContext, bool reverseDistance, DrawCallsListType listType)
{
- SortDrawCalls(renderContext, reverseDistance, DrawCallsLists[(int32)listType], DrawCalls.Get());
+ SortDrawCalls(renderContext, reverseDistance, DrawCallsLists[(int32)listType], DrawCalls);
}
///
@@ -514,7 +514,7 @@ public:
/// If set to true reverse draw call distance to the view. Results in back to front sorting.
/// The collected draw calls indices list.
/// The collected draw calls list.
- void SortDrawCalls(const RenderContext& renderContext, bool reverseDistance, DrawCallsList& list, const DrawCall* drawCalls);
+ void SortDrawCalls(const RenderContext& renderContext, bool reverseDistance, DrawCallsList& list, const RenderListBuffer& drawCalls);
///
/// Executes the collected draw calls.
@@ -524,7 +524,7 @@ public:
/// The input scene color. It's optional and used in forward/postFx rendering.
API_FUNCTION() FORCE_INLINE void ExecuteDrawCalls(API_PARAM(Ref) const RenderContext& renderContext, DrawCallsListType listType, GPUTextureView* input = nullptr)
{
- ExecuteDrawCalls(renderContext, DrawCallsLists[(int32)listType], DrawCalls.Get(), input);
+ ExecuteDrawCalls(renderContext, DrawCallsLists[(int32)listType], DrawCalls, input);
}
///
@@ -535,7 +535,7 @@ public:
/// The input scene color. It's optional and used in forward/postFx rendering.
FORCE_INLINE void ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsList& list, GPUTextureView* input = nullptr)
{
- ExecuteDrawCalls(renderContext, list, DrawCalls.Get(), input);
+ ExecuteDrawCalls(renderContext, list, DrawCalls, input);
}
///
@@ -545,14 +545,14 @@ public:
/// The collected draw calls indices list.
/// The collected draw calls list.
/// The input scene color. It's optional and used in forward/postFx rendering.
- void ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsList& list, const DrawCall* drawCalls, GPUTextureView* input);
+ void ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsList& list, const RenderListBuffer& drawCalls, GPUTextureView* input);
};
///
/// Represents data per instance element used for instanced rendering.
///
-struct FLAXENGINE_API InstanceData
-{
+PACK_STRUCT(struct FLAXENGINE_API InstanceData
+ {
Float3 InstanceOrigin;
float PerInstanceRandom;
Float3 InstanceTransform1;
@@ -560,11 +560,11 @@ struct FLAXENGINE_API InstanceData
Float3 InstanceTransform2;
Float3 InstanceTransform3;
Half4 InstanceLightmapArea;
-};
+ });
struct SurfaceDrawCallHandler
{
- static void GetHash(const DrawCall& drawCall, int32& batchKey);
+ static void GetHash(const DrawCall& drawCall, uint32& batchKey);
static bool CanBatch(const DrawCall& a, const DrawCall& b);
static void WriteDrawCall(InstanceData* instanceData, const DrawCall& drawCall);
};
diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp
index 29e72d369..ff66ec32a 100644
--- a/Source/Engine/Renderer/Renderer.cpp
+++ b/Source/Engine/Renderer/Renderer.cpp
@@ -373,7 +373,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
{
auto& shadowContext = renderContextBatch.Contexts[i];
shadowContext.List->SortDrawCalls(shadowContext, false, DrawCallsListType::Depth);
- shadowContext.List->SortDrawCalls(shadowContext, false, shadowContext.List->ShadowDepthDrawCallsList, renderContext.List->DrawCalls.Get());
+ shadowContext.List->SortDrawCalls(shadowContext, false, shadowContext.List->ShadowDepthDrawCallsList, renderContext.List->DrawCalls);
}
}
diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp
index 100a7cda7..9449c2290 100644
--- a/Source/Engine/Renderer/ShadowsPass.cpp
+++ b/Source/Engine/Renderer/ShadowsPass.cpp
@@ -631,7 +631,7 @@ void ShadowsPass::RenderShadow(RenderContextBatch& renderContextBatch, RendererP
context->ClearDepth(rt);
auto& shadowContext = renderContextBatch.Contexts[shadowData.ContextIndex + faceIndex];
shadowContext.List->ExecuteDrawCalls(shadowContext, DrawCallsListType::Depth);
- shadowContext.List->ExecuteDrawCalls(shadowContext, shadowContext.List->ShadowDepthDrawCallsList, renderContext.List->DrawCalls.Get(), nullptr);
+ shadowContext.List->ExecuteDrawCalls(shadowContext, shadowContext.List->ShadowDepthDrawCallsList, renderContext.List->DrawCalls, nullptr);
}
// Restore GPU context
@@ -709,7 +709,7 @@ void ShadowsPass::RenderShadow(RenderContextBatch& renderContextBatch, RendererS
context->ClearDepth(rt);
auto& shadowContext = renderContextBatch.Contexts[shadowData.ContextIndex + faceIndex];
shadowContext.List->ExecuteDrawCalls(shadowContext, DrawCallsListType::Depth);
- shadowContext.List->ExecuteDrawCalls(shadowContext, shadowContext.List->ShadowDepthDrawCallsList, renderContext.List->DrawCalls.Get(), nullptr);
+ shadowContext.List->ExecuteDrawCalls(shadowContext, shadowContext.List->ShadowDepthDrawCallsList, renderContext.List->DrawCalls, nullptr);
}
// Restore GPU context
@@ -779,7 +779,7 @@ void ShadowsPass::RenderShadow(RenderContextBatch& renderContextBatch, RendererD
context->ClearDepth(rt);
auto& shadowContext = renderContextBatch.Contexts[shadowData.ContextIndex + cascadeIndex];
shadowContext.List->ExecuteDrawCalls(shadowContext, DrawCallsListType::Depth);
- shadowContext.List->ExecuteDrawCalls(shadowContext, shadowContext.List->ShadowDepthDrawCallsList, renderContext.List->DrawCalls.Get(), nullptr);
+ shadowContext.List->ExecuteDrawCalls(shadowContext, shadowContext.List->ShadowDepthDrawCallsList, renderContext.List->DrawCalls, nullptr);
}
// Restore GPU context
diff --git a/Source/Engine/Threading/ConcurrentQueue.h b/Source/Engine/Threading/ConcurrentQueue.h
index 595233e52..27b61fb24 100644
--- a/Source/Engine/Threading/ConcurrentQueue.h
+++ b/Source/Engine/Threading/ConcurrentQueue.h
@@ -35,11 +35,9 @@ template
class ConcurrentQueue : public moodycamel::ConcurrentQueue
{
public:
-
typedef moodycamel::ConcurrentQueue Base;
public:
-
///
/// Gets an estimate of the total number of elements currently in the queue.
///
@@ -52,7 +50,16 @@ public:
/// Adds item to the collection.
///
/// The item to add.
- FORCE_INLINE void Add(T& item)
+ FORCE_INLINE void Add(const T& item)
+ {
+ enqueue(item);
+ }
+
+ ///
+ /// Adds item to the collection.
+ ///
+ /// The item to add.
+ FORCE_INLINE void Add(T&& item)
{
enqueue(item);
}
diff --git a/Source/Engine/Threading/JobSystem.cpp b/Source/Engine/Threading/JobSystem.cpp
index 70de78ed0..198bf4cde 100644
--- a/Source/Engine/Threading/JobSystem.cpp
+++ b/Source/Engine/Threading/JobSystem.cpp
@@ -339,6 +339,9 @@ void JobSystem::Wait(int64 label)
WaitMutex.Lock();
WaitSignal.Wait(WaitMutex, 1);
WaitMutex.Unlock();
+
+ // Wake up any thread to prevent stalling in highly multi-threaded environment
+ JobsSignal.NotifyOne();
}
#if JOB_SYSTEM_USE_STATS