Merge branch 'stabilization/2106' into JsonSerialization/ArrayDefaultsFix

This commit is contained in:
AMZN-koppersr
2021-06-17 09:32:43 -07:00
272 changed files with 4465 additions and 3534 deletions
@@ -13,13 +13,6 @@ add_subdirectory(asset_processor_tests)
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
## AP Python Tests ##
ly_add_pytest(
NAME AssetPipelineTests.AuxiliaryContent
PATH ${CMAKE_CURRENT_LIST_DIR}/auxiliary_content_tests/auxiliary_content_tests.py
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
TEST_SUITE periodic
)
ly_add_pytest(
NAME AssetPipelineTests.BankInfoParser
PATH ${CMAKE_CURRENT_LIST_DIR}/wwise_bank_dependency_tests/bank_info_parser_tests.py
@@ -1,96 +0,0 @@
"""
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
its licensors.
For complete copyright and license terms please see the LICENSE at the root of this
distribution (the "License"). All use of this software is governed by the License,
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import pytest
import ly_test_tools
import os
import sys
import shutil
import subprocess
import glob
from ly_test_tools.builtin.helpers import *
from ly_test_tools.environment.process_utils import *
from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP
logger = logging.getLogger(__name__)
project_list = ['AutomatedTesting']
@pytest.mark.system
@pytest.mark.SUITE_periodic
class TestAuxiliaryContent:
@pytest.fixture(autouse=True)
def setup_teardown(self, request, workspace, project):
path_to_dev = workspace.paths.engine_root()
os.chdir(path_to_dev)
auxiliaryContentDirName = str.lower(project) + f"_{ASSET_PROCESSOR_PLATFORM_MAP[workspace.asset_processor_platform]}_paks"
self.auxiliaryContentPath = os.path.join(path_to_dev, auxiliaryContentDirName)
def teardown():
if (os.path.exists(self.auxiliaryContentPath)):
shutil.rmtree(self.auxiliaryContentPath)
request.addfinalizer(teardown)
@staticmethod
def scanForLevelPak(path_toscan):
files = glob.glob('{0}/**/level.pak'.format(path_toscan), recursive=True)
return len(files)
@pytest.mark.parametrize('level', ['alldependencies'])
@pytest.mark.parametrize('project', project_list)
def test_CreateAuxiliaryContent_DontSkipLevelPaks(self, workspace, level):
"""
This test ensure that Auxiliary Content contain level.pak files
Test Steps:
1. Run auxiliary content against project under test
2. Validate auxiliary content exists
3. Verifies that level.pak exists
"""
path_to_dev = workspace.paths.engine_root()
bin_path = workspace.paths.build_directory()
auxiliaryContentScriptPath = os.path.join(path_to_dev, 'BuildReleaseAuxiliaryContent.py')
subprocess.check_call(['python', auxiliaryContentScriptPath,
"--buildFolder={0}".format(bin_path),
"--platforms=pc",
f"--project-path={workspace.project}"])
assert os.path.exists(self.auxiliaryContentPath)
assert not self.scanForLevelPak(self.auxiliaryContentPath) == 0
@pytest.mark.parametrize('level', ['alldependencies'])
@pytest.mark.parametrize('project', project_list)
def test_CreateAuxiliaryContent_SkipLevelPaks(self, workspace, level):
"""
This test ensure that Auxiliary Content contain no level.pak file
Test Steps:
1. Run auxiliary content against project under test with skiplevelPaks flag
2. Validate auxiliary content exists
3. Validate level.pak was added to auxiliary content
"""
path_to_dev = workspace.paths.engine_root()
bin_path = workspace.paths.build_directory()
auxiliaryContentScriptPath = os.path.join(path_to_dev, 'BuildReleaseAuxiliaryContent.py')
subprocess.check_call(['python', auxiliaryContentScriptPath,
"--buildFolder={0}".format(bin_path),
"--platforms=pc",
"--skiplevelPaks",
f"--project-path={workspace.project}"])
assert os.path.exists(self.auxiliaryContentPath)
assert self.scanForLevelPak(self.auxiliaryContentPath) == 0
@@ -93,11 +93,13 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','C4044457_Material_RestitutionCombine.setreg_override', 'AutomatedTesting/Registry')
def test_C4044457_Material_RestitutionCombine(self, request, workspace, editor, launcher_platform):
from . import C4044457_Material_RestitutionCombine as test_module
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','C4044456_Material_FrictionCombine.setreg_override', 'AutomatedTesting/Registry')
def test_C4044456_Material_FrictionCombine(self, request, workspace, editor, launcher_platform):
from . import C4044456_Material_FrictionCombine as test_module
self._run_test(request, workspace, editor, test_module)
@@ -194,6 +196,7 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','C18981526_Material_RestitutionCombinePriority.setreg_override', 'AutomatedTesting/Registry')
def test_C18981526_Material_RestitutionCombinePriority(self, request, workspace, editor, launcher_platform):
from . import C18981526_Material_RestitutionCombinePriority as test_module
self._run_test(request, workspace, editor, test_module)
@@ -229,6 +232,7 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','C18977601_Material_FrictionCombinePriority.setreg_override', 'AutomatedTesting/Registry')
def test_C18977601_Material_FrictionCombinePriority(self, request, workspace, editor, launcher_platform):
from . import C18977601_Material_FrictionCombinePriority as test_module
self._run_test(request, workspace, editor, test_module)
@@ -250,6 +254,7 @@ class TestAutomation(TestAutomationBase):
@pytest.mark.xfail(
reason="This test needs new physics asset with multiple materials to be more stable.")
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','C4044697_Material_PerfaceMaterialValidation.setreg_override', 'AutomatedTesting/Registry')
def test_C4044697_Material_PerfaceMaterialValidation(self, request, workspace, editor, launcher_platform):
from . import C4044697_Material_PerfaceMaterialValidation as test_module
self._run_test(request, workspace, editor, test_module)
@@ -282,6 +287,7 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.setreg_override', 'AutomatedTesting/Registry')
def test_C15556261_PhysXMaterials_CharacterControllerMaterialAssignment(self, request, workspace, editor, launcher_platform):
from . import C15556261_PhysXMaterials_CharacterControllerMaterialAssignment as test_module
self._run_test(request, workspace, editor, test_module)
@@ -326,6 +332,7 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','C4044461_Material_Restitution.setreg_override', 'AutomatedTesting/Registry')
def test_C4044461_Material_Restitution(self, request, workspace, editor, launcher_platform):
from . import C4044461_Material_Restitution as test_module
self._run_test(request, workspace, editor, test_module)
@@ -0,0 +1,115 @@
{
"Amazon": {
"Gems": {
"PhysX": {
"PhysXSystemConfiguration": {
"CollisionConfig": {
"Layers": {
"LayerNames": [
"Default",
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
"TouchBend"
]
},
"Groups": {
"GroupPresets": [
{
"Name": "All",
"ReadOnly": true
},
{
"Id": {
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
},
"Name": "None",
"Group": {
"Mask": 0
},
"ReadOnly": true
},
{
"Id": {
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
},
"Name": "All_NoTouchBend",
"Group": {
"Mask": 9223372036854775807
},
"ReadOnly": true
}
]
}
},
"MaterialLibrary": {
"assetId": {
"guid": "{70D4A444-AFD4-57C4-9885-63F25AC3C281}"
},
"loadBehavior": "QueueLoad",
"assetHint": "levels/physics/c15556261_physxmaterials_charactercontrollermaterialassignment/library.physmaterial"
}
}
}
}
}
}
@@ -0,0 +1,115 @@
{
"Amazon": {
"Gems": {
"PhysX": {
"PhysXSystemConfiguration": {
"CollisionConfig": {
"Layers": {
"LayerNames": [
"Default",
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
"TouchBend"
]
},
"Groups": {
"GroupPresets": [
{
"Name": "All",
"ReadOnly": true
},
{
"Id": {
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
},
"Name": "None",
"Group": {
"Mask": 0
},
"ReadOnly": true
},
{
"Id": {
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
},
"Name": "All_NoTouchBend",
"Group": {
"Mask": 9223372036854775807
},
"ReadOnly": true
}
]
}
},
"MaterialLibrary": {
"assetId": {
"guid": "{B8749DAB-15DA-5A61-B565-C853673604CD}"
},
"loadBehavior": "QueueLoad",
"assetHint": "levels/physics/c18977601_material_frictioncombinepriority/friction_combine.physmaterial"
}
}
}
}
}
}
@@ -0,0 +1,115 @@
{
"Amazon": {
"Gems": {
"PhysX": {
"PhysXSystemConfiguration": {
"CollisionConfig": {
"Layers": {
"LayerNames": [
"Default",
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
"TouchBend"
]
},
"Groups": {
"GroupPresets": [
{
"Name": "All",
"ReadOnly": true
},
{
"Id": {
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
},
"Name": "None",
"Group": {
"Mask": 0
},
"ReadOnly": true
},
{
"Id": {
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
},
"Name": "All_NoTouchBend",
"Group": {
"Mask": 9223372036854775807
},
"ReadOnly": true
}
]
}
},
"MaterialLibrary": {
"assetId": {
"guid": "{AED48B18-0F3F-5E59-A8FF-30DB134B307B}"
},
"loadBehavior": "QueueLoad",
"assetHint": "levels/physics/c18981526_material_restitutioncombinepriority/restitution_combine.physmaterial"
}
}
}
}
}
}
@@ -0,0 +1,115 @@
{
"Amazon": {
"Gems": {
"PhysX": {
"PhysXSystemConfiguration": {
"CollisionConfig": {
"Layers": {
"LayerNames": [
"Default",
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
"TouchBend"
]
},
"Groups": {
"GroupPresets": [
{
"Name": "All",
"ReadOnly": true
},
{
"Id": {
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
},
"Name": "None",
"Group": {
"Mask": 0
},
"ReadOnly": true
},
{
"Id": {
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
},
"Name": "All_NoTouchBend",
"Group": {
"Mask": 9223372036854775807
},
"ReadOnly": true
}
]
}
},
"MaterialLibrary": {
"assetId": {
"guid": "{8D2C4A29-E0FC-564F-82C9-24BBA30C5A90}"
},
"loadBehavior": "QueueLoad",
"assetHint": "levels/physics/c4044456_material_frictioncombine/friction_combine.physmaterial"
}
}
}
}
}
}
@@ -0,0 +1,115 @@
{
"Amazon": {
"Gems": {
"PhysX": {
"PhysXSystemConfiguration": {
"CollisionConfig": {
"Layers": {
"LayerNames": [
"Default",
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
"TouchBend"
]
},
"Groups": {
"GroupPresets": [
{
"Name": "All",
"ReadOnly": true
},
{
"Id": {
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
},
"Name": "None",
"Group": {
"Mask": 0
},
"ReadOnly": true
},
{
"Id": {
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
},
"Name": "All_NoTouchBend",
"Group": {
"Mask": 9223372036854775807
},
"ReadOnly": true
}
]
}
},
"MaterialLibrary": {
"assetId": {
"guid": "{D5D6A6DE-E636-5638-B30D-6CE2FDC321F8}"
},
"loadBehavior": "QueueLoad",
"assetHint": "levels/physics/c4044457_material_restitutioncombine/restitution_combine.physmaterial"
}
}
}
}
}
}
@@ -0,0 +1,115 @@
{
"Amazon": {
"Gems": {
"PhysX": {
"PhysXSystemConfiguration": {
"CollisionConfig": {
"Layers": {
"LayerNames": [
"Default",
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
"TouchBend"
]
},
"Groups": {
"GroupPresets": [
{
"Name": "All",
"ReadOnly": true
},
{
"Id": {
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
},
"Name": "None",
"Group": {
"Mask": 0
},
"ReadOnly": true
},
{
"Id": {
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
},
"Name": "All_NoTouchBend",
"Group": {
"Mask": 9223372036854775807
},
"ReadOnly": true
}
]
}
},
"MaterialLibrary": {
"assetId": {
"guid": "{E4117B5B-8D9A-5C1D-BA1E-C36542A6588D}"
},
"loadBehavior": "QueueLoad",
"assetHint": "levels/physics/c4044461_material_restitution/restitution.physmaterial"
}
}
}
}
}
}
@@ -0,0 +1,115 @@
{
"Amazon": {
"Gems": {
"PhysX": {
"PhysXSystemConfiguration": {
"CollisionConfig": {
"Layers": {
"LayerNames": [
"Default",
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
"TouchBend"
]
},
"Groups": {
"GroupPresets": [
{
"Name": "All",
"ReadOnly": true
},
{
"Id": {
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
},
"Name": "None",
"Group": {
"Mask": 0
},
"ReadOnly": true
},
{
"Id": {
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
},
"Name": "All_NoTouchBend",
"Group": {
"Mask": 9223372036854775807
},
"ReadOnly": true
}
]
}
},
"MaterialLibrary": {
"assetId": {
"guid": "{2E85B457-ED19-5FE3-90B4-6EFFB4D0E682}"
},
"loadBehavior": "QueueLoad",
"assetHint": "levels/physics/c4044697_material_perfacematerialvalidation/test_library.physmaterial"
}
}
}
}
}
}
@@ -406,6 +406,7 @@ namespace AZ
AZStd::vector<AZ::BehaviorParameter> eventParamsTypes{ AZStd::initializer_list<AZ::BehaviorParameter>{
CreateBehaviorEventParameter<decay_array<T>>()... } };
behaviorContext->Class<AZ::Event<T...>>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly)
->Attribute(AZ::Script::Attributes::EventHandlerCreationFunction, createHandlerHolder)
->Attribute(AZ::Script::Attributes::EventParameterTypes, eventParamsTypes)
->Method("HasHandlerConnected", &AZ::Event<T...>::HasHandlerConnected)
@@ -413,6 +414,7 @@ namespace AZ
behaviorContext->Class<AZ::EventHandler<T...>>()
->Method("Disconnect", &AZ::EventHandler<T...>::Disconnect)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly)
;
}
}
@@ -29,15 +29,20 @@ namespace Benchmark
{},
m_pathString));
auto& prefabDom = m_prefabSystemComponent->FindTemplateDom(instance->GetTemplateId());
for (auto _ : state)
{
state.PauseTiming();
AzFramework::Spawnable spawnable;
AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(spawnable, prefabDom);
state.ResumeTiming();
// Create a vector to store spawnables so that they don't get destroyed immediately after construction.
AZStd::vector<AZStd::unique_ptr<AzFramework::Spawnable>> spawnables;
spawnables.reserve(numSpawnables);
for (int spwanableCounter = 0; spwanableCounter < numSpawnables; ++spwanableCounter)
{
AZStd::unique_ptr<AzFramework::Spawnable> spawnable = AZStd::make_unique<AzFramework::Spawnable>();
AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(*spawnable, prefabDom);
spawnables.push_back(AZStd::move(spawnable));
}
}
state.SetComplexityN(numSpawnables);
@@ -50,3 +55,4 @@ namespace Benchmark
}
#endif
+1 -8
View File
@@ -4060,17 +4060,10 @@ void CCryEditApp::SetEditorWindowTitle(QString sTitleStr, QString sPreTitleStr,
{
if (MainWindow::instance() || m_pConsoleDialog)
{
QString platform = "";
#ifdef WIN64
platform = "[x64]";
#else
platform = "[x86]";
#endif //WIN64
if (sTitleStr.isEmpty())
{
sTitleStr = QObject::tr("Open 3D Engine Editor Beta %1 - Build %2").arg(platform).arg(LY_BUILD);
sTitleStr = QObject::tr("O3DE Editor [Developer Preview]");
}
if (!sPreTitleStr.isEmpty())
@@ -47,8 +47,6 @@ CEditorPreferencesPage_AWS::CEditorPreferencesPage_AWS()
{
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
InitializeSettings();
// TODO Update with AWS svg.
m_icon = QIcon(":/res/AWS_preferences_icon.svg");
}
@@ -12,6 +12,7 @@
#include "BuilderManager.h"
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <native/connection/connectionManager.h>
@@ -186,10 +187,9 @@ namespace AssetProcessor
QDir projectCacheRoot;
AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot);
QString gameName = AssetUtilities::ComputeProjectName();
QString projectPath = AssetUtilities::ComputeProjectPath();
QDir engineRoot;
AssetUtilities::ComputeEngineRoot(engineRoot);
AZ::SettingsRegistryInterface::FixedValueString projectName = AZ::Utils::GetProjectName();
AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
AZ::IO::FixedMaxPathString enginePath = AZ::Utils::GetEnginePath();
int portNumber = 0;
ApplicationServerBus::BroadcastResult(portNumber, &ApplicationServerBus::Events::GetServerListeningPort);
@@ -197,14 +197,14 @@ namespace AssetProcessor
AZStd::string params;
#if !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
params = AZStd::string::format(
R"(-task=%s -id="%s" -project-name="%s" -project-cache-path="%s" -project-path="%s" -engine-path="%s" -port %d)", task,
builderGuid.c_str(), gameName.toUtf8().constData(), projectCacheRoot.absolutePath().toUtf8().constData(),
projectPath.toUtf8().constData(), engineRoot.absolutePath().toUtf8().constData(), portNumber);
R"(-task=%s -id="%s" -project-name="%s" -project-cache-path="%s" -project-path="%s" -engine-path="%s" -port %d)",
task, builderGuid.c_str(), projectName.c_str(), projectCacheRoot.absolutePath().toUtf8().constData(),
projectPath.c_str(), enginePath.c_str(), portNumber);
#else
params = AZStd::string::format(
R"(-task=%s -id="%s" -project-name="\"%s\"" -project-cache-path="\"%s\"" -project-path="\"%s\"" -engine-path="\"%s\"" -port %d)",
task, builderGuid.c_str(), gameName.toUtf8().constData(), projectCacheRoot.absolutePath().toUtf8().constData(),
projectPath.toUtf8().constData(), engineRoot.absolutePath().toUtf8().constData(), portNumber);
task, builderGuid.c_str(), projectName.c_str(), projectCacheRoot.absolutePath().toUtf8().constData(),
projectPath.c_str(), enginePath.c_str(), portNumber);
#endif // !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
if (moduleFilePath && moduleFilePath[0])
@@ -77,6 +77,7 @@ namespace O3DE::ProjectManager
return ProjectManagerScreen::CreateProject;
}
// Called when pressing "Create New Project"
void CreateProjectCtrl::NotifyCurrentScreen()
{
ScreenWidget* currentScreen = reinterpret_cast<ScreenWidget*>(m_stack->currentWidget());
@@ -84,6 +85,11 @@ namespace O3DE::ProjectManager
{
currentScreen->NotifyCurrentScreen();
}
// Gather the gems from the project template. When we will have multiple project templates, we need to re-gather them
// on changing the template and let the user know that any further changes on top of the template will be lost.
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
m_gemCatalogScreen->ReinitForProject(projectTemplatePath + "/Template", /*isNewProject=*/true);
}
void CreateProjectCtrl::HandleBackButton()
@@ -151,9 +157,6 @@ namespace O3DE::ProjectManager
{
m_stack->setCurrentIndex(m_stack->currentIndex() + 1);
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
m_gemCatalogScreen->ReinitForProject(projectTemplatePath + "/Template", /*isNewProject=*/true);
Update();
}
else
@@ -89,17 +89,18 @@ namespace O3DE::ProjectManager
return ProjectManagerScreen::UpdateProject;
}
// Called when pressing "Edit Project Settings..."
void UpdateProjectCtrl::NotifyCurrentScreen()
{
m_stack->setCurrentIndex(ScreenOrder::Settings);
Update();
// Gather the available gems that will be shown in the gem catalog.
m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/false);
}
void UpdateProjectCtrl::HandleGemsButton()
{
// The next page is the gem catalog. Gather the available gems that will be shown in the gem catalog.
m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/false);
m_stack->setCurrentWidget(m_gemCatalogScreen);
Update();
}
@@ -151,7 +151,7 @@ namespace AZ
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<AssImpAnimationImporter, SceneCore::LoadingComponent>()->Version(4); // [LYN-3971] Bone pruning crash fix in AssImp SDK
serializeContext->Class<AssImpAnimationImporter, SceneCore::LoadingComponent>()->Version(5); // [LYN-4226] Invert PostRotation matrix in animation chains
}
}
@@ -43,7 +43,7 @@ namespace AWSCore
bool UseAWSCredentials()
{
return false;
return true;
}
//! Request body for the service API request.
@@ -25,20 +25,24 @@
#include <AzCore/Module/ModuleManagerBus.h>
#include <ResourceMapping/AWSResourceMappingUtils.h>
#include <QSysInfo>
#include <QString>
namespace AWSCore
{
static constexpr const char* EngineVersionJsonKey = "O3DEVersion";
constexpr const char* EngineVersionJsonKey = "O3DEVersion";
constexpr char EditorAWSPreferencesFileName[] = "editor_aws_preferences.setreg";
constexpr char AWSAttributionSettingsPrefixKey[] = "/Amazon/AWS/Preferences";
constexpr char AWSAttributionEnabledKey[] = "/Amazon/AWS/Preferences/AWSAttributionEnabled";
constexpr char AWSAttributionDelaySecondsKey[] = "/Amazon/AWS/Preferences/AWSAttributionDelaySeconds";
constexpr char AWSAttributionLastTimeStampKey[] = "/Amazon/AWS/Preferences/AWSAttributionLastTimeStamp";
constexpr char AWSAttributionApiId[] = "xbzx78kvbk";
constexpr char AWSAttributionApiId[] = "2zxvvmv8d7";
constexpr char AWSAttributionChinaApiId[] = "";
constexpr char AWSAttributionApiStage[] = "prod";
const int AWSAttributionDefaultDelayInDays = 7;
AWSAttributionManager::AWSAttributionManager()
{
@@ -58,12 +62,11 @@ namespace AWSCore
{
if (ShouldGenerateMetric())
{
// 1. Gather metadata and assemble metric
// Gather metadata and assemble metric
AttributionMetric metric;
UpdateMetric(metric);
// 2. Identify region and chose attribution endpoint
// 3. Post metric
// Post metric
SubmitMetric(metric);
}
}
@@ -104,8 +107,7 @@ namespace AWSCore
AZ::u64 delayInSeconds = 0;
if (!m_settingsRegistry->Get(delayInSeconds, AWSAttributionDelaySecondsKey))
{
AZ_Warning("AWSAttributionManager", false, "AWSAttribution delay key not found. Defaulting to delay to day");
delayInSeconds = 86400;
delayInSeconds = 86400 * AWSAttributionDefaultDelayInDays;
m_settingsRegistry->Set(AWSAttributionDelaySecondsKey, delayInSeconds);
}
@@ -243,7 +245,8 @@ namespace AWSCore
metric.SetO3DEVersion(engineVersion);
AZStd::string platform = this->GetPlatform();
metric.SetPlatform(platform, "");
QString productName = QSysInfo::prettyProductName();
metric.SetPlatform(platform, productName.toStdString().c_str());
AZStd::vector<AZStd::string> gemNames;
GetActiveAWSGems(gemNames);
@@ -256,6 +259,7 @@ namespace AWSCore
void AWSAttributionManager::SubmitMetric(AttributionMetric& metric)
{
AWSCore::ServiceAPI::AWSAttributionRequestJob::Config* config = ServiceAPI::AWSAttributionRequestJob::GetDefaultConfig();
// Identify region and chose attribution endpoint
SetApiEndpointAndRegion(config);
ServiceAPI::AWSAttributionRequestJob* requestJob = ServiceAPI::AWSAttributionRequestJob::Create(
@@ -266,7 +270,12 @@ namespace AWSCore
UpdateLastSend();
AZ_Printf("AWSAttributionManager", "AWSAttribution metric submit success");
}, {}, config);
},
[this](ServiceAPI::AWSAttributionRequestJob* failJob)
{
AZ_Error("AWSAttributionManager", false, "Metrics send error: %s", failJob->error.message.c_str());
},
config);
requestJob->parameters.metric = metric;
requestJob->Start();
@@ -19,14 +19,16 @@
namespace AWSCore
{
constexpr char AWSAttributionMetricDefaultO3DEVersion[] = "1.1";
AttributionMetric::AttributionMetric(const AZStd::string& timestamp)
: m_version("1.1")
: m_version(AWSAttributionMetricDefaultO3DEVersion)
, m_timestamp(timestamp)
{
}
AttributionMetric::AttributionMetric()
: m_version("1.1")
: m_version(AWSAttributionMetricDefaultO3DEVersion)
{
m_timestamp = AttributionMetric::GenerateTimeStamp();
}
@@ -32,6 +32,8 @@
#include <AzCore/Module/ModuleManagerBus.h>
#include <TestFramework/AWSCoreFixture.h>
#include <QSysInfo>
#include <QString>
using namespace AWSCore;
@@ -405,6 +407,7 @@ namespace AWSAttributionUnitTest
AZStd::string serializedMetricValue = metric.SerializeToJson();
ASSERT_TRUE(serializedMetricValue.find("\"o3de_version\":\"1.0.0.0\"") != AZStd::string::npos);
ASSERT_TRUE(serializedMetricValue.find(AZ::GetPlatformName(AZ::g_currentPlatform)) != AZStd::string::npos);
ASSERT_TRUE(serializedMetricValue.find(QSysInfo::prettyProductName().toStdString().c_str()) != AZStd::string::npos);
ASSERT_TRUE(serializedMetricValue.find("AWSCore.Editor") != AZStd::string::npos);
ASSERT_TRUE(serializedMetricValue.find("AWSClientAuth") != AZStd::string::npos);
@@ -25,8 +25,6 @@ AlphaSource_Packed = 0
AlphaSource_Split = 1
AlphaSource_None = 2
ForwardPassIndex = 1
function ConfigureAlphaBlending(shaderItem)
shaderItem:GetRenderStatesOverride():SetDepthEnabled(true)
shaderItem:GetRenderStatesOverride():SetDepthWriteMask(DepthWriteMask_Zero)
@@ -58,15 +56,17 @@ end
function Process(context)
local opacityMode = context:GetMaterialPropertyValue_enum("opacity.mode")
local forwardPassEDS = context:GetShaderByTag("ForwardPass_EDS")
if(opacityMode == OpacityMode_Blended) then
ConfigureAlphaBlending(context:GetShader(ForwardPassIndex))
context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent")
ConfigureAlphaBlending(forwardPassEDS)
forwardPassEDS:SetDrawListTagOverride("transparent")
elseif(opacityMode == OpacityMode_TintedTransparent) then
ConfigureDualSourceBlending(context:GetShader(ForwardPassIndex))
context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent")
ConfigureDualSourceBlending(forwardPassEDS)
forwardPassEDS:SetDrawListTagOverride("transparent")
else
ResetAlphaBlending(context:GetShader(ForwardPassIndex))
context:GetShader(ForwardPassIndex):SetDrawListTagOverride("") -- reset to default draw list
ResetAlphaBlending(forwardPassEDS)
forwardPassEDS:SetDrawListTagOverride("") -- reset to default draw list
end
end
@@ -74,7 +74,9 @@ function Process(context)
shadowMapWithPS:SetEnabled(opacityMode == OpacityMode_Cutout)
forwardPass:SetEnabled(opacityMode == OpacityMode_Cutout)
TrySetShaderEnabled(lowEndForwardEDS, (opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent))
-- Only enable lowEndForwardEDS in Opaque mode, Transparent mode will be handled by forwardPassEDS. The transparent pass uses the "transparent" draw tag
-- for both standard and low end pipelines, so this keeps both shaders from rendering to the transparent draw list.
TrySetShaderEnabled(lowEndForwardEDS, opacityMode == OpacityMode_Opaque)
TrySetShaderEnabled(lowEndForward, opacityMode == OpacityMode_Cutout)
end
@@ -226,7 +226,7 @@ float ProjectedShadow::GetVisibilityEsm()
}
const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize;
const Texture2DArray<float> expShadowmap = PassSrg::m_projectedExponentialShadowmap;
const Texture2DArray<float> shadowmap = PassSrg::m_projectedExponentialShadowmap;
if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin &&
m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin)
@@ -243,10 +243,12 @@ float ProjectedShadow::GetVisibilityEsm()
const float depth = PerspectiveDepthToLinear(
m_shadowPosition.z,
coefficients);
const float expDepthInShadowmap = expShadowmap.Sample(
const float occluder = shadowmap.Sample(
PassSrg::LinearSampler,
float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r;
const float ratio = exp(-EsmExponentialShift * depth) * expDepthInShadowmap;
const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder);
const float ratio = exp(exponent);
// pow() mitigates light bleeding to shadows from near shadow casters.
return saturate( pow(ratio, 8) );
}
@@ -265,7 +267,7 @@ float ProjectedShadow::GetVisibilityEsmPcf()
}
const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize;
const Texture2DArray<float> expShadowmap = PassSrg::m_projectedExponentialShadowmap;
const Texture2DArray<float> shadowmap = PassSrg::m_projectedExponentialShadowmap;
if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin &&
m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin)
@@ -282,10 +284,12 @@ float ProjectedShadow::GetVisibilityEsmPcf()
const float depth = PerspectiveDepthToLinear(
m_shadowPosition.z,
coefficients);
const float expDepthInShadowmap = expShadowmap.Sample(
const float occluder = shadowmap.Sample(
PassSrg::LinearSampler,
float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r;
float ratio = exp(-EsmExponentialShift * depth) * expDepthInShadowmap;
const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder);
float ratio = exp(exponent);
static const float pcfFallbackThreshold = 1.04;
if (ratio > pcfFallbackThreshold)
@@ -92,6 +92,8 @@ partial ShaderResourceGroup ViewSrg
uint m_filteringSampleCount;
float2 m_unprojectConstants;
float m_bias;
float m_esmExponent;
float3 m_padding;
};
StructuredBuffer<ProjectedShadow> m_projectedShadows;
@@ -56,7 +56,6 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
return; // Early return if filter is disabled.
}
float depth = 0.;
switch (o_shadowmapLightType)
{
case ShadowmapLightType::Directional:
@@ -68,9 +67,15 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
// and it often causes light bleeding with ESM.
// So this converts it to "depth" to emphasize the difference
// within the frustum.
depth = (depthInClip - distanceMin) / (1. - distanceMin);
}
const float depth = (depthInClip - distanceMin) / (1. - distanceMin);
// Todo: Expose Esm exponent slider for directional lights
// This would remove the exp calculation below, collapsing it into a subtraction in DirectionalLightShadow.azsli
// ATOM-15775
const float outValue = exp(EsmExponentialShift * depth);
PassSrg::m_outputShadowmap[dispatchId].r = outValue;
break;
}
case ShadowmapLightType::Spot:
{
const float3 coefficients = float3(
@@ -84,12 +89,9 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
// and it often causes light bleeding with ESM.
// So this converts it to a linear depth to emphasize the
// difference like a orthogonal depth.
depth = PerspectiveDepthToLinear(depthInClip, coefficients);
}
PassSrg::m_outputShadowmap[dispatchId].r = PerspectiveDepthToLinear(depthInClip, coefficients);
break;
}
}
const float outValue = exp(EsmExponentialShift * depth);
PassSrg::m_outputShadowmap[dispatchId].r = outValue;
}
@@ -100,10 +100,13 @@ namespace AZ
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
//! Sets the shadowmap Pcf (percentage closer filtering) method.
virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0;
//! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow.
virtual void SetEsmExponent(LightHandle handle, float exponent) = 0;
//! Sets all of the the disk data for the provided LightHandle.
virtual void SetDiskData(LightHandle handle, const DiskLightData& data) = 0;
};
} // namespace Render
} // namespace AZ
@@ -82,6 +82,8 @@ namespace AZ
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
//! Sets the shadowmap Pcf (percentage closer filtering) method.
virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0;
//! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow.
virtual void SetEsmExponent(LightHandle handle, float exponent) = 0;
//! Sets all of the the point data for the provided LightHandle.
virtual void SetPointData(LightHandle handle, const PointLightData& data) = 0;
};
@@ -343,6 +343,11 @@ namespace AZ
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method);
}
void DiskLightFeatureProcessor::SetEsmExponent(LightHandle handle, float exponent)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, exponent);
}
void DiskLightFeatureProcessor::UpdateShadow(LightHandle handle)
{
const DiskLightData& diskLight = m_diskLightData.GetData(handle.GetIndex());
@@ -60,6 +60,7 @@ namespace AZ
void SetPredictionSampleCount(LightHandle handle, uint16_t count) override;
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
void SetPcfMethod(LightHandle handle, PcfMethod method) override;
void SetEsmExponent(LightHandle handle, float esmExponent) override;
void SetDiskData(LightHandle handle, const DiskLightData& data) override;
@@ -192,9 +192,7 @@ namespace AZ
OnShaderReloaded();
}
void LightCullingTilePreparePass::OnShaderVariantReinitialized(
const AZ::RPI::Shader&, const AZ::RPI::ShaderVariantId&,
AZ::RPI::ShaderVariantStableId)
void LightCullingTilePreparePass::OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant&)
{
OnShaderReloaded();
}
@@ -56,7 +56,7 @@ namespace AZ
// ShaderReloadNotificationBus overrides...
void OnShaderReinitialized(const AZ::RPI::Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<AZ::RPI::ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const AZ::RPI::Shader& shader, const AZ::RPI::ShaderVariantId& shaderVariantId, AZ::RPI::ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant& shaderVariant) override;
// Scope producer functions...
void CompileResources(const RHI::FrameGraphCompileContext& context) override;
@@ -312,5 +312,10 @@ namespace AZ
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method);
}
void PointLightFeatureProcessor::SetEsmExponent(LightHandle handle, float esmExponent)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, esmExponent);
}
} // namespace Render
} // namespace AZ
@@ -57,6 +57,7 @@ namespace AZ
void SetPredictionSampleCount(LightHandle handle, uint16_t count) override;
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
void SetPcfMethod(LightHandle handle, PcfMethod method) override;
void SetEsmExponent(LightHandle handle, float esmExponent) override;
void SetPointData(LightHandle handle, const PointLightData& data) override;
const Data::Instance<RPI::Buffer> GetLightBuffer() const;
@@ -199,7 +199,7 @@ namespace AZ
}
}
void MorphTargetDispatchItem::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset<AZ::RPI::ShaderAsset>& shaderAsset)
void MorphTargetDispatchItem::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset<RPI::ShaderAsset>& shaderAsset)
{
if (!Init())
{
@@ -207,7 +207,7 @@ namespace AZ
}
}
void MorphTargetDispatchItem::OnShaderVariantReinitialized([[maybe_unused]] const RPI::Shader& shader, [[maybe_unused]] const RPI::ShaderVariantId& shaderVariantId, [[maybe_unused]] RPI::ShaderVariantStableId shaderVariantStableId)
void MorphTargetDispatchItem::OnShaderVariantReinitialized(const RPI::ShaderVariant&)
{
if (!Init())
{
@@ -72,8 +72,8 @@ namespace AZ
// ShaderInstanceNotificationBus::Handler overrides
void OnShaderReinitialized(const RPI::Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<AZ::RPI::ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override;
void OnShaderAssetReinitialized(const Data::Asset<RPI::ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override;
RHI::DispatchItem m_dispatchItem;
@@ -458,9 +458,13 @@ namespace AZ
bool ProfilingCaptureSystemComponent::CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath)
{
// Start the cpu profiling
RHI::CpuProfiler::Get()->SetProfilerEnabled(true);
bool wasEnabled = RHI::CpuProfiler::Get()->IsProfilerEnabled();
if (!wasEnabled)
{
RHI::CpuProfiler::Get()->SetProfilerEnabled(true);
}
const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath]()
const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath, wasEnabled]()
{
JsonSerializerSettings serializationSettings;
serializationSettings.m_keepDefaults = true;
@@ -481,14 +485,22 @@ namespace AZ
saveResult.GetError().c_str());
AZ_Warning("ProfilingCaptureSystemComponent", false, captureInfo.c_str());
}
else
{
AZ_Printf("ProfilingCaptureSystemComponent", "Cpu profiling statistics was saved to file [%s]\n", outputFilePath.c_str());
}
// Disable the profiler again
RHI::CpuProfiler::Get()->SetProfilerEnabled(false);
if (!wasEnabled)
{
RHI::CpuProfiler::Get()->SetProfilerEnabled(false);
}
// Notify listeners that the pass' PipelineStatistics queries capture has finished.
ProfilingCaptureNotificationBus::Broadcast(&ProfilingCaptureNotificationBus::Events::OnCaptureCpuProfilingStatisticsFinished,
saveResult.IsSuccess(),
captureInfo);
});
// Start the TickBus.
@@ -354,9 +354,9 @@ namespace AZ
Init();
}
void RayTracingPass::OnShaderVariantReinitialized([[maybe_unused]] const RPI::Shader& shader, [[maybe_unused]] const RPI::ShaderVariantId& shaderVariantId, [[maybe_unused]] RPI::ShaderVariantStableId shaderVariantStableId)
void RayTracingPass::OnShaderVariantReinitialized(const RPI::ShaderVariant&)
{
Init();
}
} // namespace RPI
} // namespace Render
} // namespace AZ
@@ -53,7 +53,7 @@ namespace AZ
// ShaderReloadNotificationBus::Handler overrides
void OnShaderReinitialized(const RPI::Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<RPI::ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override;
// load the raytracing shaders and setup pipeline states
void Init();
@@ -162,12 +162,21 @@ namespace AZ::Render
void ProjectedShadowFeatureProcessor::SetPcfMethod(ShadowId id, PcfMethod method)
{
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetPcfMethod().");
ShadowData& shadowData = m_shadowData.GetElement<ShadowDataIndex>(id.GetIndex());
shadowData.m_pcfMethod = method;
m_deviceBufferNeedsUpdate = true;
}
void ProjectedShadowFeatureProcessor::SetEsmExponent(ShadowId id, float exponent)
{
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetEsmExponent().");
ShadowData& shadowData = m_shadowData.GetElement<ShadowDataIndex>(id.GetIndex());
shadowData.m_esmExponent = exponent;
m_deviceBufferNeedsUpdate = true;
}
void ProjectedShadowFeatureProcessor::SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method)
{
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowFilterMethod().");
@@ -52,6 +52,7 @@ namespace AZ::Render
void SetFieldOfViewY(ShadowId id, float fieldOfViewYRadians) override;
void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) override;
void SetPcfMethod(ShadowId id, PcfMethod method);
void SetEsmExponent(ShadowId id, float exponent);
void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) override;
void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) override;
void SetPredictionSampleCount(ShadowId id, uint16_t count) override;
@@ -73,6 +74,8 @@ namespace AZ::Render
uint32_t m_filteringSampleCount = 0;
AZStd::array<float, 2> m_unprojectConstants = { {0, 0} };
float m_bias;
float m_esmExponent = 87.0f;
float m_padding[3];
};
// CPU data used for constructing & updating ShadowData
@@ -65,9 +65,13 @@ namespace AZ
}
}
void SkinnedMeshComputePass::OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId&, RPI::ShaderVariantStableId)
void SkinnedMeshComputePass::OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant)
{
OnShaderReinitialized(shader);
ComputePass::OnShaderVariantReinitialized(shaderVariant);
if (m_skinnedMeshFeatureProcessor)
{
m_skinnedMeshFeatureProcessor->OnSkinningShaderReinitialized(m_shader);
}
}
} // namespace Render
} // namespace AZ
@@ -44,7 +44,7 @@ namespace AZ
// ShaderReloadNotificationBus::Handler overrides...
void OnShaderReinitialized(const RPI::Shader& shader) override;
void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override;
SkinnedMeshFeatureProcessor* m_skinnedMeshFeatureProcessor = nullptr;
};
@@ -12,6 +12,7 @@
#pragma once
#include <AzCore/Debug/EventTrace.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/string/string.h>
@@ -87,6 +88,8 @@ namespace AZ
//! Enable/Disable the CpuProfiler
virtual void SetProfilerEnabled(bool enabled) = 0;
virtual bool IsProfilerEnabled() const = 0 ;
};
} // namespace RPI
@@ -102,6 +102,7 @@ namespace AZ
void EndTimeRegion() final;
void FlushTimeRegionMap(TimeRegionMap& timeRegionMap) final;
void SetProfilerEnabled(bool enabled) final;
bool IsProfilerEnabled() const final;
private:
// Lazily create and register the local thread data
@@ -11,6 +11,7 @@
*/
#pragma once
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/FreeListAllocator.h>
#include <Atom/RHI/PoolAllocator.h>
#include <Atom/RHI/MemoryAllocation.h>
@@ -160,6 +161,7 @@ namespace AZ
template <class Traits>
void MemorySubAllocator<Traits>::GarbageCollect()
{
AZ_ATOM_PROFILE_FUNCTION("RHI", "MemorySubAllocator: GarbageCollect");
for (PageContext& pageContext : m_pageContexts)
{
pageContext.m_allocator.GarbageCollect();
@@ -11,6 +11,7 @@
*/
#pragma once
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/Object.h>
#include <AzCore/std/parallel/mutex.h>
#include <AzCore/std/containers/vector.h>
@@ -169,6 +170,7 @@ namespace AZ
template <typename Traits>
void ObjectCollector<Traits>::Collect(bool forceFlush)
{
AZ_ATOM_PROFILE_FUNCTION("DX12", "ObjectCollector: Collect");
m_mutex.lock();
if (m_pendingObjects.size())
{
@@ -11,6 +11,7 @@
*/
#include <Atom/RHI/CommandQueue.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/Device.h>
namespace AZ
@@ -86,6 +87,7 @@ namespace AZ
void CommandQueue::FlushCommands()
{
AZ_ATOM_PROFILE_FUNCTION("RHI", "CommandQueue: FlushCommands");
while (!m_isWorkQueueEmpty && !m_isQuitting)
{
AZStd::this_thread::yield();
@@ -186,6 +186,12 @@ namespace AZ
}
}
bool CpuProfilerImpl::IsProfilerEnabled() const
{
return m_enabled;
}
void CpuProfilerImpl::RegisterThreadStorage()
{
AZStd::unique_lock<AZStd::mutex> lock(m_threadRegisterMutex);
+3
View File
@@ -10,6 +10,7 @@
*
*/
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/Device.h>
#include <Atom/RHI/MemoryStatisticsBus.h>
@@ -151,6 +152,7 @@ namespace AZ
{
if (ValidateIsInitialized() && ValidateIsInFrame())
{
AZ_ATOM_PROFILE_FUNCTION("RHI", "Device: EndFrame");
EndFrameInternal();
m_isInFrame = false;
return ResultCode::Success;
@@ -172,6 +174,7 @@ namespace AZ
{
if (ValidateIsInitialized() && ValidateIsNotInFrame())
{
AZ_ATOM_PROFILE_FUNCTION("RHI", "Device: CompileMemoryStatistics");
MemoryStatisticsBuilder builder;
builder.Begin(memoryStatistics, reportFlags);
CompileMemoryStatisticsInternal(builder);
+9 -7
View File
@@ -9,18 +9,19 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/RHI/FrameGraph.h>
#include <Atom/RHI/SwapChainFrameAttachment.h>
#include <Atom/RHI/BufferFrameAttachment.h>
#include <Atom/RHI/ImageFrameAttachment.h>
#include <Atom/RHI/BufferScopeAttachment.h>
#include <Atom/RHI/ImageScopeAttachment.h>
#include <Atom/RHI/ResolveScopeAttachment.h>
#include <Atom/RHI/SwapChain.h>
#include <Atom/RHI/BufferPoolBase.h>
#include <Atom/RHI/BufferScopeAttachment.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/FrameGraph.h>
#include <Atom/RHI/ImageFrameAttachment.h>
#include <Atom/RHI/ImagePoolBase.h>
#include <Atom/RHI/ImageScopeAttachment.h>
#include <Atom/RHI/QueryPool.h>
#include <Atom/RHI/ResolveScopeAttachment.h>
#include <Atom/RHI/Scope.h>
#include <Atom/RHI/SwapChain.h>
#include <Atom/RHI/SwapChainFrameAttachment.h>
#include <AzCore/Debug/EventTrace.h>
#include <AzCore/std/sort.h>
@@ -76,6 +77,7 @@ namespace AZ
void FrameGraph::Clear()
{
AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameGraph: Clear");
for (Scope* scope : m_scopes)
{
scope->Deactivate();
@@ -9,10 +9,11 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/RHI/FrameGraphExecuter.h>
#include <Atom/RHI/Buffer.h>
#include <Atom/RHI/FrameGraph.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/FrameGraphExecuteGroup.h>
#include <Atom/RHI/FrameGraphExecuter.h>
#include <Atom/RHI/FrameGraph.h>
#include <Atom/RHI/Image.h>
#include <AzCore/Debug/EventTrace.h>
@@ -80,7 +81,7 @@ namespace AZ
void FrameGraphExecuter::End()
{
AZ_TRACE_METHOD();
AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameGraphExecuter: End");
AZ_Assert(m_pendingGroups.empty(), "Pending contexts in queue.");
m_groups.clear();
EndInternal();
@@ -181,7 +181,10 @@ namespace AZ
m_compileRequest = compileRequest;
FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompile);
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "FrameScheduler: Compile: OnFrameCompile");
FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompile);
}
FrameGraphCompileRequest frameGraphCompileRequest;
frameGraphCompileRequest.m_frameGraph = m_frameGraph.get();
@@ -193,7 +196,10 @@ namespace AZ
const MessageOutcome outcome = m_frameGraphCompiler->Compile(frameGraphCompileRequest);
if (outcome.IsSuccess())
{
FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompileEnd, *m_frameGraph);
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "FrameScheduler: Compile: OnFrameCompileEnd");
FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompileEnd, *m_frameGraph);
}
FrameGraphLogger::Log(*m_frameGraph, compileRequest.m_logVerbosity);
@@ -400,7 +406,11 @@ namespace AZ
m_scopeProducers.clear();
m_scopeProducerLookup.clear();
FrameEventBus::Event(m_device, &FrameEventBus::Events::OnFrameEnd);
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "FrameScheduler: EndFrame: OnFrameEnd");
FrameEventBus::Event(m_device, &FrameEventBus::Events::OnFrameEnd);
}
const AZStd::sys_time_t timeNowTicks = AZStd::GetTimeNowTicks();
m_cpuTimingStatistics.m_frameToFrameTime = timeNowTicks - m_lastFrameEndTime;
+8 -3
View File
@@ -10,6 +10,7 @@
*
*/
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/Device.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RHI/RHISystem.h>
@@ -213,19 +214,23 @@ namespace AZ
void RHISystem::FrameUpdate(FrameGraphCallback frameGraphCallback)
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
AZ_ATOM_PROFILE_FUNCTION("RHI", "RHISystem: FrameUpdate");
{
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzRender, "main per-frame work");
m_frameScheduler.BeginFrame();
frameGraphCallback(m_frameScheduler);
/**
* This exists as a hook to enable RHI sample tests, which are allowed to queue their
* own RHI scopes to the frame scheduler. This happens prior to the RPI pass graph registration.
*/
RHISystemNotificationBus::Broadcast(&RHISystemNotificationBus::Events::OnFramePrepare, m_frameScheduler);
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "RHISystem :FrameUpdate: OnFramePrepare");
RHISystemNotificationBus::Broadcast(&RHISystemNotificationBus::Events::OnFramePrepare, m_frameScheduler);
}
RHI::MessageOutcome outcome = m_frameScheduler.Compile(m_compileRequest);
if (outcome.IsSuccess())
{
@@ -14,6 +14,7 @@
#include <RHI/CommandList.h>
#include <RHI/Conversions.h>
#include <RHI/DescriptorContext.h>
#include <Atom/RHI/CpuProfiler.h>
#include <AzCore/Debug/EventTrace.h>
namespace AZ
@@ -179,6 +180,7 @@ namespace AZ
void CommandListAllocator::Collect()
{
AZ_ATOM_PROFILE_FUNCTION("DX12", "CommandListAllocator: Collect");
for (uint32_t queueIdx = 0; queueIdx < RHI::HardwareQueueClassCount; ++queueIdx)
{
m_commandListSubAllocators[queueIdx].ForEach([](Internal::CommandListSubAllocator& commandListSubAllocator)
@@ -137,6 +137,7 @@ namespace AZ
void CommandQueueContext::End()
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
AZ_ATOM_PROFILE_FUNCTION("DX12", "CommandQueueContext: End");
QueueGpuSignals(m_frameFences[m_currentFrameIndex]);
@@ -150,7 +151,7 @@ namespace AZ
{
AZ_PROFILE_SCOPE_IDLE(AZ::Debug::ProfileCategory::AzRender, "Wait and Reset Fence");
AZ_ATOM_PROFILE_FUNCTION("RHI", "CommandQueueContext: Wait on Fences");
AZ_ATOM_PROFILE_TIME_GROUP_REGION("DX12", "CommandQueueContext: Wait on Fences");
FenceEvent event("FrameFence");
m_frameFences[m_currentFrameIndex].Wait(event);
@@ -15,6 +15,7 @@
#include <RHI/Conversions.h>
#include <RHI/Device.h>
#include <RHI/Image.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h>
namespace AZ
@@ -345,6 +346,7 @@ namespace AZ
void DescriptorContext::GarbageCollect()
{
AZ_ATOM_PROFILE_FUNCTION("DX12", "DescriptorContext: GarbageCollect");
for (const auto& itr : m_platformLimitsDescriptor->m_descriptorHeapLimits)
{
for (uint32_t shaderVisibleIdx = 0; shaderVisibleIdx < PlatformLimitsDescriptor::NumHeapFlags; ++shaderVisibleIdx)
@@ -60,6 +60,7 @@ namespace AZ
void StagingMemoryAllocator::GarbageCollect()
{
AZ_ATOM_PROFILE_FUNCTION("DX12", "StagingMemoryAllocator: GarbageCollect");
m_mediumBlockAllocators.ForEach([](MemoryLinearSubAllocator& subAllocator)
{
subAllocator.GarbageCollect();
@@ -417,7 +417,7 @@ namespace AZ
AZ::IO::FileIOStream sourceMtlfileStream(inputMetalFile.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary);
if (!sourceMtlfileStream.IsOpen())
{
AZ_Error(platformName, false, "Failed because the shader file \"%s\" could not be opened", inputMetalFile);
AZ_Error(platformName, false, "Failed because the shader file \"%s\" could not be opened", inputMetalFile.c_str());
return false;
}
@@ -0,0 +1,43 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
namespace AZ
{
namespace RPI
{
//! Bus for post-load initialization of assets.
//! Assets that need to do post-load initialization should connect to this bus in their asset handler's LoadAssetData() function.
//! Be sure to disconnect from this bus as soon as initialization is complete, as it will be called every frame.
//! (Note this bus is needed rather than utilizing TickBus because TickBus is not protected by a mutex which means it can't be
//! connected on an asset load job thread).
class AssetInitEvents
: public EBusTraits
{
public:
// EBus Configuration
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
typedef AZStd::recursive_mutex MutexType;
//! This function is called every frame on the main thread to perform any necessary post-load initialization.
//! Connect to the bus after loading the asset data, and disconnect when initialization is complete.
//! @return whether initialization was successful
virtual bool PostLoadInit() = 0;
};
using AssetInitBus = AZ::EBus<AssetInitEvents>;
} // namespace RPI
} // namespace AZ
@@ -145,7 +145,7 @@ namespace AZ
// ShaderReloadNotificationBus overrides...
void OnShaderReinitialized(const Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
///////////////////////////////////////////////////////////////////
template<typename Type>
@@ -24,6 +24,11 @@ namespace AZ
//! Connect to this EBus to get notifications whenever material objects reload.
//! The bus address is the AssetId of the MaterialAsset or MaterialTypeAsset.
//!
//! Be careful when using the parameters provided by these functions. The bus ID is an AssetId, and it's possible for the system to have
//! both *old* versions and *new reloaded* versions of the asset in memory at the same time, and they will have the same AssetId. Therefore
//! your bus Handlers could receive Reinitialized messages from multiple sources. It may be necessary to check the memory addresses of these
//! parameters against local members before using this data.
class MaterialReloadNotifications
: public EBusTraits
{
@@ -78,7 +78,7 @@ namespace AZ
// ShaderReloadNotificationBus::Handler overrides...
void OnShaderReinitialized(const Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
void LoadShader();
PassDescriptor m_passDescriptor;
@@ -78,7 +78,7 @@ namespace AZ
// ShaderReloadNotificationBus overrides...
void OnShaderReinitialized(const Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
///////////////////////////////////////////////////////////////////
void LoadShader();
@@ -88,7 +88,7 @@ namespace AZ
// ShaderReloadNotificationBus overrides...
void OnShaderReinitialized(const AZ::RPI::Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override;
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
///////////////////////////////////////////////////////////////////
// Update shader variant from m_shader. It's called whenever shader, shader asset or shader variant were changed.
@@ -12,6 +12,7 @@
#pragma once
#include <Atom/RPI.Public/Shader/ShaderVariant.h>
#include <Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h>
#include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
#include <Atom/RPI.Reflect/Shader/ShaderOptionGroup.h>
@@ -57,6 +58,7 @@ namespace AZ
: public Data::InstanceData
, public Data::AssetBus::Handler
, public ShaderVariantFinderNotificationBus::Handler
, public ShaderReloadNotificationBus::Handler
{
friend class ShaderSystem;
public:
@@ -149,6 +151,15 @@ namespace AZ
void OnShaderVariantTreeAssetReady(Data::Asset<ShaderVariantTreeAsset> /*shaderVariantTreeAsset*/, bool /*isError*/) override {};
void OnShaderVariantAssetReady(Data::Asset<ShaderVariantAsset> shaderVariantAsset, bool IsError) override;
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// ShaderReloadNotificationBus overrides...
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
// Note we don't need OnShaderVariantReinitialized because the Shader class doesn't do anything with the data inside
// the ShaderVariant object. The only thing we might want to do is propagate the message upward, but that's unnecessary
// because the ShaderReloadNotificationBus uses the Shader's AssetId as the ID for all messages including those from the variants.
// And of course we don't need to handle OnShaderReinitialized because this *is* this Shader.
///////////////////////////////////////////////////////////////////
/// Returns the path to the pipeline library cache file.
AZStd::string GetPipelineLibraryPath() const;
@@ -22,10 +22,16 @@ namespace AZ
{
class Shader;
class ShaderAsset;
class ShaderVariant;
/**
* Connect to this EBus to get notifications whenever a Data::Instance<Shader> reloads its ShaderAsset.
* The bus address is the AssetId of the ShaderAsset.
* Connect to this EBus to get notifications whenever a shader system class reinitializes itself.
* The bus address is the AssetId of the ShaderAsset, even when the thing being reinitialized is a ShaderVariant or other shader related class.
*
* Be careful when using the parameters provided by these functions. The bus ID is an AssetId, and it's possible for the system to have
* both *old* versions and *new reloaded* versions of the asset in memory at the same time, and they will have the same AssetId. Therefore
* your bus Handlers could receive Reinitialized messages from multiple sources. It may be necessary to check the memory addresses of these
* parameters against local members before using this data.
*/
class ShaderReloadNotifications
: public EBusTraits
@@ -35,7 +41,7 @@ namespace AZ
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
typedef Data::AssetId BusIdType;
typedef Data::AssetId BusIdType;
//////////////////////////////////////////////////////////////////////////
virtual ~ShaderReloadNotifications() {}
@@ -47,7 +53,7 @@ namespace AZ
virtual void OnShaderReinitialized(const Shader& shader) { AZ_UNUSED(shader); }
//! Called when a particular shader variant is reinitialized.
virtual void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) { AZ_UNUSED(shader); AZ_UNUSED(shaderVariantId); AZ_UNUSED(shaderVariantStableId); }
virtual void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) { AZ_UNUSED(shaderVariant); }
};
typedef EBus<ShaderReloadNotifications> ShaderReloadNotificationBus;
@@ -23,10 +23,12 @@ namespace AZ
//! the RHI::PipelineStateType of the parent Shader instance. For shaders on the raster
//! pipeline, the RHI::DrawFilterTag is also provided.
class ShaderVariant final
: public Data::AssetBus::MultiHandler
{
friend class Shader;
public:
ShaderVariant() = default;
virtual ~ShaderVariant();
AZ_DEFAULT_COPY_MOVE(ShaderVariant);
//! Fills a pipeline state descriptor with settings provided by the ShaderVariant. (Note that
@@ -54,12 +56,21 @@ namespace AZ
bool IsRootVariant() const { return m_shaderVariantAsset->IsRootVariant(); }
ShaderVariantStableId GetStableId() const { return m_shaderVariantAsset->GetStableId(); }
const Data::Asset<ShaderAsset>& GetShaderAsset() const { return m_shaderAsset; }
const Data::Asset<ShaderVariantAsset>& GetShaderVariantAsset() const { return m_shaderVariantAsset; }
private:
// Called by Shader. Initializes runtime data from asset data. Returns whether the call succeeded.
bool Init(
const ShaderAsset& shaderAsset,
Data::Asset<ShaderVariantAsset> shaderVariantAsset);
const Data::Asset<ShaderAsset>& shaderAsset,
const Data::Asset<ShaderVariantAsset>& shaderVariantAsset);
// AssetBus overrides...
void OnAssetReloaded(Data::Asset<Data::AssetData> asset) override;
//! A reference to the shader asset that this is a variant of.
Data::Asset<ShaderAsset> m_shaderAsset;
// Cached state from the asset to avoid an indirection.
RHI::PipelineStateType m_pipelineStateType = RHI::PipelineStateType::Count;
@@ -15,6 +15,7 @@
#include <AzCore/std/containers/vector.h>
#include <AtomCore/std/containers/array_view.h>
#include <Atom/RPI.Public/AssetInitBus.h>
#include <Atom/RPI.Reflect/Base.h>
#include <Atom/RPI.Reflect/Material/MaterialTypeAsset.h>
#include <Atom/RPI.Reflect/Material/MaterialPropertyValue.h>
@@ -38,6 +39,7 @@ namespace AZ
: public AZ::Data::AssetData
, public Data::AssetBus::Handler
, public MaterialReloadNotificationBus::Handler
, public AssetInitBus::Handler
{
friend class MaterialAssetCreator;
friend class MaterialAssetHandler;
@@ -90,13 +92,17 @@ namespace AZ
AZStd::array_view<MaterialPropertyValue> GetPropertyValues() const;
private:
bool PostLoadInit();
bool PostLoadInit() override;
//! Called by asset creators to assign the asset to a ready state.
void SetReady();
// AssetBus overrides...
void OnAssetReloaded(Data::Asset<Data::AssetData> asset) override;
void OnAssetReady(Data::Asset<Data::AssetData> asset) override;
//! Replaces the MaterialTypeAsset when a reload occurs
void ReinitializeMaterialTypeAsset(Data::Asset<Data::AssetData> asset);
// MaterialReloadNotificationBus overrides...
void OnMaterialTypeAssetReinitialized(const Data::Asset<MaterialTypeAsset>& materialTypeAsset) override;
@@ -17,6 +17,7 @@
#include <AzCore/EBus/Event.h>
#include <AtomCore/std/containers/array_view.h>
#include <Atom/RPI.Public/AssetInitBus.h>
#include <Atom/RPI.Reflect/Base.h>
#include <Atom/RPI.Reflect/Material/ShaderCollection.h>
#include <Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h>
@@ -52,6 +53,7 @@ namespace AZ
class MaterialTypeAsset
: public AZ::Data::AssetData
, public Data::AssetBus::MultiHandler
, public AssetInitBus::Handler
{
friend class MaterialTypeAssetCreator;
friend class MaterialTypeAssetHandler;
@@ -100,13 +102,17 @@ namespace AZ
MaterialUvNameMap GetUvNameMap() const;
private:
bool PostLoadInit();
bool PostLoadInit() override;
//! Called by asset creators to assign the asset to a ready state.
void SetReady();
// AssetBus overrides...
void OnAssetReloaded(Data::Asset<Data::AssetData> asset) override;
void OnAssetReady(Data::Asset<Data::AssetData> asset) override;
//! Replaces the appropriate asset members when a reload occurs
void ReinitializeAsset(Data::Asset<Data::AssetData> asset);
//! Holds values for each material property, used to initialize Material instances.
//! This is indexed by MaterialPropertyIndex and aligns with entries in m_materialPropertiesLayout.
@@ -15,6 +15,7 @@
#include <AzCore/std/optional.h>
#include <AzCore/EBus/Event.h>
#include <Atom/RPI.Public/AssetInitBus.h>
#include <Atom/RPI.Reflect/Asset/AssetHandler.h>
#include <Atom/RPI.Reflect/Shader/ShaderOptionGroupLayout.h>
#include <Atom/RPI.Reflect/Shader/ShaderVariantAsset.h>
@@ -40,6 +41,7 @@ namespace AZ
: public Data::AssetData
, public ShaderVariantFinderNotificationBus::Handler
, public Data::AssetBus::Handler
, public AssetInitBus::Handler
{
friend class ShaderAssetCreator;
friend class ShaderAssetHandler;
@@ -134,8 +136,11 @@ namespace AZ
///////////////////////////////////////////////////////////////////
/// AssetBus overrides
void OnAssetReloaded(Data::Asset<Data::AssetData> asset) override;
void OnAssetReady(Data::Asset<Data::AssetData> asset) override;
///////////////////////////////////////////////////////////////////
void ReinitializeRootShaderVariant(Data::Asset<Data::AssetData> asset);
///////////////////////////////////////////////////////////////////
/// ShaderVariantFinderNotificationBus overrides
void OnShaderVariantTreeAssetReady(Data::Asset<ShaderVariantTreeAsset> shaderVariantTreeAsset, bool isError) override;
@@ -165,8 +170,13 @@ namespace AZ
RHI::ShaderStageAttributeMapList m_attributeMaps;
};
bool FinalizeAfterLoad();
bool PostLoadInit() override;
void SetReady();
//! SelectShaderApiData() must be called before most other ShaderAsset functions.
bool SelectShaderApiData();
//! Returns the active ShaderApiDataContainer which was selected in SelectShaderApiData().
ShaderApiDataContainer& GetCurrentShaderApiData();
const ShaderApiDataContainer& GetCurrentShaderApiData() const;
@@ -216,7 +226,6 @@ namespace AZ
const Data::Asset<Data::AssetData>& asset,
AZStd::shared_ptr<Data::AssetDataStream> stream,
const Data::AssetFilterCB& assetLoadFilterCB) override;
Data::AssetHandler::LoadResult PostLoadInit(const Data::Asset<Data::AssetData>& asset);
};
//////////////////////////////////////////////////////////////////////////
@@ -11,6 +11,7 @@
*/
#include <Atom/RHI/CommandList.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RHI/FrameGraphInterface.h>
#include <Atom/RHI/RHISystemInterface.h>
@@ -78,6 +79,7 @@ namespace AZ
void GpuQuerySystem::Update()
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "GpuQuerySystem: Update");
for (auto& queryPool : m_queryPoolArray)
{
if (queryPool)
@@ -242,8 +242,16 @@ namespace AZ
// MaterialReloadNotificationBus overrides...
void Material::OnMaterialAssetReinitialized(const Data::Asset<MaterialAsset>& materialAsset)
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnMaterialAssetReinitialized %s", this, materialAsset.GetHint().c_str());
OnAssetReloaded(materialAsset);
// It's important that we don't just pass materialAsset to Init() because when reloads occur,
// it's possible for old Asset objects to hang around and report reinitialization, so materialAsset
// might be stale data.
if (materialAsset.Get() == m_materialAsset.Get())
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnMaterialAssetReinitialized %s", this, materialAsset.GetHint().c_str());
OnAssetReloaded(m_materialAsset);
}
}
///////////////////////////////////////////////////////////////////
@@ -259,8 +267,6 @@ namespace AZ
void Material::OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset)
{
// TODO: I think we should make Shader handle OnShaderAssetReinitialized and treat it just like the shader reloaded.
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str());
// Note that it might not be strictly necessary to reinitialize the entire material, we might be able to get away with
// just bumping the m_currentChangeId or some other minor updates. But it's pretty hard to know what exactly needs to be
@@ -268,9 +274,9 @@ namespace AZ
OnAssetReloaded(m_materialAsset);
}
void Material::OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& /*shaderVariantId*/, ShaderVariantStableId shaderVariantStableId)
void Material::OnShaderVariantReinitialized(const ShaderVariant& shaderVariant)
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderVariantReinitialized %s variant %u", this, shader.GetAsset().GetHint().c_str(), shaderVariantStableId.GetIndex());
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderVariantReinitialized %s", this, shaderVariant.GetShaderVariantAsset().GetHint().c_str());
// Note that it would be better to check the shaderVariantId to see if that variant is relevant to this particular material before reinitializing it.
// There could be hundreds or even thousands of variants for a shader, but only one of those variants will be used by any given material. So we could
@@ -241,9 +241,8 @@ namespace AZ
LoadShader();
}
void ComputePass::OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId)
void ComputePass::OnShaderVariantReinitialized(const ShaderVariant&)
{
AZ_UNUSED(shader); AZ_UNUSED(shaderVariantId); AZ_UNUSED(shaderVariantStableId);
LoadShader();
}
@@ -57,7 +57,7 @@ namespace AZ
LoadShader();
}
void FullscreenTrianglePass::OnShaderVariantReinitialized(const Shader&, const ShaderVariantId&, ShaderVariantStableId)
void FullscreenTrianglePass::OnShaderVariantReinitialized(const ShaderVariant&)
{
LoadShader();
}
@@ -61,6 +61,11 @@ namespace AZ
{
const PassAttachmentBinding& binding = m_attachmentBindings[slotIndex];
if (!binding.m_attachment)
{
continue;
}
// Handle the depth-stencil attachment. There should be only one.
if (binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::DepthStencil)
{
@@ -98,6 +103,10 @@ namespace AZ
{
continue;
}
if (!binding.m_attachment)
{
continue;
}
if (binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::RenderTarget
|| binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::DepthStencil)
@@ -124,12 +124,9 @@ namespace AZ
RefreshShaderVariant();
}
void PipelineStateForDraw::OnShaderVariantReinitialized(
[[maybe_unused]] const Shader& shader,
const ShaderVariantId& shaderVariantId,
[[maybe_unused]] ShaderVariantStableId shaderVariantStableId)
void PipelineStateForDraw::OnShaderVariantReinitialized(const ShaderVariant& shaderVariant)
{
if(shaderVariantId == m_shaderVariantId)
if(shaderVariant.GetShaderVariantId() == m_shaderVariantId)
{
RefreshShaderVariant();
}
@@ -23,6 +23,7 @@
#include <Atom/RPI.Reflect/System/RenderPipelineDescriptor.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <Atom/RPI.Public/AssetInitBus.h>
#include <Atom/RPI.Public/FeatureProcessor.h>
#include <Atom/RPI.Public/GpuQuery/GpuQueryTypes.h>
#include <Atom/RPI.Public/Scene.h>
@@ -240,6 +241,8 @@ namespace AZ
}
AZ_ATOM_PROFILE_FUNCTION("RPI", "RPISystem: SimulationTick");
AssetInitBus::Broadcast(&AssetInitBus::Events::PostLoadInit);
// Update tick time info
FillTickTimeInfo();
@@ -279,24 +282,27 @@ namespace AZ
m_rhiSystem.FrameUpdate(
[this](RHI::FrameGraphBuilder& frameGraphBuilder)
{
// Pass system's frame update, which includes the logic of adding scope producers, has to be added here since the scope producers only can be added to the frame
// when frame started which cleans up previous scope producers.
m_passSystem.FrameUpdate(frameGraphBuilder);
{
// Pass system's frame update, which includes the logic of adding scope producers, has to be added here since the
// scope producers only can be added to the frame when frame started which cleans up previous scope producers.
m_passSystem.FrameUpdate(frameGraphBuilder);
// Update View Srgs
for (auto& scenePtr : m_scenes)
{
scenePtr->UpdateSrgs();
}
});
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "RPISystem: FrameEnd");
m_dynamicDraw.FrameEnd();
m_passSystem.FrameEnd();
// Update View Srgs
for (auto& scenePtr : m_scenes)
{
scenePtr->UpdateSrgs();
scenePtr->OnFrameEnd();
}
});
m_dynamicDraw.FrameEnd();
m_passSystem.FrameEnd();
for (auto& scenePtr : m_scenes)
{
scenePtr->OnFrameEnd();
}
m_renderTick++;
+17 -8
View File
@@ -404,6 +404,7 @@ namespace AZ
{
AZ_PROFILE_SCOPE(Debug::ProfileCategory::AzRender, "WaitForSimulationCompletion");
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "WaitForSimulationCompletion");
WaitAndCleanCompletionJob(m_simulationCompletion);
}
@@ -420,12 +421,15 @@ namespace AZ
// Get active pipelines which need to be rendered and notify them frame started
AZStd::vector<RenderPipelinePtr> activePipelines;
for (auto& pipeline : m_pipelines)
{
if (pipeline->NeedsRender())
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "OnStartFrame");
for (auto& pipeline : m_pipelines)
{
activePipelines.push_back(pipeline);
pipeline->OnStartFrame(tickInfo);
if (pipeline->NeedsRender())
{
activePipelines.push_back(pipeline);
pipeline->OnStartFrame(tickInfo);
}
}
}
@@ -444,7 +448,7 @@ namespace AZ
{
AZ_PROFILE_SCOPE(Debug::ProfileCategory::AzRender, "Setup Views");
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Setup Views");
// Collect persistent views from all pipelines to be rendered
AZStd::map<ViewPtr, RHI::DrawListMask> persistentViews;
@@ -490,7 +494,6 @@ namespace AZ
{
const auto renderLambda = [this, &fp]()
{
AZ_PROFILE_SCOPE_DYNAMIC(Debug::ProfileCategory::AzRender, "renderJob - fp:%s", fp->RTTI_GetTypeName());
fp->Render(m_renderPacket);
};
@@ -526,12 +529,14 @@ namespace AZ
// Add dynamic draw data for all the views
if (m_dynamicDrawSystem)
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "DynamicDraw SubmitDrawData");
m_dynamicDrawSystem->SubmitDrawData(this, m_renderPacket.m_views);
}
}
{
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzRender, "FinalizeDrawLists");
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "FinalizeDrawLists");
if (jobPolicy == RHI::JobPolicy::Serial)
{
for (auto& view : m_renderPacket.m_views)
@@ -542,7 +547,6 @@ namespace AZ
else
{
AZ::JobCompletion* finalizeDrawListsCompletion = aznew AZ::JobCompletion();
AZ_PROFILE_EVENT_BEGIN(Debug::ProfileCategory::AzRender, "StartFinalizeDrawListsJobs");
for (auto& view : m_renderPacket.m_views)
{
const auto finalizeDrawListsLambda = [view]()
@@ -559,11 +563,15 @@ namespace AZ
}
}
SceneNotificationBus::Event(GetId(), &SceneNotification::OnEndPrepareRender);
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Scene OnEndPrepareRender");
SceneNotificationBus::Event(GetId(), &SceneNotification::OnEndPrepareRender);
}
}
void Scene::OnFrameEnd()
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: OnFrameEnd");
for (auto& pipeline : m_pipelines)
{
if (pipeline->NeedsRender())
@@ -702,6 +710,7 @@ namespace AZ
void Scene::RebuildPipelineStatesLookup()
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: RebuildPipelineStatesLookup");
m_pipelineStatesLookup.clear();
AZStd::queue<ParentPass*> parents;
@@ -21,7 +21,6 @@
#include <AtomCore/Instance/InstanceDatabase.h>
#include <AzCore/Interface/Interface.h>
#include <Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h>
#include <Atom/RPI.Public/Shader/ShaderReloadDebugTracker.h>
namespace AZ
@@ -55,8 +54,9 @@ namespace AZ
RHI::ResultCode Shader::Init(ShaderAsset& shaderAsset)
{
Data::AssetBus::Handler::BusDisconnect();
ShaderReloadNotificationBus::Handler::BusDisconnect();
ShaderVariantFinderNotificationBus::Handler::BusDisconnect();
ShaderVariantFinderNotificationBus::Handler::BusConnect(shaderAsset.GetId());
RHI::RHISystemInterface* rhiSystem = RHI::RHISystemInterface::Get();
RHI::DrawListTagRegistry* drawListTagRegistry = rhiSystem->GetDrawListTagRegistry();
@@ -68,7 +68,7 @@ namespace AZ
AZStd::unique_lock<decltype(m_variantCacheMutex)> lock(m_variantCacheMutex);
m_shaderVariants.clear();
}
m_rootVariant.Init(shaderAsset, shaderAsset.GetRootVariant());
m_rootVariant.Init(Data::Asset<ShaderAsset>{&shaderAsset, AZ::Data::AssetLoadBehavior::PreLoad}, shaderAsset.GetRootVariant());
if (m_pipelineLibraryHandle.IsNull())
{
@@ -100,8 +100,10 @@ namespace AZ
AZ_Error("Shader", false, "Failed to acquire a DrawListTag. Entries are full.");
}
}
ShaderVariantFinderNotificationBus::Handler::BusConnect(m_asset.GetId());
Data::AssetBus::Handler::BusConnect(m_asset.GetId());
ShaderReloadNotificationBus::Handler::BusConnect(m_asset.GetId());
return RHI::ResultCode::Success;
}
@@ -110,6 +112,7 @@ namespace AZ
{
ShaderVariantFinderNotificationBus::Handler::BusDisconnect();
Data::AssetBus::Handler::BusDisconnect();
ShaderReloadNotificationBus::Handler::BusDisconnect();
if (m_pipelineLibraryHandle.IsValid())
{
@@ -139,7 +142,6 @@ namespace AZ
Data::Asset<ShaderAsset> newAsset = { asset.GetAs<ShaderAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
AZ_Assert(newAsset, "Reloaded ShaderAsset is null");
Data::AssetBus::Handler::BusDisconnect();
Init(*newAsset.Get());
ShaderReloadNotificationBus::Event(asset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderReinitialized, *this);
}
@@ -152,7 +154,14 @@ namespace AZ
{
AZ_Assert(shaderVariantAsset, "Reloaded ShaderVariantAsset is null");
const ShaderVariantStableId stableId = shaderVariantAsset->GetStableId();
const ShaderVariantId& shaderVariantId = shaderVariantAsset->GetShaderVariantId();
// We make a copy of the updated variant because OnShaderVariantReinitialized must not be called inside
// m_variantCacheMutex or deadlocks may occur.
// Or if there is an error, we leave this object in its default state to indicate there was an error.
// [GFX TODO] We really should have a dedicated message/event for this, but that will be covered by a future task where
// we will merge ShaderReloadNotificationBus messages into one. For now, we just indicate the error by passing an empty ShaderVariant,
// all our call sites don't use this data anyway.
ShaderVariant updatedVariant;
if (isError)
{
@@ -163,7 +172,7 @@ namespace AZ
return;
}
AZStd::unique_lock<decltype(m_variantCacheMutex)> lock(m_variantCacheMutex);
m_shaderVariants.erase(stableId);
m_shaderVariants.erase(stableId);
}
else
{
@@ -176,26 +185,47 @@ namespace AZ
{
ShaderVariant& shaderVariant = iter->second;
if (!shaderVariant.Init(*m_asset.Get(), shaderVariantAsset))
if (!shaderVariant.Init(m_asset, shaderVariantAsset))
{
AZ_Error("Shader", false, "Failed to init shaderVariant with StableId=%u", shaderVariantAsset->GetStableId());
m_shaderVariants.erase(stableId);
}
else
{
updatedVariant = shaderVariant;
}
}
else
{
//This is the first time the shader variant asset comes to life.
ShaderVariant newVariant;
newVariant.Init(*m_asset, shaderVariantAsset);
m_shaderVariants.emplace(stableId, newVariant);
updatedVariant.Init(m_asset, shaderVariantAsset);
m_shaderVariants.emplace(stableId, updatedVariant);
}
}
//Even if there was an error, the interested parties should be notified.
ShaderReloadNotificationBus::Event(m_asset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this, shaderVariantId, stableId);
// [GFX TODO] It might make more sense to call OnShaderReinitialized here
ShaderReloadNotificationBus::Event(m_asset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, updatedVariant);
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// ShaderReloadNotificationBus overrides...
void Shader::OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset)
{
// When reloads occur, it's possible for old Asset objects to hang around and report reinitialization,
// so we can reduce unnecessary reinitialization in that case.
if (shaderAsset.Get() == m_asset.Get())
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Shader::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str());
Init(*m_asset.Get());
ShaderReloadNotificationBus::Event(shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderReinitialized, *this);
}
}
///////////////////////////////////////////////////////////////////
ConstPtr<RHI::PipelineLibraryData> Shader::LoadPipelineLibrary() const
{
if (IO::FileIOBase::GetInstance())
@@ -325,7 +355,7 @@ namespace AZ
}
ShaderVariant newVariant;
newVariant.Init(*m_asset, shaderVariantAsset);
newVariant.Init(m_asset, shaderVariantAsset);
m_shaderVariants.emplace(shaderVariantStableId, newVariant);
return m_shaderVariants.at(shaderVariantStableId);
@@ -9,11 +9,13 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/RPI.Public/Shader/ShaderVariant.h>
#include <Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h>
#include <Atom/RPI.Public/Shader/ShaderReloadDebugTracker.h>
#include <Atom/RHI/DrawListTagRegistry.h>
#include <Atom/RHI/RHISystemInterface.h>
#include <Atom/RHI.Reflect/ShaderStageFunction.h>
namespace AZ
@@ -21,15 +23,26 @@ namespace AZ
namespace RPI
{
bool ShaderVariant::Init(
const ShaderAsset& shaderAsset,
Data::Asset<ShaderVariantAsset> shaderVariantAsset)
{
m_pipelineStateType = shaderAsset.GetPipelineStateType();
m_pipelineLayoutDescriptor = shaderAsset.GetPipelineLayoutDescriptor();
const Data::Asset<ShaderAsset>& shaderAsset,
const Data::Asset<ShaderVariantAsset>& shaderVariantAsset)
{
Data::AssetBus::MultiHandler::BusDisconnect();
Data::AssetBus::MultiHandler::BusConnect(shaderAsset.GetId());
Data::AssetBus::MultiHandler::BusConnect(shaderVariantAsset.GetId());
m_shaderAsset = shaderAsset;
m_pipelineStateType = shaderAsset->GetPipelineStateType();
m_pipelineLayoutDescriptor = shaderAsset->GetPipelineLayoutDescriptor();
m_shaderVariantAsset = shaderVariantAsset;
return true;
}
ShaderVariant::~ShaderVariant()
{
Data::AssetBus::MultiHandler::BusDisconnect();
}
void ShaderVariant::ConfigurePipelineState(RHI::PipelineStateDescriptor& descriptor) const
{
descriptor.m_pipelineLayoutDescriptor = m_pipelineLayoutDescriptor;
@@ -78,5 +91,25 @@ namespace AZ
{
return m_shaderVariantAsset->GetOutputContract();
}
void ShaderVariant::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderVariant::OnAssetReloaded %s", this, asset.GetHint().c_str());
if (asset.GetAs<ShaderVariantAsset>())
{
Data::Asset<ShaderVariantAsset> shaderVariantAsset = { asset.GetAs<ShaderVariantAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
Init(m_shaderAsset, shaderVariantAsset);
ShaderReloadNotificationBus::Event(m_shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this);
}
if (asset.GetAs<ShaderAsset>())
{
Data::Asset<ShaderAsset> shaderAsset = { asset.GetAs<ShaderAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
Init(shaderAsset, m_shaderVariantAsset);
ShaderReloadNotificationBus::Event(m_shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this);
}
}
} // namespace RPI
} // namespace AZ
@@ -323,9 +323,8 @@ namespace AZ
void ShaderVariantAsyncLoader::Reset()
{
// [GFX TODO ATOM-14544] Idealy we want to be able to reset the ShaderVariantAsyncLoader but this is causing some problems that need to be worked out first.
//Shutdown();
//Init();
Shutdown();
Init();
}
///////////////////////////////////////////////////////////////////
@@ -18,6 +18,7 @@
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Component/TickBus.h>
namespace AZ
{
@@ -47,6 +48,7 @@ namespace AZ
{
MaterialReloadNotificationBus::Handler::BusDisconnect();
Data::AssetBus::Handler::BusDisconnect();
AssetInitBus::Handler::BusDisconnect();
}
const Data::Asset<MaterialTypeAsset>& MaterialAsset::GetMaterialTypeAsset() const
@@ -97,6 +99,8 @@ namespace AZ
{
if (!m_materialTypeAsset.Get())
{
AssetInitBus::Handler::BusDisconnect();
// Any MaterialAsset with invalid MaterialTypeAsset is not a successfully-loaded asset.
return false;
}
@@ -104,23 +108,30 @@ namespace AZ
{
Data::AssetBus::Handler::BusConnect(m_materialTypeAsset.GetId());
MaterialReloadNotificationBus::Handler::BusConnect(m_materialTypeAsset.GetId());
AssetInitBus::Handler::BusDisconnect();
return true;
}
}
void MaterialAsset::OnMaterialTypeAssetReinitialized(const Data::Asset<MaterialTypeAsset>&)
void MaterialAsset::OnMaterialTypeAssetReinitialized(const Data::Asset<MaterialTypeAsset>& materialTypeAsset)
{
// MaterialAsset doesn't need to reinitialize any of its own data when MaterialTypeAsset reinitializes,
// because all it depends on is the MaterialTypeAsset reference, rather than the data inside it.
// Ultimately it's the Material that cares about these changes, so we just forward any signal we get.
MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialAssetReinitialized, Data::Asset<MaterialAsset>{this, AZ::Data::AssetLoadBehavior::PreLoad});
// When reloads occur, it's possible for old Asset objects to hang around and report reinitialization,
// so we can reduce unnecessary reinitialization in that case.
if (materialTypeAsset.Get() == m_materialTypeAsset.Get())
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnMaterialTypeAssetReinitialized %s", this, materialTypeAsset.GetHint().c_str());
// MaterialAsset doesn't need to reinitialize any of its own data when MaterialTypeAsset reinitializes,
// because all it depends on is the MaterialTypeAsset reference, rather than the data inside it.
// Ultimately it's the Material that cares about these changes, so we just forward any signal we get.
MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialAssetReinitialized, Data::Asset<MaterialAsset>{this, AZ::Data::AssetLoadBehavior::PreLoad});
}
}
void MaterialAsset::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
void MaterialAsset::ReinitializeMaterialTypeAsset(Data::Asset<Data::AssetData> asset)
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnAssetReloaded %s", this, asset.GetHint().c_str());
Data::Asset<MaterialTypeAsset> newMaterialTypeAsset = { asset.GetAs<MaterialTypeAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
if (newMaterialTypeAsset)
@@ -135,16 +146,31 @@ namespace AZ
}
}
void MaterialAsset::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnAssetReloaded %s", this, asset.GetHint().c_str());
ReinitializeMaterialTypeAsset(asset);
}
void MaterialAsset::OnAssetReady(Data::Asset<Data::AssetData> asset)
{
// Regarding why we listen to both OnAssetReloaded and OnAssetReady, see explanation in ShaderAsset::OnAssetReady.
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnAssetReady %s", this, asset.GetHint().c_str());
ReinitializeMaterialTypeAsset(asset);
}
Data::AssetHandler::LoadResult MaterialAssetHandler::LoadAssetData(
const AZ::Data::Asset<AZ::Data::AssetData>& asset,
AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
const AZ::Data::AssetFilterCB& assetLoadFilterCB)
{
Data::AssetHandler::LoadResult baseResult = Base::LoadAssetData(asset, stream, assetLoadFilterCB);
bool postLoadResult = asset.GetAs<MaterialAsset>()->PostLoadInit();
return ((baseResult == Data::AssetHandler::LoadResult::LoadComplete) && postLoadResult) ?
Data::AssetHandler::LoadResult::LoadComplete :
Data::AssetHandler::LoadResult::Error;
if (Base::LoadAssetData(asset, stream, assetLoadFilterCB) == Data::AssetHandler::LoadResult::LoadComplete)
{
asset.GetAs<MaterialAsset>()->AssetInitBus::Handler::BusConnect();
return Data::AssetHandler::LoadResult::LoadComplete;
}
return Data::AssetHandler::LoadResult::Error;
}
} // namespace RPI
@@ -65,6 +65,7 @@ namespace AZ
MaterialTypeAsset::~MaterialTypeAsset()
{
Data::AssetBus::MultiHandler::BusDisconnect();
AssetInitBus::Handler::BusDisconnect();
}
const ShaderCollection& MaterialTypeAsset::GetShaderCollection() const
@@ -116,6 +117,8 @@ namespace AZ
Data::AssetBus::MultiHandler::BusConnect(shaderItem.GetShaderAsset().GetId());
}
AssetInitBus::Handler::BusDisconnect();
return true;
}
@@ -127,11 +130,9 @@ namespace AZ
assetToReplace = newAsset;
}
}
void MaterialTypeAsset::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
void MaterialTypeAsset::ReinitializeAsset(Data::Asset<Data::AssetData> asset)
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialTypeAsset::OnAssetReloaded %s", this, asset.GetHint().c_str());
// The order of asset reloads is non-deterministic. If the MaterialTypeAsset reloads before these
// dependency assets, this will make sure the MaterialTypeAsset gets the latest ones when they reload.
// Or in some cases a these assets could get updated and reloaded without reloading the MaterialTypeAsset at all.
@@ -146,16 +147,31 @@ namespace AZ
MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialTypeAssetReinitialized, Data::Asset<MaterialTypeAsset>{this, AZ::Data::AssetLoadBehavior::PreLoad});
}
void MaterialTypeAsset::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialTypeAsset::OnAssetReloaded %s", this, asset.GetHint().c_str());
ReinitializeAsset(asset);
}
void MaterialTypeAsset::OnAssetReady(Data::Asset<Data::AssetData> asset)
{
// Regarding why we listen to both OnAssetReloaded and OnAssetReady, see explanation in ShaderAsset::OnAssetReady.
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialTypeAsset::OnAssetReady %s", this, asset.GetHint().c_str());
ReinitializeAsset(asset);
}
AZ::Data::AssetHandler::LoadResult MaterialTypeAssetHandler::LoadAssetData(
const AZ::Data::Asset<AZ::Data::AssetData>& asset,
AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
const AZ::Data::AssetFilterCB& assetLoadFilterCB)
{
Data::AssetHandler::LoadResult baseResult = Base::LoadAssetData(asset, stream, assetLoadFilterCB);
bool postLoadResult = asset.GetAs<MaterialTypeAsset>()->PostLoadInit();
return ((baseResult == Data::AssetHandler::LoadResult::LoadComplete) && postLoadResult) ?
Data::AssetHandler::LoadResult::LoadComplete :
Data::AssetHandler::LoadResult::Error;
if (Base::LoadAssetData(asset, stream, assetLoadFilterCB) == Data::AssetHandler::LoadResult::LoadComplete)
{
asset.GetAs<MaterialTypeAsset>()->AssetInitBus::Handler::BusConnect();
return Data::AssetHandler::LoadResult::LoadComplete;
}
return Data::AssetHandler::LoadResult::Error;
}
}
@@ -85,6 +85,7 @@ namespace AZ
{
Data::AssetBus::Handler::BusDisconnect();
ShaderVariantFinderNotificationBus::Handler::BusDisconnect();
AssetInitBus::Handler::BusDisconnect();
}
const Name& ShaderAsset::GetName() const
@@ -331,8 +332,8 @@ namespace AZ
// We may only endup here when running in a Builder context.
return m_perAPIShaderData[0];
}
bool ShaderAsset::FinalizeAfterLoad()
bool ShaderAsset::SelectShaderApiData()
{
// Use the current RHI that is active to select which shader data to use.
// We don't assert if the Factory is not available because this method could be called during build time,
@@ -370,28 +371,51 @@ namespace AZ
}
}
return true;
}
bool ShaderAsset::PostLoadInit()
{
// Once the ShaderAsset is loaded, it is necessary to listen for changes in the Root Variant Asset.
Data::AssetBus::Handler::BusConnect(GetRootVariant().GetId());
ShaderVariantFinderNotificationBus::Handler::BusConnect(GetId());
AssetInitBus::Handler::BusDisconnect();
return true;
}
void ShaderAsset::ReinitializeRootShaderVariant(Data::Asset<Data::AssetData> asset)
{
Data::Asset<ShaderVariantAsset> shaderVariantAsset = { asset.GetAs<ShaderVariantAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
AZ_Assert(shaderVariantAsset->GetStableId() == RootShaderVariantStableId, "Was expecting to update the root variant");
GetCurrentShaderApiData().m_rootShaderVariantAsset = asset;
ShaderReloadNotificationBus::Event(GetId(), &ShaderReloadNotificationBus::Events::OnShaderAssetReinitialized, Data::Asset<ShaderAsset>{ this, AZ::Data::AssetLoadBehavior::PreLoad } );
}
///////////////////////////////////////////////////////////////////////
// AssetBus overrides...
void ShaderAsset::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
{
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderAsset::OnAssetReloaded %s", this, asset.GetHint().c_str());
ReinitializeRootShaderVariant(asset);
}
void ShaderAsset::OnAssetReady(Data::Asset<Data::AssetData> asset)
{
// We have to listen to OnAssetReady, OnAssetReloaded isn't enough, because of the following scenario:
// The user changes a .shader file, which causes the AP to rebuild the ShaderAsset and root ShaderVariantAsset.
// 1) Thread A creates the new ShaderAsset, loads it, and gets the old ShaderVariantAsset.
// 2) Thread B creates the new ShaderVariantAsset, loads it, and calls OnAssetReloaded.
// 3) Main thread calls ShaderAsset::PostLoadInit which connects to the AssetBus but it's too late to receive OnAssetReloaded,
// so it continues using the old ShaderVariantAsset instead of the new one.
// The OnAssetReady bus function is called automatically whenever a connection to AssetBus is made, so listening to this gives
// us the opportunity to assign the appropriate ShaderVariantAsset.
Data::Asset<ShaderVariantAsset> shaderVariantAsset = { asset.GetAs<ShaderVariantAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
AZ_Assert(shaderVariantAsset->GetStableId() == RootShaderVariantStableId,
"Was expecting to update the root variant");
GetCurrentShaderApiData().m_rootShaderVariantAsset = asset;
ShaderReloadNotificationBus::Event(GetId(), &ShaderReloadNotificationBus::Events::OnShaderAssetReinitialized, Data::Asset<ShaderAsset>{ this, AZ::Data::AssetLoadBehavior::PreLoad } );
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderAsset::OnAssetReady %s", this, asset.GetHint().c_str());
ReinitializeRootShaderVariant(asset);
}
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
/// ShaderVariantFinderNotificationBus overrides
void ShaderAsset::OnShaderVariantTreeAssetReady(Data::Asset<ShaderVariantTreeAsset> shaderVariantTreeAsset, bool isError)
@@ -425,25 +449,25 @@ namespace AZ
{
if (Base::LoadAssetData(asset, stream, assetLoadFilterCB) == Data::AssetHandler::LoadResult::LoadComplete)
{
return PostLoadInit(asset);
}
return Data::AssetHandler::LoadResult::Error;
}
ShaderAsset* shaderAsset = asset.GetAs<ShaderAsset>();
Data::AssetHandler::LoadResult ShaderAssetHandler::PostLoadInit(const Data::Asset<Data::AssetData>& asset)
{
if (ShaderAsset* shaderAsset = asset.GetAs<ShaderAsset>())
{
if (!shaderAsset->FinalizeAfterLoad())
// The shader API selection must occur immediately ofter loading, on the same thread, rather than
// deferring to AssetInitBus::PostLoadInit. Many functions in the ShaderAsset class are invalid
// until after SelectShaderApiData() is called and some client code may need to access data in
// the ShaderAsset before then.
if (!shaderAsset->SelectShaderApiData())
{
AZ_Error("ShaderAssetHandler", false, "Shader asset failed to finalize.");
return Data::AssetHandler::LoadResult::Error;
}
shaderAsset->AssetInitBus::Handler::BusConnect();
return Data::AssetHandler::LoadResult::LoadComplete;
}
return Data::AssetHandler::LoadResult::Error;
}
///////////////////////////////////////////////////////////////////////
} // namespace RPI
@@ -218,7 +218,7 @@ namespace AZ
return false;
}
if (!m_asset->FinalizeAfterLoad())
if (!m_asset->SelectShaderApiData())
{
ReportError("Failed to finalize the ShaderAsset.");
return false;
@@ -56,7 +56,7 @@ namespace AZ
AZ::Data::Asset<ShaderAsset> SerializeInHelper(const AZ::Data::AssetId& assetId)
{
AZ::Data::Asset<ShaderAsset> asset = Base::SerializeIn(assetId);
asset->FinalizeAfterLoad();
asset->SelectShaderApiData();
asset->SetReady();
return asset;
}
@@ -10,6 +10,7 @@
#
set(FILES
Include/Atom/RPI.Public/AssetInitBus.h
Include/Atom/RPI.Public/Base.h
Include/Atom/RPI.Public/Culling.h
Include/Atom/RPI.Public/FeatureProcessor.h
@@ -13,6 +13,7 @@
#pragma once
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
namespace AZ
{
@@ -56,6 +57,16 @@ namespace AZ
ImGuiTextFilter m_timedRegionFilter;
GroupRegionMap m_groupRegionMap;
// Pause cpu profiling. The profiler will show the statistics of the last frame before pause
bool m_paused = false;
// Total frames need to be saved
int m_captureFrameCount = 1;
AZ::RHI::CpuTimingStatistics m_cpuTimingStatisticsWhenPause;
AZStd::string m_lastCapturedFilePath;
};
} // namespace Render
}
@@ -10,7 +10,10 @@
*
*/
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
#include <Atom/Feature/Utils/ProfilingCaptureBus.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <AzCore/IO/SystemFile.h> // For AZ_MAX_PATH_LEN
#include <AzCore/std/time.h>
namespace AZ
{
@@ -34,16 +37,42 @@ namespace AZ
}
}
inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics)
inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics)
{
// Cache the value to detect if it was changed by ImGui(user pressed 'x')
const bool cachedShowCpuProfiler = keepDrawing;
const ImVec2 windowSize(640.0f, 480.0f);
ImGui::SetNextWindowSize(windowSize, ImGuiCond_Once);
bool captureToFile = false;
if (ImGui::Begin("Cpu Profiler", &keepDrawing, ImGuiWindowFlags_None))
{
UpdateGroupRegionMap();
m_paused = !AZ::RHI::CpuProfiler::Get()->IsProfilerEnabled();
if (ImGui::Button(m_paused?"Resume":"Pause"))
{
m_paused = !m_paused;
AZ::RHI::CpuProfiler::Get()->SetProfilerEnabled(!m_paused);
}
// Update region map and cache the input cpu timing statistics when the profiling is not paused
if (!m_paused)
{
UpdateGroupRegionMap();
m_cpuTimingStatisticsWhenPause = currentCpuTimingStatistics;
}
if (ImGui::Button("Capture"))
{
captureToFile = true;
}
if (!m_lastCapturedFilePath.empty())
{
ImGui::SameLine();
ImGui::Text(m_lastCapturedFilePath.c_str());
}
const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics = m_cpuTimingStatisticsWhenPause;
const AZStd::sys_time_t ticksPerSecond = AZStd::GetTimeTicksPerSecond();
@@ -51,7 +80,7 @@ namespace AZ
{
// Note: converting to microseconds integer before converting to milliseconds float
const float timeInMs = static_cast<float>((duration * 1000) / (ticksPerSecond / 1000)) / 1000.0f;
ImGui::Text("%.1f ms", timeInMs);
ImGui::Text("%.2f ms", timeInMs);
};
const auto ShowRow = [ticksPerSecond, &ShowTimeInMs](const char* regionLabel, AZStd::sys_time_t duration)
@@ -158,6 +187,20 @@ namespace AZ
}
ImGui::End();
if (captureToFile)
{
AZStd::sys_time_t timeNow = AZStd::GetTimeNowSecond();
AZStd::string timeString;
AZStd::to_string(timeString, timeNow);
u64 currentTick = AZ::RPI::RPISystemInterface::Get()->GetCurrentTick();
AZStd::string frameDataFilePath = AZStd::string::format("@user@/CpuProfiler/%s_%llu.json", timeString.c_str(), currentTick);
char resolvedPath[AZ_MAX_PATH_LEN];
AZ::IO::FileIOBase::GetInstance()->ResolvePath(frameDataFilePath.c_str(), resolvedPath, AZ_MAX_PATH_LEN);
m_lastCapturedFilePath = resolvedPath;
AZ::Render::ProfilingCaptureRequestBus::Broadcast(&AZ::Render::ProfilingCaptureRequestBus::Events::CaptureCpuProfilingStatistics,
frameDataFilePath);
}
// Toggle if the bool isn't the same as the cached value
if (cachedShowCpuProfiler != keepDrawing)
{
+4
View File
@@ -8,3 +8,7 @@
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
add_subdirectory(LookDevelopmentStudioPixar)
add_subdirectory(ReferenceMaterials)
add_subdirectory(Sponza)
@@ -0,0 +1,15 @@
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# This will export its "SourcePaths" to the generated "cmake_dependencies.<project>.assetbuilder.setreg"
if(PAL_TRAIT_BUILD_HOST_TOOLS)
ly_create_alias(NAME AtomContent_LookDevelopmentStudioPixar.Builders NAMESPACE Gem)
endif()
@@ -0,0 +1,15 @@
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# This will export its "SourcePaths" to the generated "cmake_dependencies.<project>.assetbuilder.setreg"
if(PAL_TRAIT_BUILD_HOST_TOOLS)
ly_create_alias(NAME AtomContent_ReferenceMaterials.Builders NAMESPACE Gem)
endif()
+15
View File
@@ -0,0 +1,15 @@
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
# This will export its "SourcePaths" to the generated "cmake_dependencies.<project>.assetbuilder.setreg"
if(PAL_TRAIT_BUILD_HOST_TOOLS)
ly_create_alias(NAME AtomContent_Sponza.Builders NAMESPACE Gem)
endif()
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bb8c1839f46df4623818bc1b02f626d85d8f83d77cbeabd0d56c6a5c997c3ab3
size 495250984
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9bb547a502aa028624e3f95491d2e459860db5fdc5551eece757c271362c902d
size 42981863
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:962248929564f7a3a2a25813ba8ab83d72f2f4d8db71eb495bd650ad4eca5c25
size 8681159
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2c5998edda6eb34ace8b7a5f63e72f922e0daebb6aeb453142b31e605157736d
size 17366289
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a79b82df3f6f908b2ed31f9247d9befde7daf0ff53c87479920c0463cc12d437
size 1308624196

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