Merge remote-tracking branch 'origin/gi' into large-worlds
# Conflicts: # Source/Engine/Core/Math/Vector3.h
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "DynamicBuffer.h"
|
||||
#include "PixelFormatExtensions.h"
|
||||
#include "GPUDevice.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Utilities.h"
|
||||
@@ -87,3 +88,24 @@ void DynamicBuffer::Dispose()
|
||||
SAFE_DELETE_GPU_RESOURCE(_buffer);
|
||||
Data.Resize(0);
|
||||
}
|
||||
|
||||
void DynamicStructuredBuffer::InitDesc(GPUBufferDescription& desc, int32 numElements)
|
||||
{
|
||||
desc = GPUBufferDescription::Structured(numElements, _stride, _isUnorderedAccess);
|
||||
desc.Usage = GPUResourceUsage::Dynamic;
|
||||
}
|
||||
|
||||
DynamicTypedBuffer::DynamicTypedBuffer(uint32 initialCapacity, PixelFormat format, bool isUnorderedAccess, const String& name)
|
||||
: DynamicBuffer(initialCapacity, PixelFormatExtensions::SizeInBytes(format), name)
|
||||
, _format(format)
|
||||
, _isUnorderedAccess(isUnorderedAccess)
|
||||
{
|
||||
}
|
||||
|
||||
void DynamicTypedBuffer::InitDesc(GPUBufferDescription& desc, int32 numElements)
|
||||
{
|
||||
auto bufferFlags = GPUBufferFlags::ShaderResource;
|
||||
if (_isUnorderedAccess)
|
||||
bufferFlags |= GPUBufferFlags::UnorderedAccess;
|
||||
desc = GPUBufferDescription::Buffer(numElements * _stride, bufferFlags, _format, nullptr, _stride, GPUResourceUsage::Dynamic);
|
||||
}
|
||||
|
||||
@@ -170,3 +170,58 @@ protected:
|
||||
desc = GPUBufferDescription::Index(_stride, numElements, GPUResourceUsage::Dynamic);
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Dynamic structured buffer that allows to upload data to the GPU from CPU (supports dynamic resizing).
|
||||
/// </summary>
|
||||
class FLAXENGINE_API DynamicStructuredBuffer : public DynamicBuffer
|
||||
{
|
||||
private:
|
||||
bool _isUnorderedAccess;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Init
|
||||
/// </summary>
|
||||
/// <param name="initialCapacity">Initial capacity of the buffer (in bytes).</param>
|
||||
/// <param name="stride">Stride in bytes.</param>
|
||||
/// <param name="isUnorderedAccess">True if unordered access usage.</param>
|
||||
/// <param name="name">Buffer name.</param>
|
||||
DynamicStructuredBuffer(uint32 initialCapacity, uint32 stride, bool isUnorderedAccess = false, const String& name = String::Empty)
|
||||
: DynamicBuffer(initialCapacity, stride, name)
|
||||
, _isUnorderedAccess(isUnorderedAccess)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// [DynamicBuffer]
|
||||
void InitDesc(GPUBufferDescription& desc, int32 numElements) override;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Dynamic Typed buffer that allows to upload data to the GPU from CPU (supports dynamic resizing).
|
||||
/// </summary>
|
||||
class FLAXENGINE_API DynamicTypedBuffer : public DynamicBuffer
|
||||
{
|
||||
private:
|
||||
PixelFormat _format;
|
||||
bool _isUnorderedAccess;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Init
|
||||
/// </summary>
|
||||
/// <param name="initialCapacity">Initial capacity of the buffer (in bytes).</param>
|
||||
/// <param name="format">Format of the data.</param>
|
||||
/// <param name="isUnorderedAccess">True if unordered access usage.</param>
|
||||
/// <param name="name">Buffer name.</param>
|
||||
DynamicTypedBuffer(uint32 initialCapacity, PixelFormat format, bool isUnorderedAccess = false, const String& name = String::Empty);
|
||||
|
||||
protected:
|
||||
|
||||
// [DynamicBuffer]
|
||||
void InitDesc(GPUBufferDescription& desc, int32 numElements) override;
|
||||
};
|
||||
|
||||
@@ -702,6 +702,16 @@ API_ENUM(Attributes="Flags") enum class DrawPass : int32
|
||||
/// </summary>
|
||||
MotionVectors = 1 << 4,
|
||||
|
||||
/// <summary>
|
||||
/// The Global Sign Distance Field (SDF) rendering pass. Used for software raytracing though the scene on a GPU.
|
||||
/// </summary>
|
||||
GlobalSDF = 1 << 5,
|
||||
|
||||
/// <summary>
|
||||
/// The Global Surface Atlas rendering pass. Used for software raytracing though the scene on a GPU to evaluate the object surface material properties.
|
||||
/// </summary>
|
||||
GlobalSurfaceAtlas = 1 << 6,
|
||||
|
||||
/// <summary>
|
||||
/// The debug quad overdraw rendering (editor-only).
|
||||
/// </summary>
|
||||
@@ -712,13 +722,13 @@ API_ENUM(Attributes="Flags") enum class DrawPass : int32
|
||||
/// The default set of draw passes for the scene objects.
|
||||
/// </summary>
|
||||
API_ENUM(Attributes="HideInEditor")
|
||||
Default = Depth | GBuffer | Forward | Distortion | MotionVectors,
|
||||
Default = Depth | GBuffer | Forward | Distortion | MotionVectors | GlobalSDF | GlobalSurfaceAtlas,
|
||||
|
||||
/// <summary>
|
||||
/// The all draw passes combined into a single mask.
|
||||
/// </summary>
|
||||
API_ENUM(Attributes="HideInEditor")
|
||||
All = Depth | GBuffer | Forward | Distortion | MotionVectors,
|
||||
All = Depth | GBuffer | Forward | Distortion | MotionVectors | GlobalSDF | GlobalSurfaceAtlas,
|
||||
};
|
||||
|
||||
DECLARE_ENUM_OPERATORS(DrawPass);
|
||||
@@ -847,6 +857,16 @@ API_ENUM() enum class ViewMode
|
||||
/// Draw geometry overdraw to visualize performance of pixels rendering.
|
||||
/// </summary>
|
||||
QuadOverdraw = 23,
|
||||
|
||||
/// <summary>
|
||||
/// Draw Global Sign Distant Field (SDF) preview.
|
||||
/// </summary>
|
||||
GlobalSDF = 24,
|
||||
|
||||
/// <summary>
|
||||
/// Draw Global Surface Atlas preview.
|
||||
/// </summary>
|
||||
GlobalSurfaceAtlas = 25,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -997,7 +1017,7 @@ API_ENUM(Attributes="Flags") enum class ViewFlags : int64
|
||||
/// <summary>
|
||||
/// Default flags for materials/models previews generating.
|
||||
/// </summary>
|
||||
DefaultAssetPreview = Reflections | Decals | GI | DirectionalLights | PointLights | SpotLights | SkyLights | SpecularLight | AntiAliasing | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | ContactShadows,
|
||||
DefaultAssetPreview = Reflections | Decals | DirectionalLights | PointLights | SpotLights | SkyLights | SpecularLight | AntiAliasing | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | ContactShadows,
|
||||
};
|
||||
|
||||
DECLARE_ENUM_OPERATORS(ViewFlags);
|
||||
|
||||
@@ -553,7 +553,7 @@ public:
|
||||
/// <summary>
|
||||
/// Sets the rendering viewport and scissor rectangle.
|
||||
/// </summary>
|
||||
/// <param name="viewport">The viewport.</param>
|
||||
/// <param name="viewport">The viewport (in pixels).</param>
|
||||
API_FUNCTION() FORCE_INLINE void SetViewportAndScissors(const Viewport& viewport)
|
||||
{
|
||||
SetViewport(viewport);
|
||||
@@ -575,13 +575,13 @@ public:
|
||||
/// <summary>
|
||||
/// Sets the rendering viewport.
|
||||
/// </summary>
|
||||
/// <param name="viewport">The viewport.</param>
|
||||
/// <param name="viewport">The viewport (in pixels).</param>
|
||||
API_FUNCTION() virtual void SetViewport(API_PARAM(Ref) const Viewport& viewport) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the scissor rectangle.
|
||||
/// </summary>
|
||||
/// <param name="scissorRect">The scissor rectangle.</param>
|
||||
/// <param name="scissorRect">The scissor rectangle (in pixels).</param>
|
||||
API_FUNCTION() virtual void SetScissor(API_PARAM(Ref) const Rectangle& scissorRect) = 0;
|
||||
|
||||
public:
|
||||
|
||||
@@ -48,7 +48,7 @@ void DecalMaterialShader::Bind(BindParameters& params)
|
||||
bindMeta.Context = context;
|
||||
bindMeta.Constants = cb;
|
||||
bindMeta.Input = nullptr;
|
||||
bindMeta.Buffers = nullptr;
|
||||
bindMeta.Buffers = params.RenderContext.Buffers;
|
||||
bindMeta.CanSampleDepth = true;
|
||||
bindMeta.CanSampleGBuffer = false;
|
||||
MaterialParams::Bind(params.ParamsLink, bindMeta);
|
||||
|
||||
@@ -74,7 +74,7 @@ void DeferredMaterialShader::Bind(BindParameters& params)
|
||||
bindMeta.Context = context;
|
||||
bindMeta.Constants = cb;
|
||||
bindMeta.Input = nullptr;
|
||||
bindMeta.Buffers = nullptr;
|
||||
bindMeta.Buffers = params.RenderContext.Buffers;
|
||||
bindMeta.CanSampleDepth = false;
|
||||
bindMeta.CanSampleGBuffer = false;
|
||||
MaterialParams::Bind(params.ParamsLink, bindMeta);
|
||||
|
||||
@@ -62,7 +62,7 @@ void DeformableMaterialShader::Bind(BindParameters& params)
|
||||
bindMeta.Context = context;
|
||||
bindMeta.Constants = cb;
|
||||
bindMeta.Input = nullptr;
|
||||
bindMeta.Buffers = nullptr;
|
||||
bindMeta.Buffers = params.RenderContext.Buffers;
|
||||
bindMeta.CanSampleDepth = false;
|
||||
bindMeta.CanSampleGBuffer = false;
|
||||
MaterialParams::Bind(params.ParamsLink, bindMeta);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "MaterialInfo.h"
|
||||
|
||||
struct MaterialParamsLink;
|
||||
class GPUShader;
|
||||
class GPUContext;
|
||||
class GPUTextureView;
|
||||
class RenderBuffers;
|
||||
@@ -26,6 +27,12 @@ public:
|
||||
/// <returns>The constant reference to the material descriptor.</returns>
|
||||
virtual const MaterialInfo& GetInfo() const = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the shader resource.
|
||||
/// </summary>
|
||||
/// <returns>The material shader resource.</returns>
|
||||
virtual GPUShader* GetShader() const = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether material is a surface shader.
|
||||
/// </summary>
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "Engine/Graphics/RenderBuffers.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Graphics/GPULimits.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
#include "Engine/Renderer/GlobalSignDistanceFieldPass.h"
|
||||
#include "Engine/Streaming/Streaming.h"
|
||||
|
||||
bool MaterialInfo8::operator==(const MaterialInfo8& other) const
|
||||
@@ -157,6 +159,9 @@ const Char* ToString(MaterialParameterType value)
|
||||
case MaterialParameterType::TextureGroupSampler:
|
||||
result = TEXT("TextureGroupSampler");
|
||||
break;
|
||||
case MaterialParameterType::GlobalSDF:
|
||||
result = TEXT("GlobalSDF");
|
||||
break;
|
||||
default:
|
||||
result = TEXT("");
|
||||
break;
|
||||
@@ -198,7 +203,6 @@ Variant MaterialParameter::GetValue() const
|
||||
case MaterialParameterType::GPUTexture:
|
||||
return _asGPUTexture.Get();
|
||||
default:
|
||||
CRASH;
|
||||
return Variant::Zero;
|
||||
}
|
||||
}
|
||||
@@ -303,6 +307,8 @@ void MaterialParameter::SetValue(const Variant& value)
|
||||
invalidType = true;
|
||||
}
|
||||
break;
|
||||
case MaterialParameterType::GlobalSDF:
|
||||
break;
|
||||
default:
|
||||
invalidType = true;
|
||||
}
|
||||
@@ -477,6 +483,16 @@ void MaterialParameter::Bind(BindMeta& meta) const
|
||||
case MaterialParameterType::TextureGroupSampler:
|
||||
meta.Context->BindSampler(_registerIndex, Streaming::GetTextureGroupSampler(_asInteger));
|
||||
break;
|
||||
case MaterialParameterType::GlobalSDF:
|
||||
{
|
||||
GlobalSignDistanceFieldPass::BindingData bindingData;
|
||||
if (GlobalSignDistanceFieldPass::Instance()->Get(meta.Buffers, bindingData))
|
||||
Platform::MemoryClear(&bindingData, sizeof(bindingData));
|
||||
for (int32 i = 0; i < 4; i++)
|
||||
meta.Context->BindSR(_registerIndex + i, bindingData.Cascades[i] ? bindingData.Cascades[i]->ViewVolume() : nullptr);
|
||||
*((GlobalSignDistanceFieldPass::ConstantsData*)(meta.Constants.Get() + _offset)) = bindingData.Constants;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -128,6 +128,11 @@ enum class MaterialParameterType : byte
|
||||
/// The texture sampler derived from texture group settings.
|
||||
/// </summary>
|
||||
TextureGroupSampler = 19,
|
||||
|
||||
/// <summary>
|
||||
/// The Global SDF (textures and constants).
|
||||
/// </summary>
|
||||
GlobalSDF = 20,
|
||||
};
|
||||
|
||||
const Char* ToString(MaterialParameterType value);
|
||||
|
||||
@@ -98,8 +98,6 @@ public:
|
||||
/// <returns>The created and loaded material or null if failed.</returns>
|
||||
static MaterialShader* CreateDummy(MemoryReadStream& shaderCacheStream, const MaterialInfo& info);
|
||||
|
||||
GPUShader* GetShader() const;
|
||||
|
||||
/// <summary>
|
||||
/// Clears the loaded data.
|
||||
/// </summary>
|
||||
@@ -114,5 +112,6 @@ public:
|
||||
|
||||
// [IMaterial]
|
||||
const MaterialInfo& GetInfo() const override;
|
||||
GPUShader* GetShader() const override;
|
||||
bool IsReady() const override;
|
||||
};
|
||||
|
||||
@@ -22,6 +22,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
||||
const int32 envProbeShaderRegisterIndex = srv + 0;
|
||||
const int32 skyLightShaderRegisterIndex = srv + 1;
|
||||
const int32 dirLightShaderRegisterIndex = srv + 2;
|
||||
const bool canUseShadow = view.Pass != DrawPass::Depth;
|
||||
|
||||
// Set fog input
|
||||
if (cache->Fog)
|
||||
@@ -39,7 +40,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
||||
{
|
||||
const auto& dirLight = cache->DirectionalLights.First();
|
||||
const auto shadowPass = ShadowsPass::Instance();
|
||||
const bool useShadow = shadowPass->LastDirLightIndex == 0;
|
||||
const bool useShadow = shadowPass->LastDirLightIndex == 0 && canUseShadow;
|
||||
if (useShadow)
|
||||
{
|
||||
data.DirectionalLightShadow = shadowPass->LastDirLight;
|
||||
@@ -49,7 +50,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
||||
{
|
||||
context->UnBindSR(dirLightShaderRegisterIndex);
|
||||
}
|
||||
dirLight.SetupLightData(&data.DirectionalLight, view, useShadow);
|
||||
dirLight.SetupLightData(&data.DirectionalLight, useShadow);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -62,7 +63,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
||||
if (cache->SkyLights.HasItems())
|
||||
{
|
||||
auto& skyLight = cache->SkyLights.First();
|
||||
skyLight.SetupLightData(&data.SkyLight, view, false);
|
||||
skyLight.SetupLightData(&data.SkyLight, false);
|
||||
const auto texture = skyLight.Image ? skyLight.Image->GetTexture() : nullptr;
|
||||
context->BindSR(skyLightShaderRegisterIndex, GET_TEXTURE_VIEW_SAFE(texture));
|
||||
}
|
||||
@@ -103,7 +104,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
||||
const auto& light = cache->PointLights[i];
|
||||
if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.World.GetTranslation()) != ContainmentType::Disjoint)
|
||||
{
|
||||
light.SetupLightData(&data.LocalLights[data.LocalLightsCount], view, false);
|
||||
light.SetupLightData(&data.LocalLights[data.LocalLightsCount], false);
|
||||
data.LocalLightsCount++;
|
||||
}
|
||||
}
|
||||
@@ -112,7 +113,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
||||
const auto& light = cache->SpotLights[i];
|
||||
if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.World.GetTranslation()) != ContainmentType::Disjoint)
|
||||
{
|
||||
light.SetupLightData(&data.LocalLights[data.LocalLightsCount], view, false);
|
||||
light.SetupLightData(&data.LocalLights[data.LocalLightsCount], false);
|
||||
data.LocalLightsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ void TerrainMaterialShader::Bind(BindParameters& params)
|
||||
bindMeta.Context = context;
|
||||
bindMeta.Constants = cb;
|
||||
bindMeta.Input = nullptr;
|
||||
bindMeta.Buffers = nullptr;
|
||||
bindMeta.Buffers = params.RenderContext.Buffers;
|
||||
bindMeta.CanSampleDepth = false;
|
||||
bindMeta.CanSampleGBuffer = false;
|
||||
MaterialParams::Bind(params.ParamsLink, bindMeta);
|
||||
|
||||
@@ -89,12 +89,12 @@ namespace
|
||||
}
|
||||
else
|
||||
{
|
||||
auto v = Half2(0, 0);
|
||||
auto v = Half2::Zero;
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].TexCoord = v;
|
||||
}
|
||||
{
|
||||
auto v = Half2(0, 0);
|
||||
auto v = Half2::Zero;
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].LightmapUVs = v;
|
||||
}
|
||||
|
||||
@@ -531,6 +531,17 @@ void MeshData::TransformBuffer(const Matrix& matrix)
|
||||
}
|
||||
}
|
||||
|
||||
void MeshData::NormalizeBlendWeights()
|
||||
{
|
||||
ASSERT(Positions.Count() == BlendWeights.Count());
|
||||
for (int32 i = 0; i < Positions.Count(); i++)
|
||||
{
|
||||
const float sum = BlendWeights[i].SumValues();
|
||||
const float invSum = sum > ZeroTolerance ? 1.0f / sum : 0.0f;
|
||||
BlendWeights[i] *= invSum;
|
||||
}
|
||||
}
|
||||
|
||||
void MeshData::Merge(MeshData& other)
|
||||
{
|
||||
// Merge index buffer (and remap indices)
|
||||
@@ -600,6 +611,21 @@ bool MaterialSlotEntry::UsesProperties() const
|
||||
Normals.TextureIndex != -1;
|
||||
}
|
||||
|
||||
BoundingBox ModelLodData::GetBox() const
|
||||
{
|
||||
if (Meshes.IsEmpty())
|
||||
return BoundingBox::Empty;
|
||||
BoundingBox bounds;
|
||||
Meshes[0]->CalculateBox(bounds);
|
||||
for (int32 i = 1; i < Meshes.Count(); i++)
|
||||
{
|
||||
BoundingBox b;
|
||||
Meshes[i]->CalculateBox(b);
|
||||
BoundingBox::Merge(bounds, b, bounds);
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
void ModelData::CalculateLODsScreenSizes()
|
||||
{
|
||||
const float autoComputeLodPowerBase = 0.5f;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Core/Common.h"
|
||||
#include "Engine/Core/Math/BoundingSphere.h"
|
||||
#include "Engine/Core/Math/BoundingBox.h"
|
||||
#include "Engine/Core/Math/Int4.h"
|
||||
@@ -281,16 +280,7 @@ public:
|
||||
/// <summary>
|
||||
/// Normalizes the blend weights. Requires to have vertices with positions and blend weights setup.
|
||||
/// </summary>
|
||||
void NormalizeBlendWeights()
|
||||
{
|
||||
ASSERT(Positions.Count() == BlendWeights.Count());
|
||||
for (int32 i = 0; i < Positions.Count(); i++)
|
||||
{
|
||||
const float sum = BlendWeights[i].SumValues();
|
||||
const float invSum = sum > ZeroTolerance ? 1.0f / sum : 0.0f;
|
||||
BlendWeights[i] *= invSum;
|
||||
}
|
||||
}
|
||||
void NormalizeBlendWeights();
|
||||
|
||||
/// <summary>
|
||||
/// Merges this mesh data with the specified other mesh.
|
||||
@@ -409,6 +399,11 @@ public:
|
||||
{
|
||||
Meshes.ClearDelete();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bounding box combined for all meshes in this model LOD.
|
||||
/// </summary>
|
||||
BoundingBox GetBox() const;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -404,7 +404,7 @@ bool UpdateMesh(SkinnedMesh* mesh, MonoArray* verticesObj, MonoArray* trianglesO
|
||||
}
|
||||
else
|
||||
{
|
||||
auto v = Half2(0, 0);
|
||||
auto v = Half2::Zero;
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb[i].TexCoord = v;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,11 @@ RenderBuffers::RenderBuffers(const SpawnParams& params)
|
||||
#undef CREATE_TEXTURE
|
||||
}
|
||||
|
||||
String RenderBuffers::CustomBuffer::ToString() const
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
RenderBuffers::~RenderBuffers()
|
||||
{
|
||||
Release();
|
||||
@@ -61,6 +66,15 @@ void RenderBuffers::Prepare()
|
||||
UPDATE_LAZY_KEEP_RT(HalfResDepth);
|
||||
UPDATE_LAZY_KEEP_RT(LuminanceMap);
|
||||
#undef UPDATE_LAZY_KEEP_RT
|
||||
for (int32 i = CustomBuffers.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
CustomBuffer* e = CustomBuffers[i];
|
||||
if (frameIndex - e->LastFrameUsed >= LAZY_FRAMES_COUNT)
|
||||
{
|
||||
Delete(e);
|
||||
CustomBuffers.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GPUTexture* RenderBuffers::RequestHalfResDepth(GPUContext* context)
|
||||
@@ -184,4 +198,5 @@ void RenderBuffers::Release()
|
||||
UPDATE_LAZY_KEEP_RT(HalfResDepth);
|
||||
UPDATE_LAZY_KEEP_RT(LuminanceMap);
|
||||
#undef UPDATE_LAZY_KEEP_RT
|
||||
CustomBuffers.ClearDelete();
|
||||
}
|
||||
|
||||
@@ -16,23 +16,36 @@
|
||||
#define GBUFFER2_FORMAT PixelFormat::R8G8B8A8_UNorm
|
||||
#define GBUFFER3_FORMAT PixelFormat::R8G8B8A8_UNorm
|
||||
|
||||
// Light accumulation buffer format (direct+indirect light, materials emissive)
|
||||
#define LIGHT_BUFFER_FORMAT PixelFormat::R11G11B10_Float
|
||||
|
||||
/// <summary>
|
||||
/// The scene rendering buffers container.
|
||||
/// </summary>
|
||||
API_CLASS() class FLAXENGINE_API RenderBuffers : public ScriptingObject
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE(RenderBuffers);
|
||||
protected:
|
||||
DECLARE_SCRIPTING_TYPE(RenderBuffers);
|
||||
|
||||
/// <summary>
|
||||
/// The custom rendering state.
|
||||
/// </summary>
|
||||
class CustomBuffer : public Object
|
||||
{
|
||||
public:
|
||||
String Name;
|
||||
uint64 LastFrameUsed = 0;
|
||||
|
||||
String ToString() const override;
|
||||
};
|
||||
|
||||
protected:
|
||||
int32 _width = 0;
|
||||
int32 _height = 0;
|
||||
float _aspectRatio = 0.0f;
|
||||
Viewport _viewport;
|
||||
|
||||
Array<GPUTexture*, FixedAllocation<32>> _resources;
|
||||
|
||||
public:
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
@@ -80,15 +93,16 @@ public:
|
||||
GPUTexture* TemporalAA = nullptr;
|
||||
uint64 LastFrameTemporalAA = 0;
|
||||
|
||||
public:
|
||||
// Maps the custom buffer type into the object that holds the state.
|
||||
Array<CustomBuffer*, HeapAllocation> CustomBuffers;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="RenderBuffers"/> class.
|
||||
/// </summary>
|
||||
~RenderBuffers();
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Prepares buffers for rendering a scene. Called before rendering so other parts can reuse calculated value.
|
||||
/// </summary>
|
||||
@@ -102,7 +116,6 @@ public:
|
||||
GPUTexture* RequestHalfResDepth(GPUContext* context);
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets the buffers width (in pixels).
|
||||
/// </summary>
|
||||
@@ -143,6 +156,31 @@ public:
|
||||
return _viewport;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
const T* FindCustomBuffer(const StringView& name) const
|
||||
{
|
||||
for (CustomBuffer* e : CustomBuffers)
|
||||
{
|
||||
if (e->Name == name)
|
||||
return (const T*)e;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T* GetCustomBuffer(const StringView& name)
|
||||
{
|
||||
for (CustomBuffer* e : CustomBuffers)
|
||||
{
|
||||
if (e->Name == name)
|
||||
return (T*)e;
|
||||
}
|
||||
CustomBuffer* result = New<T>();
|
||||
result->Name = name;
|
||||
CustomBuffers.Add(result);
|
||||
return (T*)result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current GPU memory usage by all the buffers (in bytes).
|
||||
/// </summary>
|
||||
@@ -162,7 +200,6 @@ public:
|
||||
API_FIELD(ReadOnly) GPUTexture* MotionVectors;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Allocates the buffers.
|
||||
/// </summary>
|
||||
|
||||
@@ -229,6 +229,8 @@ SceneRenderTask::~SceneRenderTask()
|
||||
{
|
||||
if (Buffers)
|
||||
Buffers->DeleteObjectNow();
|
||||
if (_customActorsScene)
|
||||
Delete(_customActorsScene);
|
||||
}
|
||||
|
||||
void SceneRenderTask::CameraCut()
|
||||
@@ -270,18 +272,29 @@ void SceneRenderTask::CollectPostFxVolumes(RenderContext& renderContext)
|
||||
}
|
||||
}
|
||||
|
||||
void AddActorToSceneRendering(SceneRendering* s, Actor* a)
|
||||
{
|
||||
if (a && a->IsActiveInHierarchy())
|
||||
{
|
||||
int32 key = -1;
|
||||
s->AddActor(a, key);
|
||||
for (Actor* child : a->Children)
|
||||
AddActorToSceneRendering(s, child);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneRenderTask::OnCollectDrawCalls(RenderContext& renderContext)
|
||||
{
|
||||
// Draw actors (collect draw calls)
|
||||
if ((ActorsSource & ActorsSources::CustomActors) != 0)
|
||||
{
|
||||
for (auto a : CustomActors)
|
||||
{
|
||||
if (a && a->GetIsActive())
|
||||
{
|
||||
a->DrawHierarchy(renderContext);
|
||||
}
|
||||
}
|
||||
if (_customActorsScene == nullptr)
|
||||
_customActorsScene = New<SceneRendering>();
|
||||
else
|
||||
_customActorsScene->Clear();
|
||||
for (Actor* a : CustomActors)
|
||||
AddActorToSceneRendering(_customActorsScene, a);
|
||||
_customActorsScene->Draw(renderContext);
|
||||
}
|
||||
if ((ActorsSource & ActorsSources::Scenes) != 0)
|
||||
{
|
||||
@@ -403,7 +416,7 @@ void SceneRenderTask::OnEnd(GPUContext* context)
|
||||
// Swap matrices
|
||||
View.PrevView = View.View;
|
||||
View.PrevProjection = View.Projection;
|
||||
Matrix::Multiply(View.PrevView, View.PrevProjection, View.PrevViewProjection);
|
||||
View.PrevViewProjection = View.ViewProjection();
|
||||
}
|
||||
|
||||
bool SceneRenderTask::Resize(int32 width, int32 height)
|
||||
|
||||
@@ -220,6 +220,10 @@ public:
|
||||
API_CLASS() class FLAXENGINE_API SceneRenderTask : public RenderTask
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE(SceneRenderTask);
|
||||
protected:
|
||||
class SceneRendering* _customActorsScene = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="SceneRenderTask"/> class.
|
||||
|
||||
@@ -97,6 +97,16 @@ public:
|
||||
/// </summary>
|
||||
API_FIELD() bool IsOfflinePass = false;
|
||||
|
||||
/// <summary>
|
||||
/// Flag used by single-frame rendering passes (eg. thumbnail rendering, model view caching) to reject LOD transitions animations and other temporal draw effects.
|
||||
/// </summary>
|
||||
API_FIELD() bool IsSingleFrame = false;
|
||||
|
||||
/// <summary>
|
||||
/// Flag used by custom passes to skip any object culling when drawing.
|
||||
/// </summary>
|
||||
API_FIELD() bool IsCullingDisabled = false;
|
||||
|
||||
/// <summary>
|
||||
/// The static flags mask used to hide objects that don't have a given static flags. Eg. use StaticFlags::Lightmap to render only objects that can use lightmap.
|
||||
/// </summary>
|
||||
|
||||
@@ -282,16 +282,18 @@ bool ShaderAssetBase::LoadShaderCache(ShaderCacheResult& result)
|
||||
editorDefine.Definition = "1";
|
||||
#endif
|
||||
InitCompilationOptions(options);
|
||||
if (ShadersCompilation::Compile(options))
|
||||
const bool failed = ShadersCompilation::Compile(options);
|
||||
|
||||
// Encrypt source code
|
||||
Encryption::EncryptBytes(reinterpret_cast<byte*>(source), sourceLength);
|
||||
|
||||
if (failed)
|
||||
{
|
||||
LOG(Error, "Failed to compile shader '{0}'", parent->ToString());
|
||||
return true;
|
||||
}
|
||||
LOG(Info, "Shader '{0}' compiled! Cache size: {1} bytes", parent->ToString(), cacheStream.GetPosition());
|
||||
|
||||
// Encrypt source code
|
||||
Encryption::EncryptBytes(reinterpret_cast<byte*>(source), sourceLength);
|
||||
|
||||
// Save compilation result (based on current caching policy)
|
||||
if (cachingMode == ShaderStorage::CachingMode::AssetInternal)
|
||||
{
|
||||
@@ -345,7 +347,7 @@ bool ShaderAssetBase::LoadShaderCache(ShaderCacheResult& result)
|
||||
result.Data.Link(cacheChunk->Data);
|
||||
}
|
||||
#if COMPILE_WITH_SHADER_CACHE_MANAGER
|
||||
// Check if has cached shader
|
||||
// Check if has cached shader
|
||||
else if (cachedEntry.IsValid() || ShaderCacheManager::TryGetEntry(shaderProfile, parent->GetID(), cachedEntry))
|
||||
{
|
||||
// Load results from cache
|
||||
|
||||
@@ -12,7 +12,7 @@ class GPUShaderProgram;
|
||||
/// <summary>
|
||||
/// The runtime version of the shaders cache supported by the all graphics back-ends. The same for all the shader cache formats (easier to sync and validate).
|
||||
/// </summary>
|
||||
#define GPU_SHADER_CACHE_VERSION 8
|
||||
#define GPU_SHADER_CACHE_VERSION 9
|
||||
|
||||
/// <summary>
|
||||
/// Represents collection of shader programs with permutations and custom names.
|
||||
|
||||
@@ -431,11 +431,6 @@ bool GPUTexture::Init(const GPUTextureDescription& desc)
|
||||
LOG(Warning, "Cannot create texture. Only 2D Texture can be used as a Depth Stencil. Description: {0}", desc.ToString());
|
||||
return true;
|
||||
}
|
||||
if (desc.MipLevels != 1)
|
||||
{
|
||||
LOG(Warning, "Cannot create texture. Volume texture cannot have more than 1 mip level. Description: {0}", desc.ToString());
|
||||
return true;
|
||||
}
|
||||
if (desc.ArraySize != 1)
|
||||
{
|
||||
LOG(Warning, "Cannot create texture. Volume texture cannot create array of volume textures. Description: {0}", desc.ToString());
|
||||
@@ -607,7 +602,25 @@ GPUTask* GPUTexture::UploadMipMapAsync(const BytesContainer& data, int32 mipInde
|
||||
ASSERT(IsAllocated());
|
||||
ASSERT(mipIndex < MipLevels() && data.IsValid());
|
||||
ASSERT(data.Length() >= slicePitch);
|
||||
// TODO: support texture data upload to the GPU on a main thread during rendering without this async task (faster direct upload)
|
||||
|
||||
// Optimize texture upload invoked during rendering
|
||||
if (IsInMainThread() && GPUDevice::Instance->IsRendering())
|
||||
{
|
||||
// Update all array slices
|
||||
const byte* dataSource = data.Get();
|
||||
for (int32 arrayIndex = 0; arrayIndex < _desc.ArraySize; arrayIndex++)
|
||||
{
|
||||
GPUDevice::Instance->GetMainContext()->UpdateTexture(this, arrayIndex, mipIndex, dataSource, rowPitch, slicePitch);
|
||||
dataSource += slicePitch;
|
||||
}
|
||||
if (mipIndex == HighestResidentMipIndex() - 1)
|
||||
{
|
||||
// Mark as mip loaded
|
||||
SetResidentMipLevels(ResidentMipLevels() + 1);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto task = ::New<GPUUploadTextureMipTask>(this, mipIndex, data, rowPitch, slicePitch, copyData);
|
||||
ASSERT_LOW_LAYER(task && task->HasReference(this));
|
||||
return task;
|
||||
@@ -800,5 +813,6 @@ void GPUTexture::SetResidentMipLevels(int32 count)
|
||||
if (_residentMipLevels == count || !IsRegularTexture())
|
||||
return;
|
||||
_residentMipLevels = count;
|
||||
onResidentMipsChanged();
|
||||
OnResidentMipsChanged();
|
||||
ResidentMipsChanged(this);
|
||||
}
|
||||
|
||||
@@ -568,12 +568,17 @@ public:
|
||||
/// Sets the number of resident mipmap levels in the texture (already uploaded to the GPU).
|
||||
/// </summary>
|
||||
API_PROPERTY() void SetResidentMipLevels(int32 count);
|
||||
|
||||
/// <summary>
|
||||
/// Event called when texture residency gets changed. Texture Mip gets loaded into GPU memory and is ready to use.
|
||||
/// </summary>
|
||||
Delegate<GPUTexture*> ResidentMipsChanged;
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool OnInit() = 0;
|
||||
uint64 calculateMemoryUsage() const;
|
||||
virtual void onResidentMipsChanged() = 0;
|
||||
virtual void OnResidentMipsChanged() = 0;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -233,6 +233,7 @@ protected:
|
||||
{
|
||||
Swap(_streamingTexture->_texture, _newTexture);
|
||||
_streamingTexture->GetTexture()->SetResidentMipLevels(_uploadedMipCount);
|
||||
_streamingTexture->ResidencyChanged();
|
||||
SAFE_DELETE_GPU_RESOURCE(_newTexture);
|
||||
|
||||
// Base
|
||||
@@ -447,6 +448,7 @@ Task* StreamingTexture::CreateStreamingTask(int32 residency)
|
||||
{
|
||||
// Do the quick data release
|
||||
_texture->ReleaseGPU();
|
||||
ResidencyChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user