Merged from main

This commit is contained in:
pereslav
2021-05-18 13:10:44 +01:00
1102 changed files with 6650 additions and 72333 deletions
@@ -12,6 +12,7 @@
#pragma once
#include <AzCore/Debug/AssetTrackingTypes.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
namespace AssetMemoryAnalyzer
{
@@ -79,7 +79,7 @@ namespace ImageProcessingAtom
builderDescriptor.m_busId = azrtti_typeid<ImageBuilderWorker>();
builderDescriptor.m_createJobFunction = AZStd::bind(&ImageBuilderWorker::CreateJobs, &m_imageBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
builderDescriptor.m_processJobFunction = AZStd::bind(&ImageBuilderWorker::ProcessJob, &m_imageBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
builderDescriptor.m_version = 22; // [ATOM-14765]
builderDescriptor.m_version = 23; // [ATOM-14022]
builderDescriptor.m_analysisFingerprint = ImageProcessingAtom::BuilderSettingManager::Instance()->GetAnalysisFingerprint();
m_imageBuilder.BusConnect(builderDescriptor.m_busId);
AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBusTraits::RegisterBuilderInformation, builderDescriptor);
@@ -0,0 +1,197 @@
/*
* 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.
*
*/
// Description : Contains portable definition of structs and enums to match
// those in DXGIFormat.h in the DirectX SDK
#pragma once
#include <AzCore/PlatformDef.h>
#if __has_include(<dxgiformat.h>)
# include <dxgiformat.h>
// For non-windows platforms need to define the formats so that the ImageExtension
// class used by the editor can have access to these
#else
#define DXGI_FORMAT_DEFINED 1
typedef enum DXGI_FORMAT
{
DXGI_FORMAT_UNKNOWN = 0,
DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
DXGI_FORMAT_R32G32B32A32_UINT = 3,
DXGI_FORMAT_R32G32B32A32_SINT = 4,
DXGI_FORMAT_R32G32B32_TYPELESS = 5,
DXGI_FORMAT_R32G32B32_FLOAT = 6,
DXGI_FORMAT_R32G32B32_UINT = 7,
DXGI_FORMAT_R32G32B32_SINT = 8,
DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
DXGI_FORMAT_R16G16B16A16_UNORM = 11,
DXGI_FORMAT_R16G16B16A16_UINT = 12,
DXGI_FORMAT_R16G16B16A16_SNORM = 13,
DXGI_FORMAT_R16G16B16A16_SINT = 14,
DXGI_FORMAT_R32G32_TYPELESS = 15,
DXGI_FORMAT_R32G32_FLOAT = 16,
DXGI_FORMAT_R32G32_UINT = 17,
DXGI_FORMAT_R32G32_SINT = 18,
DXGI_FORMAT_R32G8X24_TYPELESS = 19,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
DXGI_FORMAT_R10G10B10A2_UNORM = 24,
DXGI_FORMAT_R10G10B10A2_UINT = 25,
DXGI_FORMAT_R11G11B10_FLOAT = 26,
DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
DXGI_FORMAT_R8G8B8A8_UNORM = 28,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
DXGI_FORMAT_R8G8B8A8_UINT = 30,
DXGI_FORMAT_R8G8B8A8_SNORM = 31,
DXGI_FORMAT_R8G8B8A8_SINT = 32,
DXGI_FORMAT_R16G16_TYPELESS = 33,
DXGI_FORMAT_R16G16_FLOAT = 34,
DXGI_FORMAT_R16G16_UNORM = 35,
DXGI_FORMAT_R16G16_UINT = 36,
DXGI_FORMAT_R16G16_SNORM = 37,
DXGI_FORMAT_R16G16_SINT = 38,
DXGI_FORMAT_R32_TYPELESS = 39,
DXGI_FORMAT_D32_FLOAT = 40,
DXGI_FORMAT_R32_FLOAT = 41,
DXGI_FORMAT_R32_UINT = 42,
DXGI_FORMAT_R32_SINT = 43,
DXGI_FORMAT_R24G8_TYPELESS = 44,
DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
DXGI_FORMAT_R8G8_TYPELESS = 48,
DXGI_FORMAT_R8G8_UNORM = 49,
DXGI_FORMAT_R8G8_UINT = 50,
DXGI_FORMAT_R8G8_SNORM = 51,
DXGI_FORMAT_R8G8_SINT = 52,
DXGI_FORMAT_R16_TYPELESS = 53,
DXGI_FORMAT_R16_FLOAT = 54,
DXGI_FORMAT_D16_UNORM = 55,
DXGI_FORMAT_R16_UNORM = 56,
DXGI_FORMAT_R16_UINT = 57,
DXGI_FORMAT_R16_SNORM = 58,
DXGI_FORMAT_R16_SINT = 59,
DXGI_FORMAT_R8_TYPELESS = 60,
DXGI_FORMAT_R8_UNORM = 61,
DXGI_FORMAT_R8_UINT = 62,
DXGI_FORMAT_R8_SNORM = 63,
DXGI_FORMAT_R8_SINT = 64,
DXGI_FORMAT_A8_UNORM = 65,
DXGI_FORMAT_R1_UNORM = 66,
DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
DXGI_FORMAT_BC1_TYPELESS = 70,
DXGI_FORMAT_BC1_UNORM = 71,
DXGI_FORMAT_BC1_UNORM_SRGB = 72,
DXGI_FORMAT_BC2_TYPELESS = 73,
DXGI_FORMAT_BC2_UNORM = 74,
DXGI_FORMAT_BC2_UNORM_SRGB = 75,
DXGI_FORMAT_BC3_TYPELESS = 76,
DXGI_FORMAT_BC3_UNORM = 77,
DXGI_FORMAT_BC3_UNORM_SRGB = 78,
DXGI_FORMAT_BC4_TYPELESS = 79,
DXGI_FORMAT_BC4_UNORM = 80,
DXGI_FORMAT_BC4_SNORM = 81,
DXGI_FORMAT_BC5_TYPELESS = 82,
DXGI_FORMAT_BC5_UNORM = 83,
DXGI_FORMAT_BC5_SNORM = 84,
DXGI_FORMAT_B5G6R5_UNORM = 85,
DXGI_FORMAT_B5G5R5A1_UNORM = 86,
DXGI_FORMAT_B8G8R8A8_UNORM = 87,
DXGI_FORMAT_B8G8R8X8_UNORM = 88,
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
DXGI_FORMAT_BC6H_TYPELESS = 94,
DXGI_FORMAT_BC6H_UF16 = 95,
DXGI_FORMAT_BC6H_SF16 = 96,
DXGI_FORMAT_BC7_TYPELESS = 97,
DXGI_FORMAT_BC7_UNORM = 98,
DXGI_FORMAT_BC7_UNORM_SRGB = 99,
DXGI_FORMAT_EAC_R11_TYPELESS = 200,
DXGI_FORMAT_EAC_R11_UNORM = 201,
DXGI_FORMAT_EAC_R11_SNORM = 202,
DXGI_FORMAT_EAC_RG11_TYPELESS = 203,
DXGI_FORMAT_EAC_RG11_UNORM = 204,
DXGI_FORMAT_EAC_RG11_SNORM = 205,
DXGI_FORMAT_ETC2_TYPELESS = 206,
DXGI_FORMAT_ETC2_UNORM = 207,
DXGI_FORMAT_ETC2_UNORM_SRGB = 208,
DXGI_FORMAT_ETC2A_TYPELESS = 209,
DXGI_FORMAT_ETC2A_UNORM = 210,
DXGI_FORMAT_ETC2A_UNORM_SRGB = 211,
DXGI_FORMAT_PVRTC2_TYPELESS = 250,
DXGI_FORMAT_PVRTC2_UNORM = 251,
DXGI_FORMAT_PVRTC2_UNORM_SRGB = 252,
DXGI_FORMAT_PVRTC4_TYPELESS = 253,
DXGI_FORMAT_PVRTC4_UNORM = 254,
DXGI_FORMAT_PVRTC4_UNORM_SRGB = 255,
DXGI_FORMAT_ASTC_4x4_TYPELESS = 260,
DXGI_FORMAT_ASTC_4x4_UNORM = 261,
DXGI_FORMAT_ASTC_4x4_UNORM_SRGB = 262,
DXGI_FORMAT_ASTC_5x4_TYPELESS = 263,
DXGI_FORMAT_ASTC_5x4_UNORM = 264,
DXGI_FORMAT_ASTC_5x4_UNORM_SRGB = 265,
DXGI_FORMAT_ASTC_5x5_TYPELESS = 266,
DXGI_FORMAT_ASTC_5x5_UNORM = 267,
DXGI_FORMAT_ASTC_5x5_UNORM_SRGB = 268,
DXGI_FORMAT_ASTC_6x5_TYPELESS = 269,
DXGI_FORMAT_ASTC_6x5_UNORM = 270,
DXGI_FORMAT_ASTC_6x5_UNORM_SRGB = 271,
DXGI_FORMAT_ASTC_6x6_TYPELESS = 272,
DXGI_FORMAT_ASTC_6x6_UNORM = 273,
DXGI_FORMAT_ASTC_6x6_UNORM_SRGB = 274,
DXGI_FORMAT_ASTC_8x5_TYPELESS = 275,
DXGI_FORMAT_ASTC_8x5_UNORM = 276,
DXGI_FORMAT_ASTC_8x5_UNORM_SRGB = 277,
DXGI_FORMAT_ASTC_8x6_TYPELESS = 278,
DXGI_FORMAT_ASTC_8x6_UNORM = 279,
DXGI_FORMAT_ASTC_8x6_UNORM_SRGB = 280,
DXGI_FORMAT_ASTC_8x8_TYPELESS = 281,
DXGI_FORMAT_ASTC_8x8_UNORM = 282,
DXGI_FORMAT_ASTC_8x8_UNORM_SRGB = 283,
DXGI_FORMAT_ASTC_10x5_TYPELESS = 284,
DXGI_FORMAT_ASTC_10x5_UNORM = 285,
DXGI_FORMAT_ASTC_10x5_UNORM_SRGB = 286,
DXGI_FORMAT_ASTC_10x6_TYPELESS = 287,
DXGI_FORMAT_ASTC_10x6_UNORM = 288,
DXGI_FORMAT_ASTC_10x6_UNORM_SRGB = 289,
DXGI_FORMAT_ASTC_10x8_TYPELESS = 290,
DXGI_FORMAT_ASTC_10x8_UNORM = 291,
DXGI_FORMAT_ASTC_10x8_UNORM_SRGB = 292,
DXGI_FORMAT_ASTC_10x10_TYPELESS = 293,
DXGI_FORMAT_ASTC_10x10_UNORM = 294,
DXGI_FORMAT_ASTC_10x10_UNORM_SRGB = 295,
DXGI_FORMAT_ASTC_12x10_TYPELESS = 296,
DXGI_FORMAT_ASTC_12x10_UNORM = 297,
DXGI_FORMAT_ASTC_12x10_UNORM_SRGB = 298,
DXGI_FORMAT_ASTC_12x12_TYPELESS = 299,
DXGI_FORMAT_ASTC_12x12_UNORM = 300,
DXGI_FORMAT_ASTC_12x12_UNORM_SRGB = 301,
DXGI_FORMAT_FORCE_UINT = 0xffffffff
} DXGI_FORMAT;
#endif
@@ -15,9 +15,6 @@
#include <AzCore/std/algorithm.h>
#include <ImageProcessing_Traits_Platform.h>
//! The following defines and constants are extracted from ImageExtensionHelper.h
//! Please make sure they are always synced with ImageExtensionHelper.h
#define IMAGE_BUIDER_MAKEFOURCC(ch0, ch1, ch2, ch3) \
((AZ::u32)(AZ::u8)(ch0) | ((AZ::u32)(AZ::u8)(ch1) << 8) | \
((AZ::u32)(AZ::u8)(ch2) << 16) | ((AZ::u32)(AZ::u8)(ch3) << 24))
@@ -19,6 +19,7 @@
#include <Processing/ImageFlags.h>
#include <Atom/RHI.Reflect/Format.h>
#include <Atom/RHI.Reflect/ImageSubresource.h>
#include <Atom/RPI.Reflect/Image/StreamingImageAssetCreator.h>
#include <Atom/RPI.Reflect/Image/ImageMipChainAssetCreator.h>
@@ -238,14 +239,9 @@ namespace ImageProcessingAtom
uint8_t* mipBuffer;
uint32_t pitch;
m_imageObject->GetImagePointer(mip, mipBuffer, pitch);
uint32_t mipBufferSize = m_imageObject->GetMipBufSize(mip);
RHI::ImageSubresourceLayout layout;
layout.m_bytesPerImage = mipBufferSize / arraySize;
layout.m_rowCount = layout.m_bytesPerImage / pitch;
layout.m_size = RHI::Size(m_imageObject->GetWidth(mip), m_imageObject->GetHeight(mip) / arraySize, 1);
layout.m_bytesPerRow = pitch;
RHI::Format format = Utils::PixelFormatToRHIFormat(m_imageObject->GetPixelFormat(), m_imageObject->HasImageFlags(EIF_SRGBRead));
RHI::ImageSubresourceLayout layout = RHI::GetImageSubresourceLayout(RHI::Size(m_imageObject->GetWidth(mip), m_imageObject->GetHeight(mip) / arraySize, 1), format);
builder.BeginMip(layout);
for (uint32_t arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex)
@@ -12,9 +12,6 @@
#pragma once
//! The following constants are extracted from ImageExtensionHelper.h
//! Please make sure they are always synced with the same constants defined in ImageExtensionHelper.h
namespace ImageProcessingAtom
{
// flags to propagate from the RC to the engine through GetImageFlags()
@@ -164,7 +164,7 @@ namespace ImageProcessingAtom
AZ::Color m_colMinARGB; // ARGB will be added the properties of the DDS file
AZ::Color m_colMaxARGB; // ARGB will be added the properties of the DDS file
float m_averageBrightness; // will be added to the properties of the DDS file
AZ::u32 m_imageFlags; // combined from CImageExtensionHelper::EIF_Cubemap,...
AZ::u32 m_imageFlags; //
AZ::u32 m_numPersistentMips; // number of mipmaps won't be splitted
public:
@@ -12,7 +12,7 @@
#pragma once
#include <AzDXGIFormat.h> // DX10+ formats. DXGI_FORMAT
#include <Processing/AzDXGIFormat.h> // DX10+ formats. DXGI_FORMAT
#include <Atom/ImageProcessing/PixelFormats.h>
@@ -41,6 +41,7 @@ set(FILES
Source/BuilderSettings/PresetSettings.h
Source/BuilderSettings/TextureSettings.cpp
Source/BuilderSettings/TextureSettings.h
Source/Processing/AzDXGIFormat.h
Source/Processing/DDSHeader.h
Source/Processing/ImageAssetProducer.cpp
Source/Processing/ImageAssetProducer.h
@@ -1,27 +0,0 @@
{
"gem_name": "ImageProcessingAtom",
"Dependencies": [
{
"Uuid": "a218db9eb2114477b46600fea4441a6c",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RPI"
}
],
"GemFormatVersion": 4,
"Uuid": "9d10b00be96045caa64c705e5772cb64",
"Name": "ImageProcessingAtom",
"DisplayName": "Atom.Asset.ImageProcessing",
"Version": "0.1.0",
"Summary": "Contains Asset Processor builder for processing image files for Atom and UI for Atom texture property editing in Asset Browser",
"Tags": [ "Atom Image Builder", "Atom Texture Property Editor" ],
"LinkType": "Dynamic",
"IconPath": "preview.png",
"Modules": [
{
"Name": "Editor",
"Type": "EditorModule"
}
]
}
-27
View File
@@ -1,27 +0,0 @@
{
"gem_name": "Atom_Asset_Shader",
"Dependencies": [
{
"Uuid": "a218db9eb2114477b46600fea4441a6c",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RPI"
}
],
"GemFormatVersion": 4,
"Uuid": "d32452026dae4b7dba2ad89dbde9c48f",
"Name": "Atom_Asset_Shader",
"DisplayName": "Atom.Asset.Shader",
"Version": "0.1.0",
"Summary": "The systems necessary to build and use AZSL Shaders",
"Tags": ["Assets", "Atom", "Shader"],
"LinkType": "Dynamic",
"IconPath": "preview.png",
"Modules": [
{
"Name": "Builders",
"Type": "EditorModule"
}
]
}
-25
View File
@@ -1,25 +0,0 @@
{
"gem_name": "Atom_Bootstrap",
"Dependencies": [
{
"Uuid": "a218db9eb2114477b46600fea4441a6c",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RPI.Public"
}
],
"GemFormatVersion": 4,
"Uuid": "c7ff89ad6e8b4b45b2fadef2bcf12d6e",
"Name": "Atom_Bootstrap",
"DisplayName": "Atom.Bootstrap",
"Version": "0.1.0",
"Summary": "Bootstrap gem to setup any necessary Atom components.",
"Tags": ["Atom", "Bootstrap"],
"IconPath": "preview.png",
"Modules": [
{
"Type": "GameModule"
}
]
}
-25
View File
@@ -1,25 +0,0 @@
{
"gem_name": "Atom_Component_DebugCamera",
"Dependencies": [
{
"Uuid": "a218db9eb2114477b46600fea4441a6c",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RPI"
}
],
"GemFormatVersion": 4,
"Uuid": "013d1b42ad314c929b292c143bcbf045",
"Version": "0.1.0",
"Name": "Atom_Component_DebugCamera",
"DisplayName": "Atom.Component.DebugCamera",
"Tags": ["Atom", "Camera", "Debug"],
"Summary": "Debug Camera for testing RPI/RHI",
"IconPath": "preview.png",
"Modules": [
{
"Type": "GameModule"
}
]
}
@@ -0,0 +1,10 @@
The papermill 'Image base lighting' (IBL) images are modified from the following:
http://www.hdrlabs.com/sibl/archive.html
'Papermill Ruins E'
All sIBL-sets on this page, including the images within, are licensed under the Creative Commons Attribution-Noncommercial-Share Alike 3.0 License.
Creative Commons License: http://creativecommons.org/licenses/by-nc-sa/3.0/us/
Remember: Do what you want with them, but always mention where you got them from...
@@ -274,6 +274,10 @@ namespace AZ
passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurPass"), &Render::ReflectionScreenSpaceBlurPass::Create);
passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurChildPass"), &Render::ReflectionScreenSpaceBlurChildPass::Create);
passSystem->AddPassCreator(Name("ReflectionCopyFrameBufferPass"), &Render::ReflectionCopyFrameBufferPass::Create);
// setup handler for load pass template mappings
m_loadTemplatesHandler = RPI::PassSystemInterface::OnReadyLoadTemplatesEvent::Handler([this]() { this->LoadPassTemplateMappings(); });
RPI::PassSystemInterface::Get()->ConnectEvent(m_loadTemplatesHandler);
}
void CommonSystemComponent::Deactivate()
@@ -292,5 +296,12 @@ namespace AZ
AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor<TransformServiceFeatureProcessor>();
AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor<AuxGeomFeatureProcessor>();
}
void CommonSystemComponent::LoadPassTemplateMappings()
{
const char* passTemplatesFile = "Passes/PassTemplates.azasset";
RPI::PassSystemInterface::Get()->LoadPassTemplateMappings(passTemplatesFile);
}
} // namespace Render
} // namespace AZ
@@ -14,6 +14,8 @@
#include <AzCore/Component/Component.h>
#include <Atom_Feature_Traits_Platform.h>
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
#if AZ_TRAIT_LUXCORE_SUPPORTED
#include "LuxCore/LuxCoreRenderer.h"
#endif
@@ -41,6 +43,11 @@ namespace AZ
void Activate() override;
void Deactivate() override;
// Load pass template mappings for this gem
void LoadPassTemplateMappings();
RPI::PassSystemInterface::OnReadyLoadTemplatesEvent::Handler m_loadTemplatesHandler;
#if AZ_TRAIT_LUXCORE_SUPPORTED
// LuxCore
LuxCoreRenderer m_luxCore;
@@ -134,7 +134,14 @@ namespace AZ
{
m_decalData.GetData(decal.GetIndex()) = m_decalData.GetData(sourceDecal.GetIndex());
const auto materialAsset = GetMaterialUsedByDecal(sourceDecal);
m_materialToTextureArrayLookupTable.at(materialAsset).m_useCount++;
if (materialAsset.IsValid())
{
m_materialToTextureArrayLookupTable.at(materialAsset).m_useCount++;
}
else
{
AZ_Warning("DecalTextureArrayFeatureProcessor", false, "CloneDecal called on a decal with no material set.");
}
m_deviceBufferNeedsUpdate = true;
}
return decal;
@@ -49,11 +49,6 @@ namespace AZ
}
}
DiffuseProbeGridRayTracingPass::~DiffuseProbeGridRayTracingPass()
{
delete m_rayTracingScopeProducerShaderTable;
}
void DiffuseProbeGridRayTracingPass::CreateRayTracingPipelineState()
{
RHI::Ptr<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
@@ -118,19 +113,28 @@ namespace AZ
void DiffuseProbeGridRayTracingPass::FrameBeginInternal(FramePrepareParams params)
{
RPI::Scene* scene = m_pipeline->GetScene();
RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor<RayTracingFeatureProcessor>();
if (!rayTracingFeatureProcessor)
{
return;
}
if (!m_initialized)
{
CreateRayTracingPipelineState();
CreateShaderTableScope();
m_initialized = true;
}
if (!m_rayTracingShaderTable)
{
RHI::Ptr<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
RHI::RayTracingBufferPools& rayTracingBufferPools = rayTracingFeatureProcessor->GetBufferPools();
m_rayTracingShaderTable = RHI::Factory::Get().CreateRayTracingShaderTable();
m_rayTracingShaderTable->Init(*device.get(), rayTracingBufferPools);
}
RPI::Scene* scene = m_pipeline->GetScene();
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty())
{
@@ -138,70 +142,9 @@ namespace AZ
return;
}
RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor<RayTracingFeatureProcessor>();
uint32_t rayTracingRevision = rayTracingFeatureProcessor->GetRevision();
if (m_rayTracingRevision != rayTracingRevision)
{
// scene changed, need to rebuild the shader table
m_rayTracingRevision = rayTracingRevision;
// [GFX TODO][ATOM-13575] Move the RHI::RayTracingShaderTable build into the RHI frame and remove this scope
params.m_frameGraphBuilder->ImportScopeProducer(*m_rayTracingScopeProducerShaderTable);
}
RenderPass::FrameBeginInternal(params);
}
void DiffuseProbeGridRayTracingPass::CreateShaderTableScope()
{
struct ScopeData { };
const auto prepareFunction = [this]([[maybe_unused]] RHI::FrameGraphInterface& scopeBuilder, [[maybe_unused]] ScopeData& scopeData) {};
const auto compileFunction = [this]([[maybe_unused]] const RHI::FrameGraphCompileContext& context, [[maybe_unused]] const ScopeData& scopeData) {};
const auto executeFunction = [this]([[maybe_unused]] const RHI::FrameGraphExecuteContext& context, [[maybe_unused]] const ScopeData& scopeData)
{
RHI::Ptr<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
RayTracingFeatureProcessor* rayTracingFeatureProcessor = m_pipeline->GetScene()->GetFeatureProcessor<RayTracingFeatureProcessor>();
RHI::RayTracingBufferPools& rayTracingBufferPools = rayTracingFeatureProcessor->GetBufferPools();
if (!rayTracingFeatureProcessor->GetSubMeshCount())
{
m_rayTracingShaderTable = nullptr;
return;
}
// build the ray tracing shader table descriptor
RHI::RayTracingShaderTableDescriptor descriptor;
RHI::RayTracingShaderTableDescriptor* descriptorBuild = descriptor.Build(AZ::Name("RayTracingShaderTable"), m_rayTracingPipelineState)
->RayGenerationRecord(AZ::Name("RayGen"))
->MissRecord(AZ::Name("Miss"));
// add a hit group for each mesh to the shader table
for (uint32_t i = 0; i < rayTracingFeatureProcessor->GetSubMeshCount(); ++i)
{
descriptorBuild->HitGroupRecord(AZ::Name("HitGroup"));
}
m_rayTracingShaderTable->Init(*device.get(), &descriptor, rayTracingBufferPools);
};
AZStd::string uuidString = AZ::Uuid::CreateRandom().ToString<AZStd::string>();
AZStd::string scopeName = AZStd::string::format("DiffuseProbeRayTracingBuildShaderTable_%s", uuidString.c_str());
m_rayTracingScopeProducerShaderTable =
aznew RHI::ScopeProducerFunction<
ScopeData,
decltype(prepareFunction),
decltype(compileFunction),
decltype(executeFunction)>(
RHI::ScopeId{ scopeName },
ScopeData{ },
prepareFunction,
compileFunction,
executeFunction);
}
void DiffuseProbeGridRayTracingPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
{
RenderPass::SetupFrameGraphDependencies(frameGraph);
@@ -211,7 +154,6 @@ namespace AZ
RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor<RayTracingFeatureProcessor>();
frameGraph.SetEstimatedItemCount(aznumeric_cast<uint32_t>(diffuseProbeGridFeatureProcessor->GetProbeGrids().size()));
frameGraph.ExecuteAfter(m_rayTracingScopeProducerShaderTable->GetScopeId());
for (const auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
{
@@ -326,6 +268,31 @@ namespace AZ
diffuseProbeGrid->GetRayTraceSrg()->Compile();
}
}
uint32_t rayTracingRevision = rayTracingFeatureProcessor->GetRevision();
if (m_rayTracingRevision != rayTracingRevision)
{
// scene changed, need to rebuild the shader table
m_rayTracingRevision = rayTracingRevision;
AZStd::shared_ptr<RHI::RayTracingShaderTableDescriptor> descriptor = AZStd::make_shared<RHI::RayTracingShaderTableDescriptor>();
if (rayTracingFeatureProcessor->GetSubMeshCount())
{
// build the ray tracing shader table descriptor
RHI::RayTracingShaderTableDescriptor* descriptorBuild = descriptor->Build(AZ::Name("RayTracingShaderTable"), m_rayTracingPipelineState)
->RayGenerationRecord(AZ::Name("RayGen"))
->MissRecord(AZ::Name("Miss"));
// add a hit group for each mesh to the shader table
for (uint32_t i = 0; i < rayTracingFeatureProcessor->GetSubMeshCount(); ++i)
{
descriptorBuild->HitGroupRecord(AZ::Name("HitGroup"));
}
}
m_rayTracingShaderTable->Build(descriptor);
}
}
void DiffuseProbeGridRayTracingPass::BuildCommandListInternal([[maybe_unused]] const RHI::FrameGraphExecuteContext& context)
@@ -35,8 +35,6 @@ namespace AZ
AZ_RTTI(DiffuseProbeGridRayTracingPass, "{CB0DF817-3D07-4AC7-8574-F5EE529B8DCA}", RPI::RenderPass);
AZ_CLASS_ALLOCATOR(DiffuseProbeGridRayTracingPass, SystemAllocator, 0);
virtual ~DiffuseProbeGridRayTracingPass() override;
//! Creates a DiffuseProbeGridRayTracingPass
static RPI::Ptr<DiffuseProbeGridRayTracingPass> Create(const RPI::PassDescriptor& descriptor);
@@ -44,7 +42,6 @@ namespace AZ
explicit DiffuseProbeGridRayTracingPass(const RPI::PassDescriptor& descriptor);
void CreateRayTracingPipelineState();
void CreateShaderTableScope();
// Scope producer functions
void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override;
@@ -65,7 +62,6 @@ namespace AZ
// ray tracing shader table
RHI::Ptr<RHI::RayTracingShaderTable> m_rayTracingShaderTable;
RHI::ScopeProducer* m_rayTracingScopeProducerShaderTable = nullptr;
// ray tracing global shader resource group asset and pipeline state
Data::Asset<RPI::ShaderResourceGroupAsset> m_globalSrgAsset;
-43
View File
@@ -1,43 +0,0 @@
{
"gem_name": "Atom_Feature_Common",
"Dependencies": [
{
"Uuid": "a218db9eb2114477b46600fea4441a6c",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RPI"
}
],
"GemFormatVersion": 4,
"Uuid": "b58e5eed0901428ca78544b04dbd61bd",
"Name": "Atom_Feature_Common",
"DisplayName": "Atom.Feature.Common",
"Version": "0.1.0",
"LinkType": "Dynamic",
"Summary": "Provides commonly used render features.",
"Tags": [ "Atom", "Feature", "Common" ],
"IconPath": "preview.png",
"Modules": [
{
"Type": "GameModule"
},
{
"Name": "Builders",
"Type": "EditorModule"
},
{
"Name": "Public",
"Type": "StaticLib"
},
{
"Name": "Editor",
"Type": "EditorModule",
"Extends": "GameModule"
},
{
"Name": "StaticLibrary",
"Type": "StaticLib"
}
]
}
@@ -100,7 +100,9 @@ namespace AZ
Size size,
uint32_t rowCount,
uint32_t bytesPerRow,
uint32_t bytesPerImage);
uint32_t bytesPerImage,
uint32_t numBlocksWidth,
uint32_t numBlocksHeight);
/// The size of the image subresource in pixels. Certain formats have alignment requirements.
/// Block compressed formats are 4 pixel aligned. Other non-standard formats may be 2 pixel aligned.
@@ -114,6 +116,13 @@ namespace AZ
/// The number of bytes in a single image slice. 3D textures are comprised of m_size.m_depth image slices.
uint32_t m_bytesPerImage = 0;
/// The number of blocks in width based on the texture fomat
uint32_t m_blockElementWidth = 1;
/// The number of blocks in height based on the texture fomat
uint32_t m_blockElementHeight = 1;
};
struct ImageSubresourceLayoutPlaced : ImageSubresourceLayout
@@ -18,6 +18,7 @@
#include <Atom/RHI/FrameGraphExecuter.h>
#include <Atom/RHI/FrameGraphCompiler.h>
#include <Atom/RHI/FrameGraph.h>
#include <Atom/RHI/RayTracingShaderTable.h>
#include <Atom/RHI/ScopeProducer.h>
#include <Atom/RHI/ScopeProducerEmpty.h>
#include <Atom/RHI/TransientAttachmentPool.h>
@@ -181,6 +182,9 @@ namespace AZ
const TransientAttachmentPoolDescriptor* GetTransientAttachmentPoolDescriptor() const;
//! Adds a RayTracingShaderTable to be built this frame
void QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable);
private:
const ScopeId m_rootScopeId{"Root"};
@@ -190,6 +194,7 @@ namespace AZ
void PrepareProducers();
void CompileProducers();
void CompileShaderResourceGroups();
void BuildRayTracingShaderTables();
ScopeProducer* FindScopeProducer(const ScopeId& scopeId);
@@ -224,6 +229,9 @@ namespace AZ
AZStd::unique_ptr<ScopeProducerEmpty> m_rootScopeProducer;
AZStd::vector<ScopeProducer*> m_scopeProducers;
AZStd::unordered_map<ScopeId, ScopeProducer*> m_scopeProducerLookup;
// list of RayTracingShaderTables that should be built this frame
AZStd::vector<RHI::Ptr<RayTracingShaderTable>> m_rayTracingShaderTablesToBuild;
};
}
}
@@ -57,6 +57,7 @@ namespace AZ
const RHI::TransientAttachmentStatistics* GetTransientAttachmentStatistics() const override;
const RHI::TransientAttachmentPoolDescriptor* GetTransientAttachmentPoolDescriptor() const override;
ConstPtr<PlatformLimitsDescriptor> GetPlatformLimitsDescriptor() const override;
void QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable) override;
//////////////////////////////////////////////////////////////////////////
private:
@@ -26,6 +26,7 @@ namespace AZ
class PipelineState;
class PipelineStateCache;
class PlatformLimitsDescriptor;
class RayTracingShaderTable;
struct CpuTimingStatistics;
struct FrameSchedulerCompileRequest;
struct TransientAttachmentStatistics;
@@ -61,6 +62,8 @@ namespace AZ
virtual const RHI::TransientAttachmentPoolDescriptor* GetTransientAttachmentPoolDescriptor() const = 0;
virtual ConstPtr<PlatformLimitsDescriptor> GetPlatformLimitsDescriptor() const = 0;
virtual void QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable) = 0;
};
//! This bus exists to give RHI samples the ability to slot in scopes manually
@@ -97,18 +97,30 @@ namespace AZ
virtual ~RayTracingShaderTable() = default;
static RHI::Ptr<RHI::RayTracingShaderTable> CreateRHIRayTracingShaderTable();
void Init(Device& device, const RayTracingBufferPools& rayTracingBufferPools);
ResultCode Init(Device& device, const RayTracingShaderTableDescriptor* descriptor, const RayTracingBufferPools& rayTracingBufferPools);
//! Queues this RayTracingShaderTable to be built by the FrameScheduler.
//! Note that the descriptor must be heap allocated, preferably using make_shared.
void Build(const AZStd::shared_ptr<RayTracingShaderTableDescriptor> descriptor);
protected:
AZStd::shared_ptr<RayTracingShaderTableDescriptor> m_descriptor;
const RayTracingBufferPools* m_bufferPools = nullptr;
private:
// explicit shutdown is not allowed for this type
void Shutdown() override final;
friend class FrameScheduler;
/// Called by the FrameScheduler to validate the state prior to building
void Validate();
//////////////////////////////////////////////////////////////////////////
// Platform API
virtual RHI::ResultCode InitInternal(RHI::Device& deviceBase, const RHI::RayTracingShaderTableDescriptor* descriptor, const RayTracingBufferPools& bufferPools) = 0;
virtual RHI::ResultCode BuildInternal() = 0;
//////////////////////////////////////////////////////////////////////////
bool m_isQueuedForBuild = false;
};
}
}
@@ -102,11 +102,13 @@ namespace AZ
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<ImageSubresourceLayout>()
->Version(0)
->Version(1)
->Field("m_size", &ImageSubresourceLayout::m_size)
->Field("m_rowCount", &ImageSubresourceLayout::m_rowCount)
->Field("m_bytesPerRow", &ImageSubresourceLayout::m_bytesPerRow)
->Field("m_bytesPerImage", &ImageSubresourceLayout::m_bytesPerImage)
->Field("m_blockElementWidth", &ImageSubresourceLayout::m_blockElementWidth)
->Field("m_blockElementHeight", &ImageSubresourceLayout::m_blockElementHeight)
;
}
}
@@ -115,11 +117,15 @@ namespace AZ
Size size,
uint32_t rowCount,
uint32_t bytesPerRow,
uint32_t bytesPerImage)
uint32_t bytesPerImage,
uint32_t blockElementWidth,
uint32_t blockElementHeight)
: m_size{size}
, m_rowCount{rowCount}
, m_bytesPerRow{bytesPerRow}
, m_bytesPerImage{bytesPerImage}
, m_blockElementWidth{blockElementWidth}
, m_blockElementHeight{blockElementHeight}
{}
ImageSubresourceLayoutPlaced::ImageSubresourceLayoutPlaced(const ImageSubresourceLayout& subresourceLayout, size_t offset)
@@ -296,8 +302,22 @@ namespace AZ
numBlocks = 4;
break;
case RHI::Format::EAC_R11_UNORM:
case RHI::Format::EAC_R11_SNORM:
isBlockCompressed = true;
bytesPerElement = 8;
numBlocks = 4;
break;
case RHI::Format::EAC_RG11_UNORM:
case RHI::Format::EAC_RG11_SNORM:
isBlockCompressed = true;
bytesPerElement = 16;
numBlocks = 4;
break;
default:
AZ_Assert(false, "Unimplemented esoteric format.");
AZ_Assert(false, "Unimplemented esoteric format %i.", static_cast<int>(imageFormat));
}
if (isBlockCompressed)
@@ -316,6 +336,8 @@ namespace AZ
subresourceLayout.m_rowCount = numBlocksHigh;
subresourceLayout.m_size.m_width = imageSize.m_width;
subresourceLayout.m_size.m_height = imageSize.m_height;
subresourceLayout.m_blockElementWidth = numBlocks;
subresourceLayout.m_blockElementHeight = numBlocks;
}
else if (isPacked)
{
@@ -27,6 +27,7 @@
#include <Atom/RHI/ShaderResourceGroupPool.h>
#include <Atom/RHI/TransientAttachmentPool.h>
#include <Atom/RHI/ResourcePoolDatabase.h>
#include <Atom/RHI/RayTracingShaderTable.h>
#include <AzCore/Debug/EventTrace.h>
#include <AzCore/Jobs/Algorithms.h>
@@ -204,6 +205,9 @@ namespace AZ
// Compile all invalidated shader resource groups.
CompileShaderResourceGroups();
// Build RayTracingShaderTables
BuildRayTracingShaderTables();
}
return outcome;
}
@@ -314,6 +318,25 @@ namespace AZ
}
}
void FrameScheduler::BuildRayTracingShaderTables()
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameScheduler: BuildRayTracingShaderTables");
for (auto rayTracingShaderTable : m_rayTracingShaderTablesToBuild)
{
rayTracingShaderTable->Validate();
[[maybe_unused]] ResultCode resultCode = rayTracingShaderTable->BuildInternal();
AZ_Assert(resultCode == ResultCode::Success, "RayTracingShaderTable build failed");
rayTracingShaderTable->m_isQueuedForBuild = false;
}
// clear the list now that all RayTracingShaderTables have been built for this frame
m_rayTracingShaderTablesToBuild.clear();
}
ResultCode FrameScheduler::BeginFrame()
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
@@ -528,5 +551,10 @@ namespace AZ
{
return m_transientAttachmentPool ? &m_transientAttachmentPool->GetDescriptor() : nullptr;
}
void FrameScheduler::QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable)
{
m_rayTracingShaderTablesToBuild.push_back(rayTracingShaderTable);
}
}
}
@@ -290,5 +290,9 @@ namespace AZ
return m_platformLimitsDescriptor;
}
void RHISystem::QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable)
{
m_frameScheduler.QueueRayTracingShaderTableForBuild(rayTracingShaderTable);
}
} //namespace RPI
} //namespace AZ
@@ -12,6 +12,7 @@
#include <Atom/RHI/Factory.h>
#include <Atom/RHI/RayTracingShaderTable.h>
#include <Atom/RHI/RHISystemInterface.h>
namespace AZ
{
@@ -77,21 +78,28 @@ namespace AZ
return rayTracingShaderTable;
}
ResultCode RayTracingShaderTable::Init(Device& device, const RayTracingShaderTableDescriptor* descriptor, const RayTracingBufferPools& bufferPools)
void RayTracingShaderTable::Init(Device& device, const RayTracingBufferPools& bufferPools)
{
#if defined (AZ_RHI_ENABLE_VALIDATION)
// [GFX TODO][ATOM-5217] Validate shaders in the ray tracing shader table are present in the pipeline state
#endif
ResultCode resultCode = InitInternal(device, descriptor, bufferPools);
if (resultCode == ResultCode::Success)
{
DeviceObject::Init(device);
}
return resultCode;
DeviceObject::Init(device);
m_bufferPools = &bufferPools;
}
void RayTracingShaderTable::Shutdown()
void RayTracingShaderTable::Build(const AZStd::shared_ptr<RayTracingShaderTableDescriptor> descriptor)
{
AZ_Assert(!m_isQueuedForBuild, "Attempting to build a RayTracingShaderTable that's already been queued. Only build once per frame.")
m_descriptor = descriptor;
RHI::RHISystemInterface::Get()->QueueRayTracingShaderTableForBuild(this);
m_isQueuedForBuild = true;
}
void RayTracingShaderTable::Validate()
{
AZ_Assert(m_isQueuedForBuild, "Attempting to build a RayTracingShaderTable that is not queued.");
AZ_Assert(m_bufferPools, "RayTracingBufferPools pointer is null.");
}
}
}
@@ -271,7 +271,7 @@ namespace AZ
// Staging sizes
uint32_t stagingRowPitch = RHI::AlignUp(subresourceLayout.m_bytesPerRow, DX12_TEXTURE_DATA_PITCH_ALIGNMENT);
uint32_t stagingSlicePitch = RHI::AlignUp(subresourceLayout.m_rowCount*stagingRowPitch, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
const uint32_t compressedTexelBlockSizeHeight = subresourceLayout.m_size.m_height / subresourceLayout.m_rowCount;
const uint32_t compressedTexelBlockSizeHeight = subresourceLayout.m_blockElementHeight;
// ImageHeight must be bigger than or equal to the Image's row count. Images with a RowCount that is less than the ImageHeight indicates a block compression.
// Images with a RowCount which is higher than the ImageHeight indicates a planar image, which is not supported for streaming images.
@@ -386,7 +386,7 @@ namespace AZ
const uint32_t numRowsToCopy = endRow - startRow;
// Calculate the blocksize for BC formatted images; the copy command works in texels.
const uint32_t heightToCopy = (endRow - startRow) * compressedTexelBlockSizeHeight;
uint32_t heightToCopy = (endRow - startRow) * compressedTexelBlockSizeHeight;
// Copy subresource data to staging memory
{
@@ -402,6 +402,14 @@ namespace AZ
}
}
//Clamp heightToCopy to match subresourceLayout.m_size.m_height as it is possible to go over
//if subresourceLayout.m_size.m_height is not perfectly divisible by compressedTexelBlockSizeHeight
if(destHeight+heightToCopy > subresourceLayout.m_size.m_height)
{
uint32_t HeightDiff = (destHeight + heightToCopy) - subresourceLayout.m_size.m_height;
heightToCopy -= HeightDiff;
}
// Add copy command to copy image subresource from staging memory to image gpu resource
// Source location
@@ -415,7 +415,7 @@ namespace AZ
// this assert typically happens when a shader needs a particular Srg (e.g., the ViewSrg) but the code did not bind it,
// check the pass code in this callstack to determine why it was not bound
AZ_Assert(false, "ShaderResourceGroup in slot '%d' is null at DrawItem submit time. This is not valid and means the shader is expecting an Srg that is not currently bound in the pipeline. Current bindings: %s",
AZ_Assert(false, "ShaderResourceGroup in slot '%d' is null at DrawItem submit time. This is not valid and means the shader is expecting an Srg that isF not currently bound in the pipeline. Current bindings: %s",
srgSlot,
slotSrgString.c_str());
@@ -121,15 +121,15 @@ namespace AZ
}
#endif
RHI::ResultCode RayTracingShaderTable::InitInternal([[maybe_unused]] RHI::Device& deviceBase, [[maybe_unused]] const RHI::RayTracingShaderTableDescriptor* descriptor, [[maybe_unused]] const RHI::RayTracingBufferPools& bufferPools)
RHI::ResultCode RayTracingShaderTable::BuildInternal()
{
#ifdef AZ_DX12_DXR_SUPPORT
// advance to the next buffer
m_currentBufferIndex = (m_currentBufferIndex + 1) % BufferCount;
ShaderTableBuffers& buffers = m_buffers[m_currentBufferIndex];
// clear the shader table if a null descriptor was passed in
if (!descriptor)
// clear the shader table if the descriptor has no ray generation shader
if (m_descriptor->GetRayGenerationRecord().empty())
{
buffers.m_rayGenerationTable = nullptr;
buffers.m_rayGenerationTableSize = 0;
@@ -144,7 +144,7 @@ namespace AZ
// retrieve the ID3D12StateObjectProperties interface from the raytracing pipeline state object
// this is needed to get the shader identifiers to put in the table
const RayTracingPipelineState* rayTracingPipelineState = static_cast<const RayTracingPipelineState*>(descriptor->GetPipelineState().get());
const RayTracingPipelineState* rayTracingPipelineState = static_cast<const RayTracingPipelineState*>(m_descriptor->GetPipelineState().get());
Microsoft::WRL::ComPtr<ID3D12StateObjectProperties> stateObjectProperties;
[[maybe_unused]] HRESULT hr = rayTracingPipelineState->Get()->QueryInterface(IID_GRAPHICS_PPV_ARGS(stateObjectProperties.GetAddressOf()));
@@ -153,28 +153,28 @@ namespace AZ
// ray generation shader table
{
// RayGeneration table must have one and only one record
AZ_Assert(descriptor->GetRayGenerationRecord().size() == 1, "Descriptor must contain one and only one RayGeneration record");
uint32_t shaderRecordSize = RHI::AlignUp(FindLargestRecordSize(descriptor->GetRayGenerationRecord()), D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
AZ_Assert(m_descriptor->GetRayGenerationRecord().size() == 1, "Descriptor must contain one and only one RayGeneration record");
uint32_t shaderRecordSize = RHI::AlignUp(FindLargestRecordSize(m_descriptor->GetRayGenerationRecord()), D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
buffers.m_rayGenerationTable = BuildTable(deviceBase, bufferPools, descriptor->GetRayGenerationRecord(), shaderRecordSize, L"Ray Generation Shader Table", stateObjectProperties);
buffers.m_rayGenerationTable = BuildTable(GetDevice(), *m_bufferPools, m_descriptor->GetRayGenerationRecord(), shaderRecordSize, L"Ray Generation Shader Table", stateObjectProperties);
buffers.m_rayGenerationTableSize = shaderRecordSize;
}
// miss shader table
{
uint32_t shaderRecordSize = RHI::AlignUp(FindLargestRecordSize(descriptor->GetMissRecords()), D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
uint32_t shaderRecordSize = RHI::AlignUp(FindLargestRecordSize(m_descriptor->GetMissRecords()), D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
buffers.m_missTable = BuildTable(deviceBase, bufferPools, descriptor->GetMissRecords(), shaderRecordSize, L"Miss Shader Table", stateObjectProperties);
buffers.m_missTableSize = shaderRecordSize * static_cast<uint32_t>(descriptor->GetMissRecords().size());
buffers.m_missTable = BuildTable(GetDevice(), *m_bufferPools, m_descriptor->GetMissRecords(), shaderRecordSize, L"Miss Shader Table", stateObjectProperties);
buffers.m_missTableSize = shaderRecordSize * static_cast<uint32_t>(m_descriptor->GetMissRecords().size());
buffers.m_missTableStride = shaderRecordSize;
}
// hit group shader table
{
uint32_t shaderRecordSize = RHI::AlignUp(FindLargestRecordSize(descriptor->GetHitGroupRecords()), D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
uint32_t shaderRecordSize = RHI::AlignUp(FindLargestRecordSize(m_descriptor->GetHitGroupRecords()), D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
buffers.m_hitGroupTable = BuildTable(deviceBase, bufferPools, descriptor->GetHitGroupRecords(), shaderRecordSize, L"HitGroup Shader Table", stateObjectProperties);
buffers.m_hitGroupTableSize = shaderRecordSize * static_cast<uint32_t>(descriptor->GetHitGroupRecords().size());
buffers.m_hitGroupTable = BuildTable(GetDevice(), *m_bufferPools, m_descriptor->GetHitGroupRecords(), shaderRecordSize, L"HitGroup Shader Table", stateObjectProperties);
buffers.m_hitGroupTableSize = shaderRecordSize * static_cast<uint32_t>(m_descriptor->GetHitGroupRecords().size());
buffers.m_hitGroupTableStride = shaderRecordSize;
}
#endif
@@ -61,8 +61,8 @@ namespace AZ
#endif
//////////////////////////////////////////////////////////////////////////
// RHI::PipelineState
RHI::ResultCode InitInternal(RHI::Device& deviceBase, const RHI::RayTracingShaderTableDescriptor* descriptor, const RHI::RayTracingBufferPools& bufferPools) override;
// RHI::RayTracingShaderTable
RHI::ResultCode BuildInternal() override;
//////////////////////////////////////////////////////////////////////////
static const uint32_t BufferCount = 3;
-35
View File
@@ -1,35 +0,0 @@
{
"gem_name": "Atom_RHI_DX12",
"Dependencies": [
{
"Uuid": "fb7f322c8bdb42228d9e155c954f98bd",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RHI"
}
],
"GemFormatVersion": 4,
"Uuid": "e011969cf32442fdaac2443a960ab5ff",
"Name": "Atom_RHI_DX12",
"DisplayName": "Atom RHI.DX12",
"Version": "0.1.0",
"Summary": "The DirectX 12 backend for the Atom Render Hardware Interface",
"Tags": ["Atom", "RHI", "DX12"],
"LinkType": "Dynamic",
"IconPath": "preview.png",
"Modules": [
{
"Name": "Private",
"Type": "GameModule"
},
{
"Name": "Reflect",
"Type": "StaticLib"
},
{
"Name": "Builders",
"Type": "EditorModule"
}
]
}
@@ -190,8 +190,8 @@ namespace AZ
const uint32_t stagingRowPitch = RHI::AlignUp(subresourceLayout.m_bytesPerRow, bufferOffsetAlign);
const uint32_t stagingSlicePitch = RHI::AlignUp(subresourceLayout.m_rowCount * stagingRowPitch, bufferOffsetAlign);
const uint32_t rowsPerSplit = static_cast<uint32_t>(m_descriptor.m_stagingSizeInBytes) / stagingRowPitch;
const uint32_t compressedTexelBlockSizeHeight = subresourceLayout.m_size.m_height / subresourceLayout.m_rowCount;
const uint32_t compressedTexelBlockSizeHeight = subresourceLayout.m_blockElementHeight;
// ImageHeight must be bigger than or equal to the Image's row count. Images with a RowCount that is less than the ImageHeight indicates a block compression.
// Images with a RowCount which is higher than the ImageHeight indicates a planar image, which is not supported for streaming images.
if (subresourceLayout.m_size.m_height < subresourceLayout.m_rowCount)
@@ -281,7 +281,7 @@ namespace AZ
const uint32_t endRow = AZStd::min(startRow + rowsPerSplit, subresourceLayout.m_rowCount);
// Calculate the blocksize for BC formatted images; the copy command works in texels.
const uint32_t heightToCopy = (endRow - startRow) * compressedTexelBlockSizeHeight;
uint32_t heightToCopy = (endRow - startRow) * compressedTexelBlockSizeHeight;
// Copy subresource data to staging memory.
uint8_t* stagingDataStart = framePacket->m_stagingResourceData + framePacket->m_dataOffset;
@@ -293,6 +293,14 @@ namespace AZ
const uint32_t bytesCopied = (endRow - startRow) * stagingRowPitch;
Platform::SynchronizeBufferOnCPU(framePacket->m_stagingResource, framePacket->m_dataOffset, bytesCopied);
//Clamp heightToCopy to match subresourceLayout.m_size.m_height as it is possible to go over
//if subresourceLayout.m_size.m_height is not perfectly divisible by compressedTexelBlockSizeHeight
if(destHeight+heightToCopy > subresourceLayout.m_size.m_height)
{
uint32_t HeightDiff = (destHeight + heightToCopy) - subresourceLayout.m_size.m_height;
heightToCopy -= HeightDiff;
}
const RHI::Size sourceSize = RHI::Size(subresourceLayout.m_size.m_width, heightToCopy, 1);
const RHI::Origin sourceOrigin = RHI::Origin(0, destHeight, depth);
CopyBufferToImage(framePacket, image, stagingRowPitch, bytesCopied,
-35
View File
@@ -1,35 +0,0 @@
{
"gem_name": "Atom_RHI_Metal",
"Dependencies": [
{
"Uuid": "fb7f322c8bdb42228d9e155c954f98bd",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RHI"
}
],
"GemFormatVersion": 4,
"Uuid": "5f27cdc951e64fe0be9d823dc7acbc28",
"Name": "Atom_RHI_Metal",
"DisplayName": "Atom RHI.Metal",
"Version": "0.1.0",
"Summary": "The Metal backend for the Atom Render Hardware Interface",
"Tags": ["Atom", "RHI", "Metal"],
"LinkType": "Dynamic",
"IconPath": "preview.png",
"Modules": [
{
"Name": "Private",
"Type": "GameModule"
},
{
"Name": "Reflect",
"Type": "StaticLib"
},
{
"Name": "Builders",
"Type": "EditorModule"
}
]
}
@@ -33,8 +33,8 @@ namespace AZ
RayTracingShaderTable() = default;
//////////////////////////////////////////////////////////////////////////
// RHI::PipelineState
RHI::ResultCode InitInternal([[maybe_unused]] RHI::Device& deviceBase, [[maybe_unused]] const RHI::RayTracingShaderTableDescriptor* descriptor, [[maybe_unused]] const RHI::RayTracingBufferPools& bufferPools) override {return RHI::ResultCode::Success;}
// RHI::RayTracingShaderTable
RHI::ResultCode BuildInternal() override {return RHI::ResultCode::Success;}
//////////////////////////////////////////////////////////////////////////
};
}
-26
View File
@@ -1,26 +0,0 @@
{
"gem_name": "Atom_RHI_Null",
"GemFormatVersion": 4,
"Uuid": "1f64c07a7d2f4722a3969fcf3be34d30",
"Name": "Atom_RHI_Null",
"DisplayName": "Atom RHI.Null",
"Version": "0.1.0",
"Summary": "The Null backend for the Atom Render Hardware Interface",
"Tags": ["Atom", "RHI", "Null"],
"LinkType": "Dynamic",
"IconPath": "preview.png",
"Modules": [
{
"Name": "Private",
"Type": "GameModule"
},
{
"Name": "Reflect",
"Type": "StaticLib"
},
{
"Name": "Builders",
"Type": "EditorModule"
}
]
}
@@ -214,7 +214,7 @@ namespace AZ
const uint32_t stagingRowPitch = RHI::AlignUp(subresourceLayout.m_bytesPerRow, bufferOffsetAlign);
const uint32_t stagingSlicePitch = subresourceLayout.m_rowCount * stagingRowPitch;
const uint32_t rowsPerSplit = static_cast<uint32_t>(m_descriptor.m_stagingSizeInBytes) / stagingRowPitch;
const uint32_t compressedTexelBlockSizeHeight = subresourceLayout.m_size.m_height / subresourceLayout.m_rowCount;
const uint32_t compressedTexelBlockSizeHeight = subresourceLayout.m_blockElementHeight;
// ImageHeight must be bigger than or equal to the Image's row count. Images with a RowCount that is less than the ImageHeight indicates a block compression.
// Images with a RowCount which is higher than the ImageHeight indicates a planar image, which is not supported for streaming images.
@@ -333,7 +333,7 @@ namespace AZ
const uint32_t endRow = AZStd::min(startRow + rowsPerSplit, subresourceLayout.m_rowCount);
// Calculate the blocksize for BC formatted images; the copy command works in texels.
const uint32_t heightToCopy = (endRow - startRow) * compressedTexelBlockSizeHeight;
uint32_t heightToCopy = (endRow - startRow) * compressedTexelBlockSizeHeight;
// Copy subresource data to staging memory.
{
@@ -348,6 +348,14 @@ namespace AZ
framePacket->m_stagingBuffer->GetBufferMemoryView()->Unmap(RHI::HostMemoryAccess::Write);
}
//Clamp heightToCopy to match subresourceLayout.m_size.m_height as it is possible to go over
//if subresourceLayout.m_size.m_height is not perfectly divisible by compressedTexelBlockSizeHeight
if(destHeight+heightToCopy > subresourceLayout.m_size.m_height)
{
uint32_t HeightDiff = (destHeight + heightToCopy) - subresourceLayout.m_size.m_height;
heightToCopy -= HeightDiff;
}
// Add copy command to copy image subresource from staging memory to image GPU resource.
copyDescriptor.m_destinationOrigin.m_top = destHeight;
copyDescriptor.m_sourceSize.m_height = heightToCopy;
@@ -75,9 +75,9 @@ namespace AZ
return static_cast<Buffer*>(shaderTableBuffer.get());
}
RHI::ResultCode RayTracingShaderTable::InitInternal([[maybe_unused]] RHI::Device& deviceBase, [[maybe_unused]] const RHI::RayTracingShaderTableDescriptor* descriptor, [[maybe_unused]] const RHI::RayTracingBufferPools& bufferPools)
RHI::ResultCode RayTracingShaderTable::BuildInternal()
{
auto& device = static_cast<Device&>(deviceBase);
auto& device = static_cast<Device&>(GetDevice());
auto& physicalDevice = static_cast<const PhysicalDevice&>(device.GetPhysicalDevice());
const VkPhysicalDeviceRayTracingPipelinePropertiesKHR& rayTracingPipelineProperties = physicalDevice.GetPhysicalDeviceRayTracingPipelineProperties();
uint32_t shaderHandleSize = rayTracingPipelineProperties.shaderGroupHandleSize;
@@ -87,8 +87,8 @@ namespace AZ
m_currentBufferIndex = (m_currentBufferIndex + 1) % BufferCount;
ShaderTableBuffers& buffers = m_buffers[m_currentBufferIndex];
// clear the shader table if a null descriptor was passed in
if (!descriptor)
// clear the shader table if the descriptor has no ray generation shader
if (m_descriptor->GetRayGenerationRecord().empty())
{
buffers.m_rayGenerationTable = nullptr;
buffers.m_rayGenerationTableStride = 0;
@@ -108,34 +108,34 @@ namespace AZ
buffers.m_hitGroupTableStride = RHI::AlignUp(alignedShaderHandleSize, rayTracingPipelineProperties.shaderGroupBaseAlignment);
// calculate sub-table sizes
buffers.m_rayGenerationTableSize = buffers.m_rayGenerationTableStride * aznumeric_cast<uint32_t>(descriptor->GetRayGenerationRecord().size());
buffers.m_missTableSize = buffers.m_missTableStride * aznumeric_cast<uint32_t>(descriptor->GetMissRecords().size());
buffers.m_hitGroupTableSize = buffers.m_hitGroupTableStride * aznumeric_cast<uint32_t>(descriptor->GetHitGroupRecords().size());
buffers.m_rayGenerationTableSize = buffers.m_rayGenerationTableStride * aznumeric_cast<uint32_t>(m_descriptor->GetRayGenerationRecord().size());
buffers.m_missTableSize = buffers.m_missTableStride * aznumeric_cast<uint32_t>(m_descriptor->GetMissRecords().size());
buffers.m_hitGroupTableSize = buffers.m_hitGroupTableStride * aznumeric_cast<uint32_t>(m_descriptor->GetHitGroupRecords().size());
const RayTracingPipelineState* rayTracingPipelineState = static_cast<const RayTracingPipelineState*>(descriptor->GetPipelineState().get());
const RayTracingPipelineState* rayTracingPipelineState = static_cast<const RayTracingPipelineState*>(m_descriptor->GetPipelineState().get());
// build sub-tables
buffers.m_rayGenerationTable = BuildTable(
rayTracingPipelineProperties,
rayTracingPipelineState,
bufferPools,
descriptor->GetRayGenerationRecord(),
*m_bufferPools,
m_descriptor->GetRayGenerationRecord(),
buffers.m_rayGenerationTableStride,
"RayGenerationTable");
buffers.m_missTable = BuildTable(
rayTracingPipelineProperties,
rayTracingPipelineState,
bufferPools,
descriptor->GetMissRecords(),
*m_bufferPools,
m_descriptor->GetMissRecords(),
buffers.m_missTableStride,
"MissTable");
buffers.m_hitGroupTable = BuildTable(
rayTracingPipelineProperties,
rayTracingPipelineState,
bufferPools,
descriptor->GetHitGroupRecords(),
*m_bufferPools,
m_descriptor->GetHitGroupRecords(),
buffers.m_hitGroupTableStride,
"HitGroupTable");
@@ -59,7 +59,7 @@ namespace AZ
//////////////////////////////////////////////////////////////////////////
// RHI::RayTracingShaderTable
RHI::ResultCode InitInternal(RHI::Device& deviceBase, const RHI::RayTracingShaderTableDescriptor* descriptor, const RHI::RayTracingBufferPools& bufferPools) override;
RHI::ResultCode BuildInternal() override;
//////////////////////////////////////////////////////////////////////////
static const uint32_t BufferCount = 3;
-39
View File
@@ -1,39 +0,0 @@
{
"gem_name": "Atom_RHI_Vulkan",
"Dependencies": [
{
"Uuid": "fb7f322c8bdb42228d9e155c954f98bd",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RHI"
}
],
"GemFormatVersion": 4,
"Uuid": "150d40d376124d98a388dfe890551c03",
"Name": "Atom_RHI_Vulkan",
"DisplayName": "Atom RHI.Vulkan",
"Version": "0.1.0",
"Summary": "The Vulkan backend for the Atom Render Hardware Interface",
"Tags": ["Atom", "RHI", "Vulkan"],
"LinkType": "Dynamic",
"IconPath": "preview.png",
"Modules": [
{
"Name": "Private",
"Type": "GameModule"
},
{
"Name": "Reflect",
"Type": "StaticLib"
},
{
"Name": "Glad",
"Type": "StaticLib"
},
{
"Name": "Builders",
"Type": "EditorModule"
}
]
}
-30
View File
@@ -1,30 +0,0 @@
{
"gem_name": "Atom_RHI",
"GemFormatVersion": 4,
"Uuid": "fb7f322c8bdb42228d9e155c954f98bd",
"Name": "Atom_RHI",
"DisplayName": "Atom RHI",
"Version": "0.1.0",
"Summary": "The Atom Render Hardware Interface",
"Tags": ["Atom", "RHI"],
"LinkType": "Dynamic",
"IconPath": "preview.png",
"Modules": [
{
"Name": "Private",
"Type": "GameModule"
},
{
"Name": "Public",
"Type": "StaticLib"
},
{
"Name": "Reflect",
"Type": "StaticLib"
},
{
"Name": "Tests",
"Type": "Standalone"
}
]
}
@@ -1,136 +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.
*
*/
#pragma once
// NOTE: Nest this array, so Azslc will output a size of the bindingslot to 1
struct FloatBuffer
{
float buffer;
};
// Listed on update frequency
ShaderResourceGroupSemantic FrequencyPerScene
{
FrequencyId = 6;
};
ShaderResourceGroupSemantic FloatBufferSemanticId
{
FrequencyId = 7;
};
ShaderResourceGroup ImageSrg : FrequencyPerScene
{
Sampler m_sampler
{
MaxAnisotropy = 16;
AddressU = Wrap;
AddressV = Wrap;
AddressW = Wrap;
};
// Array of textures
Texture2D m_textureArray[];
}
ShaderResourceGroup FloatBufferSrg : FloatBufferSemanticId
{
StructuredBuffer<FloatBuffer> m_floatBuffer;
};
// Helper functions to read data from the FloatBuffer. The FloatBuffer is accessed with a descriptor and a index.
// The descriptor holds the initial offset within the FloatBuffer, and the index is a sub-index, which increments with each property that is being read.
// The data needs to be read in the same order as it is allocated on the host.
// All float setters
void SetFloat(out float outFloat, in uint desc, inout uint index)
{
outFloat = FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer;
index += 1;
}
void SetFloat2(out float2 outFloat, in uint desc, inout uint index)
{
outFloat.x = FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer;
outFloat.y = FloatBufferSrg::m_floatBuffer[desc + index + 1].buffer;
index += 2;
}
void SetFloat3(out float3 outFloat, in uint desc, inout uint index)
{
outFloat.x = FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer;
outFloat.y = FloatBufferSrg::m_floatBuffer[desc + index + 1].buffer;
outFloat.z = FloatBufferSrg::m_floatBuffer[desc + index + 2].buffer;
index += 3;
}
void SetFloat4(out float4 outFloat, in uint desc, inout uint index)
{
outFloat.x = FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer;
outFloat.y = FloatBufferSrg::m_floatBuffer[desc + index + 1].buffer;
outFloat.z = FloatBufferSrg::m_floatBuffer[desc + index + 2].buffer;
outFloat.w = FloatBufferSrg::m_floatBuffer[desc + index + 3].buffer;
index += 4;
}
// All matrix setters
void SetFloat4x4(out float4x4 outFloat, in uint desc, inout uint index)
{
[unroll(4)]
for(uint i = 0; i < 4; i++)
{
SetFloat4(outFloat[i], desc, index);
}
}
// All uint setters
void SetUint(out uint outUInt, in uint desc, inout uint index)
{
outUInt = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer);
index += 1;
}
void SetUint2(out uint2 outUInt, in uint desc, inout uint index)
{
outUInt.x = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer);
outUInt.y = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 1].buffer);
index += 2;
}
void SetUint3(out uint3 outUInt, in uint desc, inout uint index)
{
outUInt.x = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer);
outUInt.y = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 1].buffer);
outUInt.z = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 2].buffer);
index += 3;
}
void SetUint4(out uint4 outUInt, in uint desc, inout uint index)
{
outUInt.x = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer);
outUInt.y = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 1].buffer);
outUInt.z = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 2].buffer);
outUInt.w = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 3].buffer);
index += 4;
}
// All double setters
void SetDouble(out double outDouble, in uint desc, inout uint index)
{
uint lowBits;
uint highBits;
SetUint(highBits, desc, index);
SetUint(lowBits, desc, index);
outDouble = asdouble(lowBits, highBits);
}
@@ -21,7 +21,6 @@ set(FILES
Shader/ImagePreview.shader
ShaderLib/Atom/RPI/Math.azsli
ShaderLib/Atom/RPI/TangentSpace.azsli
ShaderLib/Atom/RPI/ShaderResourceGroups/BindlessPrototypeSrg.azsli
ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli
ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultObjectSrg.azsli
)
@@ -89,7 +89,7 @@ namespace AZ
// --- Members ---
// Cached pointer to the pass library to simplify code
PassLibrary* m_passLibary = nullptr;
PassLibrary* m_passLibrary = nullptr;
// ClassNames are used to look up PassCreators. This list is 1-to-1 with the PassCreator list
AZStd::vector<Name> m_passClassNames;
@@ -56,6 +56,9 @@ namespace AZ
// The list of passes created from this template
AZStd::vector<Pass*> m_passes;
// The pass templates mapping asset id which this template is coming from.
Data::AssetId m_mappingAssetId;
};
typedef AZStd::unordered_map<Name, TemplateEntry> TemplateEntriesByName;
@@ -105,7 +108,7 @@ namespace AZ
bool LoadPassAsset(const Name& name, const Data::Asset<PassAsset>& passAsset, bool hotReloading = false);
// Find asset with specified pass template asset id and load pass template from the asset.
void LoadPassAsset(const Name& name, const Data::AssetId& passAssetId);
bool LoadPassAsset(const Name& name, const Data::AssetId& passAssetId);
// Data::AssetBus::Handler overrides...
void OnAssetReloaded(Data::Asset<Data::AssetData> asset) override;
@@ -55,6 +55,10 @@ namespace AZ
//! Initializes the PassSystem and the Root Pass and creates the Pass InstanceDatabase
void Init();
//! Initialize and load pass templates
//! This function need to be called after Init()
void InitPassTemplates();
//! Deletes the Root Pass and shuts down the PassSystem
void Shutdown();
@@ -74,6 +78,7 @@ namespace AZ
void SetHotReloading(bool hotReloading) override;
void SetTargetedPassDebuggingName(const AZ::Name& targetPassName) override;
const AZ::Name& GetTargetedPassDebuggingName() const override;
void ConnectEvent(OnReadyLoadTemplatesEvent::Handler& handler) override;
// PassSystemInterface factory related functions...
void AddPassCreator(Name className, PassCreator createFunction) override;
@@ -139,6 +144,9 @@ namespace AZ
// Counts the number of passes
int32_t m_passCounter = 0;
// Events
OnReadyLoadTemplatesEvent m_loadTemplatesEvent;
};
} // namespace RPI
} // namespace AZ
@@ -64,7 +64,10 @@ namespace AZ
//! initializing a scene;
virtual void ProcessQueuedChanges() = 0;
//! Load pass templates listed in a name-assetid mapping asset
//! Load pass templates listed in a name-assetid mapping asset
//! This function should be called before the render pipelines which use templates from this mappings are created.
//! To load pass template mapping before any render pipelines are created, use OnReadyLoadTemplatesEvent::Handler to
//! load desired pass template mappings
virtual bool LoadPassTemplateMappings(const AZStd::string& templateMappingPath) = 0;
//! Writes a pass template to a .pass file which can then be used as a pass asset. Useful for
@@ -148,6 +151,12 @@ namespace AZ
//! Find the SwapChainPass associated with window Handle
virtual SwapChainPass* FindSwapChainPass(AzFramework::NativeWindowHandle windowHandle) const = 0;
using OnReadyLoadTemplatesEvent = AZ::Event<>;
//! Connect a handler to listen to the event that the pass system is ready to load pass templates
//! The event is triggered when pass system is initialized and asset system is ready.
//! The handler can add new pass templates or load pass template mappings from assets
virtual void ConnectEvent(OnReadyLoadTemplatesEvent::Handler& handler) = 0;
private:
// These functions are only meant to be used by the Pass class
@@ -164,17 +173,10 @@ namespace AZ
virtual void UnregisterPass(Pass* pass) = 0;
};
//! Notifications of the pass system such attachments were rebuilt, pass tree changes
class PassSystemNotificiations
: public AZ::EBusTraits
namespace PassSystemEvents
{
public:
}
//! Notify when any pass's attachment was rebuilt
virtual void OnPassAttachmentsBuilt() = 0;
};
using PassSystemNotificiationBus = AZ::EBus<PassSystemNotificiations>;
} // namespace RPI
} // namespace AZ
@@ -91,6 +91,8 @@ namespace AZ
const AZ::Matrix4x4& GetViewToWorldMatrix() const;
const AZ::Matrix4x4& GetViewToClipMatrix() const;
const AZ::Matrix4x4& GetWorldToClipMatrix() const;
//! Get the camera's world transform, converted from the viewToWorld matrix's native y-up to z-up
AZ::Transform GetCameraTransform() const;
//! Finalize draw lists in this view. This function should only be called when all
//! draw packets for current frame are added.
@@ -92,6 +92,8 @@ namespace AZ
virtual ViewPtr GetCurrentView(const Name& contextName) const = 0;
};
using ViewportContextRequests = AZ::Interface<ViewportContextRequestsInterface>;
class ViewportContextManagerNotifications
: public AZ::EBusTraits
{
@@ -137,13 +137,19 @@ namespace AZ
template<typename AssetDataT>
Data::Asset<AssetDataT> LoadCriticalAsset(const AZStd::string& assetFilePath, TraceLevel reporting)
{
AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown;
AzFramework::AssetSystemRequestBus::BroadcastResult(status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, assetFilePath);
if (status != AzFramework::AssetSystem::AssetStatus_Compiled)
bool apConnected = false;
AzFramework::AssetSystemRequestBus::BroadcastResult(
apConnected, &AzFramework::AssetSystemRequestBus::Events::ConnectedWithAssetProcessor);
if (apConnected)
{
AssetUtilsInternal::ReportIssue(reporting, AZStd::string::format("Could not compile asset '%s'", assetFilePath.c_str()).c_str());
return {};
AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown;
AzFramework::AssetSystemRequestBus::BroadcastResult(
status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, assetFilePath);
if (status != AzFramework::AssetSystem::AssetStatus_Compiled)
{
AssetUtilsInternal::ReportIssue(reporting, AZStd::string::format("Could not compile asset '%s'", assetFilePath.c_str()).c_str());
return {};
}
}
return LoadAssetByProductPath<AssetDataT>(assetFilePath.c_str(), reporting);
@@ -44,9 +44,6 @@ namespace AZ
//! The path of the only one view srg asset for the RPI system. This is used to create any RPI::View.
AZStd::string m_viewSrgAssetPath = "shaderlib/viewsrg_viewsrg.azsrg";
//! Path of pass templates' name-assetid mapping file.
AZStd::string m_passTemplatesMappingPath = "Passes/PassTemplates.azasset";
ImageSystemDescriptor m_imageSystemDescriptor;
GpuQuerySystemDescriptor m_gpuQuerySystemDescriptor;
DynamicDrawSystemDescriptor m_dynamicDrawSystemDescriptor;
@@ -36,7 +36,7 @@ namespace AZ
{
void PassFactory::Init(PassLibrary* passLibrary)
{
m_passLibary = passLibrary;
m_passLibrary = passLibrary;
AddCorePasses();
}
@@ -125,7 +125,7 @@ namespace AZ
Ptr<Pass> PassFactory::CreatePassFromTemplate(Name templateName, Name passName)
{
const AZStd::shared_ptr<PassTemplate>& passTemplate = m_passLibary->GetPassTemplate(templateName);
const AZStd::shared_ptr<PassTemplate>& passTemplate = m_passLibrary->GetPassTemplate(templateName);
if (passTemplate == nullptr)
{
AZ_Error("PassFactory", false, "FAILED TO CREATE PASS [%s]. Could not find pass template [%s]", passName.GetCStr(), templateName.GetCStr());
@@ -143,7 +143,7 @@ namespace AZ
return nullptr;
}
const AZStd::shared_ptr<PassTemplate>& passTemplate = m_passLibary->GetPassTemplate(passRequest->m_templateName);
const AZStd::shared_ptr<PassTemplate>& passTemplate = m_passLibrary->GetPassTemplate(passRequest->m_templateName);
if (passTemplate == nullptr)
{
AZ_Error("PassFactory", false, "FAILED TO CREATE PASS [%s]. Could not find pass template [%s]", passRequest->m_passName.GetCStr(), passRequest->m_templateName.GetCStr());
@@ -262,6 +262,7 @@ namespace AZ
}
// Handle template mapping reload
// Note: it's a known issue that when mapping asset got reloaded, we only handle the new entries
Data::Asset<AnyAsset> templateMappings = { asset.GetAs<AnyAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
if (templateMappings)
{
@@ -310,7 +311,7 @@ namespace AZ
return success;
}
void PassLibrary::LoadPassAsset(const Name& name, const Data::AssetId& passAssetId)
bool PassLibrary::LoadPassAsset(const Name& name, const Data::AssetId& passAssetId)
{
Data::Asset<PassAsset> passAsset;
if (passAssetId.IsValid())
@@ -325,11 +326,20 @@ namespace AZ
{
Data::AssetBus::MultiHandler::BusConnect(passAssetId);
}
return loadSuccess;
}
bool PassLibrary::LoadPassTemplateMappings(const AZStd::string& templateMappingPath)
{
Data::Asset<AnyAsset> mappingAsset = AssetUtils::LoadCriticalAsset<AnyAsset>(templateMappingPath.c_str(), AssetUtils::TraceLevel::Error);
if (m_templateMappingAssets.find(mappingAsset.GetId()) != m_templateMappingAssets.end())
{
AZ_Warning("PassLibrary", false, "Pass template mapping [%s] was already loaded", mappingAsset.GetHint().c_str());
return true;
}
bool success = LoadPassTemplateMappings(mappingAsset);
if (success)
{
@@ -350,13 +360,29 @@ namespace AZ
}
const AZStd::unordered_map<AZStd::string, Data::AssetId>& assetMapping = mappings->GetAssetMapping();
Data::AssetId mappingAssetId = mappingAsset.GetId();
m_templateEntries.reserve(m_templateEntries.size() + assetMapping.size());
for (const auto& assetInfo : assetMapping)
{
Name templateName = AZ::Name(assetInfo.first);
if (!HasTemplate(templateName))
{
LoadPassAsset(templateName, assetInfo.second);
bool loaded = LoadPassAsset(templateName, assetInfo.second);
if (loaded)
{
auto& entry = m_templateEntries[templateName];
entry.m_mappingAssetId = mappingAssetId;
}
}
else
{
// Report a warning if the template was setup in another mappping asset.
// We won't report a warning if the template was loaded from same asset. This only happens when the asset got reloaded.
if (m_templateEntries[templateName].m_mappingAssetId != mappingAssetId)
{
AZ_Warning("PassLibrary", false, "Template [%s] was aleady added to the library. Duplicated template from [%s]",
templateName.GetCStr(), mappingAsset.ToString<AZStd::string>().c_str());
}
}
}
@@ -100,6 +100,12 @@ namespace AZ
m_rootPass->m_flags.m_partOfHierarchy = true;
}
void PassSystem::InitPassTemplates()
{
AZ_Assert(m_rootPass, "PassSystem::Init() need to be called");
m_loadTemplatesEvent.Signal();
}
bool PassSystem::LoadPassTemplateMappings(const AZStd::string& templateMappingPath)
{
return m_passLibrary.LoadPassTemplateMappings(templateMappingPath);
@@ -213,7 +219,6 @@ namespace AZ
DebugPrintPassHierarchy();
}
#endif
PassSystemNotificiationBus::Broadcast(&PassSystemNotificiationBus::Events::OnPassAttachmentsBuilt);
}
m_isBuilding = false;
@@ -323,6 +328,11 @@ namespace AZ
return m_targetedPassDebugName;
}
void PassSystem::ConnectEvent(OnReadyLoadTemplatesEvent::Handler& handler)
{
handler.Connect(m_loadTemplatesEvent);
}
// --- Pass Factory Functions ---
void PassSystem::AddPassCreator(Name className, PassCreator createFunction)
@@ -369,12 +369,7 @@ namespace AZ
m_bufferSystem.Init();
m_dynamicDraw.Init(m_descriptor.m_dynamicDrawSystemDescriptor);
// Have pass system load default pass template mapping
bool passSystemReady = m_passSystem.LoadPassTemplateMappings(m_descriptor.m_passTemplatesMappingPath);
if (!passSystemReady)
{
return;
}
m_passSystem.InitPassTemplates();
m_systemAssetsInitialized = true;
}
@@ -99,7 +99,6 @@ namespace AZ
{
WaitAndCleanCompletionJob(m_simulationCompletion);
SceneRequestBus::Handler::BusDisconnect();
DisableAllFeatureProcessors();
// Remove all the render pipelines. Need to process queued changes with pass system before and after remove render pipelines
AZ::RPI::PassSystemInterface::Get()->ProcessQueuedChanges();
@@ -111,6 +110,8 @@ namespace AZ
m_pipelines.clear();
AZ::RPI::PassSystemInterface::Get()->ProcessQueuedChanges();
Deactivate();
delete m_cullingScene;
}
@@ -138,8 +139,11 @@ namespace AZ
void Scene::Deactivate()
{
AZ_Assert(m_activated, "Not activated");
if (!m_activated)
{
return;
}
for (auto& fp : m_featureProcessors)
{
fp->Deactivate();
@@ -240,7 +244,6 @@ namespace AZ
fp->Deactivate();
}
m_featureProcessors.clear();
m_pipelineStatesLookup.clear();
}
FeatureProcessor* Scene::GetFeatureProcessor(const FeatureProcessorId& featureProcessorId) const
+10 -1
View File
@@ -110,6 +110,15 @@ namespace AZ
InvalidateSrg();
}
AZ::Transform View::GetCameraTransform() const
{
static const Quaternion yUpToZUp = Quaternion::CreateRotationX(-AZ::Constants::HalfPi);
return AZ::Transform::CreateFromQuaternionAndTranslation(
Quaternion::CreateFromMatrix4x4(m_viewToWorldMatrix) * yUpToZUp,
m_viewToWorldMatrix.GetTranslation()
).GetOrthogonalized();
}
void View::SetCameraTransform(const AZ::Matrix3x4& cameraTransform)
{
m_position = cameraTransform.GetTranslation();
@@ -118,7 +127,7 @@ namespace AZ
// is in a Z-up world and an identity matrix means that it faces along the positive-Y axis and Z is up.
// An identity view matrix on the other hand looks along the negative Z-axis.
// So we adjust for this by rotating the camera world matrix by 90 degrees around the X axis.
AZ::Matrix3x4 zUpToYUp = AZ::Matrix3x4::CreateRotationX(AZ::Constants::HalfPi);
static AZ::Matrix3x4 zUpToYUp = AZ::Matrix3x4::CreateRotationX(AZ::Constants::HalfPi);
AZ::Matrix3x4 yUpWorld = cameraTransform * zUpToYUp;
float viewToWorldMatrixRaw[16] = {
@@ -194,12 +194,7 @@ namespace AZ
AZ::Transform ViewportContext::GetCameraTransform() const
{
const Matrix4x4& worldToViewMatrix = GetDefaultView()->GetViewToWorldMatrix();
const Quaternion zUpToYUp = Quaternion::CreateRotationX(-AZ::Constants::HalfPi);
return AZ::Transform::CreateFromQuaternionAndTranslation(
Quaternion::CreateFromMatrix4x4(worldToViewMatrix) * zUpToYUp,
worldToViewMatrix.GetTranslation()
).GetOrthogonalized();
return GetDefaultView()->GetCameraTransform();
}
void ViewportContext::SetCameraTransform(const AZ::Transform& transform)
@@ -12,6 +12,7 @@
#include <Atom/RPI.Reflect/Shader/ShaderVariantTreeAsset.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/algorithm.h>
@@ -40,15 +41,12 @@ namespace AZ
Data::AssetId ShaderVariantTreeAsset::GetShaderVariantTreeAssetIdFromShaderAssetId(const Data::AssetId& shaderAssetId)
{
//From the shaderAssetId We can deduce the path of the shader asset, and from the path of the shader asset we can deduce the path of the ShaderVariantTreeAsset.
AZStd::string shaderAssetPath;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(shaderAssetPath
, &AZ::Data::AssetCatalogRequests::GetAssetPathById
, shaderAssetId);
AZStd::string shaderAssetPathRoot;
AZStd::string shaderAssetPathName;
AzFramework::StringFunc::Path::Split(shaderAssetPath.c_str(), nullptr /*drive*/, &shaderAssetPathRoot, &shaderAssetPathName, nullptr /*extension*/);
AZ::IO::FixedMaxPath shaderAssetPath;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(shaderAssetPath.Native(), &AZ::Data::AssetCatalogRequests::GetAssetPathById
, shaderAssetId);
AZ::IO::FixedMaxPath shaderAssetPathRoot = shaderAssetPath.ParentPath();
AZ::IO::FixedMaxPath shaderAssetPathName = shaderAssetPath.Stem();
AZStd::string shaderVariantTreeAssetDir;
AzFramework::StringFunc::Path::Join(ShaderVariantTreeAsset::CommonSubFolderLowerCase, shaderAssetPathRoot.c_str(), shaderVariantTreeAssetDir);
AZStd::string shaderVariantTreeAssetFilename = AZStd::string::format("%s.%s", shaderAssetPathName.c_str(), ShaderVariantTreeAsset::Extension);
@@ -63,8 +61,7 @@ namespace AZ
{
// If the game project did not customize the shadervariantlist, let's see if the original author of the .shader file
// provided a shadervariantlist.
shaderVariantTreeAssetDir = shaderAssetPathRoot;
AzFramework::StringFunc::Path::Join(shaderVariantTreeAssetDir.c_str(), shaderVariantTreeAssetFilename.c_str(), shaderVariantTreeAssetPath);
AzFramework::StringFunc::Path::Join(shaderAssetPathRoot.c_str(), shaderVariantTreeAssetFilename.c_str(), shaderVariantTreeAssetPath);
AZ::Data::AssetCatalogRequestBus::BroadcastResult(shaderVariantTreeAssetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath
, shaderVariantTreeAssetPath.c_str(), AZ::Data::s_invalidAssetType, false);
}
-48
View File
@@ -1,48 +0,0 @@
{
"gem_name": "Atom_RPI",
"Dependencies": [
{
"Uuid": "fb7f322c8bdb42228d9e155c954f98bd",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RHI"
}
],
"GemFormatVersion": 4,
"Uuid": "a218db9eb2114477b46600fea4441a6c",
"Name": "Atom_RPI",
"DisplayName": "Atom RPI",
"Version": "0.1.0",
"Summary": "The Atom Render Pipeline Interface",
"Tags": ["Atom", "RPI"],
"LinkType": "Dynamic",
"IconPath": "preview.png",
"Modules": [
{
"Name": "Builders",
"Type": "EditorModule"
},
{
"Name": "Private",
"Type": "GameModule"
},
{
"Name": "Public",
"Type": "StaticLib"
},
{
"Name": "Reflect",
"Type": "StaticLib"
},
{
"Name": "Editor",
"Type": "EditorModule",
"Extends": "Private"
},
{
"Name": "Tests",
"Type": "Standalone"
}
]
}
@@ -1,17 +0,0 @@
{
"gem_name": "AtomToolsFramework",
"GemFormatVersion": 4,
"Uuid": "3e0ee0c27f204f5188146baac822d020",
"Name": "AtomToolsFramework",
"DisplayName": "AtomToolsFramework",
"Version": "0.1.0",
"Summary": "AtomToolsFramework",
"Tags": [ "Untagged" ],
"IconPath": "preview.png",
"Modules": [
{
"Name": "Editor",
"Type": "EditorModule"
}
]
}
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ac53da9855838fcf6782c990247c69c14c2ff5c10624dc5afe89617def9cc7ca
size 9021888
@@ -0,0 +1,15 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "AZ::Render::ModelPreset",
"ClassData": {
"displayName": "Hermanubis",
"modelAsset": {
"assetId": {
"guid": "{1F650917-AA74-5107-9C49-648C957B33DA}",
"subId": 275904906
},
"assetHint": "materialeditor/viewportmodels/Hermanubis.azmodel"
}
}
}
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ec4187f51a4b598fc075f48dd7edb7728b14b285a95530228428a8c3f43c25fc
size 10931856
@@ -1,15 +0,0 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "AZ::Render::ModelPreset",
"ClassData": {
"displayName": "Lucy",
"modelAsset": {
"assetId": {
"guid": "{CF4634D9-EC73-51D4-8F8E-AA25E7A6561A}",
"subId": 277335264
},
"assetHint": "materialeditor/viewportmodels/lucy.azmodel"
}
}
}
-58
View File
@@ -1,58 +0,0 @@
{
"gem_name": "MaterialEditor",
"Dependencies": [
{
"Uuid": "a218db9eb2114477b46600fea4441a6c",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RPI"
},
{
"Uuid": "b58e5eed0901428ca78544b04dbd61bd",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom Feature Common"
},
{
"Uuid": "b658359393884c4381c2fe2952b1472a",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "EditorPythonBindings"
},
{
"Uuid": "3e0ee0c27f204f5188146baac822d020",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "AtomToolsFramework"
},
{
"Uuid": "9d10b00be96045caa64c705e5772cb64",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "ImageProcessingAtom"
},
{
"Uuid": "4e981f3b17394f5d84d674fff0f54f4f",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "AtomLyIntegration.CommonFeatures"
}
],
"GemFormatVersion": 4,
"Uuid": "36f854c260b84d438dde4bc5789d8123",
"Name": "MaterialEditor",
"DisplayName": "Material Editor",
"Version": "0.1.0",
"LinkType": "Dynamic",
"Summary": "Tools for editing Atom materials",
"Tags": ["Untagged"],
"IconPath": "preview.svg",
"Modules": [
]
}
@@ -1,50 +0,0 @@
{
"gem_name": "ShaderManagementConsole",
"Dependencies": [
{
"Uuid": "a218db9eb2114477b46600fea4441a6c",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RPI"
},
{
"Uuid": "b658359393884c4381c2fe2952b1472a",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "EditorPythonBindings"
},
{
"Uuid": "3e0ee0c27f204f5188146baac822d020",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "AtomToolsFramework"
},
{
"Uuid": "9d10b00be96045caa64c705e5772cb64",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "ImageProcessingAtom"
},
{
"Uuid": "4e981f3b17394f5d84d674fff0f54f4f",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "AtomLyIntegration.CommonFeatures"
}
],
"GemFormatVersion": 4,
"Uuid": "77967ca0a6264a8e95b138a31bf78fe0",
"Name": "ShaderManagementConsole",
"DisplayName": "Shader Management Console",
"Version": "0.1.0",
"LinkType": "Dynamic",
"Summary": "Shader Management Console",
"IconPath": "preview.svg",
"Modules": [
]
}
-31
View File
@@ -1,31 +0,0 @@
{
"gem_name": "Atom_Utils",
"Dependencies": [
{
"Uuid": "fb7f322c8bdb42228d9e155c954f98bd",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RHI"
}
],
"GemFormatVersion": 4,
"Uuid": "5c850809e890497c82cd9999ecb33250",
"Name": "Atom_Utils",
"DisplayName": "Atom.Utils",
"Version": "0.1.0",
"Summary": "Various utility classes used by Atom.",
"Tags": ["Atom", "Utils"],
"LinkType": "Dynamic",
"IconPath": "preview.png",
"Modules": [
{
"Name": "Utils",
"Type": "StaticLib"
},
{
"Name": "Tests",
"Type": "Standalone"
}
]
}
+3
View File
@@ -0,0 +1,3 @@
{
"gem_name": "Atom"
}
@@ -63,6 +63,7 @@ ly_add_target(
Gem::EMotionFX_Atom
Gem::ImguiAtom
Gem::AtomFont
Gem::AtomViewportDisplayInfo
)
if(PAL_TRAIT_BUILD_HOST_TOOLS)
@@ -104,5 +105,6 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
Gem::ImguiAtom
Gem::AtomFont
Gem::AtomToolsFramework.Editor
Gem::AtomViewportDisplayInfo
)
endif()
@@ -91,13 +91,9 @@ namespace AZ
AZ_UNUSED(dependent);
}
static const AZ::Crc32 mainViewportEntityDebugDisplayId = AZ_CRC_CE("MainViewportEntityDebugDisplayId");
void AtomBridgeSystemComponent::Init()
{
#if defined(ENABLE_ATOM_DEBUG_DISPLAY) && ENABLE_ATOM_DEBUG_DISPLAY
AZ::RPI::ViewportContextManagerNotificationsBus::Handler::BusConnect();
#endif
}
void AtomBridgeSystemComponent::Activate()
@@ -112,9 +108,7 @@ namespace AZ
void AtomBridgeSystemComponent::Deactivate()
{
#if defined(ENABLE_ATOM_DEBUG_DISPLAY) && ENABLE_ATOM_DEBUG_DISPLAY
AZ::RPI::ViewportContextManagerNotificationsBus::Handler::BusDisconnect();
#endif
RPI::Scene* scene = RPI::RPISystemInterface::Get()->GetDefaultScene().get();
// Check if scene is emptry since scene might be released already when running AtomSampleViewer
if (scene)
@@ -193,36 +187,32 @@ namespace AZ
renderPipeline = bootstrapScene->GetDefaultRenderPipeline();
renderPipeline->SetDefaultView(m_view);
auto auxGeomFP = bootstrapScene->GetFeatureProcessor<RPI::AuxGeomFeatureProcessorInterface>();
if (auxGeomFP)
{
auxGeomFP->GetOrCreateDrawQueueForView(m_view.get());
}
#if defined(ENABLE_ATOM_DEBUG_DISPLAY) && ENABLE_ATOM_DEBUG_DISPLAY
// Make default AtomDebugDisplayViewportInterface for the scene
AZStd::shared_ptr<AtomDebugDisplayViewportInterface> mainEntityDebugDisplay = AZStd::make_shared<AtomDebugDisplayViewportInterface>(mainViewportEntityDebugDisplayId);
m_activeViewportsList[mainViewportEntityDebugDisplayId] = mainEntityDebugDisplay;
#endif
}
else
{
m_view = renderPipeline->GetDefaultView();
}
auto auxGeomFP = bootstrapScene->GetFeatureProcessor<RPI::AuxGeomFeatureProcessorInterface>();
if (auxGeomFP)
{
auxGeomFP->GetOrCreateDrawQueueForView(m_view.get());
}
// Make default AtomDebugDisplayViewportInterface for the scene
AZStd::shared_ptr<AtomDebugDisplayViewportInterface> mainEntityDebugDisplay = AZStd::make_shared<AtomDebugDisplayViewportInterface>(AzFramework::g_defaultSceneEntityDebugDisplayId);
m_activeViewportsList[AzFramework::g_defaultSceneEntityDebugDisplayId] = mainEntityDebugDisplay;
}
void AtomBridgeSystemComponent::OnViewportContextAdded(AZ::RPI::ViewportContextPtr viewportContext)
{
#if defined(ENABLE_ATOM_DEBUG_DISPLAY) && ENABLE_ATOM_DEBUG_DISPLAY
AZStd::shared_ptr<AtomDebugDisplayViewportInterface> viewportDebugDisplay = AZStd::make_shared<AtomDebugDisplayViewportInterface>(viewportContext);
m_activeViewportsList[viewportContext->GetId()] = viewportDebugDisplay;
#endif
}
void AtomBridgeSystemComponent::OnViewportContextRemoved(AzFramework::ViewportId viewportId)
{
#if defined(ENABLE_ATOM_DEBUG_DISPLAY) && ENABLE_ATOM_DEBUG_DISPLAY
AZ_Assert(viewportId != AzFramework::g_defaultSceneEntityDebugDisplayId, "Error trying to remove the default scene draw instance");
m_activeViewportsList.erase(viewportId);
#else
AZ_UNUSED(viewportId);
#endif
}
@@ -1,37 +0,0 @@
{
"gem_name": "Atom_AtomBridge",
"Dependencies": [
{
"Uuid": "a218db9eb2114477b46600fea4441a6c",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom RPI"
},
{
"Uuid": "c7ff89ad6e8b4b45b2fadef2bcf12d6e",
"VersionConstraints": [
"~>0.1.0"
],
"_comment": "Atom_Bootstrap"
}
],
"GemFormatVersion": 4,
"Uuid": "b55b2738aa4a46c8b034fe98e6e5158b",
"Name": "Atom_AtomBridge",
"DisplayName": "Atom.AtomBridge",
"Version": "0.1.0",
"Summary": "A short description of my Gem.",
"Tags": ["Untagged"],
"IconPath": "preview.png",
"Modules": [
{
"Type": "GameModule"
},
{
"Name": "Editor",
"Type": "EditorModule",
"Extends": "GameModule"
}
]
}
@@ -207,11 +207,15 @@ namespace AZ
// AzFramework::FontDrawInterface implementation
void DrawScreenAlignedText2d(
const AzFramework::TextDrawParameters& params,
const AZStd::string_view& string) override;
AZStd::string_view text) override;
void DrawScreenAlignedText3d(
const AzFramework::TextDrawParameters& params,
const AZStd::string_view& string) override;
AZStd::string_view text) override;
AZ::Vector2 GetTextSize(
const AzFramework::TextDrawParameters& params,
AZStd::string_view text) override;
public:
FFont(AtomFont* atomFont, const char* fontName);
@@ -233,7 +237,7 @@ namespace AZ
void Prepare(const char* str, bool updateTexture, const AtomFont::GlyphSize& glyphSize = AtomFont::defaultGlyphSize);
void DrawStringUInternal(
const RHI::Viewport& viewport,
RPI::ViewportContext* viewportContext,
RPI::ViewportContextPtr viewportContext,
float x,
float y,
float z,
@@ -282,6 +286,16 @@ namespace AZ
RPI::WindowContextSharedPtr GetDefaultWindowContext() const;
RPI::ViewportContextPtr GetDefaultViewportContext() const;
struct DrawParameters
{
TextDrawContext m_ctx;
AZ::Vector2 m_position;
AZ::Vector2 m_size;
AZ::RPI::ViewportContextPtr m_viewportContext;
const AZ::RHI::Viewport* m_viewport;
};
DrawParameters ExtractDrawParameters(const AzFramework::TextDrawParameters& params, AZStd::string_view text, bool forceCalculateSize);
private:
static constexpr uint32_t NumBuffers = 2;
static constexpr float WindowScaleWidth = 800.0f;
@@ -280,7 +280,7 @@ void AZ::FFont::DrawString(float x, float y, const char* str, const bool asciiMu
return;
}
DrawStringUInternal(GetDefaultWindowContext()->GetViewport(), GetDefaultViewportContext().get(), x, y, 1.0f, str, asciiMultiLine, ctx);
DrawStringUInternal(GetDefaultWindowContext()->GetViewport(), GetDefaultViewportContext(), x, y, 1.0f, str, asciiMultiLine, ctx);
}
void AZ::FFont::DrawString(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx)
@@ -290,12 +290,12 @@ void AZ::FFont::DrawString(float x, float y, float z, const char* str, const boo
return;
}
DrawStringUInternal(GetDefaultWindowContext()->GetViewport(), GetDefaultViewportContext().get(), x, y, z, str, asciiMultiLine, ctx);
DrawStringUInternal(GetDefaultWindowContext()->GetViewport(), GetDefaultViewportContext(), x, y, z, str, asciiMultiLine, ctx);
}
void AZ::FFont::DrawStringUInternal(
const RHI::Viewport& viewport,
RPI::ViewportContext* viewportContext,
RPI::ViewportContextPtr viewportContext,
float x,
float y,
float z,
@@ -505,7 +505,7 @@ Vec2 AZ::FFont::GetTextSizeUInternal(
}
charX = offset.x;
charY += size.y;
charY += size.y * (1.f + ctx.GetLineSpacing());
if (charY > maxH)
{
@@ -944,7 +944,7 @@ int AZ::FFont::CreateQuadsForText(const RHI::Viewport& viewport, float x, float
case '\n':
{
charX = baseXY.x + offset.x;
charY += size.y;
charY += size.y * (1.f + ctx.GetLineSpacing());
continue;
}
break;
@@ -1675,47 +1675,46 @@ static void SetCommonContextFlags(AZ::TextDrawContext& ctx, const AzFramework::T
}
}
void AZ::FFont::DrawScreenAlignedText2d(
const AzFramework::TextDrawParameters& params,
const AZStd::string_view& string)
AZ::FFont::DrawParameters AZ::FFont::ExtractDrawParameters(const AzFramework::TextDrawParameters& params, AZStd::string_view text, bool forceCalculateSize)
{
DrawParameters internalParams;
if (params.m_drawViewportId == AzFramework::InvalidViewportId ||
string.empty())
text.empty())
{
return;
return internalParams;
}
//Code mostly duplicated from CRenderer::Draw2dTextWithDepth
float posX = params.m_position.GetX();
float posY = params.m_position.GetY();
AZ::RPI::ViewportContext* viewportContext = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get()->GetViewportContextById(params.m_drawViewportId).get();
const AZ::RHI::Viewport& viewport = viewportContext->GetWindowContext()->GetViewport();
internalParams.m_viewportContext = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get()->GetViewportContextById(params.m_drawViewportId);
const AZ::RHI::Viewport& viewport = internalParams.m_viewportContext->GetWindowContext()->GetViewport();
internalParams.m_viewport = &viewport;
if (params.m_virtual800x600ScreenSize)
{
posX *= WindowScaleWidth / (viewport.m_maxX - viewport.m_minX);
posY *= WindowScaleHeight / (viewport.m_maxY - viewport.m_minY);
}
TextDrawContext ctx;
ctx.SetBaseState(GS_NODEPTHTEST);
ctx.SetColor(AZColorToLYColorF(params.m_color));
ctx.SetCharWidthScale((params.m_monospace || params.m_scaleWithWindow) ? 0.5f : 1.0f);
ctx.EnableFrame(false);
ctx.SetProportional(!params.m_monospace && params.m_scaleWithWindow);
ctx.SetSizeIn800x600(params.m_scaleWithWindow && params.m_virtual800x600ScreenSize);
ctx.SetSize(AZVec2ToLYVec2(UiDraw_TextSizeFactor * params.m_scale));
internalParams.m_ctx.SetBaseState(GS_NODEPTHTEST);
internalParams.m_ctx.SetColor(AZColorToLYColorF(params.m_color));
internalParams.m_ctx.SetCharWidthScale((params.m_monospace || params.m_scaleWithWindow) ? 0.5f : 1.0f);
internalParams.m_ctx.EnableFrame(false);
internalParams.m_ctx.SetProportional(!params.m_monospace && params.m_scaleWithWindow);
internalParams.m_ctx.SetSizeIn800x600(params.m_scaleWithWindow && params.m_virtual800x600ScreenSize);
internalParams.m_ctx.SetSize(AZVec2ToLYVec2(UiDraw_TextSizeFactor * params.m_scale));
internalParams.m_ctx.SetLineSpacing(params.m_lineSpacing);
if (params.m_monospace || !params.m_scaleWithWindow)
{
ScaleCoord(viewport, posX, posY);
}
if (params.m_hAlign != AzFramework::TextHorizontalAlignment::Left ||
params.m_vAlign != AzFramework::TextVerticalAlignment::Top)
params.m_vAlign != AzFramework::TextVerticalAlignment::Top ||
forceCalculateSize)
{
Vec2 textSize = GetTextSizeUInternal(viewport, string.data(), params.m_multiline, ctx);
Vec2 textSize = GetTextSizeUInternal(viewport, text.data(), params.m_multiline, internalParams.m_ctx);
// If we're using virtual 800x600 coordinates, convert the text size from
// pixels to that before using it as an offset.
if (ctx.m_sizeIn800x600)
if (internalParams.m_ctx.m_sizeIn800x600)
{
float width = 1.0f;
float height = 1.0f;
@@ -1741,33 +1740,46 @@ void AZ::FFont::DrawScreenAlignedText2d(
{
posY -= textSize.y;
}
internalParams.m_size = AZ::Vector2{textSize.x, textSize.y};
}
SetCommonContextFlags(internalParams.m_ctx, params);
internalParams.m_ctx.m_drawTextFlags |= eDrawText_2D;
internalParams.m_position = AZ::Vector2{posX, posY};
return internalParams;
}
void AZ::FFont::DrawScreenAlignedText2d(
const AzFramework::TextDrawParameters& params,
AZStd::string_view text)
{
DrawParameters internalParams = ExtractDrawParameters(params, text, false);
if (!internalParams.m_viewportContext)
{
return;
}
SetCommonContextFlags(ctx, params);
ctx.m_drawTextFlags |= eDrawText_2D;
DrawStringUInternal(
viewport,
viewportContext,
posX,
posY,
*internalParams.m_viewport,
internalParams.m_viewportContext,
internalParams.m_position.GetX(),
internalParams.m_position.GetY(),
params.m_position.GetZ(), // Z
string.data(),
text.data(),
params.m_multiline,
ctx
internalParams.m_ctx
);
}
void AZ::FFont::DrawScreenAlignedText3d(
const AzFramework::TextDrawParameters& params,
const AZStd::string_view& string)
AZStd::string_view text)
{
if (params.m_drawViewportId == AzFramework::InvalidViewportId ||
string.empty())
DrawParameters internalParams = ExtractDrawParameters(params, text, false);
if (!internalParams.m_viewportContext)
{
return;
}
AZ::RPI::ViewportContext* viewportContext = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get()->GetViewportContextById(params.m_drawViewportId).get();
AZ::RPI::ViewPtr currentView = viewportContext->GetDefaultView();
AZ::RPI::ViewPtr currentView = internalParams.m_viewportContext->GetDefaultView();
if (!currentView)
{
return;
@@ -1779,7 +1791,23 @@ void AZ::FFont::DrawScreenAlignedText3d(
);
AzFramework::TextDrawParameters param2d = params;
param2d.m_position = positionNDC;
DrawScreenAlignedText2d(param2d, string);
DrawStringUInternal(
*internalParams.m_viewport,
internalParams.m_viewportContext,
internalParams.m_position.GetX(),
internalParams.m_position.GetY(),
params.m_position.GetZ(), // Z
text.data(),
params.m_multiline,
internalParams.m_ctx
);
}
AZ::Vector2 AZ::FFont::GetTextSize(const AzFramework::TextDrawParameters& params, AZStd::string_view text)
{
DrawParameters sizeParams = ExtractDrawParameters(params, text, true);
return sizeParams.m_size;
}
#endif //USE_NULLFONT_ALWAYS
-19
View File
@@ -1,19 +0,0 @@
{
"gem_name": "AtomFont",
"Dependencies": [
],
"GemFormatVersion": 4,
"Uuid": "{16ef36f2e3fc4e6ca15fcc484ec895fc}",
"Name": "AtomLyIntegration_AtomFont",
"DisplayName": "AtomLyIntegration.AtomFont",
"Version": "0.1.0",
"LinkType": "Dynamic",
"Summary": "Implement ICryFont & IFFont interfaces on Atom. Uses duplicated CryFont code",
"Tags": [ "Atom", "Font" ],
"IconPath": "preview.png",
"Modules": [
{
"Type": "GameModule"
}
]
}
@@ -1,25 +0,0 @@
{
"gem_name": "AtomImGuiTools",
"GemFormatVersion": 4,
"Uuid": "1a9d10de1b8a45fab2fe04517f613962",
"Name": "AtomImGuiTools",
"DisplayName": "Atom ImGui Tools",
"Version": "0.1.0",
"Summary": "ImGui tools for Atom renderer.",
"Tags": [ "Atom", "ImGui" ],
"IconPath": "preview.png",
"Modules": [
{
"Type": "GameModule"
}
],
"Dependencies": [
{
"Uuid": "9986e22e14184f2fb6bb1e7dd185b2f9",
"VersionConstraints": [
"~>0.1"
],
"_comment": "ImGui.Atom"
}
]
}
@@ -0,0 +1,12 @@
#
# 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.
#
add_subdirectory(Code)
@@ -0,0 +1,52 @@
#
# 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.
#
ly_add_target(
NAME AtomViewportDisplayInfo GEM_MODULE
NAMESPACE Gem
FILES_CMAKE
atomviewportdisplayinfo_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
Source
PUBLIC
Include
BUILD_DEPENDENCIES
PRIVATE
AZ::AzCore
AZ::AtomCore
Legacy::CryCommon
Gem::Atom_RHI.Reflect
Gem::Atom_RPI.Public
)
################################################################################
# Tests
################################################################################
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_add_target(
NAME AtomViewportDisplayInfo.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
NAMESPACE Gem
FILES_CMAKE
atomviewportdisplayinfo_test_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
Include
Tests
BUILD_DEPENDENCIES
PRIVATE
AZ::AzTest
)
ly_add_googletest(
NAME Gem::AtomViewportDisplayInfo.Tests
)
endif()
@@ -0,0 +1,61 @@
/*
* 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/base.h>
#include <AzCore/EBus/EBus.h>
namespace AZ
{
namespace AtomBridge
{
//! The level of information to display in the viewport info display overlay.
enum class ViewportInfoDisplayState : int
{
NoInfo = 0,
NormalInfo = 1,
FullInfo = 2,
CompactInfo = 3,
Invalid
};
//! This bus is used to request changes to the viewport info display overlay.
class AtomViewportInfoDisplayRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = EBusAddressPolicy::Single;
//! Gets the current viewport info overlay state.
virtual ViewportInfoDisplayState GetDisplayState() const = 0;
//! Sets the current viewport info overlay state.
//! The overlay will be drawn to the default viewport context every frame, if enabled.
virtual void SetDisplayState(ViewportInfoDisplayState state) = 0;
};
using AtomViewportInfoDisplayRequestBus = AZ::EBus<AtomViewportInfoDisplayRequests>;
//! This bus is used to listen for state changes in the viewport info display overlay.
class AtomViewportInfoDisplayNotifications
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = EBusAddressPolicy::Single;
//! Called when the ViewportInfoDisplayState (via the r_displayInfo CVar) has changed.
virtual void OnViewportInfoDisplayStateChanged([[maybe_unused]]ViewportInfoDisplayState state){}
};
using AtomViewportInfoDisplayNotificationBus = AZ::EBus<AtomViewportInfoDisplayNotifications>;
}
}
@@ -0,0 +1,316 @@
/*
* 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.
*
*/
#include "AtomViewportDisplayInfoSystemComponent.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl>
#include <AzCore/Console/IConsole.h>
#include <AzCore/Interface/Interface.h>
#include <Atom/RPI.Public/ViewportContextBus.h>
#include <Atom/RPI.Public/ViewportContext.h>
#include <Atom/RPI.Public/View.h>
#include <Atom/RPI.Public/Pass/ParentPass.h>
#include <Atom/RHI/Factory.h>
#include <CryCommon/ISystem.h>
#include <CryCommon/IConsole.h>
namespace AZ::Render
{
AZ_CVAR(int, r_displayInfo, 1, [](const int& newDisplayInfoVal)->void
{
// Forward this event to the system component so it can update accordingly.
// This callback only gets triggered by console commands, so this will not recurse.
AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast(
&AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState,
aznumeric_cast<AtomBridge::ViewportInfoDisplayState>(newDisplayInfoVal)
);
}, AZ::ConsoleFunctorFlags::DontReplicate,
"Toggles debugging information display.\n"
"Usage: r_displayInfo [0=off/1=show/2=enhanced/3=compact]"
);
AZ_CVAR(float, r_fpsCalcInterval, 1.0f, nullptr, AZ::ConsoleFunctorFlags::DontReplicate,
"The time period over which to calculate the framerate for r_displayInfo."
);
void AtomViewportDisplayInfoSystemComponent::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
serialize->Class<AtomViewportDisplayInfoSystemComponent, AZ::Component>()
->Version(0)
;
if (AZ::EditContext* ec = serialize->GetEditContext())
{
ec->Class<AtomViewportDisplayInfoSystemComponent>("Viewport Display Info", "Manages debug viewport information through r_displayInfo")
->ClassElement(Edit::ClassElements::EditorData, "")
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
->Attribute(Edit::Attributes::AutoExpand, true)
;
}
}
}
void AtomViewportDisplayInfoSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("ViewportDisplayInfoService"));
}
void AtomViewportDisplayInfoSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC("ViewportDisplayInfoService"));
}
void AtomViewportDisplayInfoSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
required.push_back(AZ_CRC("RPISystem", 0xf2add773));
}
void AtomViewportDisplayInfoSystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
}
void AtomViewportDisplayInfoSystemComponent::Activate()
{
AZ::Name apiName = AZ::RHI::Factory::Get().GetName();
if (!apiName.IsEmpty())
{
m_rendererDescription = AZStd::string::format("Atom using %s RHI", apiName.GetCStr());
}
AZ::RPI::ViewportContextNotificationBus::Handler::BusConnect(
AZ::RPI::ViewportContextRequests::Get()->GetDefaultViewportContextName());
AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Handler::BusConnect();
}
void AtomViewportDisplayInfoSystemComponent::Deactivate()
{
AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Handler::BusDisconnect();
AZ::RPI::ViewportContextNotificationBus::Handler::BusDisconnect();
}
AZ::RPI::ViewportContextPtr AtomViewportDisplayInfoSystemComponent::GetViewportContext() const
{
return AZ::RPI::ViewportContextRequests::Get()->GetDefaultViewportContext();
}
void AtomViewportDisplayInfoSystemComponent::DrawLine(AZStd::string_view line, AZ::Color color)
{
m_drawParams.m_color = color;
AZ::Vector2 textSize = m_fontDrawInterface->GetTextSize(m_drawParams, line);
m_fontDrawInterface->DrawScreenAlignedText2d(m_drawParams, line);
m_drawParams.m_position.SetY(m_drawParams.m_position.GetY() + textSize.GetY() + m_lineSpacing);
}
void AtomViewportDisplayInfoSystemComponent::OnRenderTick()
{
if (!m_fontDrawInterface)
{
auto fontQueryInterface = AZ::Interface<AzFramework::FontQueryInterface>::Get();
if (!fontQueryInterface)
{
return;
}
m_fontDrawInterface =
fontQueryInterface->GetDefaultFontDrawInterface();
}
AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext();
if (!m_fontDrawInterface || !viewportContext || !viewportContext->GetRenderScene())
{
return;
}
m_fpsInterval = AZStd::chrono::seconds(r_fpsCalcInterval);
UpdateFramerate();
const AtomBridge::ViewportInfoDisplayState displayLevel = GetDisplayState();
if (displayLevel == AtomBridge::ViewportInfoDisplayState::NoInfo)
{
return;
}
if (m_updateRootPassQuery)
{
if (auto rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass())
{
rootPass->SetPipelineStatisticsQueryEnabled(displayLevel != AtomBridge::ViewportInfoDisplayState::CompactInfo);
m_updateRootPassQuery = false;
}
}
m_drawParams.m_drawViewportId = viewportContext->GetId();
auto viewportSize = viewportContext->GetViewportSize();
m_drawParams.m_position = AZ::Vector3(viewportSize.m_width, 0.f, 1.f);
m_drawParams.m_color = AZ::Colors::White;
m_drawParams.m_scale = AZ::Vector2(0.7f);
m_drawParams.m_hAlign = AzFramework::TextHorizontalAlignment::Right;
m_drawParams.m_monospace = false;
m_drawParams.m_depthTest = false;
m_drawParams.m_virtual800x600ScreenSize = true;
m_drawParams.m_scaleWithWindow = false;
m_drawParams.m_multiline = true;
m_drawParams.m_lineSpacing = 0.5f;
// Calculate line spacing based on the font's actual line height
const float lineHeight = m_fontDrawInterface->GetTextSize(m_drawParams, " ").GetY();
m_lineSpacing = lineHeight * m_drawParams.m_lineSpacing;
DrawRendererInfo();
if (displayLevel == AtomBridge::ViewportInfoDisplayState::FullInfo)
{
DrawCameraInfo();
}
if (displayLevel != AtomBridge::ViewportInfoDisplayState::CompactInfo)
{
DrawPassInfo();
}
DrawFramerate();
}
AtomBridge::ViewportInfoDisplayState AtomViewportDisplayInfoSystemComponent::GetDisplayState() const
{
return aznumeric_cast<AtomBridge::ViewportInfoDisplayState>(r_displayInfo.operator int());
}
void AtomViewportDisplayInfoSystemComponent::SetDisplayState(AtomBridge::ViewportInfoDisplayState state)
{
r_displayInfo = aznumeric_cast<int>(state);
AtomBridge::AtomViewportInfoDisplayNotificationBus::Broadcast(
&AtomBridge::AtomViewportInfoDisplayNotificationBus::Events::OnViewportInfoDisplayStateChanged,
state);
m_updateRootPassQuery = true;
}
void AtomViewportDisplayInfoSystemComponent::DrawRendererInfo()
{
DrawLine(m_rendererDescription, AZ::Colors::Yellow);
}
void AtomViewportDisplayInfoSystemComponent::DrawCameraInfo()
{
AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext();
AZ::RPI::ViewPtr currentView = viewportContext->GetDefaultView();
if (currentView == nullptr)
{
return;
}
auto viewportSize = viewportContext->GetViewportSize();
AzFramework::CameraState cameraState;
AzFramework::SetCameraClippingVolumeFromPerspectiveFovMatrixRH(cameraState, currentView->GetViewToClipMatrix());
const AZ::Transform transform = currentView->GetCameraTransform();
const AZ::Vector3 translation = transform.GetTranslation();
const AZ::Vector3 rotation = transform.GetEulerDegrees();
DrawLine(AZStd::string::format(
"CamPos=%.2f %.2f %.2f Angl=%3.0f %3.0f %4.0f ZN=%.2f ZF=%.0f",
translation.GetX(), translation.GetY(), translation.GetZ(),
rotation.GetX(), rotation.GetY(), rotation.GetZ(),
cameraState.m_nearClip, cameraState.m_farClip
));
}
void AtomViewportDisplayInfoSystemComponent::DrawPassInfo()
{
auto rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass();
const RPI::PipelineStatisticsResult stats = rootPass->GetLatestPipelineStatisticsResult();
AZStd::function<int(const AZ::RPI::Ptr<AZ::RPI::Pass>)> containingPassCount = [&containingPassCount](const AZ::RPI::Ptr<AZ::RPI::Pass> pass)
{
int count = 1;
if (auto passAsParent = pass->AsParent())
{
for (const auto& child : passAsParent->GetChildren())
{
count += containingPassCount(child);
}
}
return count;
};
const int numPasses = containingPassCount(rootPass);
DrawLine(AZStd::string::format(
"Total Passes: %d Vertex Count: %lld Primitive Count: %lld",
numPasses,
aznumeric_cast<long long>(stats.m_vertexCount),
aznumeric_cast<long long>(stats.m_primitiveCount)
));
}
void AtomViewportDisplayInfoSystemComponent::UpdateFramerate()
{
if (!m_tickRequests)
{
m_tickRequests = AZ::TickRequestBus::FindFirstHandler();
if (!m_tickRequests)
{
return;
}
}
AZ::ScriptTimePoint currentTime = m_tickRequests->GetTimeAtCurrentTick();
// Only keep as much sampling data as is required by our FPS history.
while (!m_fpsHistory.empty() && (currentTime.Get() - m_fpsHistory.front().Get()) > m_fpsInterval)
{
m_fpsHistory.pop_front();
}
// Discard entries with a zero time-delta (can happen when we don't have window focus).
if (m_fpsHistory.empty() || (currentTime.Get() - m_fpsHistory.back().Get()) != AZStd::chrono::seconds(0))
{
m_fpsHistory.push_back(currentTime);
}
}
void AtomViewportDisplayInfoSystemComponent::DrawFramerate()
{
AZStd::chrono::duration<double> actualInterval = AZStd::chrono::seconds(0);
AZStd::optional<AZ::ScriptTimePoint> lastTime;
AZStd::optional<double> minFPS;
AZStd::optional<double> maxFPS;
for (const AZ::ScriptTimePoint& time : m_fpsHistory)
{
if (lastTime.has_value())
{
AZStd::chrono::duration<double> deltaTime = time.Get() - lastTime.value().Get();
double fps = AZStd::chrono::seconds(1) / deltaTime;
if (!minFPS.has_value())
{
minFPS = fps;
maxFPS = fps;
}
else
{
minFPS = AZStd::min(minFPS.value(), fps);
maxFPS = AZStd::max(maxFPS.value(), fps);
}
actualInterval += deltaTime;
}
lastTime = time;
}
const double averageFPS = aznumeric_cast<double>(m_fpsHistory.size()) / actualInterval.count();
const double frameIntervalSeconds = m_fpsInterval.count();
DrawLine(
AZStd::string::format(
"FPS %.1f [%.0f..%.0f], frame avg over %.1fs",
averageFPS,
minFPS.value_or(0.0),
maxFPS.value_or(0.0),
frameIntervalSeconds),
AZ::Colors::Yellow);
}
} // namespace AZ::Render
@@ -0,0 +1,79 @@
/*
* 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/Component/Component.h>
#include <CryCommon/CrySystemBus.h>
#include <AzCore/Script/ScriptTimePoint.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzFramework/Font/FontInterface.h>
#include <Atom/RPI.Public/Base.h>
#include <Atom/RPI.Public/ViewportContextBus.h>
#include <AtomLyIntegration/AtomViewportDisplayInfo/AtomViewportInfoDisplayBus.h>
namespace AZ
{
class TickRequests;
namespace Render
{
class AtomViewportDisplayInfoSystemComponent
: public AZ::Component
, public AZ::RPI::ViewportContextNotificationBus::Handler
, public AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Handler
{
public:
AZ_COMPONENT(AtomViewportDisplayInfoSystemComponent, "{AC32F173-E7E2-4943-8E6C-7C3091978221}");
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
protected:
// AZ::Component overrides...
void Activate() override;
void Deactivate() override;
// AZ::RPI::ViewportContextNotificationBus::Handler overrides...
void OnRenderTick() override;
// AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Handler overrides...
AtomBridge::ViewportInfoDisplayState GetDisplayState() const override;
void SetDisplayState(AtomBridge::ViewportInfoDisplayState state) override;
private:
AZ::RPI::ViewportContextPtr GetViewportContext() const;
void DrawLine(AZStd::string_view line, AZ::Color color = AZ::Colors::White);
void UpdateFramerate();
void DrawRendererInfo();
void DrawCameraInfo();
void DrawPassInfo();
void DrawFramerate();
AZStd::string m_rendererDescription;
AzFramework::TextDrawParameters m_drawParams;
AzFramework::FontDrawInterface* m_fontDrawInterface = nullptr;
float m_lineSpacing;
AZStd::chrono::duration<double> m_fpsInterval = AZStd::chrono::seconds(1);
AZStd::deque<AZ::ScriptTimePoint> m_fpsHistory;
AZStd::optional<AZStd::chrono::system_clock::time_point> m_lastMemoryUpdate;
AZ::TickRequests* m_tickRequests = nullptr;
bool m_updateRootPassQuery = true;
};
} // namespace Render
} // namespace AZ
@@ -0,0 +1,51 @@
/*
* 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.
*
*/
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/Module/Module.h>
#include "AtomViewportDisplayInfoSystemComponent.h"
namespace AZ
{
namespace Render
{
class AtomViewportDisplayInfoModule
: public AZ::Module
{
public:
AZ_RTTI(AtomViewportDisplayInfoModule, "{B10C0E55-03A1-4A46-AE3E-D3615AEAA659}", AZ::Module);
AZ_CLASS_ALLOCATOR(AtomViewportDisplayInfoModule, AZ::SystemAllocator, 0);
AtomViewportDisplayInfoModule()
: AZ::Module()
{
m_descriptors.insert(m_descriptors.end(), {
AtomViewportDisplayInfoSystemComponent::CreateDescriptor(),
});
}
AZ::ComponentTypeList GetRequiredSystemComponents() const override
{
return AZ::ComponentTypeList{
azrtti_typeid<AtomViewportDisplayInfoSystemComponent>(),
};
}
};
} // namespace Render
} // namespace AZ
// DO NOT MODIFY THIS LINE UNLESS YOU RENAME THE GEM
// The first parameter should be GemName_GemIdLower
// The second should be the fully qualified name of the class above
AZ_DECLARE_MODULE_CLASS(Gem_AtomViewportDisplayInfo, AZ::Render::AtomViewportDisplayInfoModule)
@@ -10,9 +10,11 @@
*
*/
#pragma once
#include <AzTest/AzTest.h>
namespace Multiplayer
AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);
TEST(AtomViewportDisplayInfoSanityTest, Sanity)
{
EXPECT_EQ(1, 1);
}
@@ -0,0 +1,16 @@
#
# 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.
#
set(FILES
Source/AtomViewportDisplayInfoSystemComponent.cpp
Source/AtomViewportDisplayInfoSystemComponent.h
Source/Module.cpp
)
@@ -0,0 +1,14 @@
#
# 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.
#
set(FILES
Source/Tests/test_Main.cpp
)
@@ -0,0 +1,12 @@
{
"gem_name": "AtomLyIntegration_AtomViewportDisplayInfo",
"display_name": "Atom Viewport Display Info Overlay",
"summary": "Provides a diagnostic viewport overlay for the default O3DE Atom viewport.",
"canonical_tags": [
"Gem"
],
"user_tags": [
"AtomLyIntegration",
"AtomViewportDisplayInfo"
]
}
+1
View File
@@ -16,3 +16,4 @@ add_subdirectory(EMotionFXAtom)
add_subdirectory(AtomFont)
add_subdirectory(TechnicalArt)
add_subdirectory(AtomBridge)
add_subdirectory(AtomViewportDisplayInfo)
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bb8c1839f46df4623818bc1b02f626d85d8f83d77cbeabd0d56c6a5c997c3ab3
size 495250984
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9bb547a502aa028624e3f95491d2e459860db5fdc5551eece757c271362c902d
size 42981863
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:962248929564f7a3a2a25813ba8ab83d72f2f4d8db71eb495bd650ad4eca5c25
size 8681159
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2c5998edda6eb34ace8b7a5f63e72f922e0daebb6aeb453142b31e605157736d
size 17366289
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a79b82df3f6f908b2ed31f9247d9befde7daf0ff53c87479920c0463cc12d437
size 1308624196
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b9892d5de71db58217f9c942f542c058891ab2f0949443c48111aa71fe621cae
size 128078160
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:353ff22364447796ec01799a16e6ee39fbcde337a5fee4de409069316eccbb8f
size 6942256
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e934a8772f33e6c7bc11e70071c5d14147d01d123a5bed3bd51fc861047f17cb
size 305364828
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:247402172cb0539faaae937659507bd72087e629004e3eb2e8f67df97063a92f
size 70531613
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:aa4f9fbb9fc332fa0fb3f35df3b21ef72439073a854ad55d637efbed89ad3b3c
size 562609478
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8f5a6f8d7abb7c7283c921d884be51addd99526fefd8c12c733d2e955b2f09f5
size 26738740

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