Compare commits

..

126 Commits

Author SHA1 Message Date
mafiesto4 3bf3264f48 Fix compilation with the latest GDK 2026-05-14 18:28:17 +02:00
mafiesto4 b043490413 Merge remote-tracking branch 'origin/master' into 1.13 2026-05-13 18:20:30 +02:00
mafiesto4 48f302b4fd Fix rare asset loading problems 2026-05-13 16:05:03 +02:00
mafiesto4 d9c787a661 Merge remote-tracking branch 'origin/master' into 1.13
# Conflicts:
#	Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
#	Source/Engine/Graphics/Graphics.h
#	Source/Engine/Renderer/ShadowsPass.cpp
2026-05-13 16:03:53 +02:00
mafiesto4 ec9f05fe11 Fix memory alloc when renaming GPU resource on Vulkan 2026-05-12 17:10:28 +02:00
mafiesto4 b039e3779d Fix Global Surface Atlas tiles padding and position precision to have proper stability 2026-05-12 17:10:02 +02:00
mafiesto4 fc8a9b69d2 Move new Temporal AA code to shared header 2026-05-12 17:09:21 +02:00
mafiesto4 b38f6c5721 Merge branch 'HydrogenC-reverse-z' into 1.13 2026-05-12 17:07:50 +02:00
mafiesto4 0c1af2f243 Fix various rendering elements with Reversed Z enabled and simplify code
#2684
2026-05-11 18:26:21 +02:00
mafiesto4 7f2ba7a81e Fix shaders cache to be invalidated when changing ReverseZ option
#2684
2026-05-08 10:53:40 +02:00
mafiesto4 fb21ffd3be Rename FLAX_REVERSE_Z macro to REVERSE_Z
#2684
2026-05-08 10:52:46 +02:00
mafiesto4 7127ccda37 Fix depth bounds in reversed Z
#2684
2026-05-08 09:02:17 +02:00
mafiesto4 ead71e6836 Add support for using macros in scripting function parameter default values 2026-05-07 23:01:16 +02:00
mafiesto4 241441d5b9 Merge branch 'reverse-z' of https://github.com/HydrogenC/FlaxEngine into HydrogenC-reverse-z
# Conflicts:
#	Source/Engine/Graphics/GPUDevice.cpp
#	Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp
#	Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp
#	Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp
#	Source/Engine/Renderer/LightPass.cpp
#	Source/Engine/Renderer/ReflectionsPass.cpp
#	Source/Engine/Renderer/ShadowsPass.cpp
#	Source/Shaders/SSR.hlsl
#	Source/Shaders/ShadowsSampling.hlsl
#	Source/Shaders/Sky.shader
2026-05-07 19:55:03 +02:00
mafiesto4 14b0fb355a Fix compilation with Large Worlds 2026-05-07 18:27:36 +02:00
mafiesto4 4489f43777 Add DefaultProbeCubemapFormat to Graphics Settings with option to compress env probe textures 2026-05-07 18:20:34 +02:00
mafiesto4 c17a9f653e Add minor improvements and adjust 3rd DDGI cascade for better world coverage 2026-05-07 16:38:15 +02:00
mafiesto4 e7fd901807 Add improved fallback GI outside the DDGI range to use a special ambient probe for stability 2026-05-07 16:21:17 +02:00
mafiesto4 bdabcd5e43 Fix regression to properly resume render pass when flushing barriers mid-pass
141a8de0da
2026-05-07 09:03:22 +02:00
mafiesto4 6cc8f693f3 Fix directional light rendering to be skipped when color alpha is zero 2026-05-07 08:41:48 +02:00
mafiesto4 1079791bed Add rendering stats for Data Upload 2026-05-07 00:02:33 +02:00
mafiesto4 627f3a2dec Show full timespan in editor incl. seconds 2026-05-06 17:31:27 +02:00
mafiesto4 2f05a0987e Add ShowInPlayMode to HideInEditor attribute for properties/fields that should display in editor only during play mode 2026-05-06 16:54:34 +02:00
mafiesto4 6335bcdc93 Add in-built editors for DateTime and TimeSpan 2026-05-06 16:42:38 +02:00
mafiesto4 650fa781d3 Simplify shader code for point/spot lights to use permutations instead 2026-05-06 12:59:35 +02:00
mafiesto4 000d786d49 Add Temporal Antialiasing as default AA method 2026-05-06 12:39:49 +02:00
mafiesto4 3eb85000aa Fix error when drag&drop new actor on Windows in Editor 2026-05-06 12:39:32 +02:00
mafiesto4 9c5daf419b Fix default shadow depth bias values and control them based on shadow resolution/quality mix 2026-05-06 12:39:15 +02:00
mafiesto4 9a85ae7142 Add soft PCSS shadows on Ultra quality
Add new `SourceAngle` property to Directional light that controls PCSS penumbra size
2026-05-06 12:37:42 +02:00
mafiesto4 fad0f7a345 Compact PCF shadow sampling code 2026-05-05 08:47:57 +02:00
mafiesto4 aac399c6a1 Add CascadeBlendSize to Directional Light and fix sun shadow fade at distance 2026-05-04 23:41:00 +02:00
mafiesto4 4c5035e433 Fix scene search performance regression 2026-05-04 23:05:25 +02:00
mafiesto4 b14c2cfc74 Optimize Global Surface Atlas full direct lighting redraw to copy whole emissive atlas at once 2026-05-04 18:11:01 +02:00
mafiesto4 cbcfa4013b Add Graphics::MotionVectors::MinObjectScreenSize to skip too small objects from drawing motion vectors 2026-05-04 17:29:58 +02:00
mafiesto4 429f8e5336 Add highlight to Motion Vectors Debug view for better content optimizing 2026-05-04 16:43:41 +02:00
mafiesto4 6cc0edf0eb Optimize shadows and depth rendering with instancing support for transparent shaders 2026-05-04 15:12:40 +02:00
mafiesto4 f7d8f36add Optimize draw calls batching and instancing with better sort keys generation and processing 2026-05-04 12:34:29 +02:00
mafiesto4 2e98300693 Add minor changes 2026-05-04 08:47:21 +02:00
mafiesto4 83de99877c Fix directional light cascaded shadow maps rendering stability 2026-05-04 08:46:43 +02:00
mafiesto4 7a569d4f14 Add selection drawing and picking gizmo to Foliage Types editing tab 2026-04-30 18:19:12 +02:00
mafiesto4 24675ace93 Refactor Temporal Anti-Aliasing shader to have less ghosting and quality scalability
Fix lots of ghosting artifacts.
Fix aliasing on small cables/lines during camera movement.
Add scalability via AA Quality setting for TAA.
2026-04-30 17:58:19 +02:00
mafiesto4 3a5d831e71 Minor changes 2026-04-29 18:34:39 +02:00
mafiesto4 0aecb35ab1 Fix Global Surface Atlas rasterization of objects with negative scale 2026-04-29 18:34:14 +02:00
mafiesto4 c4bb39aeac Improve Global Surface Atlas objects dirtying limit to pick the largers objects first 2026-04-29 17:52:51 +02:00
mafiesto4 61431a6400 Optimize Global Surface Atlas defragmentation with copying old atlas to avoid redrawing all objects 2026-04-29 17:19:40 +02:00
mafiesto4 d4da1d80d0 Optimize Global Surface Atlas with object draws limit per frame 2026-04-29 17:05:17 +02:00
mafiesto4 3bede1d6bc Optimize Global Surface Atlas updates distribution for subobjects (eg. foliage instances) 2026-04-28 22:21:38 +02:00
mafiesto4 ce4ad8aa71 Optimize RendererAllocation by reducing fragmentation with operating on power-of-2 blocks 2026-04-28 21:55:52 +02:00
mafiesto4 75bd206416 Fix regression crash on Vulkan when clearing many textures at once 2026-04-28 20:19:35 +02:00
mafiesto4 578af12f2b Optimize Global Surface Atlas objects to cache shader data 2026-04-28 20:18:18 +02:00
mafiesto4 acbbd34ecf Optimize scene rendering async job to use interleaved ranges instead of fighting for a shared index 2026-04-28 13:16:44 +02:00
mafiesto4 c8b06ba7ec Optimize scene rendering loop to cache more data on stack 2026-04-28 13:07:19 +02:00
mafiesto4 ad46b74f6a Optimize foliage drawing by caching per-instance world matrix 2026-04-28 12:50:19 +02:00
mafiesto4 47a9d76938 Optimize foliage drawing memory access a bit more 2026-04-28 11:48:52 +02:00
mafiesto4 442cb8f2dd Minor improvements 2026-04-28 00:25:31 +02:00
mafiesto4 45e121bf77 Fix Guid diff serialization and loading invalid values 2026-04-28 00:24:57 +02:00
mafiesto4 8e76d0d9d8 Fix GPUTexture.DownloadData to use correct bindings api 2026-04-28 00:24:34 +02:00
mafiesto4 f4905cfccc Optimize foliage rendering with less cache misses 2026-04-28 00:24:05 +02:00
mafiesto4 bf9a015959 Optimize FoliageInstance size to cut down memory by and reduce cache misses when drawing foliage 2026-04-27 22:54:11 +02:00
mafiesto4 4fd7f51fdf Optimize LightmapUVs to be stored already as Half4 to avoid runtime conversions during rendering 2026-04-27 21:53:11 +02:00
mafiesto4 f5e483069d Optimize CPU rendering of shadowed foliage by splitting draw contexts into separate async jobs 2026-04-27 17:14:56 +02:00
mafiesto4 0bd28ecb65 Fix compilation 2026-04-27 16:09:28 +02:00
mafiesto4 9eec54171c Fix compilation on Linux 2026-04-27 14:37:00 +02:00
mafiesto4 486781661e Optimize foliage instance bounds calculations 2026-04-27 14:32:19 +02:00
mafiesto4 b201897ae6 Optimize foliage serialization by batching instance data, performing quantization, and LZ4 compression
Cuts down foliage data size by over 50% and improves load times.
2026-04-27 14:30:19 +02:00
mafiesto4 c33ada2715 Fix unnecessary memory allocations within D3D object debug name assignment 2026-04-27 14:27:32 +02:00
mafiesto4 dcb9b5150f Optimize large scene/prefa/json assets metadata loading by avoiding parsing full contents 2026-04-27 14:27:00 +02:00
mafiesto4 f905b4013b Optimize large scene files loading by aligning json pool allocator pages to 64kB 2026-04-27 14:26:12 +02:00
mafiesto4 b0033a35b7 Improve foliage count display in editor tab 2026-04-27 14:25:23 +02:00
mafiesto4 f47a2909fe Update LZ4 library to v1.10 2026-04-27 14:24:56 +02:00
mafiesto4 b1c76ec7f9 Merge remote-tracking branch 'origin/1.12' into 1.13 2026-04-25 10:31:41 +02:00
mafiesto4 db2130f340 Add No parameters text to material instance panel with base material that doesn't have parameters 2026-04-24 23:49:40 +02:00
mafiesto4 edb3badcb3 Optimize content modifications watching events processing in large projects 2026-04-24 23:47:22 +02:00
mafiesto4 c33b2cc11e Optimize first scene startup by preloading it during loading screen 2026-04-24 17:56:12 +02:00
mafiesto4 135110387d Fix loading SceneReference property in Visual Script 2026-04-24 17:55:07 +02:00
mafiesto4 6b3502675a Fix deprecated flag usage when loading scenes over multiple frames 2026-04-24 17:54:40 +02:00
mafiesto4 615e847e01 Add new Level.PreloadSceneAsync for streaming levels before they need to be loaded in 2026-04-24 17:54:25 +02:00
mafiesto4 468e05c6e8 Fix crash on Vulkan when constant buffer is missing 2026-04-24 12:20:32 +02:00
mafiesto4 a46402df6b Merge remote-tracking branch 'origin/1.12' into 1.13 2026-04-24 11:50:19 +02:00
mafiesto4 1fa9aadebd Fix crash on cursor changes regression 2026-04-24 11:50:15 +02:00
mafiesto4 c0f52235c6 Fix compilation on Xbox with new D3D12MA lib used 2026-04-24 11:21:42 +02:00
mafiesto4 c782f07b76 Add GetTextureData function to texture API in C# 2026-04-24 11:21:18 +02:00
mafiesto4 dc9a8a2f84 Fix editor shutdown error when script compilation fails 2026-04-24 11:21:02 +02:00
mafiesto4 49943e13de Fix various API issues 2026-04-24 11:20:45 +02:00
mafiesto4 1988fae929 Add support for loading custom mouse cursor images 2026-04-24 11:20:04 +02:00
mafiesto4 804315bb3e Add VSync support to Vulkan 2026-04-23 20:25:36 +02:00
mafiesto4 0cacc58b53 Fix minor issues in D3D12 2026-04-23 18:39:09 +02:00
mafiesto4 7437b69d52 Add GPUMemoryStats for GPU video memory stats
Add new `Total/GPU` category to memory profiler.
Implement for D3D12 and Vulkan with allocators.
2026-04-23 18:38:47 +02:00
mafiesto4 f5f4fb29f2 Cleanup code and disable unused Json/Dump features from D3D12MA 2026-04-23 17:13:30 +02:00
mafiesto4 33617a702a Add D3D12MemoryAllocator for resource allocations on DX12
v3.1.0
2026-04-23 17:12:26 +02:00
mafiesto4 84b53bb9c8 Optimize various rendering effects with GPUDrawPass 2026-04-23 14:30:02 +02:00
mafiesto4 c3ea883b21 Fix crash on Android when mouse device is not connected 2026-04-23 10:18:43 +02:00
mafiesto4 f41d01f4a9 Optimize Vulkan render passes with a new GPUDrawPass to manually control attachment operations in higher-level API 2026-04-23 10:18:13 +02:00
mafiesto4 141a8de0da Optimize Vulkan texture clears with render pass attachments clear operation 2026-04-23 09:44:31 +02:00
mafiesto4 63b6fafa1b Add Escape key to deselect in Editor 2026-04-23 09:14:19 +02:00
mafiesto4 2ce1103530 Add VersionControlInfo to output game build info and log game version with branch/commit info 2026-04-22 23:11:29 +02:00
mafiesto4 6121a6fadf Merge remote-tracking branch 'origin/1.12' into 1.13 2026-04-22 17:56:23 +02:00
mafiesto4 145134f145 Add 1.13 for future update 2026-04-16 14:31:32 +02:00
ExMatics HydrogenC 3f78e47918 Fix for shadow atlas not being cleared correctly 2024-10-10 22:13:43 +08:00
ExMatics HydrogenC 7b4a9f1a63 Fix depth function 2024-10-10 21:15:46 +08:00
ExMatics HydrogenC 561d40fd71 Merge remote-tracking branch 'upstream/master' into reverse-z 2024-10-10 17:42:43 +08:00
ExMatics HydrogenC 133340b2ea Fix sky color being too dark 2024-06-06 12:56:32 +08:00
ExMatics HydrogenC 344665e34f Merge branch 'reverse-z' of https://github.com/HydrogenC/FlaxEngine into reverse-z 2024-06-06 12:13:51 +08:00
ExMatics HydrogenC 5d188c8c2d Simplify SetMatrix code 2024-06-06 12:13:32 +08:00
ExMatics HydrogenC 9447f3d569 Fix build tool command line 2024-06-06 11:16:00 +08:00
ExMatics HydrogenC df8dc9173a Add command line controls for reverse z 2024-06-06 00:07:28 +08:00
ExMatics HydrogenC b186d19faa Fix typo 2024-06-05 23:37:10 +08:00
ExMatics HydrogenC ea749f12a3 Add depth function to conditional compiling 2024-06-05 23:36:41 +08:00
ExMatics HydrogenC 74750fd604 Fix spot light 2024-06-05 23:09:43 +08:00
ExMatics HydrogenC b52e8bad4c Fix shadow casting 2024-06-05 23:02:21 +08:00
ExMatics HydrogenC 44f8e86245 Fix code depth sampling for unreversed z 2024-06-05 22:39:20 +08:00
ExMatics HydrogenC b036692154 Fix shadow bias and unify indent 2024-06-05 22:36:15 +08:00
ExMatics HydrogenC 5d050ca020 Make reverse z define dynamic 2024-06-05 21:51:07 +08:00
ExMatics HydrogenC 1b6a31b6e5 Finish conditional compiling 2024-06-05 21:15:08 +08:00
ExMatics HydrogenC ab4743fdb1 Add more comditional compiling 2024-06-05 18:20:38 +08:00
ExMatics HydrogenC 49629222c1 Revert VolumeParticle.shader 2024-06-05 07:41:40 +08:00
ExMatics HydrogenC 9d6778ff1e Add a bit conditional compiling 2024-06-05 07:40:03 +08:00
ExMatics HydrogenC ce73394531 add todo in BoundingFrustrum 2024-06-04 23:24:28 +08:00
ExMatics HydrogenC 463c8dba0d fix depth function 2024-06-04 23:22:41 +08:00
ExMatics HydrogenC 9bb6104cf7 Merge remote-tracking branch 'upstream/master' into reverse-z 2024-06-04 12:08:07 +08:00
ExMatics HydrogenC 151f4a4923 Merge branch 'reverse-z' of https://github.com/HydrogenC/FlaxEngine into reverse-z 2024-06-04 12:07:53 +08:00
ExMatics HydrogenC 36f588a792 Fix more shaders 2024-06-04 12:07:50 +08:00
ExMatics HydrogenC 07c7a250cc Revert unexpected deletions 2024-06-04 09:55:06 +08:00
ExMatics HydrogenC eab4a8c404 Fix shaders for reverse z 2024-06-04 09:30:26 +08:00
ExMatics HydrogenC cde3e3d710 Fix editor raycast 2024-06-04 08:39:14 +08:00
ExMatics HydrogenC a8dc67a1b2 Implement reverse z 2024-06-03 22:02:35 +08:00
241 changed files with 21241 additions and 2663 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
# Redirect to our own Git LFS server # Redirect to our own Git LFS server
[lfs] [lfs]
url="https://git.flaxengine.com/flax/flaxengine.git/info/lfs" url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
locksverify = false locksverify = false
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+3 -2
View File
@@ -2,9 +2,9 @@
"Name": "Flax", "Name": "Flax",
"Version": { "Version": {
"Major": 1, "Major": 1,
"Minor": 12, "Minor": 13,
"Revision": 0, "Revision": 0,
"Build": 6912 "Build": 7003
}, },
"Company": "Flax", "Company": "Flax",
"Copyright": "Copyright (c) 2012-2026 Wojciech Figat. All rights reserved.", "Copyright": "Copyright (c) 2012-2026 Wojciech Figat. All rights reserved.",
@@ -13,6 +13,7 @@
"Configuration": { "Configuration": {
"UseCSharp": true, "UseCSharp": true,
"UseLargeWorlds": false, "UseLargeWorlds": false,
"UseReverseZ": true,
"UseDotNet": true, "UseDotNet": true,
"Windows": { "Windows": {
"UseSDL": false, "UseSDL": false,
+1
View File
@@ -257,6 +257,7 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/GrammarAndSpelling/GrammarChecking/Exceptions/=Try_0020to_0020scripting/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/GrammarAndSpelling/GrammarChecking/Exceptions/=Try_0020to_0020scripting/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/GrammarAndSpelling/GrammarChecking/Exceptions/=will_0020fallback/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/GrammarAndSpelling/GrammarChecking/RulesStates/=LanguageTool_002EEN_002EE_005FG/@EntryIndexedValue">DisabledByUser</s:String> <s:String x:Key="/Default/GrammarAndSpelling/GrammarChecking/RulesStates/=LanguageTool_002EEN_002EE_005FG/@EntryIndexedValue">DisabledByUser</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=EEA05B0ED8200E4BA9D2D3F1052EBFFD/@KeyIndexDefined">True</s:Boolean> <s:Boolean x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=EEA05B0ED8200E4BA9D2D3F1052EBFFD/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=EEA05B0ED8200E4BA9D2D3F1052EBFFD/Color/@EntryValue">Blue</s:String> <s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=EEA05B0ED8200E4BA9D2D3F1052EBFFD/Color/@EntryValue">Blue</s:String>
+5
View File
@@ -360,6 +360,11 @@ public:
/// </summary> /// </summary>
Array<BinaryModuleInfo, InlinedAllocation<64>> BinaryModules; Array<BinaryModuleInfo, InlinedAllocation<64>> BinaryModules;
/// <summary>
/// Cached version of the built binaries from project Version Control.
/// </summary>
String VersionControlInfo;
public: public:
/// <summary> /// <summary>
@@ -42,6 +42,13 @@ bool CompileScriptsStep::DeployBinaries(CookingData& data, const String& path, c
return true; return true;
} }
// Metadata
auto versionControlInfoMember = document.FindMember("VersionControlInfo");
if (versionControlInfoMember != document.MemberEnd() && data.VersionControlInfo.IsEmpty())
{
data.VersionControlInfo = versionControlInfoMember->value.GetText();
}
// Deploy all references // Deploy all references
auto referencesMember = document.FindMember("References"); auto referencesMember = document.FindMember("References");
if (referencesMember != document.MemberEnd()) if (referencesMember != document.MemberEnd())
@@ -245,8 +252,15 @@ bool CompileScriptsStep::Perform(CookingData& data)
writer.String(target); writer.String(target);
writer.JKEY("Platform"); writer.JKEY("Platform");
writer.String(platform); writer.String(platform);
writer.JKEY("Architecture");
writer.String(architecture);
writer.JKEY("Configuration"); writer.JKEY("Configuration");
writer.String(configuration); writer.String(configuration);
if (data.VersionControlInfo.HasChars())
{
writer.JKEY("VersionControlInfo");
writer.String(data.VersionControlInfo);
}
writer.JKEY("BinaryModules"); writer.JKEY("BinaryModules");
writer.StartArray(); writer.StartArray();
@@ -50,6 +50,10 @@
#endif #endif
#include "FlaxEngine.Gen.h" #include "FlaxEngine.Gen.h"
#ifndef REVERSE_Z
#define REVERSE_Z 0
#endif
Dictionary<String, CookAssetsStep::ProcessAssetFunc> CookAssetsStep::AssetProcessors; Dictionary<String, CookAssetsStep::ProcessAssetFunc> CookAssetsStep::AssetProcessors;
void IBuildCache::InvalidateCacheShaders() void IBuildCache::InvalidateCacheShaders()
@@ -233,6 +237,11 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
LOG(Info, "{0} option has been modified.", TEXT("ShadersGenerateDebugData")); LOG(Info, "{0} option has been modified.", TEXT("ShadersGenerateDebugData"));
invalidateShaders = true; invalidateShaders = true;
} }
if (REVERSE_Z != Settings.Global.ShadersReverseZ)
{
LOG(Info, "{0} option has been modified.", TEXT("ShadersReverseZ"));
invalidateShaders = true;
}
#if PLATFORM_TOOLS_WINDOWS #if PLATFORM_TOOLS_WINDOWS
if (data.Platform == BuildPlatform::Windows32 || data.Platform == BuildPlatform::Windows64) if (data.Platform == BuildPlatform::Windows32 || data.Platform == BuildPlatform::Windows64)
{ {
@@ -1076,6 +1085,7 @@ bool CookAssetsStep::Perform(CookingData& data)
{ {
cache.Settings.Global.ShadersNoOptimize = buildSettings->ShadersNoOptimize; cache.Settings.Global.ShadersNoOptimize = buildSettings->ShadersNoOptimize;
cache.Settings.Global.ShadersGenerateDebugData = buildSettings->ShadersGenerateDebugData; cache.Settings.Global.ShadersGenerateDebugData = buildSettings->ShadersGenerateDebugData;
cache.Settings.Global.ShadersReverseZ = REVERSE_Z;
cache.Settings.Global.StreamingSettingsAssetId = gameSettings->Streaming; cache.Settings.Global.StreamingSettingsAssetId = gameSettings->Streaming;
cache.Settings.Global.ShadersVersion = GPU_SHADER_CACHE_VERSION; cache.Settings.Global.ShadersVersion = GPU_SHADER_CACHE_VERSION;
cache.Settings.Global.MaterialGraphVersion = MATERIAL_GRAPH_VERSION; cache.Settings.Global.MaterialGraphVersion = MATERIAL_GRAPH_VERSION;
@@ -97,6 +97,7 @@ public:
{ {
bool ShadersNoOptimize; bool ShadersNoOptimize;
bool ShadersGenerateDebugData; bool ShadersGenerateDebugData;
bool ShadersReverseZ;
Guid StreamingSettingsAssetId; Guid StreamingSettingsAssetId;
int32 ShadersVersion; int32 ShadersVersion;
int32 MaterialGraphVersion; int32 MaterialGraphVersion;
@@ -261,6 +261,7 @@ namespace FlaxEditor.CustomEditors.Editors
public static List<ItemInfo> GetItemsForType(ScriptType type, bool useProperties, bool useFields, bool usePropertiesWithoutSetter = false) public static List<ItemInfo> GetItemsForType(ScriptType type, bool useProperties, bool useFields, bool usePropertiesWithoutSetter = false)
{ {
var items = new List<ItemInfo>(); var items = new List<ItemInfo>();
var isPlayMode = Editor.IsPlayMode;
if (useProperties) if (useProperties)
{ {
@@ -278,7 +279,7 @@ namespace FlaxEditor.CustomEditors.Editors
continue; continue;
// Skip hidden fields, handle special attributes // Skip hidden fields, handle special attributes
if ((!p.IsPublic && !showInEditor) || attributes.Any(x => x is HideInEditorAttribute)) if ((!p.IsPublic && !showInEditor) || attributes.Any(x => x is HideInEditorAttribute hide && (!isPlayMode || !hide.ShowInPlayMode)))
continue; continue;
items.Add(new ItemInfo(p, attributes)); items.Add(new ItemInfo(p, attributes));
@@ -293,11 +294,10 @@ namespace FlaxEditor.CustomEditors.Editors
for (int i = 0; i < fields.Length; i++) for (int i = 0; i < fields.Length; i++)
{ {
var f = fields[i]; var f = fields[i];
var attributes = f.GetAttributes(true); var attributes = f.GetAttributes(true);
// Skip hidden fields, handle special attributes // Skip hidden fields, handle special attributes
if ((!f.IsPublic && !attributes.Any(x => x is ShowInEditorAttribute)) || attributes.Any(x => x is HideInEditorAttribute)) if ((!f.IsPublic && !attributes.Any(x => x is ShowInEditorAttribute)) || attributes.Any(x => x is HideInEditorAttribute hide && (!isPlayMode || !hide.ShowInPlayMode)))
continue; continue;
items.Add(new ItemInfo(f, attributes)); items.Add(new ItemInfo(f, attributes));
@@ -0,0 +1,90 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using FlaxEngine;
using FlaxEngine.GUI;
using System;
namespace FlaxEditor.CustomEditors.Editors
{
/// <summary>
/// Default implementation of the inspector used to edit TimeSpan value type properties.
/// </summary>
[CustomEditor(typeof(TimeSpan)), DefaultEditor]
class TimeSpanEditor : CustomEditor
{
private TextBox _textBox;
private bool _isRefreshing;
/// <inheritdoc />
public override DisplayStyle Style => DisplayStyle.Inline;
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
if (HasDifferentTypes)
return;
_textBox = layout.Custom<TextBox>().CustomControl;
_textBox.EditEnd += OnEditEnd;
}
private void OnEditEnd()
{
if (_isRefreshing)
return;
if (TimeSpan.TryParse(_textBox.Text, out var timeSpan))
SetValue(timeSpan);
}
/// <inheritdoc />
public override void Refresh()
{
base.Refresh();
_isRefreshing = true;
_textBox.Text = HasDifferentValues ? "Multiple Values" : ((TimeSpan)Values[0]).ToString("G");
_isRefreshing = false;
}
}
/// <summary>
/// Default implementation of the inspector used to edit DateTime value type properties.
/// </summary>
[CustomEditor(typeof(DateTime)), DefaultEditor]
class DateTimeEditor : CustomEditor
{
private TextBox _textBox;
private bool _isRefreshing;
/// <inheritdoc />
public override DisplayStyle Style => DisplayStyle.Inline;
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
if (HasDifferentTypes)
return;
_textBox = layout.Custom<TextBox>().CustomControl;
_textBox.EditEnd += OnEditEnd;
}
private void OnEditEnd()
{
if (_isRefreshing)
return;
if (DateTime.TryParse(_textBox.Text, out var timeSpan))
SetValue(timeSpan);
}
/// <inheritdoc />
public override void Refresh()
{
base.Refresh();
_isRefreshing = true;
_textBox.Text = HasDifferentValues ? "Multiple Values" : ((DateTime)Values[0]).ToString("g");
_isRefreshing = false;
}
}
}
+1 -5
View File
@@ -139,15 +139,11 @@ namespace FlaxEditor.Gizmo
DrawSelectionDepth(context, renderContext.Task, customDepth); DrawSelectionDepth(context, renderContext.Task, customDepth);
_actors.Clear(); _actors.Clear();
var near = renderContext.View.Near;
var far = renderContext.View.Far;
var projection = renderContext.View.Projection;
// Render outline // Render outline
_material.SetParameterValue("OutlineColor0", _color0); _material.SetParameterValue("OutlineColor0", _color0);
_material.SetParameterValue("OutlineColor1", _color1); _material.SetParameterValue("OutlineColor1", _color1);
_material.SetParameterValue("CustomDepth", customDepth); _material.SetParameterValue("CustomDepth", customDepth);
_material.SetParameterValue("ViewInfo", new Float4(1.0f / projection.M11, 1.0f / projection.M22, far / (far - near), (-far * near) / (far - near) / far)); _material.SetParameterValue("ViewInfo", renderContext.View.ViewInfo);
Renderer.DrawPostFxMaterial(context, ref renderContext, _material, output, input.View()); Renderer.DrawPostFxMaterial(context, ref renderContext, _material, output, input.View());
// Cleanup // Cleanup
+16 -10
View File
@@ -24,7 +24,7 @@ namespace FlaxEditor.Modules
private bool _rebuildInitFlag; private bool _rebuildInitFlag;
private int _itemsCreated; private int _itemsCreated;
private int _itemsDeleted; private int _itemsDeleted;
private readonly HashSet<MainContentFolderTreeNode> _dirtyNodes = new HashSet<MainContentFolderTreeNode>(); private readonly HashSet<ContentFolderTreeNode> _dirtyNodes = new HashSet<ContentFolderTreeNode>();
/// <summary> /// <summary>
/// The project directory. /// The project directory.
@@ -1309,26 +1309,31 @@ namespace FlaxEditor.Modules
internal void OnDirectoryEvent(MainContentFolderTreeNode node, FileSystemEventArgs e) internal void OnDirectoryEvent(MainContentFolderTreeNode node, FileSystemEventArgs e)
{ {
// Ensure to be ready for external events // Ignore events during fast setup
if (_isDuringFastSetup) if (_isDuringFastSetup)
return; return;
ContentFolderTreeNode dirtyNode = node;
// TODO: maybe we could make it faster! since we have a path so it would be easy to just create or delete given file. but remember about subdirectories // Filter the node based on modified path
// (eg. if we have event for 'Content/Folder1/Folder2' and node is 'Content/Folder1' then we should process but skip other 'Content' subfolders)
var path = StringUtils.NormalizePath(Path.GetDirectoryName(e.FullPath));
var pathItem = node.Folder.Find(path) as ContentFolder;
if (pathItem != null)
{
dirtyNode = pathItem.Node;
}
// Switch type
switch (e.ChangeType) switch (e.ChangeType)
{ {
case WatcherChangeTypes.Created: case WatcherChangeTypes.Created:
case WatcherChangeTypes.Deleted: case WatcherChangeTypes.Deleted:
case WatcherChangeTypes.Renamed: case WatcherChangeTypes.Renamed:
{
lock (_dirtyNodes) lock (_dirtyNodes)
{ {
_dirtyNodes.Add(node); _dirtyNodes.Add(dirtyNode);
} }
break; break;
} }
}
} }
private void OnScriptsReload() private void OnScriptsReload()
@@ -1383,14 +1388,15 @@ namespace FlaxEditor.Modules
// Update all dirty content tree nodes // Update all dirty content tree nodes
lock (_dirtyNodes) lock (_dirtyNodes)
{ {
Profiler.BeginEvent("ContentDatabase.Refresh");
foreach (var node in _dirtyNodes) foreach (var node in _dirtyNodes)
{ {
LoadFolder(node, true); LoadFolder(node, true);
if (_enableEvents)
WorkspaceModified?.Invoke();
} }
if (_enableEvents && _dirtyNodes.Count != 0)
WorkspaceModified?.Invoke();
_dirtyNodes.Clear(); _dirtyNodes.Clear();
Profiler.EndEvent();
} }
// Lazy-rebuilds // Lazy-rebuilds
+2
View File
@@ -465,6 +465,8 @@ namespace FlaxEditor.Modules
internal void ProgressFailed(string message) internal void ProgressFailed(string message)
{ {
if (StatusBar == null)
return;
_progressFailed = true; _progressFailed = true;
StatusBar.StatusColor = Style.Current.Statusbar.Failed; StatusBar.StatusColor = Style.Current.Statusbar.Failed;
StatusBar.Text = message; StatusBar.Text = message;
@@ -17,7 +17,7 @@ namespace FlaxEditor.Tools.Foliage
private int _selectedInstanceIndex = -1; private int _selectedInstanceIndex = -1;
/// <summary> /// <summary>
/// The foliage painting gizmo. /// The foliage editing gizmo.
/// </summary> /// </summary>
public EditFoliageGizmo Gizmo; public EditFoliageGizmo Gizmo;
@@ -66,8 +66,6 @@ namespace FlaxEditor.Tools.Foliage
base.Init(owner); base.Init(owner);
Gizmo = new EditFoliageGizmo(owner, this); Gizmo = new EditFoliageGizmo(owner, this);
SelectionOutline = FlaxEngine.Object.New<EditFoliageSelectionOutline>();
SelectionOutline.GizmoMode = this;
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -84,6 +82,11 @@ namespace FlaxEditor.Tools.Foliage
base.OnActivated(); base.OnActivated();
Owner.Gizmos.Active = Gizmo; Owner.Gizmos.Active = Gizmo;
if (SelectionOutline == null)
{
SelectionOutline = FlaxEngine.Object.New<EditFoliageSelectionOutline>();
SelectionOutline.GizmoMode = this;
}
((MainEditorGizmoViewport)Owner).OverrideSelectionOutline(SelectionOutline); ((MainEditorGizmoViewport)Owner).OverrideSelectionOutline(SelectionOutline);
SelectedInstanceIndex = -1; SelectedInstanceIndex = -1;
} }
@@ -6,7 +6,7 @@ using FlaxEngine;
namespace FlaxEditor.Tools.Foliage namespace FlaxEditor.Tools.Foliage
{ {
/// <summary> /// <summary>
/// The custom outline for drawing the selected foliage instances outlines. /// The custom outline for drawing the selected foliage instance.
/// </summary> /// </summary>
/// <seealso cref="FlaxEditor.Gizmo.SelectionOutline" /> /// <seealso cref="FlaxEditor.Gizmo.SelectionOutline" />
[HideInEditor] [HideInEditor]
+2 -3
View File
@@ -5,7 +5,6 @@ using System.Collections.Generic;
using FlaxEditor.GUI.Tabs; using FlaxEditor.GUI.Tabs;
using FlaxEditor.Modules; using FlaxEditor.Modules;
using FlaxEditor.SceneGraph.Actors; using FlaxEditor.SceneGraph.Actors;
using FlaxEditor.Viewport.Modes;
using FlaxEngine; using FlaxEngine;
using FlaxEngine.GUI; using FlaxEngine.GUI;
@@ -214,7 +213,7 @@ namespace FlaxEditor.Tools.Foliage
private void InitSculptMode() private void InitSculptMode()
{ {
var tab = _modes.AddTab(FoliageTypes = new FoliageTypesTab(this)); var tab = _modes.AddTab(FoliageTypes = new FoliageTypesTab(this, Editor.Windows.EditWin.Viewport.EditFoliageTypesGizmo));
tab.Selected += OnTabSelected; tab.Selected += OnTabSelected;
} }
@@ -251,7 +250,7 @@ namespace FlaxEditor.Tools.Foliage
switch (_modes.SelectedTabIndex) switch (_modes.SelectedTabIndex)
{ {
case 0: case 0:
Editor.Windows.EditWin.Viewport.Gizmos.SetActiveMode<NoGizmoMode>(); Editor.Windows.EditWin.Viewport.Gizmos.SetActiveMode<FoliageTypesGizmoMode>();
break; break;
case 1: case 1:
Editor.Windows.EditWin.Viewport.Gizmos.SetActiveMode<PaintFoliageGizmoMode>(); Editor.Windows.EditWin.Viewport.Gizmos.SetActiveMode<PaintFoliageGizmoMode>();
@@ -0,0 +1,44 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using FlaxEditor.Gizmo;
namespace FlaxEditor.Tools.Foliage
{
/// <summary>
/// Gizmo for editing foliage types.
/// </summary>
public sealed class FoliageTypesGizmo : GizmoBase
{
/// <summary>
/// The parent mode.
/// </summary>
public readonly FoliageTypesGizmoMode GizmoMode;
/// <summary>
/// Initializes a new instance of the <see cref="EditFoliageGizmo"/> class.
/// </summary>
/// <param name="owner">The owner.</param>
/// <param name="mode">The mode.</param>
public FoliageTypesGizmo(IGizmoOwner owner, FoliageTypesGizmoMode mode)
: base(owner)
{
GizmoMode = mode;
}
/// <inheritdoc />
public override void Pick()
{
// Get mouse ray and try to hit foliage instance
var foliage = GizmoMode.SelectedFoliage;
if (!foliage)
return;
var ray = Owner.MouseRay;
if (foliage.Intersects(ref ray, out _, out _, out var instanceIndex))
{
// Select hit instance type
var instance = foliage.GetInstance(instanceIndex);
GizmoMode.SelectedTypeIndex = instance.Type;
}
}
}
}
@@ -0,0 +1,86 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using FlaxEditor.Gizmo;
using FlaxEditor.SceneGraph.Actors;
using FlaxEditor.Viewport;
using FlaxEditor.Viewport.Modes;
namespace FlaxEditor.Tools.Foliage
{
/// <summary>
/// Foliage types editing mode.
/// </summary>
/// <seealso cref="FlaxEditor.Viewport.Modes.EditorGizmoMode" />
public class FoliageTypesGizmoMode : EditorGizmoMode
{
/// <summary>
/// The foliage types gizmo.
/// </summary>
public FoliageTypesGizmo Gizmo;
/// <summary>
/// The foliage type editing selection outline.
/// </summary>
public FoliageTypesOutline SelectionOutline;
/// <summary>
/// The selected foliage type index.
/// </summary>
public int SelectedTypeIndex
{
get => Editor.Instance.Windows.ToolboxWin.Foliage.SelectedFoliageTypeIndex;
set => Editor.Instance.Windows.ToolboxWin.Foliage.SelectedFoliageTypeIndex = value;
}
/// <summary>
/// Gets the selected foliage actor (see <see cref="Modules.SceneEditingModule"/>).
/// </summary>
public FlaxEngine.Foliage SelectedFoliage
{
get
{
var sceneEditing = Editor.Instance.SceneEditing;
var foliageNode = sceneEditing.SelectionCount == 1 ? sceneEditing.Selection[0] as FoliageNode : null;
return (FlaxEngine.Foliage)foliageNode?.Actor;
}
}
/// <inheritdoc />
public override void Init(IGizmoOwner owner)
{
base.Init(owner);
Gizmo = new FoliageTypesGizmo(owner, this);
}
/// <inheritdoc />
public override void Dispose()
{
FlaxEngine.Object.Destroy(ref SelectionOutline);
base.Dispose();
}
/// <inheritdoc />
public override void OnActivated()
{
base.OnActivated();
Owner.Gizmos.Active = Gizmo;
if (SelectionOutline == null)
{
SelectionOutline = FlaxEngine.Object.New<FoliageTypesOutline>();
SelectionOutline.GizmoMode = this;
}
((MainEditorGizmoViewport)Owner).OverrideSelectionOutline(SelectionOutline);
}
/// <inheritdoc />
public override void OnDeactivated()
{
((MainEditorGizmoViewport)Owner).OverrideSelectionOutline(null);
base.OnDeactivated();
}
}
}
@@ -0,0 +1,62 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using FlaxEditor.Gizmo;
using FlaxEngine;
namespace FlaxEditor.Tools.Foliage
{
/// <summary>
/// The custom outline for drawing the selected foliage type.
/// </summary>
/// <seealso cref="FlaxEditor.Gizmo.SelectionOutline" />
[HideInEditor]
public class FoliageTypesOutline : SelectionOutline
{
/// <summary>
/// The parent mode.
/// </summary>
public FoliageTypesGizmoMode GizmoMode;
/// <inheritdoc />
public override bool CanRender()
{
if (!HasDataReady)
return false;
var foliage = GizmoMode.SelectedFoliage;
if (!foliage)
return false;
var typeIndex = GizmoMode.SelectedTypeIndex;
if (typeIndex < 0 || typeIndex >= foliage.FoliageTypesCount)
return false;
return true;
}
/// <inheritdoc />
public override void Render(GPUContext context, ref RenderContext renderContext, GPUTexture input, GPUTexture output)
{
base.Render(context, ref renderContext, input, output);
// Restore debug option
var foliage = GizmoMode.SelectedFoliage;
if (foliage)
foliage._drawFoliageType = -1;
}
/// <inheritdoc />
protected override void DrawSelectionDepth(GPUContext context, SceneRenderTask task, GPUTexture customDepth)
{
var foliage = GizmoMode.SelectedFoliage;
if (!foliage)
return;
var typeIndex = GizmoMode.SelectedTypeIndex;
if (typeIndex < 0 || typeIndex >= foliage.FoliageTypesCount)
return;
// Draw instances of the given type
foliage._drawFoliageType = typeIndex;
_actors.Add(foliage);
Renderer.DrawSceneDepth(context, task, customDepth, _actors);
}
}
}
@@ -334,7 +334,8 @@ namespace FlaxEditor.Tools.Foliage
/// Initializes a new instance of the <see cref="FoliageTypesTab"/> class. /// Initializes a new instance of the <see cref="FoliageTypesTab"/> class.
/// </summary> /// </summary>
/// <param name="tab">The parent tab.</param> /// <param name="tab">The parent tab.</param>
public FoliageTypesTab(FoliageTab tab) /// <param name="mode">The gizmo mode.</param>
public FoliageTypesTab(FoliageTab tab, FoliageTypesGizmoMode mode)
: base("Foliage Types") : base("Foliage Types")
{ {
Tab = tab; Tab = tab;
+8 -3
View File
@@ -1514,9 +1514,14 @@ namespace FlaxEditor.Viewport
Matrix.Multiply(ref v, ref p, out var ivp); Matrix.Multiply(ref v, ref p, out var ivp);
ivp.Invert(); ivp.Invert();
// Create near and far points // Create near and far points, with device depth of 1 and 0 respectively
var nearPoint = new Vector3(mousePosition, _nearPlane); #if REVERSE_Z
var farPoint = new Vector3(mousePosition, _farPlane); var nearPoint = new Vector3(mousePosition, 1.0f);
var farPoint = new Vector3(mousePosition, 0.0f);
#else
var nearPoint = new Vector3(mousePosition, 0.0f);
var farPoint = new Vector3(mousePosition, 1.0f);
#endif
viewport.Unproject(ref nearPoint, ref ivp, out nearPoint); viewport.Unproject(ref nearPoint, ref ivp, out nearPoint);
viewport.Unproject(ref farPoint, ref ivp, out farPoint); viewport.Unproject(ref farPoint, ref ivp, out farPoint);
@@ -179,12 +179,17 @@ namespace FlaxEditor.Viewport
public Tools.Terrain.EditTerrainGizmoMode EditTerrainGizmo; public Tools.Terrain.EditTerrainGizmoMode EditTerrainGizmo;
/// <summary> /// <summary>
/// The paint foliage gizmo. /// The edit foliage types gizmo.
/// </summary>
public Tools.Foliage.FoliageTypesGizmoMode EditFoliageTypesGizmo;
/// <summary>
/// The paint foliage instances gizmo.
/// </summary> /// </summary>
public Tools.Foliage.PaintFoliageGizmoMode PaintFoliageGizmo; public Tools.Foliage.PaintFoliageGizmoMode PaintFoliageGizmo;
/// <summary> /// <summary>
/// The edit foliage gizmo. /// The edit foliage instances gizmo.
/// </summary> /// </summary>
public Tools.Foliage.EditFoliageGizmoMode EditFoliageGizmo; public Tools.Foliage.EditFoliageGizmoMode EditFoliageGizmo;
@@ -276,6 +281,7 @@ namespace FlaxEditor.Viewport
Gizmos.AddMode(SculptTerrainGizmo = new Tools.Terrain.SculptTerrainGizmoMode()); Gizmos.AddMode(SculptTerrainGizmo = new Tools.Terrain.SculptTerrainGizmoMode());
Gizmos.AddMode(PaintTerrainGizmo = new Tools.Terrain.PaintTerrainGizmoMode()); Gizmos.AddMode(PaintTerrainGizmo = new Tools.Terrain.PaintTerrainGizmoMode());
Gizmos.AddMode(EditTerrainGizmo = new Tools.Terrain.EditTerrainGizmoMode()); Gizmos.AddMode(EditTerrainGizmo = new Tools.Terrain.EditTerrainGizmoMode());
Gizmos.AddMode(EditFoliageTypesGizmo = new Tools.Foliage.FoliageTypesGizmoMode());
Gizmos.AddMode(PaintFoliageGizmo = new Tools.Foliage.PaintFoliageGizmoMode()); Gizmos.AddMode(PaintFoliageGizmo = new Tools.Foliage.PaintFoliageGizmoMode());
Gizmos.AddMode(EditFoliageGizmo = new Tools.Foliage.EditFoliageGizmoMode()); Gizmos.AddMode(EditFoliageGizmo = new Tools.Foliage.EditFoliageGizmoMode());
@@ -343,10 +349,12 @@ namespace FlaxEditor.Viewport
/// <param name="customSelectionOutline">The custom selection outline or null if use default one.</param> /// <param name="customSelectionOutline">The custom selection outline or null if use default one.</param>
public void OverrideSelectionOutline(SelectionOutline customSelectionOutline) public void OverrideSelectionOutline(SelectionOutline customSelectionOutline)
{ {
if (Task == null)
return;
if (_customSelectionOutline != null) if (_customSelectionOutline != null)
{ {
Task.RemoveCustomPostFx(_customSelectionOutline); Task.RemoveCustomPostFx(_customSelectionOutline);
Object.Destroy(ref _customSelectionOutline);
Task.AddCustomPostFx(customSelectionOutline ? customSelectionOutline : SelectionOutline); Task.AddCustomPostFx(customSelectionOutline ? customSelectionOutline : SelectionOutline);
} }
else if (customSelectionOutline != null) else if (customSelectionOutline != null)
@@ -530,7 +538,7 @@ namespace FlaxEditor.Viewport
} }
/// <summary> /// <summary>
/// Toggles game view view mode on or off. /// Toggles view mode on/off.
/// </summary> /// </summary>
public void ToggleGameView() public void ToggleGameView()
{ {
@@ -547,9 +555,9 @@ namespace FlaxEditor.Viewport
// Set flags & values // Set flags & values
Task.ViewFlags = _gameViewActive ? _preGameViewFlags : ViewFlags.DefaultGame; Task.ViewFlags = _gameViewActive ? _preGameViewFlags : ViewFlags.DefaultGame;
Task.ViewMode = _gameViewActive ? _preGameViewViewMode : ViewMode.Default; Task.ViewMode = _gameViewActive ? _preGameViewViewMode : ViewMode.Default;
ShowFpsCounter = _gameViewActive ? _gameViewWasFpsCounterShown : false; ShowFpsCounter = _gameViewActive && _gameViewWasFpsCounterShown;
ShowNavigation = _gameViewActive ? _gameViewWasNavigationShown : false; ShowNavigation = _gameViewActive && _gameViewWasNavigationShown;
Grid.Enabled = _gameViewActive ? _gameViewWasGridShown : false; Grid.Enabled = _gameViewActive && _gameViewWasGridShown;
_gameViewActive = !_gameViewActive; _gameViewActive = !_gameViewActive;
@@ -730,6 +738,20 @@ namespace FlaxEditor.Viewport
base.OnLeftMouseButtonUp(); base.OnLeftMouseButtonUp();
} }
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
if (base.OnKeyDown(key))
return true;
if (key == KeyboardKeys.Escape)
{
_editor.SceneEditing.Deselect();
}
return false;
}
/// <inheritdoc /> /// <inheritdoc />
public override bool OnMouseUp(Float2 location, MouseButton button) public override bool OnMouseUp(Float2 location, MouseButton button)
{ {
@@ -843,8 +865,8 @@ namespace FlaxEditor.Viewport
if (_task != null) if (_task != null)
{ {
// Release if task is not used to save screenshot for project icon // Release if task is not used to save screenshot for project icon
ReleaseTaskResources();
Object.Destroy(ref _task); Object.Destroy(ref _task);
ReleaseResources();
} }
base.OnDestroy(); base.OnDestroy();
@@ -860,6 +882,7 @@ namespace FlaxEditor.Viewport
_savedTask = _task; _savedTask = _task;
_savedBackBuffer = _backBuffer; _savedBackBuffer = _backBuffer;
ReleaseTaskResources();
_task = null; _task = null;
_backBuffer = null; _backBuffer = null;
} }
@@ -870,20 +893,20 @@ namespace FlaxEditor.Viewport
{ {
_savedTask.Enabled = false; _savedTask.Enabled = false;
Object.Destroy(_savedTask); Object.Destroy(_savedTask);
ReleaseResources(); ReleaseTaskResources();
_savedTask = null; _savedTask = null;
} }
Object.Destroy(ref _savedBackBuffer); Object.Destroy(ref _savedBackBuffer);
} }
private void ReleaseResources() private void ReleaseTaskResources()
{ {
if (Task) if (_task)
{ {
Task.RemoveCustomPostFx(SelectionOutline); _task.RemoveCustomPostFx(SelectionOutline);
Task.RemoveCustomPostFx(EditorPrimitives); _task.RemoveCustomPostFx(EditorPrimitives);
Task.RemoveCustomPostFx(_editorSpritesRenderer); _task.RemoveCustomPostFx(_editorSpritesRenderer);
Task.RemoveCustomPostFx(_customSelectionOutline); _task.RemoveCustomPostFx(_customSelectionOutline);
} }
Object.Destroy(ref SelectionOutline); Object.Destroy(ref SelectionOutline);
Object.Destroy(ref EditorPrimitives); Object.Destroy(ref EditorPrimitives);
@@ -233,7 +233,7 @@ namespace FlaxEditor.Windows.Assets
var materialInstance = proxy.Window?.Asset; var materialInstance = proxy.Window?.Asset;
if (materialInstance == null) if (materialInstance == null)
{ {
layout.Label("No parameters"); layout.Label("No parameters", TextAlignment.Center);
return; return;
} }
if (!materialInstance.IsLoaded || (materialInstance.BaseMaterial && !materialInstance.BaseMaterial.IsLoaded)) if (!materialInstance.IsLoaded || (materialInstance.BaseMaterial && !materialInstance.BaseMaterial.IsLoaded))
@@ -246,7 +246,10 @@ namespace FlaxEditor.Windows.Assets
base.Initialize(layout); base.Initialize(layout);
if (parameters.Length == 0) if (parameters.Length == 0)
{
layout.Label("No parameters", TextAlignment.Center);
return; return;
}
var parametersGroup = SurfaceUtils.InitGraphParametersGroup(layout); var parametersGroup = SurfaceUtils.InitGraphParametersGroup(layout);
var settingButton = parametersGroup.AddSettingsButton(); var settingButton = parametersGroup.AddSettingsButton();
+1 -1
View File
@@ -49,7 +49,7 @@ namespace FlaxEditor.Windows.Profiler
{ {
Title = "Draw (GPU)", Title = "Draw (GPU)",
AnchorPreset = AnchorPresets.HorizontalStretchTop, AnchorPreset = AnchorPresets.HorizontalStretchTop,
Offsets = new Margin(0, 0, _drawTimeCPU.Height + 2, 0), Offsets = new Margin(0, 0, _drawTimeCPU.Height + 2, SingleChart.DefaultHeight),
FormatSample = v => (Mathf.RoundToInt(v * 10.0f) / 10.0f) + " ms", FormatSample = v => (Mathf.RoundToInt(v * 10.0f) / 10.0f) + " ms",
Parent = mainPanel, Parent = mainPanel,
}; };
+10
View File
@@ -429,6 +429,9 @@ void Asset::Reload()
ScopeLock lock(Locker); ScopeLock lock(Locker);
// Cancel any still-running loading task (e.g. if WaitForLoaded timed out)
Platform::AtomicStore(&_loadingTask, 0);
if (IsLoaded()) if (IsLoaded())
{ {
// Unload current data // Unload current data
@@ -611,6 +614,13 @@ bool Asset::onLoad(LoadAssetTask* task)
Locker.Lock(); Locker.Lock();
// Re-check after acquiring lock (loading task may have been cleared by Reload, or replaced by a new task)
if (Platform::AtomicRead(&_loadingTask) == 0)
{
Locker.Unlock();
return true;
}
// Load asset // Load asset
LoadResult result; LoadResult result;
#if USE_EDITOR #if USE_EDITOR
+2 -2
View File
@@ -101,9 +101,9 @@ bool Material::CanUseLightmap() const
return _materialShader && _materialShader->CanUseLightmap(); return _materialShader && _materialShader->CanUseLightmap();
} }
bool Material::CanUseInstancing(InstancingHandler& handler) const bool Material::CanUseInstancing(const RenderContext& renderContext, InstancingHandler& handler) const
{ {
return _materialShader && _materialShader->CanUseInstancing(handler); return _materialShader && _materialShader->CanUseInstancing(renderContext, handler);
} }
void Material::Bind(BindParameters& params) void Material::Bind(BindParameters& params)
+1 -1
View File
@@ -48,7 +48,7 @@ public:
bool IsReady() const override; bool IsReady() const override;
DrawPass GetDrawModes() const override; DrawPass GetDrawModes() const override;
bool CanUseLightmap() const override; bool CanUseLightmap() const override;
bool CanUseInstancing(InstancingHandler& handler) const override; bool CanUseInstancing(const RenderContext& renderContext, InstancingHandler& handler) const override;
void Bind(BindParameters& params) override; void Bind(BindParameters& params) override;
// [ShaderAssetBase] // [ShaderAssetBase]
@@ -168,9 +168,9 @@ bool MaterialInstance::CanUseLightmap() const
return _baseMaterial && _baseMaterial->CanUseLightmap(); return _baseMaterial && _baseMaterial->CanUseLightmap();
} }
bool MaterialInstance::CanUseInstancing(InstancingHandler& handler) const bool MaterialInstance::CanUseInstancing(const RenderContext& renderContext, InstancingHandler& handler) const
{ {
return _baseMaterial && _baseMaterial->CanUseInstancing(handler); return _baseMaterial && _baseMaterial->CanUseInstancing(renderContext, handler);
} }
void MaterialInstance::Bind(BindParameters& params) void MaterialInstance::Bind(BindParameters& params)
@@ -53,7 +53,7 @@ public:
bool IsReady() const override; bool IsReady() const override;
DrawPass GetDrawModes() const override; DrawPass GetDrawModes() const override;
bool CanUseLightmap() const override; bool CanUseLightmap() const override;
bool CanUseInstancing(InstancingHandler& handler) const override; bool CanUseInstancing(const RenderContext& renderContext, InstancingHandler& handler) const override;
void Bind(BindParameters& params) override; void Bind(BindParameters& params) override;
protected: protected:
+11
View File
@@ -27,6 +27,17 @@ API_STRUCT(NoDefault) struct FLAXENGINE_API SceneReference
{ {
return ID != other.ID; return ID != other.ID;
} }
FORCE_INLINE SceneReference& operator=(const Guid& id)
{
ID = id;
return *this;
}
FORCE_INLINE operator Guid() const
{
return ID;
}
}; };
template<> template<>
@@ -9,6 +9,7 @@
#include "Engine/Level/Types.h" #include "Engine/Level/Types.h"
#include "Engine/Debug/Exceptions/JsonParseException.h" #include "Engine/Debug/Exceptions/JsonParseException.h"
#include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Profiler/ProfilerMemory.h"
#if USE_EDITOR #if USE_EDITOR
#include "Engine/Core/Collections/HashSet.h" #include "Engine/Core/Collections/HashSet.h"
#include "Engine/Core/Collections/Dictionary.h" #include "Engine/Core/Collections/Dictionary.h"
@@ -20,17 +21,66 @@ bool JsonStorageProxy::IsValidExtension(const StringView& extension)
return extension == DEFAULT_SCENE_EXTENSION || extension == DEFAULT_PREFAB_EXTENSION || extension == DEFAULT_JSON_EXTENSION; return extension == DEFAULT_SCENE_EXTENSION || extension == DEFAULT_PREFAB_EXTENSION || extension == DEFAULT_JSON_EXTENSION;
} }
StringAnsiView ParseJsonString(const StringAnsiView& json, int32 start)
{
while (start < json.Length() && json[start] != '\"')
start++;
int32 end = start + 1;
while (end < json.Length() && json[end] != '\"')
end++;
return json.Substring(start + 1, end - start - 1);
}
bool JsonStorageProxy::GetAssetInfo(const StringView& path, Guid& resultId, String& resultDataTypeName) bool JsonStorageProxy::GetAssetInfo(const StringView& path, Guid& resultId, String& resultDataTypeName)
{ {
PROFILE_CPU(); PROFILE_CPU();
// TODO: we could just open file and start reading until we find 'ID:..' without parsing whole file - could be much more faster PROFILE_MEM(Content);
ZoneText(*path, path.Length());
// Read the first part of the file to get asset metadata (ID and TypeName)
auto file = File::Open(path, FileMode::OpenExisting, FileAccess::Read, FileShare::All);
if (!file)
return false;
Array<byte> fileData;
fileData.Resize(256);
uint32 read = 0;
file->Read(fileData.Get(), fileData.Count(), &read);
Delete(file);
file = nullptr;
if (read != 0)
{
// Naive Json parsing to get ID and TypeName without full parsing
StringAnsiView json((const char*)fileData.Get(), read);
StringAnsiView idStart("\"ID\": ");
StringAnsiView typenameStart("\"TypeName\": ");
bool hasOneOfThem = false;
for (int32 i = 0; i < json.Length() - 7; i++)
{
if (json.Substring(i).StartsWith(idStart))
{
StringAnsiView value = ParseJsonString(json, i + idStart.Length());
if (Guid::Parse(value, resultId))
continue;
if (hasOneOfThem)
return true;
hasOneOfThem = true;
i += value.Length() + idStart.Length() + 2;
}
if (json.Substring(i).StartsWith(typenameStart))
{
StringAnsiView value = ParseJsonString(json, i + typenameStart.Length());
resultDataTypeName = String(value);
if (hasOneOfThem)
return true;
hasOneOfThem = true;
i += value.Length() + typenameStart.Length() + 2;
}
}
}
// Load file // Load file
Array<byte> fileData;
if (File::ReadAllBytes(path, fileData)) if (File::ReadAllBytes(path, fileData))
{
return false; return false;
}
// Parse data // Parse data
rapidjson_flax::Document document; rapidjson_flax::Document document;
@@ -89,11 +139,8 @@ void FindObjectIds(const rapidjson_flax::Value& obj, const rapidjson_flax::Docum
} }
} }
#endif
bool JsonStorageProxy::ChangeId(const StringView& path, const Guid& newId) bool JsonStorageProxy::ChangeId(const StringView& path, const Guid& newId)
{ {
#if USE_EDITOR
PROFILE_CPU(); PROFILE_CPU();
// Load file // Load file
@@ -140,8 +187,6 @@ bool JsonStorageProxy::ChangeId(const StringView& path, const Guid& newId)
return true; return true;
return false; return false;
#else
LOG(Warning, "Editing cooked content is invalid.");
return true;
#endif
} }
#endif
@@ -30,6 +30,7 @@ public:
/// <returns>True if found any asset, otherwise false.</returns> /// <returns>True if found any asset, otherwise false.</returns>
static bool GetAssetInfo(const StringView& path, Guid& resultId, String& resultDataTypeName); static bool GetAssetInfo(const StringView& path, Guid& resultId, String& resultDataTypeName);
#if USE_EDITOR
/// <summary> /// <summary>
/// Changes asset ID. /// Changes asset ID.
/// </summary> /// </summary>
@@ -37,4 +38,5 @@ public:
/// <param name="newId">Asset ID to set</param> /// <param name="newId">Asset ID to set</param>
/// <returns>True if found any asset, otherwise false.</returns> /// <returns>True if found any asset, otherwise false.</returns>
static bool ChangeId(const StringView& path, const Guid& newId); static bool ChangeId(const StringView& path, const Guid& newId);
#endif
}; };
@@ -113,6 +113,8 @@ CreateAssetContext::CreateAssetContext(const StringView& inputPath, const String
CreateAssetResult CreateAssetContext::Run(const CreateAssetFunction& callback) CreateAssetResult CreateAssetContext::Run(const CreateAssetFunction& callback)
{ {
PROFILE_CPU();
PROFILE_MEM(Content);
ASSERT(callback.IsBinded()); ASSERT(callback.IsBinded());
// Call action // Call action
@@ -207,6 +209,9 @@ void CreateAssetContext::AddMeta(JsonWriter& writer) const
void CreateAssetContext::ApplyChanges() void CreateAssetContext::ApplyChanges()
{ {
PROFILE_CPU();
PROFILE_MEM(Content);
// Get access // Get access
auto storage = ContentStorageManager::TryGetStorage(TargetAssetPath); auto storage = ContentStorageManager::TryGetStorage(TargetAssetPath);
if (storage && storage->IsLoaded()) if (storage && storage->IsLoaded())
@@ -274,6 +279,8 @@ bool AssetsImportingManager::Create(const String& tag, const StringView& outputP
bool AssetsImportingManager::Import(const StringView& inputPath, const StringView& outputPath, Guid& assetId, void* arg) bool AssetsImportingManager::Import(const StringView& inputPath, const StringView& outputPath, Guid& assetId, void* arg)
{ {
PROFILE_CPU();
PROFILE_MEM(Content);
LOG(Info, "Importing file '{0}' to '{1}'...", inputPath, outputPath); LOG(Info, "Importing file '{0}' to '{1}'...", inputPath, outputPath);
// Check if input file exists // Check if input file exists
@@ -347,6 +354,7 @@ String AssetsImportingManager::GetImportPath(const String& path)
bool AssetsImportingManager::Create(const Function<CreateAssetResult(CreateAssetContext&)>& callback, const StringView& inputPath, const StringView& outputPath, Guid& assetId, void* arg) bool AssetsImportingManager::Create(const Function<CreateAssetResult(CreateAssetContext&)>& callback, const StringView& inputPath, const StringView& outputPath, Guid& assetId, void* arg)
{ {
PROFILE_CPU(); PROFILE_CPU();
PROFILE_MEM(Content);
ZoneText(*outputPath, outputPath.Length()); ZoneText(*outputPath, outputPath.Length());
const auto startTime = Platform::GetTimeSeconds(); const auto startTime = Platform::GetTimeSeconds();
+21 -1
View File
@@ -44,12 +44,32 @@ public:
IMPLEMENT_ENGINE_SETTINGS_GETTER(BuildSettings, GameCooking); IMPLEMENT_ENGINE_SETTINGS_GETTER(BuildSettings, GameCooking);
#include "Engine/Content/Deprecated.h" #include "Engine/Content/Deprecated.h"
PRAGMA_DISABLE_DEPRECATION_WARNINGS;
bool GraphicsSettings::GetUeeHDRProbes() const
{
return UseHDRProbes;
}
void GraphicsSettings::SetUeeHDRProbes(bool value) void GraphicsSettings::SetUeeHDRProbes(bool value)
{ {
MARK_CONTENT_DEPRECATED(); MARK_CONTENT_DEPRECATED();
UseHDRProbes = value; DefaultProbeCubemapFormat = value ? ProbeCubemapFormats::R11G11B10 : ProbeCubemapFormats::R8G8B8A8;
} }
bool GraphicsSettings::GetUseHDRProbes() const
{
return UseHDRProbes;
}
void GraphicsSettings::SetUseHDRProbes(bool value)
{
DefaultProbeCubemapFormat = value ? ProbeCubemapFormats::R11G11B10 : ProbeCubemapFormats::R8G8B8A8;
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS;
void GraphicsSettings::OnDeserializing(const CallbackContext& context) void GraphicsSettings::OnDeserializing(const CallbackContext& context)
{ {
#if 0 // TODO: move to Linear color space as default once it's ready for production #if 0 // TODO: move to Linear color space as default once it's ready for production
+29 -4
View File
@@ -31,6 +31,22 @@ public:
R16G16B16A16, R16G16B16A16,
}; };
/// <summary>
/// The environment probes cubemap texture storage formats.
/// </summary>
API_ENUM(Attributes = "EnumDisplay(EnumDisplayAttribute.FormatMode.None)")
enum class ProbeCubemapFormats
{
// LDR uncompressed format (32-bit per pixel).
R8G8B8A8,
// HDR uncompressed format (32-bit per pixel, no alpha).
R11G11B10,
// HDR compressed format (8-bit per pixel, no alpha). Converted into ASTC/Basis for mobile/web. Realtime probes will fallback to R11G11B10.
BC6,
// HDR compressed format (8-bit per pixel). Converted into ASTC/Basis for mobile/web. Realtime probes will fallback to R11G11B10.
BC7,
};
public: public:
/// <summary> /// <summary>
/// Enables rendering synchronization with the refresh rate of the display device to avoid "tearing" artifacts. /// Enables rendering synchronization with the refresh rate of the display device to avoid "tearing" artifacts.
@@ -87,9 +103,16 @@ public:
ProbeCubemapResolution DefaultProbeResolution = ProbeCubemapResolution::_128; ProbeCubemapResolution DefaultProbeResolution = ProbeCubemapResolution::_128;
/// <summary> /// <summary>
/// If checked, Environment Probes will use HDR texture format. Improves quality in very bright scenes at cost of higher memory usage. /// Environment Probes texture storage format. Controls the quality fo reflections and memory usage of probes data.
/// </summary> /// </summary>
API_FIELD(Attributes="EditorOrder(1502), EditorDisplay(\"Quality\")") API_FIELD(Attributes="EditorOrder(1502), EditorDisplay(\"Quality\")")
ProbeCubemapFormats DefaultProbeCubemapFormat = ProbeCubemapFormats::BC6;
/// <summary>
/// If checked, Environment Probes will use HDR texture format. Improves quality in very bright scenes at cost of higher memory usage.
/// [Deprecated in v1.13]
/// </summary>
DEPRECATED("Use DefaultProbeCubemapFormat instead.")
bool UseHDRProbes = false; bool UseHDRProbes = false;
/// <summary> /// <summary>
@@ -127,7 +150,7 @@ public:
/// <summary> /// <summary>
/// The Global Illumination probes spacing distance (in world units). Defines the quality of the GI resolution. Adjust to 200-500 to improve performance and lower frequency GI data. /// The Global Illumination probes spacing distance (in world units). Defines the quality of the GI resolution. Adjust to 200-500 to improve performance and lower frequency GI data.
/// </summary> /// </summary>
API_FIELD(Attributes="EditorOrder(2120), Limit(50, 1000), EditorDisplay(\"Global Illumination\")") API_FIELD(Attributes="EditorOrder(2120), Limit(50, 1000), EditorDisplay(\"Global Illumination\"), ValueCategory(Utils.ValueCategory.Distance)")
float GIProbesSpacing = 100; float GIProbesSpacing = 100;
/// <summary> /// <summary>
@@ -175,8 +198,10 @@ private:
/// Renamed UeeHDRProbes into UseHDRProbes /// Renamed UeeHDRProbes into UseHDRProbes
/// [Deprecated on 12.10.2022, expires on 12.10.2024] /// [Deprecated on 12.10.2022, expires on 12.10.2024]
/// </summary> /// </summary>
API_PROPERTY(Attributes="Serialize, Obsolete, NoUndo") DEPRECATED("Use UseHDRProbes instead.") bool GetUeeHDRProbes() const { return UseHDRProbes; } API_PROPERTY(Attributes="Serialize, Obsolete, NoUndo") DEPRECATED("Use DefaultProbeCubemapFormat instead.") bool GetUeeHDRProbes() const;
API_PROPERTY(Attributes="Serialize, Obsolete, NoUndo") DEPRECATED("Use UseHDRProbes instead.") void SetUeeHDRProbes(bool value); API_PROPERTY(Attributes="Serialize, Obsolete, NoUndo") DEPRECATED("Use DefaultProbeCubemapFormat instead.") void SetUeeHDRProbes(bool value);
API_PROPERTY(Attributes="Serialize, Obsolete, NoUndo") DEPRECATED("Use DefaultProbeCubemapFormat instead.") bool GetUseHDRProbes() const;
API_PROPERTY(Attributes="Serialize, Obsolete, NoUndo") DEPRECATED("Use DefaultProbeCubemapFormat instead.") void SetUseHDRProbes(bool value);
API_FUNCTION(Attributes="OnDeserializing", Hidden) void OnDeserializing(const CallbackContext& context); API_FUNCTION(Attributes="OnDeserializing", Hidden) void OnDeserializing(const CallbackContext& context);
public: public:
@@ -59,6 +59,11 @@ void BoundingFrustum::SetMatrix(const Matrix& matrix)
_pFar.Normal.Z = matrix.M34 - matrix.M33; _pFar.Normal.Z = matrix.M34 - matrix.M33;
_pFar.D = matrix.M44 - matrix.M43; _pFar.D = matrix.M44 - matrix.M43;
_pFar.Normalize(); _pFar.Normalize();
#if REVERSE_Z
// Swap far and near planes if reverse z
Swap(_pFar, _pNear);
#endif
} }
Plane BoundingFrustum::GetPlane(int32 index) const Plane BoundingFrustum::GetPlane(int32 index) const
@@ -243,6 +243,11 @@ namespace FlaxEngine
far.Normal.Z = matrix.M34 - matrix.M33; far.Normal.Z = matrix.M34 - matrix.M33;
far.D = matrix.M44 - matrix.M43; far.D = matrix.M44 - matrix.M43;
far.Normalize(); far.Normalize();
#if REVERSE_Z
// Swap far and near planes if reverse z
(near, far) = (far, near);
#endif
} }
private static Vector3 Get3PlanesInterPoint(ref Plane p1, ref Plane p2, ref Plane p3) private static Vector3 Get3PlanesInterPoint(ref Plane p1, ref Plane p2, ref Plane p3)
+32
View File
@@ -66,6 +66,12 @@ public:
double Values[4][4]; double Values[4][4];
double Raw[16]; double Raw[16];
}; };
public:
/// <summary>A matrix with all of its components set to zero.</summary>
static const Double4x4 Zero;
/// <summary>The identity matrix.</summary>
static const Double4x4 Identity;
public: public:
/// <summary> /// <summary>
@@ -73,6 +79,32 @@ public:
/// </summary> /// </summary>
Double4x4() = default; Double4x4() = default;
/// <summary>
/// Initializes a new instance of the <see cref="Matrix"/> struct.
/// </summary>
Double4x4(double m11, double m12, double m13, double m14,
double m21, double m22, double m23, double m24,
double m31, double m32, double m33, double m34,
double m41, double m42, double m43, double m44)
: M11(m11)
, M12(m12)
, M13(m13)
, M14(m14)
, M21(m21)
, M22(m22)
, M23(m23)
, M24(m24)
, M31(m31)
, M32(m32)
, M33(m33)
, M34(m34)
, M41(m41)
, M42(m42)
, M43(m43)
, M44(m44)
{
}
Double4x4(const Matrix& matrix); Double4x4(const Matrix& matrix);
public: public:
+22 -4
View File
@@ -10,6 +10,7 @@
#include "../Types/String.h" #include "../Types/String.h"
static_assert(sizeof(Matrix) == 4 * 4 * 4, "Invalid Matrix type size."); static_assert(sizeof(Matrix) == 4 * 4 * 4, "Invalid Matrix type size.");
static_assert(sizeof(Double4x4) == 8 * 4 * 4, "Invalid Double4x4 type size.");
const Matrix Matrix::Zero(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); const Matrix Matrix::Zero(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
const Matrix Matrix::Identity( const Matrix Matrix::Identity(
@@ -18,6 +19,13 @@ const Matrix Matrix::Identity(
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f); 0.0f, 0.0f, 0.0f, 1.0f);
const Double4x4 Double4x4::Zero(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
const Double4x4 Double4x4::Identity(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
Matrix::Matrix(const Matrix3x3& matrix) Matrix::Matrix(const Matrix3x3& matrix)
{ {
Platform::MemoryCopy(&M11, &matrix.M11, sizeof(Float3)); Platform::MemoryCopy(&M11, &matrix.M11, sizeof(Float3));
@@ -514,10 +522,15 @@ void Matrix::OrthoOffCenter(float left, float right, float bottom, float top, fl
result = Identity; result = Identity;
result.M11 = 2.0f / (right - left); result.M11 = 2.0f / (right - left);
result.M22 = 2.0f / (top - bottom); result.M22 = 2.0f / (top - bottom);
result.M33 = zRange;
result.M41 = (left + right) / (left - right); result.M41 = (left + right) / (left - right);
result.M42 = (top + bottom) / (bottom - top); result.M42 = (top + bottom) / (bottom - top);
#if REVERSE_Z
result.M33 = -zRange;
result.M43 = zFar * zRange;
#else
result.M33 = zRange;
result.M43 = -zNear * zRange; result.M43 = -zNear * zRange;
#endif
} }
void Matrix::PerspectiveFov(float fov, float aspect, float zNear, float zFar, Matrix& result) void Matrix::PerspectiveFov(float fov, float aspect, float zNear, float zFar, Matrix& result)
@@ -533,16 +546,21 @@ void Matrix::PerspectiveFov(float fov, float aspect, float zNear, float zFar, Ma
void Matrix::PerspectiveOffCenter(float left, float right, float bottom, float top, float zNear, float zFar, Matrix& result) void Matrix::PerspectiveOffCenter(float left, float right, float bottom, float top, float zNear, float zFar, Matrix& result)
{ {
const float zRange = zFar / (zFar - zNear); const float zRange = 1.0f / (zFar - zNear);
result = Zero; result = Zero;
result.M11 = 2.0f * zNear / (right - left); result.M11 = 2.0f * zNear / (right - left);
result.M22 = 2.0f * zNear / (top - bottom); result.M22 = 2.0f * zNear / (top - bottom);
result.M31 = (left + right) / (left - right); result.M31 = (left + right) / (left - right);
result.M32 = (top + bottom) / (bottom - top); result.M32 = (top + bottom) / (bottom - top);
result.M33 = zRange;
result.M34 = 1.0f; result.M34 = 1.0f;
result.M43 = -zNear * zRange; #if REVERSE_Z
result.M33 = -zNear * zRange;
result.M43 = zFar * zNear * zRange;
#else
result.M33 = zFar * zRange;
result.M43 = -zFar * zNear * zRange;
#endif
} }
void Matrix::RotationX(float angle, Matrix& result) void Matrix::RotationX(float angle, Matrix& result)
+22 -7
View File
@@ -2176,10 +2176,15 @@ namespace FlaxEngine
result = Identity; result = Identity;
result.M11 = 2.0f / (right - left); result.M11 = 2.0f / (right - left);
result.M22 = 2.0f / (top - bottom); result.M22 = 2.0f / (top - bottom);
result.M33 = zRange;
result.M41 = (left + right) / (left - right); result.M41 = (left + right) / (left - right);
result.M42 = (top + bottom) / (bottom - top); result.M42 = (top + bottom) / (bottom - top);
#if REVERSE_Z
result.M33 = -zRange;
result.M43 = zfar * zRange;
#else
result.M33 = zRange;
result.M43 = -znear * zRange; result.M43 = -znear * zRange;
#endif
} }
/// <summary> /// <summary>
@@ -2238,14 +2243,19 @@ namespace FlaxEngine
public static void PerspectiveFov(float fov, float aspect, float znear, float zfar, out Matrix result) public static void PerspectiveFov(float fov, float aspect, float znear, float zfar, out Matrix result)
{ {
var yScale = (float)(1.0f / Math.Tan(fov * 0.5f)); var yScale = (float)(1.0f / Math.Tan(fov * 0.5f));
var q = zfar / (zfar - znear); var zRange = 1.0f / (zfar - znear);
result = new Matrix result = new Matrix
{ {
M11 = yScale / aspect, M11 = yScale / aspect,
M22 = yScale, M22 = yScale,
M33 = q,
M34 = 1.0f, M34 = 1.0f,
M43 = -q * znear, #if REVERSE_Z
M33 = -znear * zRange,
M43 = znear * zfar * zRange,
#else
M33 = zfar * zRange,
M43 = -znear * zfar * zRange,
#endif
}; };
} }
@@ -2275,16 +2285,21 @@ namespace FlaxEngine
/// <param name="result">When the method completes, contains the created projection matrix.</param> /// <param name="result">When the method completes, contains the created projection matrix.</param>
public static void PerspectiveOffCenter(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result) public static void PerspectiveOffCenter(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result)
{ {
float zRange = zfar / (zfar - znear); float zRange = 1.0f / (zfar - znear);
result = new Matrix result = new Matrix
{ {
M11 = 2.0f * znear / (right - left), M11 = 2.0f * znear / (right - left),
M22 = 2.0f * znear / (top - bottom), M22 = 2.0f * znear / (top - bottom),
M31 = (left + right) / (left - right), M31 = (left + right) / (left - right),
M32 = (top + bottom) / (bottom - top), M32 = (top + bottom) / (bottom - top),
M33 = zRange,
M34 = 1.0f, M34 = 1.0f,
M43 = -znear * zRange, #if REVERSE_Z
M33 = -znear * zRange,
M43 = znear * zfar * zRange,
#else
M33 = zfar * zRange,
M43 = -znear * zfar * zRange,
#endif
}; };
} }
+9
View File
@@ -57,6 +57,15 @@ public:
{ {
} }
/// <summary>
/// Initializes a new instance of the <see cref="Rectangle"/> struct.
/// </summary>
/// <param name="packed">The location and size packed.</param>
Rectangle(const Float4& packed)
{
Platform::MemoryCopy(this, &packed, sizeof(*this));
}
public: public:
String ToString() const; String ToString() const;
+11 -4
View File
@@ -150,11 +150,18 @@ void Transform::LocalToWorldVector(const Vector3& vector, Vector3& result) const
Vector3::Transform(tmp, Orientation, result); Vector3::Transform(tmp, Orientation, result);
} }
void Transform::LocalToWorld(const Vector3& point, Vector3& result) const void Transform::LocalToWorld(const Float3& point, Float3& result) const
{ {
Vector3 tmp = point * Scale; Float3 tmp = point * Scale;
Vector3::Transform(tmp, Orientation, tmp); Float3::Transform(tmp, Orientation, tmp);
Vector3::Add(tmp, Translation, result); Float3::Add(tmp, Translation, result);
}
void Transform::LocalToWorld(const Double3& point, Double3& result) const
{
Double3 tmp = point * Scale;
Double3::Transform(tmp, Orientation, tmp);
Double3::Add(tmp, Translation, result);
} }
void Transform::WorldToLocal(const Transform& other, Transform& result) const void Transform::WorldToLocal(const Transform& other, Transform& result) const
+8 -1
View File
@@ -219,7 +219,14 @@ public:
/// </summary> /// </summary>
/// <param name="point">The local space point.</param> /// <param name="point">The local space point.</param>
/// <param name="result">The world space point.</param> /// <param name="result">The world space point.</param>
void LocalToWorld(const Vector3& point, Vector3& result) const; void LocalToWorld(const Float3& point, Float3& result) const;
/// <summary>
/// Performs transformation of the given point in local space to the world space of this transform.
/// </summary>
/// <param name="point">The local space point.</param>
/// <param name="result">The world space point.</param>
void LocalToWorld(const Double3& point, Double3& result) const;
/// <summary> /// <summary>
/// Performs transformation of the given transform in local space to the world space of this transform. /// Performs transformation of the given transform in local space to the world space of this transform.
+5 -7
View File
@@ -296,15 +296,13 @@ namespace FlaxEngine
/// <summary> /// <summary>
/// Converts a screen space point into a corresponding point in world space. /// Converts a screen space point into a corresponding point in world space.
/// </summary> /// </summary>
/// <param name="source">The vector to project.</param> /// <param name="source">The vector to project, screen uv and device depth.</param>
/// <param name="projection">The projection matrix.</param> /// <param name="projection">The projection matrix.</param>
/// <param name="view">The view matrix.</param> /// <param name="view">The view matrix.</param>
/// <param name="world">The world matrix.</param>
/// <returns>The unprojected Vector.</returns> /// <returns>The unprojected Vector.</returns>
public Vector3 Unproject(Vector3 source, Matrix projection, Matrix view, Matrix world) public Vector3 Unproject(Vector3 source, Matrix projection, Matrix view)
{ {
Matrix.Multiply(ref world, ref view, out Matrix matrix); Matrix.Multiply(ref view, ref projection, out Matrix matrix);
Matrix.Multiply(ref matrix, ref projection, out matrix);
Matrix.Invert(ref matrix, out matrix); Matrix.Invert(ref matrix, out matrix);
Unproject(ref source, ref matrix, out Vector3 vector); Unproject(ref source, ref matrix, out Vector3 vector);
@@ -314,8 +312,8 @@ namespace FlaxEngine
/// <summary> /// <summary>
/// Converts a screen space point into a corresponding point in world space. /// Converts a screen space point into a corresponding point in world space.
/// </summary> /// </summary>
/// <param name="source">The vector to project.</param> /// <param name="source">The vector to project, screen uv and device depth.</param>
/// <param name="matrix">An inverted combined WorldViewProjection matrix.</param> /// <param name="matrix">An inverted combined ViewProjection matrix.</param>
/// <param name="vector">The unprojected vector.</param> /// <param name="vector">The unprojected vector.</param>
public void Unproject(ref Vector3 source, ref Matrix matrix, out Vector3 vector) public void Unproject(ref Vector3 source, ref Matrix matrix, out Vector3 vector)
{ {
+1
View File
@@ -127,6 +127,7 @@ bool GameBase::Init()
if (!gameSettings) if (!gameSettings)
return true; return true;
GameBaseImpl::FirstScene = gameSettings->FirstScene; GameBaseImpl::FirstScene = gameSettings->FirstScene;
Level::PreloadSceneAsync(GameBaseImpl::FirstScene.GetID());
return false; return false;
} }
+10 -2
View File
@@ -20,6 +20,7 @@ namespace
Nullable<bool> Fullscreen; Nullable<bool> Fullscreen;
Nullable<Float2> Size; Nullable<Float2> Size;
bool CursorVisible = true; bool CursorVisible = true;
CursorType CachedCursorType = CursorType::Default;
CursorLockMode CursorLock = CursorLockMode::None; CursorLockMode CursorLock = CursorLockMode::None;
CursorLockMode PendingCursorLock = CursorLockMode::None; CursorLockMode PendingCursorLock = CursorLockMode::None;
bool LastGameViewportFocus = false; bool LastGameViewportFocus = false;
@@ -107,10 +108,17 @@ void Screen::SetCursorVisible(const bool value)
#else #else
const auto win = Engine::MainWindow; const auto win = Engine::MainWindow;
#endif #endif
if (!value && win)
{
// Cache cursor used before hiding it to restore it later (eg. if game uses image cursor and hides it for a while)
CachedCursorType = win->GetCursor();
if (CachedCursorType == CursorType::Hidden)
CachedCursorType = CursorType::Default;
}
if (win && Engine::HasGameViewportFocus()) if (win && Engine::HasGameViewportFocus())
win->SetCursor(value ? CursorType::Default : CursorType::Hidden); win->SetCursor(value ? CachedCursorType : CursorType::Hidden);
else if (win) else if (win)
win->SetCursor(CursorType::Default); win->SetCursor(CachedCursorType);
CursorVisible = value; CursorVisible = value;
} }
File diff suppressed because it is too large Load Diff
+25 -5
View File
@@ -6,6 +6,7 @@
#include "FoliageInstance.h" #include "FoliageInstance.h"
#include "FoliageCluster.h" #include "FoliageCluster.h"
#include "FoliageType.h" #include "FoliageType.h"
#include "Engine/Core/Math/BoundingFrustum.h"
#include "Engine/Core/Memory/ArenaAllocation.h" #include "Engine/Core/Memory/ArenaAllocation.h"
#include "Engine/Level/Actor.h" #include "Engine/Level/Actor.h"
@@ -19,6 +20,7 @@ API_CLASS() class FLAXENGINE_API Foliage final : public Actor
private: private:
bool _disableFoliageTypeEvents; bool _disableFoliageTypeEvents;
int32 _sceneRenderingKey = -1; int32 _sceneRenderingKey = -1;
Vector3 _cachedDrawWorldOrigin = Vector3::Zero;
public: public:
/// <summary> /// <summary>
@@ -158,15 +160,25 @@ public:
private: private:
void AddToCluster(ChunkedArray<FoliageCluster, FOLIAGE_CLUSTER_CHUNKS_SIZE>& clusters, FoliageCluster* cluster, FoliageInstance& instance); void AddToCluster(ChunkedArray<FoliageCluster, FOLIAGE_CLUSTER_CHUNKS_SIZE>& clusters, FoliageCluster* cluster, FoliageInstance& instance);
struct DrawContext struct DrawContext
{ {
RenderContext& RenderContext; RenderContext& RenderContext;
const RenderView& LodView; Model* FoliageTypeModel;
const FoliageType& FoliageType;
Vector3 ViewOrigin; Vector3 ViewOrigin;
float MinObjectPixelSizeSq;
float ViewScreenSizeSq; float ViewScreenSizeSq;
Float3 LodViewOrigin;
float MinObjectPixelSizeSq;
Float3 LodViewPosition;
int32 MinLOD, MaxLOD;
BoundingFrustum CullingFrustum;
FORCE_INLINE int32 ClampLODIndex(int32 index) const
{
return index < MinLOD ? MinLOD : index < MaxLOD ? index : MaxLOD;
}
}; };
#if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING #if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING
struct DrawKey struct DrawKey
{ {
@@ -190,7 +202,7 @@ private:
typedef Array<struct DrawCall, InlinedAllocation<8>> DrawCallsList; typedef Array<struct DrawCall, InlinedAllocation<8>> DrawCallsList;
typedef Dictionary<DrawKey, struct BatchedDrawCall, ConcurrentArenaAllocation> BatchedDrawCalls; typedef Dictionary<DrawKey, struct BatchedDrawCall, ConcurrentArenaAllocation> BatchedDrawCalls;
void DrawInstance(DrawContext& context, FoliageInstance& instance, Model* model, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const; void DrawInstance(DrawContext& context, FoliageInstance& instance, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
void DrawCluster(DrawContext& context, FoliageCluster* cluster, 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); void DrawType(RenderContext& renderContext, const FoliageType& type, DrawCallsList* drawCallsLists);
#else #else
@@ -204,7 +216,9 @@ private:
RenderContextBatch* _renderContextBatch; RenderContextBatch* _renderContextBatch;
#endif #endif
void InitType(const RenderView& view, FoliageType& type); void PreDraw(const RenderView& view);
void InitType(const RenderView& view, int32 typeIndex);
void UpdateBounds();
public: public:
/// <summary> /// <summary>
@@ -217,6 +231,12 @@ public:
/// <returns>True whether the two objects intersected, otherwise false.</returns> /// <returns>True whether the two objects intersected, otherwise false.</returns>
API_FUNCTION() bool Intersects(API_PARAM(Ref) const Ray& ray, API_PARAM(Out) Real& distance, API_PARAM(Out) Vector3& normal, API_PARAM(Out) int32& instanceIndex); API_FUNCTION() bool Intersects(API_PARAM(Ref) const Ray& ray, API_PARAM(Out) Real& distance, API_PARAM(Out) Vector3& normal, API_PARAM(Out) int32& instanceIndex);
private:
#if USE_EDITOR
// Debug filter to draw only specific foliage type (in editor).
API_FIELD(Internal) int32 _drawFoliageType = -1;
#endif
public: public:
// [Actor] // [Actor]
void Draw(RenderContext& renderContext) override; void Draw(RenderContext& renderContext) override;
+38 -13
View File
@@ -4,15 +4,15 @@
#include "Engine/Core/Math/Transform.h" #include "Engine/Core/Math/Transform.h"
#include "Engine/Core/Math/BoundingSphere.h" #include "Engine/Core/Math/BoundingSphere.h"
#include "Engine/Renderer/DrawCall.h" #include "Engine/Core/Math/Half.h"
#include "Engine/Level/Scene/Lightmap.h" #include "Engine/Core/Math/Matrix.h"
/// <summary> /// <summary>
/// Foliage instanced mesh instance. Packed data with very little of logic. Managed by the foliage chunks and foliage actor itself. /// Foliage instanced mesh instance. Packed data with very little of logic. Managed by the foliage chunks and foliage actor itself.
/// </summary> /// </summary>
API_STRUCT(NoPod) struct FLAXENGINE_API FoliageInstance API_STRUCT(NoPod, NoDefault) struct FLAXENGINE_API FoliageInstance
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(FoliageInstance); DECLARE_SCRIPTING_TYPE_MINIMAL(FoliageInstance);
/// <summary> /// <summary>
/// The local-space transformation of the mesh relative to the foliage actor. /// The local-space transformation of the mesh relative to the foliage actor.
@@ -20,14 +20,39 @@ API_STRUCT(NoPod) struct FLAXENGINE_API FoliageInstance
API_FIELD() Transform Transform; API_FIELD() Transform Transform;
/// <summary> /// <summary>
/// The model drawing state. /// The cached instance bounds (in world space).
/// </summary> /// </summary>
GeometryDrawStateData DrawState; API_FIELD() BoundingSphere Bounds;
/// <summary>
/// The previous frame index. In sync with Engine::FrameCount used to detect new frames and rendering gaps to reset state.
/// </summary>
uint64 DrawStatePrevFrame = 0;
/// <summary> /// <summary>
/// The foliage type index. Foliage types are hold in foliage actor and shared by instances using the same model. /// The foliage type index. Foliage types are hold in foliage actor and shared by instances using the same model.
/// </summary> /// </summary>
API_FIELD() int32 Type; API_FIELD() uint16 Type;
/// <summary>
/// The lightmap index for the foliage instance. -1 if unused.
/// </summary>
int8 LightmapTextureIndex = -1;
/// <summary>
/// The previous frame model LOD index used. It's locked during LOD transition to cache the transition start LOD.
/// </summary>
char DrawStatePrevLOD = -1;
/// <summary>
/// The LOD transition timer.
/// </summary>
byte DrawStateLODTransition = 255;
/// <summary>
/// Flag used to indicate whether CachedDrawWorld contains valid data.
/// </summary>
byte CachedDrawWorldValid = 0;
/// <summary> /// <summary>
/// The per-instance random value from range [0;1]. /// The per-instance random value from range [0;1].
@@ -40,14 +65,14 @@ API_STRUCT(NoPod) struct FLAXENGINE_API FoliageInstance
float CullDistance; float CullDistance;
/// <summary> /// <summary>
/// The cached instance bounds (in world space). /// Lightmap UVs area that entry occupies (packed Rectangle into Half4).
/// </summary> /// </summary>
API_FIELD() BoundingSphere Bounds; Half4 LightmapUVsArea;
/// <summary> /// <summary>
/// The lightmap entry for the foliage instance. /// Cached local-to-world transformation matrix for the instance used during rendering. Relative to the last rendering context origin. Valid only if CachedDrawWorldValid flag is set.
/// </summary> /// </summary>
LightmapEntry Lightmap; Matrix CachedDrawWorld;
public: public:
bool operator==(const FoliageInstance& v) const bool operator==(const FoliageInstance& v) const
@@ -60,7 +85,7 @@ public:
/// </summary> /// </summary>
FORCE_INLINE bool HasLightmap() const FORCE_INLINE bool HasLightmap() const
{ {
return Lightmap.TextureIndex != INVALID_INDEX; return LightmapTextureIndex != INVALID_INDEX;
} }
/// <summary> /// <summary>
@@ -68,6 +93,6 @@ public:
/// </summary> /// </summary>
FORCE_INLINE void RemoveLightmap() FORCE_INLINE void RemoveLightmap()
{ {
Lightmap.TextureIndex = INVALID_INDEX; LightmapTextureIndex = INVALID_INDEX;
} }
}; };
@@ -7,6 +7,7 @@
#include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUDevice.h"
#include "Engine/Graphics/GPUPass.h" #include "Engine/Graphics/GPUPass.h"
#include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Profiler/ProfilerGPU.h"
DefaultGPUTasksExecutor::DefaultGPUTasksExecutor() DefaultGPUTasksExecutor::DefaultGPUTasksExecutor()
: _context(nullptr) : _context(nullptr)
@@ -33,6 +34,7 @@ void DefaultGPUTasksExecutor::FrameBegin()
const int32 count = GPUDevice::Instance->GetTasksManager()->RequestWork(buffer, 32); const int32 count = GPUDevice::Instance->GetTasksManager()->RequestWork(buffer, 32);
if (count == 0) if (count == 0)
return; return;
PROFILE_GPU("GPUTasks");
GPUMemoryPass pass(_context->GPU); GPUMemoryPass pass(_context->GPU);
for (int32 i = 0; i < count; i++) for (int32 i = 0; i < count; i++)
{ {
+24 -1
View File
@@ -629,6 +629,17 @@ public:
uint32 GetHash(const BlendingMode& key); uint32 GetHash(const BlendingMode& key);
// Temp defines to put them into ComparisonFunc enum conditionally
#if REVERSE_Z
#define REVERSE_Z_COMP_DEFAULT 5
#define REVERSE_Z_COMP_DEFAULT_INV 2
#define REVERSE_Z_COMP_DEFAULT_EQ 7
#else
#define REVERSE_Z_COMP_DEFAULT 2
#define REVERSE_Z_COMP_DEFAULT_INV 5
#define REVERSE_Z_COMP_DEFAULT_EQ 4
#endif
/// <summary> /// <summary>
/// Comparison function modes /// Comparison function modes
/// </summary> /// </summary>
@@ -651,9 +662,21 @@ API_ENUM() enum class ComparisonFunc : byte
// Always pass the comparison. // Always pass the comparison.
Always = 8, Always = 8,
API_ENUM(Attributes="HideInEditor") MAX API_ENUM(Attributes="HideInEditor") MAX,
// Default comparision when rendering scene objects (Less or Greater).
API_ENUM(Attributes="HideInEditor") Default = REVERSE_Z_COMP_DEFAULT,
// Default comparision when rendering scene objects inverted (Greater or Less).
API_ENUM(Attributes="HideInEditor") DefaultInv = REVERSE_Z_COMP_DEFAULT_INV,
// Default comparision when rendering scene objects with equal (LessEqual or GreaterEqual).
API_ENUM(Attributes="HideInEditor") DefaultEqual = REVERSE_Z_COMP_DEFAULT_EQ,
}; };
// Remove temp defines to plug conditional value into the enum
#undef REVERSE_Z_COMP_DEFAULT
#undef REVERSE_Z_COMP_DEFAULT_INV
#undef REVERSE_Z_COMP_DEFAULT_EQ
/// <summary> /// <summary>
/// Rendering quality levels. /// Rendering quality levels.
/// </summary> /// </summary>
+12 -2
View File
@@ -2,6 +2,7 @@
#include "GPUContext.h" #include "GPUContext.h"
#include "GPUDevice.h" #include "GPUDevice.h"
#include "GPUPass.h"
#include "RenderTask.h" #include "RenderTask.h"
#include "Textures/GPUTexture.h" #include "Textures/GPUTexture.h"
@@ -94,8 +95,10 @@ void GPUContext::Draw(GPUTexture* dst, GPUTexture* src)
ResetRenderTarget(); ResetRenderTarget();
const float width = (float)dst->Width(); const float width = (float)dst->Width();
const float height = (float)dst->Height(); const float height = (float)dst->Height();
auto rt = dst->View();
auto rtAction = GPUDrawPassAction::Store;
GPUDrawPass drawPass(this, ToSpan(&rt, 1), ToSpan(&rtAction, 1));
SetViewport(width, height); SetViewport(width, height);
SetRenderTarget(dst->View());
BindSR(0, src->View()); BindSR(0, src->View());
SetState(_device->GetCopyLinearPS()); SetState(_device->GetCopyLinearPS());
DrawFullscreenTriangle(); DrawFullscreenTriangle();
@@ -107,8 +110,10 @@ void GPUContext::Draw(GPUTexture* dst, GPUTextureView* src)
ResetRenderTarget(); ResetRenderTarget();
const float width = (float)dst->Width(); const float width = (float)dst->Width();
const float height = (float)dst->Height(); const float height = (float)dst->Height();
auto rt = dst->View();
auto rtAction = GPUDrawPassAction::Store;
GPUDrawPass drawPass(this, ToSpan(&rt, 1), ToSpan(&rtAction, 1));
SetViewport(width, height); SetViewport(width, height);
SetRenderTarget(dst->View());
BindSR(0, src); BindSR(0, src);
SetState(_device->GetCopyLinearPS()); SetState(_device->GetCopyLinearPS());
DrawFullscreenTriangle(); DrawFullscreenTriangle();
@@ -137,3 +142,8 @@ void GPUContext::SetResourceState(GPUResource* resource, uint64 state, int32 sub
void GPUContext::ForceRebindDescriptors() void GPUContext::ForceRebindDescriptors()
{ {
} }
void GPUContext::BeginDrawPass(GPUDrawPass& pass)
{
SetRenderTarget(pass.DepthBuffer, ToSpan(pass.RenderTargets, pass.RenderTargetsCount));
}
+22 -2
View File
@@ -14,6 +14,16 @@
#undef MemoryBarrier #undef MemoryBarrier
#endif #endif
#if REVERSE_Z
#define GPU_DEPTH_RANGE_MIN 1.0f
#define GPU_DEPTH_RANGE_MAX 0.0f
#define GPU_DEPTH_RANGE_BOUNDS(min, max) max, min
#else
#define GPU_DEPTH_RANGE_MIN 0.0f
#define GPU_DEPTH_RANGE_MAX 1.0f
#define GPU_DEPTH_RANGE_BOUNDS(min, max) min, max
#endif
class GPUConstantBuffer; class GPUConstantBuffer;
class GPUShaderProgramCS; class GPUShaderProgramCS;
class GPUBuffer; class GPUBuffer;
@@ -27,6 +37,7 @@ class GPUTextureView;
class GPUBufferView; class GPUBufferView;
class GPUVertexLayout; class GPUVertexLayout;
struct GPUPass; struct GPUPass;
struct GPUDrawPass;
enum class GPUResourceAccess; enum class GPUResourceAccess;
enum class GPUQueryType; enum class GPUQueryType;
@@ -207,7 +218,7 @@ public:
/// <param name="depthBuffer">The depth buffer to clear.</param> /// <param name="depthBuffer">The depth buffer to clear.</param>
/// <param name="depthValue">The clear depth value.</param> /// <param name="depthValue">The clear depth value.</param>
/// <param name="stencilValue">The clear stencil value.</param> /// <param name="stencilValue">The clear stencil value.</param>
API_FUNCTION() virtual void ClearDepth(GPUTextureView* depthBuffer, float depthValue = 1.0f, uint8 stencilValue = 0) = 0; API_FUNCTION() virtual void ClearDepth(GPUTextureView* depthBuffer, float depthValue = GPU_DEPTH_RANGE_MAX, uint8 stencilValue = 0) = 0;
/// <summary> /// <summary>
/// Clears an unordered access buffer with a float value. /// Clears an unordered access buffer with a float value.
@@ -627,9 +638,10 @@ public:
/// <summary> /// <summary>
/// Sets the minimum and maximum depth values for depth bounds test. /// Sets the minimum and maximum depth values for depth bounds test.
/// </summary> /// </summary>
/// <remarks>Both values must be between 0.0 and 1.0, MinDepth must be less than or equal to MaxDepth.</remarks>
/// <param name="minDepth">The minimum value for depth bound test.</param> /// <param name="minDepth">The minimum value for depth bound test.</param>
/// <param name="maxDepth">The maximum value for depth bound test.</param> /// <param name="maxDepth">The maximum value for depth bound test.</param>
API_FUNCTION() virtual void SetDepthBounds(float minDepth, float maxDepth) = 0; API_FUNCTION() virtual void SetDepthBounds(float minDepth = 0.0f, float maxDepth = 1.0f) = 0;
public: public:
/// <summary> /// <summary>
@@ -697,4 +709,12 @@ public:
virtual void OverlapUA(bool end) virtual void OverlapUA(bool end)
{ {
} }
// Begins draw pass rendering. See GPUDrawPass.
virtual void BeginDrawPass(GPUDrawPass& pass);
// Ends draw pass rendering. See GPUDrawPass.
virtual void EndDrawPass()
{
}
}; };
+42 -16
View File
@@ -160,7 +160,7 @@ GPUPipelineState::Description GPUPipelineState::Description::Default =
true, // DepthWriteEnable true, // DepthWriteEnable
true, // DepthClipEnable true, // DepthClipEnable
false, // DepthBoundsEnable false, // DepthBoundsEnable
ComparisonFunc::Less, // DepthFunc ComparisonFunc::Default, // DepthFunc
false, // StencilEnable false, // StencilEnable
0xff, // StencilReadMask 0xff, // StencilReadMask
0xff, // StencilWriteMask 0xff, // StencilWriteMask
@@ -185,7 +185,7 @@ GPUPipelineState::Description GPUPipelineState::Description::DefaultNoDepth =
false, // DepthWriteEnable false, // DepthWriteEnable
false, // DepthClipEnable false, // DepthClipEnable
false, // DepthBoundsEnable false, // DepthBoundsEnable
ComparisonFunc::Less, // DepthFunc ComparisonFunc::Default, // DepthFunc
false, // StencilEnable false, // StencilEnable
0xff, // StencilReadMask 0xff, // StencilReadMask
0xff, // StencilWriteMask 0xff, // StencilWriteMask
@@ -210,7 +210,7 @@ GPUPipelineState::Description GPUPipelineState::Description::DefaultFullscreenTr
false, // DepthWriteEnable false, // DepthWriteEnable
false, // DepthClipEnable false, // DepthClipEnable
false, // DepthBoundsEnable false, // DepthBoundsEnable
ComparisonFunc::Less, // DepthFunc ComparisonFunc::Default, // DepthFunc
false, // StencilEnable false, // StencilEnable
0xff, // StencilReadMask 0xff, // StencilReadMask
0xff, // StencilWriteMask 0xff, // StencilWriteMask
@@ -361,8 +361,7 @@ void GPUDevice::OnRequestingExit()
Engine::FatalError != FatalErrorType::GPUHang && Engine::FatalError != FatalErrorType::GPUHang &&
Engine::FatalError != FatalErrorType::GPUOutOfMemory) Engine::FatalError != FatalErrorType::GPUOutOfMemory)
return; return;
// TODO: get and log actual GPU memory used by the engine (API-specific) OnCrash();
DumpResourcesToLog();
} }
GPUDevice::GPUDevice(RendererType type, ShaderProfile profile) GPUDevice::GPUDevice(RendererType type, ShaderProfile profile)
@@ -623,6 +622,16 @@ void GPUDevice::DumpResources()
extern void ClearVertexLayoutCache(); extern void ClearVertexLayoutCache();
bool UseVSync()
{
bool vsync = Graphics::UseVSync;
if (CommandLine::Options.NoVSync.HasValue())
vsync = !CommandLine::Options.NoVSync.GetValue();
else if (CommandLine::Options.VSync.HasValue())
vsync = CommandLine::Options.VSync.GetValue();
return vsync;
}
void GPUDevice::preDispose() void GPUDevice::preDispose()
{ {
Locker.Lock(); Locker.Lock();
@@ -666,26 +675,26 @@ void GPUDevice::DrawEnd()
{ {
PROFILE_CPU_NAMED("Present"); PROFILE_CPU_NAMED("Present");
// Check if use VSync // Check if use VSync (prioritize the last window, in case of multi-window in Editor)
bool useVSync = Graphics::UseVSync; bool useVSync = UseVSync();
if (CommandLine::Options.NoVSync.HasValue()) int32 vsyncTask = -1;
useVSync = !CommandLine::Options.NoVSync.GetValue();
else if (CommandLine::Options.VSync.HasValue())
useVSync = CommandLine::Options.VSync.GetValue();
// Find index of the last rendered window task (use vsync only on the last window)
int32 lastWindowIndex = -1;
for (int32 i = RenderTask::Tasks.Count() - 1; i >= 0; i--) for (int32 i = RenderTask::Tasks.Count() - 1; i >= 0; i--)
{ {
const auto task = RenderTask::Tasks[i]; const auto task = RenderTask::Tasks[i];
if (task && task->LastUsedFrame == Engine::FrameCount && task->SwapChain && task->SwapChain->IsReady()) if (task && task->LastUsedFrame == Engine::FrameCount && task->SwapChain && task->SwapChain->IsReady())
{ {
lastWindowIndex = i; vsyncTask = i;
break; break;
} }
} }
if (_rendererType == RendererType::Vulkan && RenderTask::Tasks.Contains(_lastVSyncTask))
{
// On Vulkan, maintain the last window that was VSynced to avoid recreating swapchain too often (eg. when using context menus or tooltips)
vsyncTask = RenderTask::Tasks.Find(_lastVSyncTask);
}
// Call present on all used tasks // Call present on all used tasks
_lastVSyncTask = nullptr;
int32 presentCount = 0; int32 presentCount = 0;
bool anyVSync = false; bool anyVSync = false;
#if COMPILE_WITH_PROFILER #if COMPILE_WITH_PROFILER
@@ -697,7 +706,7 @@ void GPUDevice::DrawEnd()
if (task && task->LastUsedFrame == Engine::FrameCount && task->SwapChain && task->SwapChain->IsReady()) if (task && task->LastUsedFrame == Engine::FrameCount && task->SwapChain && task->SwapChain->IsReady())
{ {
bool vsync = useVSync; bool vsync = useVSync;
if (lastWindowIndex != i) if (vsyncTask != i)
{ {
// Perform VSync only on the last window // Perform VSync only on the last window
vsync = false; vsync = false;
@@ -712,6 +721,8 @@ void GPUDevice::DrawEnd()
anyVSync |= vsync; anyVSync |= vsync;
task->OnPresent(vsync); task->OnPresent(vsync);
if (vsync)
_lastVSyncTask = task;
presentCount++; presentCount++;
} }
} }
@@ -751,6 +762,11 @@ void GPUDevice::RenderEnd()
#endif #endif
} }
void GPUDevice::OnCrash()
{
DumpResourcesToLog();
}
GPUTasksContext* GPUDevice::CreateTasksContext() GPUTasksContext* GPUDevice::CreateTasksContext()
{ {
return New<GPUTasksContext>(this); return New<GPUTasksContext>(this);
@@ -822,6 +838,16 @@ uint64 GPUDevice::GetMemoryUsage() const
return result; return result;
} }
GPUMemoryStats GPUDevice::GetMemoryStats()
{
GPUMemoryStats stats;
stats.UsedDedicatedMemory = GetMemoryUsage();
stats.TotalDedicatedMemory = TotalGraphicsMemory;
stats.UsedSystemMemory = 0;
stats.TotalSystemMemory = 0;
return stats;
}
Array<GPUResource*> GPUDevice::GetResources() const Array<GPUResource*> GPUDevice::GetResources() const
{ {
_resourcesLock.Lock(); _resourcesLock.Lock();
+40 -1
View File
@@ -33,6 +33,34 @@ class Model;
class Material; class Material;
class MaterialBase; class MaterialBase;
/// <summary>
/// Contains information about current GPU memory usage and budget.
/// </summary>
API_STRUCT(NoDefault) struct GPUMemoryStats
{
DECLARE_SCRIPTING_TYPE_MINIMAL(GPUMemoryStats);
/// <summary>
/// Amount of used dedicated video memory in bytes. Memory local to the device, and represents the fastest available memory to the GPU.
/// </summary>
API_FIELD() uint64 UsedDedicatedMemory = 0;
/// <summary>
/// Total amount of dedicated memory budget in bytes. Memory local to the device, and represents the fastest available memory to the GPU.
/// </summary>
API_FIELD() uint64 TotalDedicatedMemory = 0;
/// <summary>
/// Amount of used system video memory in bytes. Memory non-local to the device, and may have slower performance than the dedicated/local.
/// </summary>
API_FIELD() uint64 UsedSystemMemory = 0;
/// <summary>
/// Total amount of system memory budget in bytes. Memory non-local to the device, and may have slower performance than the dedicated/local.
/// </summary>
API_FIELD() uint64 TotalSystemMemory = 0;
};
/// <summary> /// <summary>
/// Graphics device object for rendering on GPU. /// Graphics device object for rendering on GPU.
/// </summary> /// </summary>
@@ -134,6 +162,7 @@ protected:
PrivateData* _res; PrivateData* _res;
Array<GPUResource*> _resources; Array<GPUResource*> _resources;
CriticalSection _resourcesLock; CriticalSection _resourcesLock;
RenderTask* _lastVSyncTask = nullptr;
void OnRequestingExit(); void OnRequestingExit();
@@ -272,10 +301,15 @@ public:
API_PROPERTY() virtual void* GetNativePtr() const = 0; API_PROPERTY() virtual void* GetNativePtr() const = 0;
/// <summary> /// <summary>
/// Gets the amount of memory usage by all the GPU resources (in bytes). /// Gets the amount of memory usage by all the GPU resources (in bytes). Returned value is estimated based on resources created by the engine and might not be accurate. Use GPUMemoryStats for more detailed memory budget usage.
/// </summary> /// </summary>
API_PROPERTY() uint64 GetMemoryUsage() const; API_PROPERTY() uint64 GetMemoryUsage() const;
/// <summary>
/// Gets the current GPU memory stats.
/// </summary>
API_PROPERTY() virtual GPUMemoryStats GetMemoryStats();
/// <summary> /// <summary>
/// Gets the list with all active GPU resources. /// Gets the list with all active GPU resources.
/// </summary> /// </summary>
@@ -417,6 +451,11 @@ protected:
/// </summary> /// </summary>
virtual void RenderEnd(); virtual void RenderEnd();
/// <summary>
/// Called when program crashed due to GPU error (out of memory, hang, error - see Engine::FatalError). By default, it logs all GPU resources to the log. Can be used to update platform-specific stats or extract crash-info.
/// </summary>
virtual void OnCrash();
public: public:
/// <summary> /// <summary>
/// Creates the texture. /// Creates the texture.
+96 -1
View File
@@ -71,4 +71,99 @@ struct FLAXENGINE_API GPUComputePass : GPUPass
} }
}; };
// TODO: add GPUDrawPass for render targets and depth/stencil setup with optimized clear for faster drawing on tiled-GPUs (mobile) /// <summary>
/// GPU pass operations on attached render targets and depth buffer. Defines the load/store actions for each attachment to optimize GPU rendering by reducing memory bandwidth usage.
/// </summary>
enum class GPUDrawPassAction
{
// No action, the content of the render target or depth buffer is undefined. Discards the resulting value of the render pass for this attachment.
None = 0,
// Loads the existing value for this attachment into the draw pass.
Load = 1,
// Loads the clear value for this attachment into the draw pass. Clear value is provided by the GPUContext::Clear performed on the texture before pass begins.
Clear = 2,
// Stores the resulting value of the render pass for this attachment.
Store = 4,
// Resolves the resulting MSAA value and stores final value into the attachment.
ResolveMultisample = 8,
// Mask of flags allowed by load operation (reading data from attachment).
LoadMask = None | Load | Clear,
// Mask of flags allowed by store operation (writing data to attachment).
StoreMask = None | Store | ResolveMultisample,
// Loads the existing value for this attachment into the draw pass and stores the resulting value of the render pass for this attachment.
LoadStore = Load | Store,
// Loads the clear value for this attachment into the draw pass and stores the resulting value of the render pass for this attachment.
ClearStore = Clear | Store,
};
/// <summary>
/// GPU pass that explicitly defines render targets and depth buffer within a rendering pass. Can be used to optimize GPU rendering on tiled GPUs with manual control over attachment operations (load, store, clear, discard, etc.) that reduce memory bandwidth usage.
/// </summary>
/// <remarks>Draw Pass discards any render targets or depth buffer bound to the context (reduces state-tracking).</remarks>
struct FLAXENGINE_API GPUDrawPass : GPUPass
{
GPUTextureView* DepthBuffer;
GPUTextureView** RenderTargets;
GPUDrawPassAction* RenderTargetsActions;
int32 RenderTargetsCount;
GPUDrawPassAction DepthAction;
GPUDrawPass(GPUContext* context, Span<GPUTextureView*> renderTargets)
: GPUPass(context)
, DepthBuffer(nullptr)
, RenderTargets(renderTargets.Get())
, RenderTargetsActions(nullptr)
, RenderTargetsCount(renderTargets.Length())
, DepthAction(GPUDrawPassAction::None)
{
Context->BeginDrawPass(*this);
}
GPUDrawPass(GPUContext* context, GPUTextureView* depthBuffer, Span<GPUTextureView*> renderTargets)
: GPUPass(context)
, DepthBuffer(depthBuffer)
, RenderTargets(renderTargets.Get())
, RenderTargetsActions(nullptr)
, RenderTargetsCount(renderTargets.Length())
, DepthAction(GPUDrawPassAction::LoadStore)
{
Context->BeginDrawPass(*this);
}
GPUDrawPass(GPUContext* context, GPUTextureView* depthBuffer, GPUDrawPassAction depthAction, Span<GPUTextureView*> renderTargets, Span<GPUDrawPassAction> renderTargetsActions)
: GPUPass(context)
, DepthBuffer(depthBuffer)
, RenderTargets(renderTargets.Get())
, RenderTargetsActions(renderTargetsActions.Get())
, RenderTargetsCount(renderTargets.Length())
, DepthAction(depthAction)
{
ASSERT_LOW_LAYER(renderTargets.Length() == renderTargetsActions.Length());
Context->BeginDrawPass(*this);
}
GPUDrawPass(GPUContext* context, Span<GPUTextureView*> renderTargets, Span<GPUDrawPassAction> renderTargetsActions)
: GPUPass(context)
, DepthBuffer(nullptr)
, RenderTargets(renderTargets.Get())
, RenderTargetsActions(renderTargetsActions.Get())
, RenderTargetsCount(renderTargets.Length())
, DepthAction(GPUDrawPassAction::None)
{
ASSERT_LOW_LAYER(renderTargets.Length() == renderTargetsActions.Length());
Context->BeginDrawPass(*this);
}
~GPUDrawPass()
{
Context->EndDrawPass();
}
};
@@ -10,6 +10,7 @@ template<int Size>
class GPUPipelineStatePermutations class GPUPipelineStatePermutations
{ {
public: public:
enum { StaticSize = Size };
GPUPipelineState* States[Size]; GPUPipelineState* States[Size];
public: public:
@@ -97,13 +98,13 @@ public:
} }
public: public:
bool Create(GPUPipelineState::Description& desc, GPUShader* shader, const StringAnsiView& psName) bool Create(GPUPipelineState::Description& desc, GPUShader* shader, const StringAnsiView& psName, int32 permutationOffset = 0)
{ {
for (int i = 0; i < Size; i++) for (int i = 0; i < Size; i++)
{ {
ASSERT(Base::States[i]); ASSERT(Base::States[i]);
desc.PS = shader->GetPS(psName, i); desc.PS = shader->GetPS(psName, i + permutationOffset);
if (Base::States[i]->Init(desc)) if (Base::States[i]->Init(desc))
return true; return true;
} }
+1
View File
@@ -32,6 +32,7 @@ bool Graphics::SpreadWorkload = true;
#if !BUILD_RELEASE || USE_EDITOR #if !BUILD_RELEASE || USE_EDITOR
float Graphics::TestValue = 0.0f; float Graphics::TestValue = 0.0f;
#endif #endif
float Graphics::MotionVectors::MinObjectScreenSize = 0.02f;
float Graphics::Shadows::MinObjectPixelSize = 2.0f; float Graphics::Shadows::MinObjectPixelSize = 2.0f;
bool Graphics::PostProcessing::ColorGradingVolumeLUT = true; bool Graphics::PostProcessing::ColorGradingVolumeLUT = true;
+10 -1
View File
@@ -39,7 +39,7 @@ public:
API_FIELD() static Quality VolumetricFogQuality; API_FIELD() static Quality VolumetricFogQuality;
/// <summary> /// <summary>
/// The shadows quality. Available values are: Low, Medium, High, Ultra (or 0, 1, 2, 3). /// The shadows filtering quality (sampling). Available values are: Low, Medium, High, Ultra (or 0, 1, 2, 3).
/// </summary> /// </summary>
API_FIELD() static Quality ShadowsQuality; API_FIELD() static Quality ShadowsQuality;
@@ -110,6 +110,15 @@ public:
API_FIELD() static float MinObjectPixelSize; API_FIELD() static float MinObjectPixelSize;
}; };
// Motion Vectors rendering configuration.
API_CLASS(Static, Attributes="DebugCommand") class FLAXENGINE_API MotionVectors
{
DECLARE_SCRIPTING_TYPE_MINIMAL(MotionVectors);
// The minimum screen size of objects to draw motion vectors. Improves performance by skipping too small objects (eg. sub-pixel) from rendering motion vectors.
API_FIELD() static float MinObjectScreenSize;
};
// Post Processing effects rendering configuration. // Post Processing effects rendering configuration.
API_CLASS(Static, Attributes="DebugCommand") class FLAXENGINE_API PostProcessing API_CLASS(Static, Attributes="DebugCommand") class FLAXENGINE_API PostProcessing
{ {
@@ -26,10 +26,10 @@ bool DeferredMaterialShader::CanUseLightmap() const
return true; return true;
} }
bool DeferredMaterialShader::CanUseInstancing(InstancingHandler& handler) const bool DeferredMaterialShader::CanUseInstancing(const RenderContext& renderContext, InstancingHandler& handler) const
{ {
handler = { SurfaceDrawCallHandler::GetHash, SurfaceDrawCallHandler::CanBatch, }; handler = { SurfaceDrawCallHandler::GetHash, SurfaceDrawCallHandler::CanBatch, };
return _instanced; return _instanced || renderContext.View.Pass == DrawPass::Depth;
} }
void DeferredMaterialShader::Bind(BindParameters& params) void DeferredMaterialShader::Bind(BindParameters& params)
@@ -182,7 +182,7 @@ bool DeferredMaterialShader::Load()
// Motion Vectors pass // Motion Vectors pass
psDesc.DepthWriteEnable = false; psDesc.DepthWriteEnable = false;
psDesc.DepthEnable = true; psDesc.DepthEnable = true;
psDesc.DepthFunc = ComparisonFunc::LessEqual; psDesc.DepthFunc = ComparisonFunc::DefaultEqual;
psDesc.VS = _shader->GetVS("VS"); psDesc.VS = _shader->GetVS("VS");
psDesc.PS = _shader->GetPS("PS_MotionVectors"); psDesc.PS = _shader->GetPS("PS_MotionVectors");
_cache.MotionVectors.Init(psDesc); _cache.MotionVectors.Init(psDesc);
@@ -200,7 +200,7 @@ bool DeferredMaterialShader::Load()
psDesc.DepthClipEnable = false; psDesc.DepthClipEnable = false;
psDesc.DepthWriteEnable = true; psDesc.DepthWriteEnable = true;
psDesc.DepthEnable = true; psDesc.DepthEnable = true;
psDesc.DepthFunc = ComparisonFunc::Less; psDesc.DepthFunc = ComparisonFunc::Default;
psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::None; psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::None;
psDesc.HS = nullptr; psDesc.HS = nullptr;
psDesc.DS = nullptr; psDesc.DS = nullptr;
@@ -77,7 +77,7 @@ public:
// [MaterialShader] // [MaterialShader]
DrawPass GetDrawModes() const override; DrawPass GetDrawModes() const override;
bool CanUseLightmap() const override; bool CanUseLightmap() const override;
bool CanUseInstancing(InstancingHandler& handler) const override; bool CanUseInstancing(const RenderContext& renderContext, InstancingHandler& handler) const override;
void Bind(BindParameters& params) override; void Bind(BindParameters& params) override;
void Unload() override; void Unload() override;
@@ -178,7 +178,11 @@ bool DeformableMaterialShader::Load()
psDesc.DepthClipEnable = false; psDesc.DepthClipEnable = false;
psDesc.DepthWriteEnable = true; psDesc.DepthWriteEnable = true;
psDesc.DepthEnable = true; psDesc.DepthEnable = true;
#if REVERSE_Z
psDesc.DepthFunc = ComparisonFunc::Greater;
#else
psDesc.DepthFunc = ComparisonFunc::Less; psDesc.DepthFunc = ComparisonFunc::Less;
#endif
psDesc.HS = nullptr; psDesc.HS = nullptr;
psDesc.DS = nullptr; psDesc.DS = nullptr;
_cache.Depth.Init(psDesc); _cache.Depth.Init(psDesc);
@@ -22,10 +22,11 @@ DrawPass ForwardMaterialShader::GetDrawModes() const
return _drawModes; return _drawModes;
} }
bool ForwardMaterialShader::CanUseInstancing(InstancingHandler& handler) const bool ForwardMaterialShader::CanUseInstancing(const RenderContext& renderContext, InstancingHandler& handler) const
{ {
handler = { SurfaceDrawCallHandler::GetHash, SurfaceDrawCallHandler::CanBatch, }; handler = { SurfaceDrawCallHandler::GetHash, SurfaceDrawCallHandler::CanBatch, };
return false; // TODO: support instancing when using ForwardShadingFeature // TODO: support instancing when using ForwardShadingFeature
return renderContext.View.Pass == DrawPass::Depth;
} }
void ForwardMaterialShader::Bind(BindParameters& params) void ForwardMaterialShader::Bind(BindParameters& params)
@@ -184,7 +185,7 @@ bool ForwardMaterialShader::Load()
psDesc.DepthClipEnable = false; psDesc.DepthClipEnable = false;
psDesc.DepthWriteEnable = true; psDesc.DepthWriteEnable = true;
psDesc.DepthEnable = true; psDesc.DepthEnable = true;
psDesc.DepthFunc = ComparisonFunc::Less; psDesc.DepthFunc = ComparisonFunc::Default;
psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::None; psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::None;
psDesc.HS = nullptr; psDesc.HS = nullptr;
psDesc.DS = nullptr; psDesc.DS = nullptr;
@@ -71,7 +71,7 @@ public:
public: public:
// [MaterialShader] // [MaterialShader]
DrawPass GetDrawModes() const override; DrawPass GetDrawModes() const override;
bool CanUseInstancing(InstancingHandler& handler) const override; bool CanUseInstancing(const RenderContext& renderContext, InstancingHandler& handler) const override;
void Bind(BindParameters& params) override; void Bind(BindParameters& params) override;
void Unload() override; void Unload() override;
+2 -1
View File
@@ -126,9 +126,10 @@ public:
/// <summary> /// <summary>
/// Returns true if material can use draw calls instancing. /// Returns true if material can use draw calls instancing.
/// </summary> /// </summary>
/// <param name="renderContext">The rendering context.</param>
/// <param name="handler">The output data for the instancing handling used to hash, batch and write draw calls. Valid only when function returns true.</param> /// <param name="handler">The output data for the instancing handling used to hash, batch and write draw calls. Valid only when function returns true.</param>
/// <returns>True if can use instancing, otherwise false.</returns> /// <returns>True if can use instancing, otherwise false.</returns>
virtual bool CanUseInstancing(InstancingHandler& handler) const virtual bool CanUseInstancing(const RenderContext& renderContext, InstancingHandler& handler) const
{ {
#if BUILD_DEBUG #if BUILD_DEBUG
handler = { nullptr, nullptr }; handler = { nullptr, nullptr };
@@ -78,7 +78,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
for (int32 i = 0; i < cache->EnvironmentProbes.Count(); i++) for (int32 i = 0; i < cache->EnvironmentProbes.Count(); i++)
{ {
const RenderEnvironmentProbeData& probe = cache->EnvironmentProbes.Get()[i]; const RenderEnvironmentProbeData& probe = cache->EnvironmentProbes.Get()[i];
const float sphereCullDistance = objectBounds.Radius + probe.Radius; const float sphereCullDistance = (float)objectBounds.Radius + probe.Radius;
const float distanceSq = Float3::DistanceSquared(probe.Position, objectBounds.Center); const float distanceSq = Float3::DistanceSquared(probe.Position, objectBounds.Center);
if (distanceSq <= sphereCullDistance * sphereCullDistance && distanceSq < minDistanceSq) if (distanceSq <= sphereCullDistance * sphereCullDistance && distanceSq < minDistanceSq)
{ {
@@ -189,7 +189,7 @@ bool TerrainMaterialShader::Load()
psDesc.DepthClipEnable = false; psDesc.DepthClipEnable = false;
psDesc.DepthWriteEnable = true; psDesc.DepthWriteEnable = true;
psDesc.DepthEnable = true; psDesc.DepthEnable = true;
psDesc.DepthFunc = ComparisonFunc::Less; psDesc.DepthFunc = ComparisonFunc::Default;
psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::None; psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::None;
psDesc.HS = nullptr; psDesc.HS = nullptr;
psDesc.DS = nullptr; psDesc.DS = nullptr;
+2 -2
View File
@@ -305,7 +305,7 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float
drawCall.Surface.GeometrySize = _box.GetSize(); drawCall.Surface.GeometrySize = _box.GetSize();
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld; drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr; drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr;
drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Rectangle::Empty; drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Half4::Zero;
drawCall.Surface.LODDitherFactor = lodDitherFactor; drawCall.Surface.LODDitherFactor = lodDitherFactor;
drawCall.PerInstanceRandom = info.PerInstanceRandom; drawCall.PerInstanceRandom = info.PerInstanceRandom;
drawCall.StencilValue = info.StencilValue; drawCall.StencilValue = info.StencilValue;
@@ -368,7 +368,7 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in
drawCall.Surface.GeometrySize = _box.GetSize(); drawCall.Surface.GeometrySize = _box.GetSize();
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld; drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr; drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr;
drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Rectangle::Empty; drawCall.Surface.LightmapUVsArea = info.LightmapUVs ? *info.LightmapUVs : Half4::Zero;
drawCall.Surface.LODDitherFactor = lodDitherFactor; drawCall.Surface.LODDitherFactor = lodDitherFactor;
drawCall.PerInstanceRandom = info.PerInstanceRandom; drawCall.PerInstanceRandom = info.PerInstanceRandom;
drawCall.StencilValue = info.StencilValue; drawCall.StencilValue = info.StencilValue;
+1 -1
View File
@@ -375,7 +375,7 @@ public:
/// <summary> /// <summary>
/// The lightmap UVs. /// The lightmap UVs.
/// </summary> /// </summary>
const Rectangle* LightmapUVs; const Half4* LightmapUVs;
}; };
}; };
+5 -5
View File
@@ -382,7 +382,7 @@ API_STRUCT() struct FLAXENGINE_API GlobalIlluminationSettings : ISerializable
/// <summary> /// <summary>
/// Draw distance of the Global Illumination effect. Scene outside the range will use fallback irradiance. /// Draw distance of the Global Illumination effect. Scene outside the range will use fallback irradiance.
/// </summary> /// </summary>
API_FIELD(Attributes="EditorOrder(30), Limit(1000), PostProcessSetting((int)GlobalIlluminationSettingsOverride.Distance)") API_FIELD(Attributes="EditorOrder(30), Limit(1000), PostProcessSetting((int)GlobalIlluminationSettingsOverride.Distance), ValueCategory(Utils.ValueCategory.Distance)")
float Distance = 20000.0f; float Distance = 20000.0f;
/// <summary> /// <summary>
@@ -1819,17 +1819,17 @@ API_STRUCT() struct FLAXENGINE_API ScreenSpaceReflectionsSettings : ISerializabl
/// <summary> /// <summary>
/// The effect fade out end distance from camera (in world units). /// The effect fade out end distance from camera (in world units).
/// </summary> /// </summary>
API_FIELD(Attributes="Limit(0), EditorOrder(31), PostProcessSetting((int)ScreenSpaceReflectionsSettingsOverride.FadeOutDistance)") API_FIELD(Attributes="Limit(0), EditorOrder(31), PostProcessSetting((int)ScreenSpaceReflectionsSettingsOverride.FadeOutDistance), ValueCategory(Utils.ValueCategory.Distance)")
float FadeOutDistance = 5000.0f; float FadeOutDistance = 5000.0f;
/// <summary> /// <summary>
/// The effect fade distance (in world units). Defines the size of the effect fade from fully visible to fully invisible at FadeOutDistance. /// The effect fade distance (in world units). Defines the size of the effect fade from fully visible to fully invisible at FadeOutDistance.
/// </summary> /// </summary>
API_FIELD(Attributes="Limit(0), EditorOrder(32), PostProcessSetting((int)ScreenSpaceReflectionsSettingsOverride.FadeDistance)") API_FIELD(Attributes="Limit(0), EditorOrder(32), PostProcessSetting((int)ScreenSpaceReflectionsSettingsOverride.FadeDistance), ValueCategory(Utils.ValueCategory.Distance)")
float FadeDistance = 500.0f; float FadeDistance = 500.0f;
/// <summary> /// <summary>
/// "The input color buffer downscale mode that uses blurred mipmaps when resolving the reflection color. Produces more realistic results by blurring distant parts of reflections in rough (low-gloss) materials. It also improves performance on most platforms but uses more memory. /// The input color buffer downscale mode that uses blurred mipmaps when resolving the reflection color. Produces more realistic results by blurring distant parts of reflections in rough (low-gloss) materials. It also improves performance on most platforms but uses more memory.
/// </summary> /// </summary>
API_FIELD(Attributes="EditorOrder(40), PostProcessSetting((int)ScreenSpaceReflectionsSettingsOverride.UseColorBufferMips), EditorDisplay(null, \"Use Color Buffer Mips\")") API_FIELD(Attributes="EditorOrder(40), PostProcessSetting((int)ScreenSpaceReflectionsSettingsOverride.UseColorBufferMips), EditorDisplay(null, \"Use Color Buffer Mips\")")
bool UseColorBufferMips = true; bool UseColorBufferMips = true;
@@ -1953,7 +1953,7 @@ API_STRUCT() struct FLAXENGINE_API AntiAliasingSettings : ISerializable
/// The anti-aliasing effect mode. /// The anti-aliasing effect mode.
/// </summary> /// </summary>
API_FIELD(Attributes="EditorOrder(0), PostProcessSetting((int)AntiAliasingSettingsOverride.Mode)") API_FIELD(Attributes="EditorOrder(0), PostProcessSetting((int)AntiAliasingSettingsOverride.Mode)")
AntialiasingMode Mode = AntialiasingMode::FastApproximateAntialiasing; AntialiasingMode Mode = AntialiasingMode::TemporalAntialiasing;
/// <summary> /// <summary>
/// The diameter (in texels) inside which jitter samples are spread. Smaller values result in crisper but more aliased output, while larger values result in more stable but blurrier output. /// The diameter (in texels) inside which jitter samples are spread. Smaller values result in crisper but more aliased output, while larger values result in more stable but blurrier output.
+44 -2
View File
@@ -684,6 +684,20 @@ float RenderTools::TemporalHalton(int32 index, int32 base)
Float2 RenderTools::GetDepthBounds(const RenderView& view, const Float3& nearPoint, const Float3& farPoint) Float2 RenderTools::GetDepthBounds(const RenderView& view, const Float3& nearPoint, const Float3& farPoint)
{ {
#if REVERSE_Z
Float3 viewNearPoint = Float3::Transform(nearPoint, view.View);
Float3 viewFarPoint = Float3::Transform(farPoint, view.View);
viewNearPoint.Z = Math::Max(viewNearPoint.Z, view.Near);
viewFarPoint.Z = Math::Min(viewFarPoint.Z, view.Far);
Float4 clipNearPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, viewNearPoint.Z, 1));
Float4 clipFarPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, viewFarPoint.Z, 1));
clipNearPoint /= clipNearPoint.W;
clipFarPoint /= clipFarPoint.W;
return Float2(clipNearPoint.Z, clipFarPoint.Z);
#else
// Point closest the view // Point closest the view
const Float4 nearPointClip = Matrix::TransformPosition(view.ViewProjection(), Float4(nearPoint, 1.0)); const Float4 nearPointClip = Matrix::TransformPosition(view.ViewProjection(), Float4(nearPoint, 1.0));
float nearDepth = nearPointClip.Z / nearPointClip.W; float nearDepth = nearPointClip.Z / nearPointClip.W;
@@ -700,8 +714,8 @@ Float2 RenderTools::GetDepthBounds(const RenderView& view, const Float3& nearPoi
nearDepth = Math::Clamp(nearDepth, 0.0f, 1.0f); nearDepth = Math::Clamp(nearDepth, 0.0f, 1.0f);
farDepth = Math::Clamp(farDepth, nearDepth, 1.0f); farDepth = Math::Clamp(farDepth, nearDepth, 1.0f);
// TODO: swap depths when using reversed depth buffer
return Float2(nearDepth, farDepth); return Float2(nearDepth, farDepth);
#endif
} }
Float2 RenderTools::GetDepthBounds(const RenderView& view, const BoundingSphere& bounds) Float2 RenderTools::GetDepthBounds(const RenderView& view, const BoundingSphere& bounds)
@@ -713,6 +727,24 @@ Float2 RenderTools::GetDepthBounds(const RenderView& view, const BoundingSphere&
Float2 RenderTools::GetDepthBounds(const RenderView& view, const Span<Float3>& points) Float2 RenderTools::GetDepthBounds(const RenderView& view, const Span<Float3>& points)
{ {
#if REVERSE_Z
// Find min and max view depth range for list of points
float nearDepth = view.Far, farDepth = view.Near;
for (int32 i = 0; i < points.Length(); i++)
{
const Float3 viewPoint = Float3::Transform(points[i], view.View);
nearDepth = Math::Min(nearDepth, viewPoint.Z);
farDepth = Math::Max(farDepth, viewPoint.Z);
}
// Project end points to clip space
Float4 clipNearPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, nearDepth, 1));
Float4 clipFarPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, farDepth, 1));
clipNearPoint /= clipNearPoint.W;
clipFarPoint /= clipFarPoint.W;
return Float2(clipNearPoint.Z, clipFarPoint.Z);
#else
// Find min and max depth range for list of points // Find min and max depth range for list of points
float nearDepth = 1.0f, farDepth = 0.0f; float nearDepth = 1.0f, farDepth = 0.0f;
for (int32 i = 0; i < points.Length(); i++) for (int32 i = 0; i < points.Length(); i++)
@@ -729,8 +761,8 @@ Float2 RenderTools::GetDepthBounds(const RenderView& view, const Span<Float3>& p
nearDepth = Math::Clamp(nearDepth, 0.0f, 1.0f); nearDepth = Math::Clamp(nearDepth, 0.0f, 1.0f);
farDepth = Math::Clamp(farDepth, nearDepth, 1.0f); farDepth = Math::Clamp(farDepth, nearDepth, 1.0f);
// TODO: swap depths when using reversed depth buffer
return Float2(nearDepth, farDepth); return Float2(nearDepth, farDepth);
#endif
} }
Float2 RenderTools::GetDepthBounds(const RenderView& view, const BoundingBox& bounds) Float2 RenderTools::GetDepthBounds(const RenderView& view, const BoundingBox& bounds)
@@ -749,11 +781,21 @@ Float2 RenderTools::GetDepthBounds(const RenderView& view, const OrientedBoundin
float RenderTools::GetDepthBounds(const RenderView& view, const Float3& point, bool near) float RenderTools::GetDepthBounds(const RenderView& view, const Float3& point, bool near)
{ {
#if REVERSE_Z
Float3 viewPoint = Float3::Transform(point, view.View);
viewPoint.Z = Math::Clamp(viewPoint.Z, view.Near, view.Far);
Float4 clipPoint = Matrix::TransformPosition(view.Projection, Float4(0, 0, viewPoint.Z, 1));
clipPoint /= clipPoint.W;
return clipPoint.Z;
#else
const Float4 pointClip = Matrix::TransformPosition(view.ViewProjection(), Float4(point, 1.0)); const Float4 pointClip = Matrix::TransformPosition(view.ViewProjection(), Float4(point, 1.0));
float depth = pointClip.Z / pointClip.W; float depth = pointClip.Z / pointClip.W;
if (depth >= 1.0f) if (depth >= 1.0f)
depth = near ? 0.0f : 1.0f; // Point is behind the view depth = near ? 0.0f : 1.0f; // Point is behind the view
return Math::Clamp(depth, 0.0f, 1.0f); return Math::Clamp(depth, 0.0f, 1.0f);
#endif
} }
float RenderTools::GetDepthBounds(const RenderView& view, float viewDistance, bool near) float RenderTools::GetDepthBounds(const RenderView& view, float viewDistance, bool near)
+6 -1
View File
@@ -173,7 +173,12 @@ public:
static Float2 GetDepthBounds(const RenderView& view, const OrientedBoundingBox& bounds); static Float2 GetDepthBounds(const RenderView& view, const OrientedBoundingBox& bounds);
static float GetDepthBounds(const RenderView& view, const Float3& point, bool near); static float GetDepthBounds(const RenderView& view, const Float3& point, bool near);
static float GetDepthBounds(const RenderView& view, float viewDistance, bool near); static float GetDepthBounds(const RenderView& view, float viewDistance, bool near);
static constexpr float DepthBoundMaxBackground = 1.0f - 0.0000001f; // Skip background/sky pixels from shading // Skip background/sky pixels from shading
#if REVERSE_Z
static constexpr float DepthBoundMaxBackground = 0.0000001f;
#else
static constexpr float DepthBoundMaxBackground = 1.0f - 0.0000001f;
#endif
// Calculates error for a given render target format to reduce floating-point precision artifacts via QuantizeColor (from Noise.hlsl). // Calculates error for a given render target format to reduce floating-point precision artifacts via QuantizeColor (from Noise.hlsl).
static Float3 GetColorQuantizationError(PixelFormat format); static Float3 GetColorQuantizationError(PixelFormat format);
+5 -1
View File
@@ -65,7 +65,11 @@ void RenderView::Prepare(RenderContext& renderContext)
void RenderView::PrepareCache(const RenderContext& renderContext, float width, float height, const Float2& temporalAAJitter, const RenderView* mainView) void RenderView::PrepareCache(const RenderContext& renderContext, float width, float height, const Float2& temporalAAJitter, const RenderView* mainView)
{ {
// The same format used by the Flax common shaders and postFx materials // The same format used by the Flax common shaders and postFx materials
ViewInfo = Float4(1.0f / Projection.M11, 1.0f / Projection.M22, Far / (Far - Near), (-Far * Near) / (Far - Near) / Far); #if REVERSE_Z
ViewInfo = Float4(1.0f / Projection.M11, 1.0f / Projection.M22, -Near / (Far - Near), (Far * Near) / (Far - Near) / Far);
#else
ViewInfo = Float4(1.0f / Projection.M11, 1.0f / Projection.M22, Far / (Far - Near), -(Far * Near) / (Far - Near) / Far);
#endif
ScreenSize = Float4(width, height, 1.0f / width, 1.0f / height); ScreenSize = Float4(width, height, 1.0f / width, 1.0f / height);
TemporalAAJitter.Z = TemporalAAJitter.X; TemporalAAJitter.Z = TemporalAAJitter.X;
@@ -188,17 +188,41 @@ bool ShaderCacheManagerService::Init()
int32 ShaderCacheVersion = -1; int32 ShaderCacheVersion = -1;
int32 MaterialGraphVersion = -1; int32 MaterialGraphVersion = -1;
int32 ParticleGraphVersion = -1; int32 ParticleGraphVersion = -1;
bool ShaderDebug; union
bool ShaderProfile; {
}; struct
CacheVersion cacheVersion; {
const String cacheVerFile = rootDir / TEXT("CacheVersion"); uint32 ShaderDebug : 1;
uint32 ShaderProfile : 1;
uint32 ReverseZ : 1;
};
uint32 Flags;
};
CacheVersion()
{
Platform::MemoryClear(this, sizeof(*this));
}
void InitDefault()
{
EngineVersion = FLAXENGINE_VERSION_BUILD;
ShaderCacheVersion = GPU_SHADER_CACHE_VERSION;
MaterialGraphVersion = MATERIAL_GRAPH_VERSION;
ParticleGraphVersion = PARTICLE_GPU_GRAPH_VERSION;
Flags = 0;
#if USE_EDITOR #if USE_EDITOR
const bool shaderDebug = CommandLine::Options.ShaderDebug.IsTrue(); ShaderDebug = CommandLine::Options.ShaderDebug.IsTrue();
const bool shaderProfile = CommandLine::Options.ShaderProfile.IsTrue(); ShaderProfile = CommandLine::Options.ShaderProfile.IsTrue();
#else
const bool shaderDebug = false;
#endif #endif
#if REVERSE_Z
ReverseZ = true;
#endif
}
};
CacheVersion cacheVersion, cacheVersionDefault;
cacheVersionDefault.InitDefault();
const String cacheVerFile = rootDir / TEXT("CacheVersion");
if (FileSystem::FileExists(cacheVerFile)) if (FileSystem::FileExists(cacheVerFile))
{ {
if (File::ReadAllBytes(cacheVerFile, (byte*)&cacheVersion, sizeof(cacheVersion))) if (File::ReadAllBytes(cacheVerFile, (byte*)&cacheVersion, sizeof(cacheVersion)))
@@ -207,34 +231,25 @@ bool ShaderCacheManagerService::Init()
LOG(Warning, "Failed to read the shaders cache database version file."); LOG(Warning, "Failed to read the shaders cache database version file.");
} }
} }
if (cacheVersion.EngineVersion != FLAXENGINE_VERSION_BUILD if (cacheVersion.EngineVersion != cacheVersionDefault.EngineVersion
|| cacheVersion.ShaderCacheVersion != GPU_SHADER_CACHE_VERSION || cacheVersion.ShaderCacheVersion != cacheVersionDefault.ShaderCacheVersion
|| cacheVersion.MaterialGraphVersion != MATERIAL_GRAPH_VERSION || cacheVersion.MaterialGraphVersion != cacheVersionDefault.MaterialGraphVersion
|| cacheVersion.ParticleGraphVersion != PARTICLE_GPU_GRAPH_VERSION || cacheVersion.ParticleGraphVersion != cacheVersionDefault.ParticleGraphVersion
|| cacheVersion.ShaderDebug != shaderDebug || cacheVersion.Flags != cacheVersionDefault.Flags
|| cacheVersion.ShaderProfile != shaderProfile
) )
{ {
LOG(Warning, "Shaders cache database is invalid. Performing reset."); LOG(Warning, "Shaders cache database is invalid. Performing reset.");
if (FileSystem::DirectoryExists(rootDir) && FileSystem::DeleteDirectory(rootDir)) if (FileSystem::DirectoryExists(rootDir) && FileSystem::DeleteDirectory(rootDir))
{ {
LOG(Warning, "Failed to reset the shaders cache database."); LOG(Warning, "Failed to reset shaders cache database.");
} }
if (FileSystem::CreateDirectory(rootDir)) if (FileSystem::CreateDirectory(rootDir))
{ {
LOG(Error, "Failed to createe the shaders cache database directory."); LOG(Error, "Failed to create shaders cache database directory.");
} }
if (File::WriteAllBytes(cacheVerFile, (byte*)&cacheVersionDefault, sizeof(cacheVersionDefault)))
cacheVersion.EngineVersion = FLAXENGINE_VERSION_BUILD;
cacheVersion.ShaderCacheVersion = GPU_SHADER_CACHE_VERSION;
cacheVersion.MaterialGraphVersion = MATERIAL_GRAPH_VERSION;
cacheVersion.ParticleGraphVersion = PARTICLE_GPU_GRAPH_VERSION;
cacheVersion.ShaderDebug = shaderDebug;
cacheVersion.ShaderProfile = shaderProfile;
if (File::WriteAllBytes(cacheVerFile, (byte*)&cacheVersion, sizeof(cacheVersion)))
{ {
LOG(Error, "Failed to create the shaders cache database version file."); LOG(Error, "Failed to create shaders cache database version file.");
} }
} }
@@ -47,6 +47,8 @@ API_ENUM() enum class GPUSamplerCompareFunction
Never = 0, Never = 0,
/// <summary>If the source data is less than the destination data, the comparison passes.</summary> /// <summary>If the source data is less than the destination data, the comparison passes.</summary>
Less = 1, Less = 1,
/// <summary>If the source data is greater than the destination data, the comparison passes.</summary>
Greater = 2,
API_ENUM(Attributes="HideInEditor") MAX API_ENUM(Attributes="HideInEditor") MAX
}; };
+1 -1
View File
@@ -535,7 +535,7 @@ public:
/// </summary> /// </summary>
/// <param name="result">The destination texture data container.</param> /// <param name="result">The destination texture data container.</param>
/// <returns>True if cannot download data, otherwise false.</returns> /// <returns>True if cannot download data, otherwise false.</returns>
API_FUNCTION() bool DownloadData(TextureData& result); API_FUNCTION() bool DownloadData(API_PARAM(Out) TextureData& result);
/// <summary> /// <summary>
/// Creates GPU async task that will gather texture data from the GPU. /// Creates GPU async task that will gather texture data from the GPU.
@@ -101,6 +101,30 @@ bool TextureMipData::GetPixels(Array<Color32>& pixels, int32 width, int32 height
src += srcRowSize; src += srcRowSize;
} }
} }
if (PixelFormatExtensions::IsBGRAOrder(format))
{
// BGRA -> RGBA
for (int32 y = 0; y < height; y++)
{
for (int32 x = 0; x < width; x++)
{
auto& color = *((Color32*)(dst + y * RowPitch + x * sizeof(Color32)));
color = Color32(color.B, color.G, color.R, color.A);
}
}
}
if (PixelFormatExtensions::IsSRGB(format))
{
// sRGB -> Linear
for (int32 y = 0; y < height; y++)
{
for (int32 x = 0; x < width; x++)
{
auto& color = *((Color32*)(dst + y * RowPitch + x * sizeof(Color32)));
color = Color32(Color::SrgbToLinear(Color(color)));
}
}
}
break; break;
default: default:
{ {
@@ -118,7 +142,10 @@ bool TextureMipData::GetPixels(Array<Color32>& pixels, int32 width, int32 height
} }
return false; return false;
} }
LOG(Error, "Unsupported texture data format {0}.", ScriptingEnum::ToString(format)); if (PixelFormatExtensions::IsCompressed(format))
LOG(Error, "Unsupported texture data format {0}. Compressed texture data cannot be accessed directly without decompressing first.", ScriptingEnum::ToString(format));
else
LOG(Error, "Unsupported texture data format {0}.", ScriptingEnum::ToString(format));
return true; return true;
} }
} }
@@ -221,7 +248,7 @@ void TextureData::Clear()
Items.Resize(0, false); Items.Resize(0, false);
} }
bool TextureData::GetPixels(Array<Color32>& pixels, int32 mipIndex, int32 arrayIndex) bool TextureData::GetPixels(Array<Color32>& pixels, int32 mipIndex, int32 arrayIndex) const
{ {
if (Items.IsValidIndex(arrayIndex) && Items.Get()[arrayIndex].Mips.IsValidIndex(mipIndex)) if (Items.IsValidIndex(arrayIndex) && Items.Get()[arrayIndex].Mips.IsValidIndex(mipIndex))
{ {
@@ -232,7 +259,7 @@ bool TextureData::GetPixels(Array<Color32>& pixels, int32 mipIndex, int32 arrayI
return true; return true;
} }
bool TextureData::GetPixels(Array<Color>& pixels, int32 mipIndex, int32 arrayIndex) bool TextureData::GetPixels(Array<Color>& pixels, int32 mipIndex, int32 arrayIndex) const
{ {
if (Items.IsValidIndex(arrayIndex) && Items.Get()[arrayIndex].Mips.IsValidIndex(mipIndex)) if (Items.IsValidIndex(arrayIndex) && Items.Get()[arrayIndex].Mips.IsValidIndex(mipIndex))
{ {
@@ -726,6 +753,17 @@ bool TextureBase::InitCSharp(void* ptr)
return Init(initData); return Init(initData);
} }
TextureData* TextureBase::GetTextureData()
{
auto result = New<TextureData>();
if (GetTextureData(*result, false))
{
Delete(result);
result = nullptr;
}
return result;
}
#endif #endif
uint64 TextureBase::GetMemoryUsage() const uint64 TextureBase::GetMemoryUsage() const
+10 -14
View File
@@ -5,20 +5,6 @@ using System.Runtime.InteropServices;
namespace FlaxEngine namespace FlaxEngine
{ {
partial class GPUTexture
{
/// <summary>
/// Downloads the texture data to be accessible from CPU. For frequent access, use staging textures, otherwise current thread will be stalled to wait for the GPU frame to copy data into staging buffer.
/// </summary>
/// <returns>Downloaded texture data container, or nul if failed.</returns>
[Unmanaged]
public TextureData DownloadData()
{
var result = new TextureData();
return DownloadData(result) ? null : result;
}
}
partial class TextureBase partial class TextureBase
{ {
/// <summary> /// <summary>
@@ -36,6 +22,16 @@ namespace FlaxEngine
/// </summary> /// </summary>
public const int MaxArraySize = 512; public const int MaxArraySize = 512;
/// <summary>
/// Loads the texture data from the asset.
/// </summary>
/// <remarks>Use with caution as this operation loads texture data from the file.</remarks>
/// <returns>The loaded texture data or null if failed.</returns>
public TextureData GetTextureData()
{
return Internal_GetTextureData(__unmanagedPtr);
}
/// <summary> /// <summary>
/// The texture data initialization container. /// The texture data initialization container.
/// </summary> /// </summary>
@@ -162,6 +162,7 @@ public:
/// <summary> /// <summary>
/// Gets the mip data. /// Gets the mip data.
/// </summary> /// </summary>
/// <remarks>Use with caution as this operation loads texture data from the file.</remarks>
/// <param name="mipIndex">The mip index (zero-based).</param> /// <param name="mipIndex">The mip index (zero-based).</param>
/// <param name="rowPitch">The data row pitch (in bytes).</param> /// <param name="rowPitch">The data row pitch (in bytes).</param>
/// <param name="slicePitch">The data slice pitch (in bytes).</param> /// <param name="slicePitch">The data slice pitch (in bytes).</param>
@@ -171,6 +172,7 @@ public:
/// <summary> /// <summary>
/// Loads the texture data from the asset. /// Loads the texture data from the asset.
/// </summary> /// </summary>
/// <remarks>Use with caution as this operation loads texture data from the file.</remarks>
/// <param name="result">The result data.</param> /// <param name="result">The result data.</param>
/// <param name="copyData">True if copy asset data to the result buffer, otherwise texture data will be linked to the internal storage (then the data is valid while asset is loaded and there is no texture data copy operations - faster).</param> /// <param name="copyData">True if copy asset data to the result buffer, otherwise texture data will be linked to the internal storage (then the data is valid while asset is loaded and there is no texture data copy operations - faster).</param>
/// <returns>True if cannot load data, otherwise false.</returns> /// <returns>True if cannot load data, otherwise false.</returns>
@@ -179,6 +181,7 @@ public:
/// <summary> /// <summary>
/// Loads the texture data from the asset (single mip). /// Loads the texture data from the asset (single mip).
/// </summary> /// </summary>
/// <remarks>Use with caution as this operation loads texture data from the file.</remarks>
/// <param name="result">The result data.</param> /// <param name="result">The result data.</param>
/// <param name="mipIndex">The mip index (zero-based).</param> /// <param name="mipIndex">The mip index (zero-based).</param>
/// <param name="arrayIndex">The array or depth slice index (zero-based).</param> /// <param name="arrayIndex">The array or depth slice index (zero-based).</param>
@@ -189,6 +192,7 @@ public:
/// <summary> /// <summary>
/// Gets the texture pixels as Color32 array. /// Gets the texture pixels as Color32 array.
/// </summary> /// </summary>
/// <remarks>Use with caution as this operation loads texture data from the file.</remarks>
/// <remarks>Supported only for 'basic' texture formats (uncompressed, single plane).</remarks> /// <remarks>Supported only for 'basic' texture formats (uncompressed, single plane).</remarks>
/// <param name="pixels">The result texture pixels array.</param> /// <param name="pixels">The result texture pixels array.</param>
/// <param name="mipIndex">The mip index (zero-based).</param> /// <param name="mipIndex">The mip index (zero-based).</param>
@@ -199,6 +203,7 @@ public:
/// <summary> /// <summary>
/// Gets the texture pixels as Color array. /// Gets the texture pixels as Color array.
/// </summary> /// </summary>
/// <remarks>Use with caution as this operation loads texture data from the file.</remarks>
/// <remarks>Supported only for 'basic' texture formats (uncompressed, single plane).</remarks> /// <remarks>Supported only for 'basic' texture formats (uncompressed, single plane).</remarks>
/// <param name="pixels">The result texture pixels array.</param> /// <param name="pixels">The result texture pixels array.</param>
/// <param name="mipIndex">The mip index (zero-based).</param> /// <param name="mipIndex">The mip index (zero-based).</param>
@@ -252,6 +257,7 @@ private:
#if !COMPILE_WITHOUT_CSHARP #if !COMPILE_WITHOUT_CSHARP
// Internal bindings // Internal bindings
API_FUNCTION(NoProxy) bool InitCSharp(void* ptr); API_FUNCTION(NoProxy) bool InitCSharp(void* ptr);
API_FUNCTION(NoProxy) TextureData* GetTextureData();
#endif #endif
public: public:
@@ -132,7 +132,7 @@ public:
/// <param name="mipIndex">The mip index (zero-based).</param> /// <param name="mipIndex">The mip index (zero-based).</param>
/// <param name="arrayIndex">The array or depth slice index (zero-based).</param> /// <param name="arrayIndex">The array or depth slice index (zero-based).</param>
/// <returns>True if failed, otherwise false.</returns> /// <returns>True if failed, otherwise false.</returns>
API_FUNCTION() bool GetPixels(API_PARAM(Out) Array<Color32>& pixels, int32 mipIndex = 0, int32 arrayIndex = 0); API_FUNCTION() bool GetPixels(API_PARAM(Out) Array<Color32>& pixels, int32 mipIndex = 0, int32 arrayIndex = 0) const;
/// <summary> /// <summary>
/// Gets the texture pixels as Color array. /// Gets the texture pixels as Color array.
@@ -142,5 +142,5 @@ public:
/// <param name="mipIndex">The mip index (zero-based).</param> /// <param name="mipIndex">The mip index (zero-based).</param>
/// <param name="arrayIndex">The array or depth slice index (zero-based).</param> /// <param name="arrayIndex">The array or depth slice index (zero-based).</param>
/// <returns>True if failed, otherwise false.</returns> /// <returns>True if failed, otherwise false.</returns>
API_FUNCTION() bool GetPixels(API_PARAM(Out) Array<Color>& pixels, int32 mipIndex = 0, int32 arrayIndex = 0); API_FUNCTION() bool GetPixels(API_PARAM(Out) Array<Color>& pixels, int32 mipIndex = 0, int32 arrayIndex = 0) const;
}; };
@@ -499,6 +499,7 @@ void GPUContextDX11::UpdateCB(GPUConstantBuffer* cb, const void* data)
return; return;
_context->UpdateSubresource(cbDX11->GetBuffer(), 0, nullptr, data, size, 1); _context->UpdateSubresource(cbDX11->GetBuffer(), 0, nullptr, data, size, 1);
RENDER_STAT_DATA_UPLOAD(size);
} }
void GPUContextDX11::Dispatch(GPUShaderProgramCS* shader, uint32 threadGroupCountX, uint32 threadGroupCountY, uint32 threadGroupCountZ) void GPUContextDX11::Dispatch(GPUShaderProgramCS* shader, uint32 threadGroupCountX, uint32 threadGroupCountY, uint32 threadGroupCountZ)
@@ -904,6 +905,7 @@ void GPUContextDX11::UpdateBuffer(GPUBuffer* buffer, const void* data, uint32 si
box.bottom = 1; box.bottom = 1;
_context->UpdateSubresource(bufferDX11->GetResource(), 0, &box, data, size, 0); _context->UpdateSubresource(bufferDX11->GetResource(), 0, &box, data, size, 0);
} }
RENDER_STAT_DATA_UPLOAD(size);
} }
void GPUContextDX11::CopyBuffer(GPUBuffer* dstBuffer, GPUBuffer* srcBuffer, uint32 size, uint32 dstOffset, uint32 srcOffset) void GPUContextDX11::CopyBuffer(GPUBuffer* dstBuffer, GPUBuffer* srcBuffer, uint32 size, uint32 dstOffset, uint32 srcOffset)
@@ -934,6 +936,7 @@ void GPUContextDX11::UpdateTexture(GPUTexture* texture, int32 arrayIndex, int32
if (texture->IsVolume()) if (texture->IsVolume())
depthPitch /= Math::Max(1, texture->Depth() >> mipIndex); depthPitch /= Math::Max(1, texture->Depth() >> mipIndex);
_context->UpdateSubresource(textureDX11->GetResource(), subresourceIndex, nullptr, data, (UINT)rowPitch, (UINT)depthPitch); _context->UpdateSubresource(textureDX11->GetResource(), subresourceIndex, nullptr, data, (UINT)rowPitch, (UINT)depthPitch);
RENDER_STAT_DATA_UPLOAD(slicePitch);
//D3D11_MAPPED_SUBRESOURCE mapped; //D3D11_MAPPED_SUBRESOURCE mapped;
//_device->GetIM()->Map(_resource, textureMipIndex, D3D11_MAP_WRITE_DISCARD, 0, &mapped); //_device->GetIM()->Map(_resource, textureMipIndex, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
@@ -25,6 +25,7 @@
bool EnableNvapi = false; bool EnableNvapi = false;
#endif #endif
#if COMPILE_WITH_AGS #if COMPILE_WITH_AGS
#define AGS_EXCLUDE_DIRECTX_12
#include <ThirdParty/AGS/amd_ags.h> #include <ThirdParty/AGS/amd_ags.h>
#include "Engine/Engine/Globals.h" #include "Engine/Engine/Globals.h"
#include "FlaxEngine.Gen.h" #include "FlaxEngine.Gen.h"
@@ -87,6 +88,37 @@ static D3D11_STENCIL_OP ToDX11(StencilOperation value)
} }
} }
static RendererType GetRendererType(GPUAdapterDX* adapter)
{
switch (adapter->MaxFeatureLevel)
{
case D3D_FEATURE_LEVEL_10_0:
return RendererType::DirectX10;
case D3D_FEATURE_LEVEL_10_1:
return RendererType::DirectX10_1;
case D3D_FEATURE_LEVEL_11_0:
case D3D_FEATURE_LEVEL_11_1:
return RendererType::DirectX11;
default:
return RendererType::Unknown;
}
}
static ShaderProfile GetShaderProfile(GPUAdapterDX* adapter)
{
switch (adapter->MaxFeatureLevel)
{
case D3D_FEATURE_LEVEL_10_0:
case D3D_FEATURE_LEVEL_10_1:
return ShaderProfile::DirectX_SM4;
case D3D_FEATURE_LEVEL_11_0:
case D3D_FEATURE_LEVEL_11_1:
return ShaderProfile::DirectX_SM5;
default:
return ShaderProfile::Unknown;
}
}
static bool TryCreateDevice(IDXGIAdapter* adapter, D3D_FEATURE_LEVEL maxFeatureLevel, D3D_FEATURE_LEVEL* featureLevel) static bool TryCreateDevice(IDXGIAdapter* adapter, D3D_FEATURE_LEVEL maxFeatureLevel, D3D_FEATURE_LEVEL* featureLevel)
{ {
ID3D11Device* device = nullptr; ID3D11Device* device = nullptr;
@@ -335,7 +367,7 @@ GPUDevice* GPUDeviceDX11::Create()
} }
GPUDeviceDX11::GPUDeviceDX11(IDXGIFactory* dxgiFactory, GPUAdapterDX* adapter) GPUDeviceDX11::GPUDeviceDX11(IDXGIFactory* dxgiFactory, GPUAdapterDX* adapter)
: GPUDeviceDX(getRendererType(adapter), getShaderProfile(adapter), adapter) : GPUDeviceDX(::GetRendererType(adapter), ::GetShaderProfile(adapter), adapter)
, _factoryDXGI(dxgiFactory) , _factoryDXGI(dxgiFactory)
{ {
Platform::MemoryClear(RasterizerStates, sizeof(RasterizerStates)); Platform::MemoryClear(RasterizerStates, sizeof(RasterizerStates));
@@ -726,7 +758,11 @@ bool GPUDeviceDX11::Init()
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
samplerDesc.MipLODBias = 0.0f; samplerDesc.MipLODBias = 0.0f;
samplerDesc.MaxAnisotropy = 1; samplerDesc.MaxAnisotropy = 1;
#if REVERSE_Z
samplerDesc.ComparisonFunc = D3D11_COMPARISON_GREATER;
#else
samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL; samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;
#endif
// Linear Clamp // Linear Clamp
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
@@ -77,6 +77,9 @@ bool GPUSamplerDX11::OnInit()
case GPUSamplerCompareFunction::Less: case GPUSamplerCompareFunction::Less:
samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS; samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS;
break; break;
case GPUSamplerCompareFunction::Greater:
samplerDesc.ComparisonFunc = D3D11_COMPARISON_GREATER;
break;
default: default:
return true; return true;
} }
@@ -8,6 +8,7 @@
#include "Engine/Graphics/PixelFormatExtensions.h" #include "Engine/Graphics/PixelFormatExtensions.h"
#include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/RenderTask.h"
#include "Engine/Graphics/Async/Tasks/GPUUploadBufferTask.h" #include "Engine/Graphics/Async/Tasks/GPUUploadBufferTask.h"
#include <ThirdParty/D3D12MemoryAllocator/D3D12MemAlloc.h>
void GPUBufferViewDX12::SetSRV(D3D12_SHADER_RESOURCE_VIEW_DESC& srvDesc) void GPUBufferViewDX12::SetSRV(D3D12_SHADER_RESOURCE_VIEW_DESC& srvDesc)
{ {
@@ -115,34 +116,24 @@ bool GPUBufferDX12::OnInit()
resourceDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_INDIRECT_BUFFER; resourceDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_INDIRECT_BUFFER;
#endif #endif
// Create allocation description // Create resource
D3D12_HEAP_PROPERTIES heapProperties; D3D12MA::ALLOCATION_DESC allocationDesc = {};
switch (_desc.Usage) switch (_desc.Usage)
{ {
case GPUResourceUsage::StagingUpload: case GPUResourceUsage::StagingUpload:
case GPUResourceUsage::Staging: case GPUResourceUsage::Staging:
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD; allocationDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD;
break; break;
case GPUResourceUsage::StagingReadback: case GPUResourceUsage::StagingReadback:
heapProperties.Type = D3D12_HEAP_TYPE_READBACK; allocationDesc.HeapType = D3D12_HEAP_TYPE_READBACK;
break; break;
default: default:
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT; allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
} }
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapProperties.CreationNodeMask = 1;
heapProperties.VisibleNodeMask = 1;
// Create resource
ID3D12Resource* resource; ID3D12Resource* resource;
#if PLATFORM_WINDOWS
D3D12_HEAP_FLAGS heapFlags = EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::VertexBuffer | GPUBufferFlags::IndexBuffer) || _desc.InitData ? D3D12_HEAP_FLAG_CREATE_NOT_ZEROED : D3D12_HEAP_FLAG_NONE;
#else
D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE;
#endif
D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON; D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON;
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateCommittedResource(&heapProperties, heapFlags, &resourceDesc, initialState, nullptr, IID_PPV_ARGS(&resource))); HRESULT result = _device->Allocator->CreateResource(&allocationDesc, &resourceDesc, initialState, nullptr, &_allocation, IID_PPV_ARGS(&resource));
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
// Set state // Set state
initResource(resource, initialState, 1); initResource(resource, initialState, 1);

Some files were not shown because too many files have changed in this diff Show More