Merge branch 'stabilization/2106' into JsonSerialization/ArrayDefaultsFix
This commit is contained in:
@@ -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
|
||||
|
||||
-96
@@ -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)
|
||||
|
||||
+115
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
@@ -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)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
+12
-6
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+10
-6
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -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
|
||||
|
||||
+2
@@ -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);
|
||||
|
||||
@@ -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,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;
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
@@ -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
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9bb547a502aa028624e3f95491d2e459860db5fdc5551eece757c271362c902d
|
||||
size 42981863
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:962248929564f7a3a2a25813ba8ab83d72f2f4d8db71eb495bd650ad4eca5c25
|
||||
size 8681159
|
||||
-3
@@ -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
Reference in New Issue
Block a user