Merge remote-tracking branch 'origin/master' into 1.12
# Conflicts: # Source/Editor/Options/InterfaceOptions.cs # Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp # Source/Engine/Graphics/Graphics.cpp # Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp # Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.h # Source/Engine/GraphicsDevice/Vulkan/Config.h # Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp # Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h # Source/Engine/GraphicsDevice/Vulkan/QueueVulkan.cpp
This commit is contained in:
@@ -207,16 +207,16 @@ public:
|
||||
API_PROPERTY() void SetAttenuation(float value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the doppler effect factor. Scale for source velocity. Default is 1.
|
||||
/// Gets the doppler effect factor. Scale for source velocity. Default is 1. Used by spatial sources only. Cannot scale the effect up (only dim it).
|
||||
/// </summary>
|
||||
API_PROPERTY(Attributes="EditorOrder(75), DefaultValue(1.0f), Limit(0, float.MaxValue, 0.1f), EditorDisplay(\"Audio Source\")")
|
||||
API_PROPERTY(Attributes="EditorOrder(75), DefaultValue(1.0f), Limit(0, 1.0f, 0.1f), EditorDisplay(\"Audio Source\")")
|
||||
FORCE_INLINE float GetDopplerFactor() const
|
||||
{
|
||||
return _dopplerFactor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the doppler effect factor. Scale for source velocity. Default is 1.
|
||||
/// Sets the doppler effect factor. Scale for source velocity. Default is 1. Used by spatial sources only. Cannot scale the effect up (only dim it).
|
||||
/// </summary>
|
||||
API_PROPERTY() void SetDopplerFactor(float value);
|
||||
|
||||
|
||||
@@ -848,6 +848,13 @@ bool AudioBackendOAL::Base_Init()
|
||||
}
|
||||
|
||||
// Init
|
||||
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); // Default attenuation model
|
||||
if (Audio::GetActiveDeviceIndex() == Math::Clamp(activeDeviceIndex, -1, Audio::Devices.Count() - 1))
|
||||
{
|
||||
// Manually create context if SetActiveDeviceIndex won't call it
|
||||
Base_OnActiveDeviceChanged();
|
||||
}
|
||||
Audio::SetActiveDeviceIndex(activeDeviceIndex);
|
||||
#ifdef AL_SOFT_source_spatialize
|
||||
if (ALC::IsExtensionSupported("AL_SOFT_source_spatialize"))
|
||||
ALC::Features = EnumAddFlags(ALC::Features, FeatureFlags::SpatialMultiChannel);
|
||||
@@ -856,13 +863,6 @@ bool AudioBackendOAL::Base_Init()
|
||||
ALC::Features = EnumAddFlags(ALC::Features, FeatureFlags::HRTF);
|
||||
#endif
|
||||
Base_SetDopplerFactor(AudioSettings::Get()->DopplerFactor);
|
||||
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); // Default attenuation model
|
||||
if (Audio::GetActiveDeviceIndex() == Math::Clamp(activeDeviceIndex, -1, Audio::Devices.Count() - 1))
|
||||
{
|
||||
// Manually create context if SetActiveDeviceIndex won't call it
|
||||
Base_OnActiveDeviceChanged();
|
||||
}
|
||||
Audio::SetActiveDeviceIndex(activeDeviceIndex);
|
||||
ALC::Inited = true;
|
||||
|
||||
// Log service info
|
||||
|
||||
@@ -246,7 +246,7 @@ VariantType::VariantType(VariantType&& other) noexcept
|
||||
VariantType& VariantType::operator=(const Types& type)
|
||||
{
|
||||
Type = type;
|
||||
if (StaticName)
|
||||
if (!StaticName)
|
||||
Allocator::Free(TypeName);
|
||||
TypeName = nullptr;
|
||||
StaticName = 0;
|
||||
@@ -265,7 +265,7 @@ VariantType& VariantType::operator=(const VariantType& other)
|
||||
{
|
||||
ASSERT(this != &other);
|
||||
Type = other.Type;
|
||||
if (StaticName)
|
||||
if (!StaticName)
|
||||
Allocator::Free(TypeName);
|
||||
StaticName = other.StaticName;
|
||||
if (StaticName)
|
||||
@@ -315,7 +315,7 @@ void VariantType::SetTypeName(const StringView& typeName)
|
||||
{
|
||||
if (StringUtils::Length(TypeName) != typeName.Length())
|
||||
{
|
||||
if (StaticName)
|
||||
if (!StaticName)
|
||||
Allocator::Free(TypeName);
|
||||
StaticName = 0;
|
||||
TypeName = static_cast<char*>(Allocator::Allocate(typeName.Length() + 1));
|
||||
@@ -328,7 +328,7 @@ void VariantType::SetTypeName(const StringAnsiView& typeName, bool staticName)
|
||||
{
|
||||
if (StringUtils::Length(TypeName) != typeName.Length() || StaticName != staticName)
|
||||
{
|
||||
if (StaticName)
|
||||
if (!StaticName)
|
||||
Allocator::Free(TypeName);
|
||||
StaticName = staticName;
|
||||
if (staticName)
|
||||
|
||||
@@ -6,14 +6,13 @@
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Random.h"
|
||||
#include "Engine/Engine/Engine.h"
|
||||
#include "Engine/Graphics/Graphics.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
#include "Engine/Graphics/RenderTools.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Content/Deprecated.h"
|
||||
#if !FOLIAGE_USE_SINGLE_QUAD_TREE
|
||||
#include "Engine/Threading/JobSystem.h"
|
||||
#if FOLIAGE_USE_DRAW_CALLS_BATCHING
|
||||
#include "Engine/Graphics/RenderTools.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "Engine/Level/SceneQuery.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
@@ -125,7 +124,7 @@ void Foliage::AddToCluster(ChunkedArray<FoliageCluster, FOLIAGE_CLUSTER_CHUNKS_S
|
||||
|
||||
#if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING
|
||||
|
||||
void Foliage::DrawInstance(RenderContext& renderContext, FoliageInstance& instance, const FoliageType& type, Model* model, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const
|
||||
void Foliage::DrawInstance(DrawContext& context, FoliageInstance& instance, Model* model, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const
|
||||
{
|
||||
const auto& meshes = model->LODs.Get()[lod].Meshes;
|
||||
for (int32 meshIndex = 0; meshIndex < meshes.Count(); meshIndex++)
|
||||
@@ -141,7 +140,7 @@ void Foliage::DrawInstance(RenderContext& renderContext, FoliageInstance& instan
|
||||
auto* e = result.TryGet(key);
|
||||
if (!e)
|
||||
{
|
||||
e = &result.Add(key, BatchedDrawCall(renderContext.List))->Value;
|
||||
e = &result.Add(key, BatchedDrawCall(context.RenderContext.List))->Value;
|
||||
ASSERT_LOW_LAYER(key.Mat);
|
||||
e->DrawCall.Material = key.Mat;
|
||||
e->DrawCall.Surface.Lightmap = EnumHasAnyFlags(_staticFlags, StaticFlags::Lightmap) && _scene ? _scene->LightmapsData.GetReadyLightmap(key.Lightmap) : nullptr;
|
||||
@@ -152,21 +151,18 @@ void Foliage::DrawInstance(RenderContext& renderContext, FoliageInstance& instan
|
||||
auto& instanceData = e->Instances.AddOne();
|
||||
Matrix world;
|
||||
const Transform transform = _transform.LocalToWorld(instance.Transform);
|
||||
const Float3 translation = transform.Translation - renderContext.View.Origin;
|
||||
const Float3 translation = transform.Translation - context.ViewOrigin;
|
||||
Matrix::Transformation(transform.Scale, transform.Orientation, translation, world);
|
||||
constexpr float worldDeterminantSign = 1.0f;
|
||||
instanceData.Store(world, world, instance.Lightmap.UVsArea, drawCall.Surface.GeometrySize, instance.Random, worldDeterminantSign, lodDitherFactor);
|
||||
}
|
||||
}
|
||||
|
||||
void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster, const FoliageType& type, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const
|
||||
void Foliage::DrawCluster(DrawContext& context, FoliageCluster* cluster, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const
|
||||
{
|
||||
// Skip clusters that around too far from view
|
||||
const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View);
|
||||
if (Float3::Distance(lodView->Position, cluster->TotalBoundsSphere.Center - lodView->Origin) - (float)cluster->TotalBoundsSphere.Radius > cluster->MaxCullDistance)
|
||||
if (Float3::Distance(context.LodView.Position, cluster->TotalBoundsSphere.Center - context.LodView.Origin) - (float)cluster->TotalBoundsSphere.Radius > cluster->MaxCullDistance)
|
||||
return;
|
||||
const Vector3 viewOrigin = renderContext.View.Origin;
|
||||
|
||||
//DebugDraw::DrawBox(cluster->Bounds, Color::Red);
|
||||
|
||||
// Draw visible children
|
||||
@@ -178,10 +174,10 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
|
||||
BoundingBox box;
|
||||
#define DRAW_CLUSTER(idx) \
|
||||
box = cluster->Children[idx]->TotalBounds; \
|
||||
box.Minimum -= viewOrigin; \
|
||||
box.Maximum -= viewOrigin; \
|
||||
if (renderContext.View.CullingFrustum.Intersects(box)) \
|
||||
DrawCluster(renderContext, cluster->Children[idx], type, drawCallsLists, result)
|
||||
box.Minimum -= context.ViewOrigin; \
|
||||
box.Maximum -= context.ViewOrigin; \
|
||||
if (context.RenderContext.View.CullingFrustum.Intersects(box)) \
|
||||
DrawCluster(context, cluster->Children[idx], drawCallsLists, result)
|
||||
DRAW_CLUSTER(0);
|
||||
DRAW_CLUSTER(1);
|
||||
DRAW_CLUSTER(2);
|
||||
@@ -192,21 +188,22 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
|
||||
{
|
||||
// Draw visible instances
|
||||
const auto frame = Engine::FrameCount;
|
||||
const auto model = type.Model.Get();
|
||||
const auto transitionLOD = renderContext.View.Pass != DrawPass::Depth; // Let the main view pass update LOD transitions
|
||||
const auto model = context.FoliageType.Model.Get();
|
||||
const auto transitionLOD = context.RenderContext.View.Pass != DrawPass::Depth; // Let the main view pass update LOD transitions
|
||||
// TODO: move DrawState to be stored per-view (so shadows can fade objects on their own)
|
||||
for (int32 i = 0; i < cluster->Instances.Count(); i++)
|
||||
{
|
||||
auto& instance = *cluster->Instances.Get()[i];
|
||||
BoundingSphere sphere = instance.Bounds;
|
||||
sphere.Center -= viewOrigin;
|
||||
if (Float3::Distance(lodView->Position, sphere.Center) - (float)sphere.Radius < instance.CullDistance &&
|
||||
renderContext.View.CullingFrustum.Intersects(sphere))
|
||||
sphere.Center -= context.ViewOrigin;
|
||||
if (Float3::Distance(context.LodView.Position, sphere.Center) - (float)sphere.Radius < instance.CullDistance &&
|
||||
context.RenderContext.View.CullingFrustum.Intersects(sphere) &&
|
||||
RenderTools::ComputeBoundsScreenRadiusSquared(sphere.Center, sphere.Radius, context.RenderContext.View) * context.ViewScreenSizeSq >= context.MinObjectPixelSizeSq)
|
||||
{
|
||||
const auto modelFrame = instance.DrawState.PrevFrame + 1;
|
||||
|
||||
// Select a proper LOD index (model may be culled)
|
||||
int32 lodIndex = RenderTools::ComputeModelLOD(model, sphere.Center, (float)sphere.Radius, renderContext);
|
||||
int32 lodIndex = RenderTools::ComputeModelLOD(model, sphere.Center, (float)sphere.Radius, context.RenderContext);
|
||||
if (lodIndex == -1)
|
||||
{
|
||||
// Handling model fade-out transition
|
||||
@@ -231,20 +228,20 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
|
||||
{
|
||||
const auto prevLOD = model->ClampLODIndex(instance.DrawState.PrevLOD);
|
||||
const float normalizedProgress = static_cast<float>(instance.DrawState.LODTransition) * (1.0f / 255.0f);
|
||||
DrawInstance(renderContext, instance, type, model, prevLOD, normalizedProgress, drawCallsLists, result);
|
||||
DrawInstance(context, instance, model, prevLOD, normalizedProgress, drawCallsLists, result);
|
||||
}
|
||||
}
|
||||
else if (instance.DrawState.LODTransition < 255)
|
||||
{
|
||||
const auto prevLOD = model->ClampLODIndex(instance.DrawState.PrevLOD);
|
||||
const float normalizedProgress = static_cast<float>(instance.DrawState.LODTransition) * (1.0f / 255.0f);
|
||||
DrawInstance(renderContext, instance, type, model, prevLOD, normalizedProgress, drawCallsLists, result);
|
||||
DrawInstance(context, instance, model, prevLOD, normalizedProgress, drawCallsLists, result);
|
||||
}
|
||||
}
|
||||
instance.DrawState.PrevFrame = frame;
|
||||
continue;
|
||||
}
|
||||
lodIndex += renderContext.View.ModelLODBias;
|
||||
lodIndex += context.RenderContext.View.ModelLODBias;
|
||||
lodIndex = model->ClampLODIndex(lodIndex);
|
||||
|
||||
if (transitionLOD)
|
||||
@@ -278,19 +275,19 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
|
||||
// Draw
|
||||
if (instance.DrawState.PrevLOD == lodIndex)
|
||||
{
|
||||
DrawInstance(renderContext, instance, type, model, lodIndex, 0.0f, drawCallsLists, result);
|
||||
DrawInstance(context, instance, model, lodIndex, 0.0f, drawCallsLists, result);
|
||||
}
|
||||
else if (instance.DrawState.PrevLOD == -1)
|
||||
{
|
||||
const float normalizedProgress = static_cast<float>(instance.DrawState.LODTransition) * (1.0f / 255.0f);
|
||||
DrawInstance(renderContext, instance, type, model, lodIndex, 1.0f - normalizedProgress, drawCallsLists, result);
|
||||
DrawInstance(context, instance, model, lodIndex, 1.0f - normalizedProgress, drawCallsLists, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto prevLOD = model->ClampLODIndex(instance.DrawState.PrevLOD);
|
||||
const float normalizedProgress = static_cast<float>(instance.DrawState.LODTransition) * (1.0f / 255.0f);
|
||||
DrawInstance(renderContext, instance, type, model, prevLOD, normalizedProgress, drawCallsLists, result);
|
||||
DrawInstance(renderContext, instance, type, model, lodIndex, normalizedProgress - 1.0f, drawCallsLists, result);
|
||||
DrawInstance(context, instance, model, prevLOD, normalizedProgress, drawCallsLists, result);
|
||||
DrawInstance(context, instance, model, lodIndex, normalizedProgress - 1.0f, drawCallsLists, result);
|
||||
}
|
||||
|
||||
//DebugDraw::DrawSphere(instance.Bounds, Color::YellowGreen);
|
||||
@@ -304,14 +301,11 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
|
||||
|
||||
#else
|
||||
|
||||
void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster, Mesh::DrawInfo& draw)
|
||||
void Foliage::DrawCluster(DrawContext& context, FoliageCluster* cluster, Mesh::DrawInfo& draw)
|
||||
{
|
||||
// Skip clusters that around too far from view
|
||||
const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View);
|
||||
if (Float3::Distance(lodView->Position, cluster->TotalBoundsSphere.Center - lodView->Origin) - (float)cluster->TotalBoundsSphere.Radius > cluster->MaxCullDistance)
|
||||
if (Float3::Distance(context.LodView.Position, cluster->TotalBoundsSphere.Center - context.LodView.Origin) - (float)cluster->TotalBoundsSphere.Radius > cluster->MaxCullDistance)
|
||||
return;
|
||||
const Vector3 viewOrigin = renderContext.View.Origin;
|
||||
|
||||
//DebugDraw::DrawBox(cluster->Bounds, Color::Red);
|
||||
|
||||
// Draw visible children
|
||||
@@ -323,10 +317,10 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
|
||||
BoundingBox box;
|
||||
#define DRAW_CLUSTER(idx) \
|
||||
box = cluster->Children[idx]->TotalBounds; \
|
||||
box.Minimum -= viewOrigin; \
|
||||
box.Maximum -= viewOrigin; \
|
||||
if (renderContext.View.CullingFrustum.Intersects(box)) \
|
||||
DrawCluster(renderContext, cluster->Children[idx], draw)
|
||||
box.Minimum -= context.ViewOrigin; \
|
||||
box.Maximum -= context.ViewOrigin; \
|
||||
if (context.RenderContext.View.CullingFrustum.Intersects(box)) \
|
||||
DrawCluster(context, cluster->Children[idx], draw)
|
||||
DRAW_CLUSTER(0);
|
||||
DRAW_CLUSTER(1);
|
||||
DRAW_CLUSTER(2);
|
||||
@@ -342,16 +336,17 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
|
||||
auto& instance = *cluster->Instances[i];
|
||||
auto& type = FoliageTypes[instance.Type];
|
||||
BoundingSphere sphere = instance.Bounds;
|
||||
sphere.Center -= viewOrigin;
|
||||
sphere.Center -= context.ViewOrigin;
|
||||
|
||||
// Check if can draw this instance
|
||||
if (type._canDraw &&
|
||||
Float3::Distance(lodView->Position, sphere.Center) - (float)sphere.Radius < instance.CullDistance &&
|
||||
renderContext.View.CullingFrustum.Intersects(sphere))
|
||||
Float3::Distance(context.LodView.Position, sphere.Center) - (float)sphere.Radius < instance.CullDistance &&
|
||||
context.RenderContext.View.CullingFrustum.Intersects(sphere) &&
|
||||
RenderTools::ComputeBoundsScreenRadiusSquared(sphere.Center, sphere.Radius, context.RenderContext.View) * context.ViewScreenSizeSq >= context.MinObjectPixelSizeSq)
|
||||
{
|
||||
Matrix world;
|
||||
const Transform transform = _transform.LocalToWorld(instance.Transform);
|
||||
const Float3 translation = transform.Translation - renderContext.View.Origin;
|
||||
const Float3 translation = transform.Translation - context.ViewOrigin;
|
||||
Matrix::Transformation(transform.Scale, transform.Orientation, translation, world);
|
||||
|
||||
// Disable motion blur
|
||||
@@ -367,7 +362,7 @@ void Foliage::DrawCluster(RenderContext& renderContext, FoliageCluster* cluster,
|
||||
draw.PerInstanceRandom = instance.Random;
|
||||
draw.DrawModes = type.DrawModes;
|
||||
draw.SetStencilValue(_layer);
|
||||
type.Model->Draw(renderContext, draw);
|
||||
type.Model->Draw(context.RenderContext, draw);
|
||||
|
||||
//DebugDraw::DrawSphere(instance.Bounds, Color::YellowGreen);
|
||||
|
||||
@@ -446,22 +441,50 @@ void Foliage::DrawFoliageJob(int32 i)
|
||||
PROFILE_CPU();
|
||||
PROFILE_MEM(Graphics);
|
||||
const FoliageType& type = FoliageTypes[i];
|
||||
if (type.IsReady() && type.Model->CanBeRendered())
|
||||
if (type._canDraw)
|
||||
{
|
||||
DrawCallsList drawCallsLists[MODEL_MAX_LODS];
|
||||
for (RenderContext& renderContext : _renderContextBatch->Contexts)
|
||||
{
|
||||
#if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING
|
||||
DrawType(renderContext, type, drawCallsLists);
|
||||
#else
|
||||
Mesh::DrawInfo draw;
|
||||
draw.Flags = GetStaticFlags();
|
||||
draw.DrawModes = (DrawPass)(DrawPass::Default & renderContext.View.Pass);
|
||||
draw.LODBias = 0;
|
||||
draw.ForcedLOD = -1;
|
||||
draw.VertexColors = nullptr;
|
||||
draw.Deformation = nullptr;
|
||||
DrawType(renderContext, type, draw);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING
|
||||
void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, DrawCallsList* drawCallsLists)
|
||||
#else
|
||||
void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Mesh::DrawInfo& draw)
|
||||
#endif
|
||||
{
|
||||
if (!type.Root || !FOLIAGE_CAN_DRAW(renderContext, type))
|
||||
return;
|
||||
const DrawPass typeDrawModes = FOLIAGE_GET_DRAW_MODES(renderContext, type);
|
||||
PROFILE_CPU_ASSET(type.Model);
|
||||
DrawContext context
|
||||
{
|
||||
renderContext,
|
||||
renderContext.LodProxyView ? *renderContext.LodProxyView : renderContext.View,
|
||||
type,
|
||||
renderContext.View.Origin,
|
||||
Math::Square(Graphics::Shadows::MinObjectPixelSize),
|
||||
renderContext.View.ScreenSize.X * renderContext.View.ScreenSize.Y,
|
||||
};
|
||||
if (context.RenderContext.View.Pass != DrawPass::Depth)
|
||||
context.MinObjectPixelSizeSq = 0.0f; // Don't use it in main view
|
||||
#if FOLIAGE_USE_DRAW_CALLS_BATCHING
|
||||
// Initialize draw calls for foliage type all LODs meshes
|
||||
for (int32 lod = 0; lod < type.Model->LODs.Count(); lod++)
|
||||
@@ -506,7 +529,7 @@ void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Dr
|
||||
|
||||
// Draw instances of the foliage type
|
||||
BatchedDrawCalls result(&renderContext.List->Memory);
|
||||
DrawCluster(renderContext, type.Root, type, drawCallsLists, result);
|
||||
DrawCluster(context, type.Root, drawCallsLists, result);
|
||||
|
||||
// Submit draw calls with valid instances added
|
||||
for (auto& e : result)
|
||||
@@ -568,10 +591,22 @@ void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Dr
|
||||
}
|
||||
}
|
||||
#else
|
||||
DrawCluster(renderContext, type.Root, draw);
|
||||
DrawCluster(context, type.Root, draw);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Foliage::InitType(const RenderView& view, FoliageType& type)
|
||||
{
|
||||
const DrawPass drawModes = type.DrawModes & view.Pass & view.GetShadowsDrawPassMask(type.ShadowsMode);
|
||||
type._canDraw = type.IsReady() && drawModes != DrawPass::None && type.Model && type.Model->CanBeRendered();
|
||||
for (int32 j = 0; j < type.Entries.Count(); j++)
|
||||
{
|
||||
auto& e = type.Entries[j];
|
||||
e.ReceiveDecals = type.ReceiveDecals != 0;
|
||||
e.ShadowsMode = type.ShadowsMode;
|
||||
}
|
||||
}
|
||||
|
||||
int32 Foliage::GetInstancesCount() const
|
||||
{
|
||||
return Instances.Count();
|
||||
@@ -1131,12 +1166,7 @@ void Foliage::Draw(RenderContext& renderContext)
|
||||
// Cache data per foliage instance type
|
||||
for (auto& type : FoliageTypes)
|
||||
{
|
||||
for (int32 j = 0; j < type.Entries.Count(); j++)
|
||||
{
|
||||
auto& e = type.Entries[j];
|
||||
e.ReceiveDecals = type.ReceiveDecals != 0;
|
||||
e.ShadowsMode = type.ShadowsMode;
|
||||
}
|
||||
InitType(renderContext.View, type);
|
||||
}
|
||||
|
||||
if (renderContext.View.Pass == DrawPass::GlobalSDF)
|
||||
@@ -1202,12 +1232,7 @@ void Foliage::Draw(RenderContext& renderContext)
|
||||
// Draw single foliage instance projection into Global Surface Atlas
|
||||
auto& instance = *(FoliageInstance*)GlobalSurfaceAtlasPass::Instance()->GetCurrentActorObject();
|
||||
auto& type = FoliageTypes[instance.Type];
|
||||
for (int32 i = 0; i < type.Entries.Count(); i++)
|
||||
{
|
||||
auto& e = type.Entries[i];
|
||||
e.ReceiveDecals = type.ReceiveDecals != 0;
|
||||
e.ShadowsMode = type.ShadowsMode;
|
||||
}
|
||||
InitType(renderContext.View, type);
|
||||
Matrix world;
|
||||
const Transform transform = _transform.LocalToWorld(instance.Transform);
|
||||
renderContext.View.GetWorldMatrix(transform, world);
|
||||
@@ -1239,8 +1264,9 @@ void Foliage::Draw(RenderContext& renderContext)
|
||||
draw.LODBias = 0;
|
||||
draw.ForcedLOD = -1;
|
||||
draw.VertexColors = nullptr;
|
||||
draw.Deformation = nullptr;
|
||||
#else
|
||||
DrawCallsList drawCallsLists[MODEL_MAX_LODS];
|
||||
DrawCallsList draw[MODEL_MAX_LODS];
|
||||
#endif
|
||||
#if FOLIAGE_USE_SINGLE_QUAD_TREE
|
||||
if (Root)
|
||||
@@ -1248,7 +1274,7 @@ void Foliage::Draw(RenderContext& renderContext)
|
||||
#else
|
||||
for (auto& type : FoliageTypes)
|
||||
{
|
||||
DrawType(renderContext, type, drawCallsLists);
|
||||
DrawType(renderContext, type, draw);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1265,14 +1291,7 @@ void Foliage::Draw(RenderContextBatch& renderContextBatch)
|
||||
{
|
||||
// Cache data per foliage instance type
|
||||
for (FoliageType& type : FoliageTypes)
|
||||
{
|
||||
for (int32 j = 0; j < type.Entries.Count(); j++)
|
||||
{
|
||||
auto& e = type.Entries[j];
|
||||
e.ReceiveDecals = type.ReceiveDecals != 0;
|
||||
e.ShadowsMode = type.ShadowsMode;
|
||||
}
|
||||
}
|
||||
InitType(view, type);
|
||||
|
||||
// Run async job for each foliage type
|
||||
_renderContextBatch = &renderContextBatch;
|
||||
|
||||
@@ -158,6 +158,15 @@ public:
|
||||
|
||||
private:
|
||||
void AddToCluster(ChunkedArray<FoliageCluster, FOLIAGE_CLUSTER_CHUNKS_SIZE>& clusters, FoliageCluster* cluster, FoliageInstance& instance);
|
||||
struct DrawContext
|
||||
{
|
||||
RenderContext& RenderContext;
|
||||
const RenderView& LodView;
|
||||
const FoliageType& FoliageType;
|
||||
Vector3 ViewOrigin;
|
||||
float MinObjectPixelSizeSq;
|
||||
float ViewScreenSizeSq;
|
||||
};
|
||||
#if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING
|
||||
struct DrawKey
|
||||
{
|
||||
@@ -181,10 +190,12 @@ private:
|
||||
|
||||
typedef Array<struct DrawCall, InlinedAllocation<8>> DrawCallsList;
|
||||
typedef Dictionary<DrawKey, struct BatchedDrawCall, ConcurrentArenaAllocation> BatchedDrawCalls;
|
||||
void DrawInstance(RenderContext& renderContext, FoliageInstance& instance, const FoliageType& type, Model* model, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
|
||||
void DrawCluster(RenderContext& renderContext, FoliageCluster* cluster, const FoliageType& type, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
|
||||
void DrawInstance(DrawContext& context, FoliageInstance& instance, Model* model, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
|
||||
void DrawCluster(DrawContext& context, FoliageCluster* cluster, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
|
||||
void DrawType(RenderContext& renderContext, const FoliageType& type, DrawCallsList* drawCallsLists);
|
||||
#else
|
||||
void DrawCluster(RenderContext& renderContext, FoliageCluster* cluster, Mesh::DrawInfo& draw);
|
||||
void DrawCluster(DrawContext& context, FoliageCluster* cluster, Mesh::DrawInfo& draw);
|
||||
void DrawType(RenderContext& renderContext, const FoliageType& type, Mesh::DrawInfo& draw);
|
||||
#endif
|
||||
#if !FOLIAGE_USE_SINGLE_QUAD_TREE
|
||||
void DrawClusterGlobalSDF(class GlobalSignDistanceFieldPass* globalSDF, const BoundingBox& globalSDFBounds, FoliageCluster* cluster, const FoliageType& type);
|
||||
@@ -192,7 +203,8 @@ private:
|
||||
void DrawFoliageJob(int32 i);
|
||||
RenderContextBatch* _renderContextBatch;
|
||||
#endif
|
||||
void DrawType(RenderContext& renderContext, const FoliageType& type, DrawCallsList* drawCallsLists);
|
||||
|
||||
void InitType(const RenderView& view, FoliageType& type);
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -47,6 +47,7 @@ API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API FoliageType : public ScriptingOb
|
||||
friend Foliage;
|
||||
private:
|
||||
uint8 _isReady : 1;
|
||||
uint8 _canDraw : 1;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -32,6 +32,7 @@ bool Graphics::SpreadWorkload = true;
|
||||
#if !BUILD_RELEASE || USE_EDITOR
|
||||
float Graphics::TestValue = 0.0f;
|
||||
#endif
|
||||
float Graphics::Shadows::MinObjectPixelSize = 2.0f;
|
||||
bool Graphics::PostProcessing::ColorGradingVolumeLUT = true;
|
||||
|
||||
#if GRAPHICS_API_NULL
|
||||
|
||||
@@ -101,8 +101,17 @@ public:
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Shadows rendering configuration.
|
||||
API_CLASS(Static, Attributes="DebugCommand") class FLAXENGINE_API Shadows
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(Shadows);
|
||||
|
||||
// The minimum size in pixels of objects to cast shadows. Improves performance by skipping too small objects (eg. sub-pixel) from rendering into shadow maps.
|
||||
API_FIELD() static float MinObjectPixelSize;
|
||||
};
|
||||
|
||||
// Post Processing effects rendering configuration.
|
||||
API_CLASS(Static, Attributes = "DebugCommand") class FLAXENGINE_API PostProcessing
|
||||
API_CLASS(Static, Attributes="DebugCommand") class FLAXENGINE_API PostProcessing
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(PostProcessing);
|
||||
|
||||
|
||||
@@ -20,15 +20,6 @@ void CmdBufferVulkan::AddWaitSemaphore(VkPipelineStageFlags waitFlags, Semaphore
|
||||
_waitSemaphores.Add(waitSemaphore);
|
||||
}
|
||||
|
||||
void CmdBufferVulkan::Wait(float timeInSecondsToWait)
|
||||
{
|
||||
if (!IsSubmitted())
|
||||
return;
|
||||
const bool failed = _device->FenceManager.WaitForFence(_fence, (uint64)(timeInSecondsToWait * 1e9));
|
||||
ASSERT(!failed);
|
||||
RefreshFenceStatus();
|
||||
}
|
||||
|
||||
void CmdBufferVulkan::Begin()
|
||||
{
|
||||
PROFILE_CPU();
|
||||
@@ -145,6 +136,16 @@ void CmdBufferVulkan::EndEvent()
|
||||
|
||||
#endif
|
||||
|
||||
void CmdBufferVulkan::Wait(float timeoutSeconds)
|
||||
{
|
||||
if (!IsSubmitted())
|
||||
return;
|
||||
PROFILE_CPU();
|
||||
const bool failed = _device->FenceManager.WaitForFence(GetFence(), timeoutSeconds);
|
||||
ASSERT(!failed);
|
||||
RefreshFenceStatus();
|
||||
}
|
||||
|
||||
void CmdBufferVulkan::RefreshFenceStatus()
|
||||
{
|
||||
if (_state == State::Submitted)
|
||||
@@ -306,14 +307,6 @@ void CmdBufferManagerVulkan::SubmitActiveCmdBuffer(SemaphoreVulkan* signalSemaph
|
||||
_activeCmdBuffer = nullptr;
|
||||
}
|
||||
|
||||
void CmdBufferManagerVulkan::WaitForCmdBuffer(CmdBufferVulkan* cmdBuffer, float timeInSecondsToWait)
|
||||
{
|
||||
ASSERT(cmdBuffer->IsSubmitted());
|
||||
const bool failed = _device->FenceManager.WaitForFence(cmdBuffer->GetFence(), (uint64)(timeInSecondsToWait * 1e9));
|
||||
ASSERT(!failed);
|
||||
cmdBuffer->RefreshFenceStatus();
|
||||
}
|
||||
|
||||
void CmdBufferManagerVulkan::GetNewActiveCommandBuffer()
|
||||
{
|
||||
PROFILE_CPU();
|
||||
|
||||
@@ -119,7 +119,6 @@ public:
|
||||
|
||||
public:
|
||||
void AddWaitSemaphore(VkPipelineStageFlags waitFlags, SemaphoreVulkan* waitSemaphore);
|
||||
void Wait(float timeInSecondsToWait = 1.0f);
|
||||
|
||||
void Begin();
|
||||
void End();
|
||||
@@ -137,6 +136,7 @@ public:
|
||||
void EndEvent();
|
||||
#endif
|
||||
|
||||
void Wait(float timeoutSeconds = VULKAN_WAIT_TIMEOUT);
|
||||
void RefreshFenceStatus();
|
||||
};
|
||||
|
||||
@@ -210,8 +210,7 @@ public:
|
||||
|
||||
public:
|
||||
void SubmitActiveCmdBuffer(SemaphoreVulkan* signalSemaphore = nullptr);
|
||||
void WaitForCmdBuffer(CmdBufferVulkan* cmdBuffer, float timeInSecondsToWait = 1.0f);
|
||||
void RefreshFenceStatus(const CmdBufferVulkan* skipCmdBuffer = nullptr)
|
||||
void RefreshFenceStatus(CmdBufferVulkan* skipCmdBuffer = nullptr)
|
||||
{
|
||||
_pool.RefreshFenceStatus(skipCmdBuffer);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,11 @@
|
||||
#define VULKAN_USE_TIMER_QUERIES 1
|
||||
#endif
|
||||
|
||||
// Fence wait operation timeout in seconds
|
||||
#ifndef VULKAN_WAIT_TIMEOUT
|
||||
#define VULKAN_WAIT_TIMEOUT 5.0f
|
||||
#endif
|
||||
|
||||
// Toggles GPUTimerQueryVulkan to use BeginQuery/EndQuery via GPuContext rather than old custom implementation
|
||||
#define GPU_VULKAN_QUERY_NEW 1
|
||||
|
||||
|
||||
@@ -2253,16 +2253,15 @@ FenceVulkan* FenceManagerVulkan::AllocateFence(bool createSignaled)
|
||||
return fence;
|
||||
}
|
||||
|
||||
bool FenceManagerVulkan::WaitForFence(FenceVulkan* fence, uint64 timeInNanoseconds) const
|
||||
bool FenceManagerVulkan::WaitForFence(FenceVulkan* fence, float timeoutSeconds) const
|
||||
{
|
||||
if (fence->IsSignaled)
|
||||
return false;
|
||||
PROFILE_CPU();
|
||||
ZoneColor(TracyWaitZoneColor);
|
||||
ASSERT(_usedFences.Contains(fence));
|
||||
if (timeInNanoseconds)
|
||||
timeInNanoseconds = 1000ll * 1000ll * 1000LL; // 1s
|
||||
const VkResult result = vkWaitForFences(_device->Device, 1, &fence->Handle, true, timeInNanoseconds);
|
||||
uint64 timeNanoseconds = (uint64)((double)timeoutSeconds * 1000000000.0);
|
||||
const VkResult result = vkWaitForFences(_device->Device, 1, &fence->Handle, true, timeNanoseconds);
|
||||
LOG_VULKAN_RESULT(result);
|
||||
if (result == VK_SUCCESS)
|
||||
{
|
||||
@@ -2290,11 +2289,11 @@ void FenceManagerVulkan::ReleaseFence(FenceVulkan*& fence)
|
||||
fence = nullptr;
|
||||
}
|
||||
|
||||
void FenceManagerVulkan::WaitAndReleaseFence(FenceVulkan*& fence, uint64 timeInNanoseconds)
|
||||
void FenceManagerVulkan::WaitAndReleaseFence(FenceVulkan*& fence, float timeoutSeconds)
|
||||
{
|
||||
ScopeLock lock(_device->_fenceLock);
|
||||
if (!fence->IsSignaled)
|
||||
WaitForFence(fence, timeInNanoseconds);
|
||||
WaitForFence(fence, timeoutSeconds);
|
||||
ResetFence(fence);
|
||||
_usedFences.Remove(fence);
|
||||
_freeFences.Add(fence);
|
||||
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
}
|
||||
|
||||
// Returns true if waiting timed out or failed, false otherwise.
|
||||
bool WaitForFence(FenceVulkan* fence, uint64 timeInNanoseconds = 0) const;
|
||||
bool WaitForFence(FenceVulkan* fence, float timeoutSeconds = VULKAN_WAIT_TIMEOUT) const;
|
||||
|
||||
void ResetFence(FenceVulkan* fence) const;
|
||||
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
void ReleaseFence(FenceVulkan*& fence);
|
||||
|
||||
// Sets the fence handle to null
|
||||
void WaitAndReleaseFence(FenceVulkan*& fence, uint64 timeInNanoseconds = 0);
|
||||
void WaitAndReleaseFence(FenceVulkan*& fence, float timeoutSeconds = VULKAN_WAIT_TIMEOUT);
|
||||
|
||||
private:
|
||||
// Returns true if fence was signaled, otherwise false.
|
||||
|
||||
@@ -62,10 +62,7 @@ void QueueVulkan::Submit(CmdBufferVulkan* cmdBuffer, uint32 signalSemaphoresCoun
|
||||
const bool WaitForIdleOnSubmit = false;
|
||||
if (WaitForIdleOnSubmit)
|
||||
{
|
||||
bool success = _device->FenceManager.WaitForFence(fence);
|
||||
ASSERT(success);
|
||||
ASSERT(_device->FenceManager.IsFenceSignaled(fence));
|
||||
cmdBuffer->GetOwner()->RefreshFenceStatus();
|
||||
cmdBuffer->Wait();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2485,7 +2485,7 @@ void PhysicsBackend::SetRigidActorPose(void* actor, const Vector3& position, con
|
||||
if (kinematic)
|
||||
{
|
||||
auto actorPhysX = (PxRigidDynamic*)actor;
|
||||
if (actorPhysX->getActorFlags() & PxActorFlag::eDISABLE_SIMULATION)
|
||||
if (actorPhysX->getActorFlags() & PxActorFlag::eDISABLE_SIMULATION || !(actorPhysX->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC))
|
||||
{
|
||||
// Ensures the disabled kinematic actor ends up in the correct pose after enabling simulation
|
||||
actorPhysX->setGlobalPose(trans, wakeUp);
|
||||
|
||||
@@ -731,6 +731,7 @@ void RenderList::AddDrawCall(const RenderContextBatch& renderContextBatch, DrawP
|
||||
DrawCallsLists[(int32)DrawCallsListType::MotionVectors].Indices.Add(index);
|
||||
}
|
||||
}
|
||||
float minObjectPixelSizeSq = Math::Square(Graphics::Shadows::MinObjectPixelSize);
|
||||
for (int32 i = 1; i < renderContextBatch.Contexts.Count(); i++)
|
||||
{
|
||||
const RenderContext& renderContext = renderContextBatch.Contexts.Get()[i];
|
||||
@@ -738,7 +739,8 @@ void RenderList::AddDrawCall(const RenderContextBatch& renderContextBatch, DrawP
|
||||
drawModes = modes & renderContext.View.Pass;
|
||||
if (drawModes != DrawPass::None &&
|
||||
(staticFlags & renderContext.View.StaticFlagsMask) == renderContext.View.StaticFlagsCompare &&
|
||||
renderContext.View.CullingFrustum.Intersects(bounds))
|
||||
renderContext.View.CullingFrustum.Intersects(bounds) &&
|
||||
RenderTools::ComputeBoundsScreenRadiusSquared(bounds.Center, bounds.Radius, renderContext.View) * (renderContext.View.ScreenSize.X * renderContext.View.ScreenSize.Y) >= minObjectPixelSizeSq)
|
||||
{
|
||||
renderContext.List->ShadowDepthDrawCallsList.Indices.Add(index);
|
||||
}
|
||||
|
||||
@@ -437,8 +437,8 @@ namespace FlaxEngine.GUI
|
||||
// Caret
|
||||
if (IsFocused && CaretPosition > -1)
|
||||
{
|
||||
float alpha = Mathf.Saturate(Mathf.Cos(_animateTime * CaretFlashSpeed) * 0.5f + 0.7f);
|
||||
alpha = alpha * alpha * alpha * alpha * alpha * alpha;
|
||||
float alpha = Mathf.Saturate(Mathf.Cos(_animateTime * CaretFlashSpeed) * 0.5f + 0.8f);
|
||||
alpha = alpha * alpha;
|
||||
Render2D.FillRectangle(CaretBounds, CaretColor * alpha);
|
||||
}
|
||||
|
||||
|
||||
@@ -310,8 +310,8 @@ namespace FlaxEngine.GUI
|
||||
// Caret
|
||||
if (IsFocused && CaretPosition > -1)
|
||||
{
|
||||
float alpha = Mathf.Saturate(Mathf.Cos(_animateTime * CaretFlashSpeed) * 0.5f + 0.7f);
|
||||
alpha = alpha * alpha * alpha * alpha * alpha * alpha;
|
||||
float alpha = Mathf.Saturate(Mathf.Cos(_animateTime * CaretFlashSpeed) * 0.5f + 0.8f);
|
||||
alpha = alpha * alpha;
|
||||
Render2D.FillRectangle(CaretBounds, CaretColor * alpha);
|
||||
}
|
||||
|
||||
|
||||
@@ -191,14 +191,18 @@ namespace FlaxEngine.GUI
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum number of characters the user can type into the text box control.
|
||||
/// </summary>
|
||||
[EditorOrder(50), Tooltip("The maximum number of characters the user can type into the text box control.")]
|
||||
[EditorOrder(50), Limit(-1), Tooltip("The maximum number of characters the user can type into the text box control.")]
|
||||
public int MaxLength
|
||||
{
|
||||
get => _maxLength;
|
||||
set
|
||||
{
|
||||
if (_maxLength <= 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(MaxLength));
|
||||
// Cap at min of -1 for no max length
|
||||
if (value <= 0)
|
||||
{
|
||||
_maxLength = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_maxLength != value)
|
||||
{
|
||||
@@ -275,7 +279,7 @@ namespace FlaxEngine.GUI
|
||||
/// Gets or sets the speed of the caret flashing animation.
|
||||
/// </summary>
|
||||
[EditorDisplay("Caret Style"), EditorOrder(2021), Tooltip("The speed of the caret flashing animation.")]
|
||||
public float CaretFlashSpeed { get; set; } = 6.0f;
|
||||
public float CaretFlashSpeed { get; set; } = 6.5f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the speed of the selection background flashing animation.
|
||||
@@ -381,7 +385,7 @@ namespace FlaxEngine.GUI
|
||||
value = value.Replace(DelChar.ToString(), "");
|
||||
|
||||
// Clamp length
|
||||
if (value.Length > MaxLength)
|
||||
if (value.Length > MaxLength && MaxLength != -1)
|
||||
value = value.Substring(0, MaxLength);
|
||||
|
||||
// Ensure to use only single line
|
||||
@@ -514,7 +518,7 @@ namespace FlaxEngine.GUI
|
||||
AutoFocus = true;
|
||||
|
||||
_isMultiline = isMultiline;
|
||||
_maxLength = 2147483646;
|
||||
_maxLength = -1;
|
||||
_selectionStart = _selectionEnd = -1;
|
||||
|
||||
var style = Style.Current;
|
||||
@@ -710,7 +714,7 @@ namespace FlaxEngine.GUI
|
||||
str = str.Replace("\n", "");
|
||||
|
||||
int selectionLength = SelectionLength;
|
||||
int charactersLeft = MaxLength - _text.Length + selectionLength;
|
||||
int charactersLeft = (MaxLength != -1 ? MaxLength : int.MaxValue) - _text.Length + selectionLength;
|
||||
Assert.IsTrue(charactersLeft >= 0);
|
||||
if (charactersLeft == 0)
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user