Merge branch 'main' into Atom/antonmic/lowEnd

This commit is contained in:
antonmic
2021-05-18 13:04:25 -07:00
2890 changed files with 39266 additions and 267516 deletions
@@ -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>
@@ -95,28 +95,32 @@ namespace UnitTest
class ImageProcessingTest
: public ::testing::Test
, public AllocatorsBase
, public ComponentApplicationBus::Handler
, public AZ::ComponentApplicationBus::Handler
{
public:
//////////////////////////////////////////////////////////////////////////
// ComponentApplicationMessages.
ComponentApplication* GetApplication() override { return nullptr; }
void RegisterComponentDescriptor(const ComponentDescriptor*) override { }
void UnregisterComponentDescriptor(const ComponentDescriptor*) override { }
void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler&) override { }
void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler&) override { }
bool AddEntity(Entity*) override { return false; }
bool RemoveEntity(Entity*) override { return false; }
bool DeleteEntity(const EntityId&) override { return false; }
Entity* FindEntity(const EntityId&) override { return nullptr; }
SerializeContext* GetSerializeContext() override { return m_context.get(); }
BehaviorContext* GetBehaviorContext() override { return nullptr; }
AZ::ComponentApplication* GetApplication() override { return nullptr; }
void RegisterComponentDescriptor(const AZ::ComponentDescriptor*) override { }
void UnregisterComponentDescriptor(const AZ::ComponentDescriptor*) override { }
void RegisterEntityAddedEventHandler(AZ::EntityAddedEvent::Handler&) override { }
void RegisterEntityRemovedEventHandler(AZ::EntityRemovedEvent::Handler&) override { }
void RegisterEntityActivatedEventHandler(AZ::EntityActivatedEvent::Handler&) override { }
void RegisterEntityDeactivatedEventHandler(AZ::EntityDeactivatedEvent::Handler&) override { }
void SignalEntityActivated(AZ::Entity*) override { }
void SignalEntityDeactivated(AZ::Entity*) override { }
bool AddEntity(AZ::Entity*) override { return false; }
bool RemoveEntity(AZ::Entity*) override { return false; }
bool DeleteEntity(const AZ::EntityId&) override { return false; }
Entity* FindEntity(const AZ::EntityId&) override { return nullptr; }
AZ::SerializeContext* GetSerializeContext() override { return m_context.get(); }
AZ::BehaviorContext* GetBehaviorContext() override { return nullptr; }
AZ::JsonRegistrationContext* GetJsonRegistrationContext() override { return m_jsonRegistrationContext.get(); }
const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
Debug::DrillerManager* GetDrillerManager() override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
AZ::Debug::DrillerManager* GetDrillerManager() override { return nullptr; }
void EnumerateEntities(const AZ::ComponentApplicationRequests::EntityCallback& /*callback*/) override {}
void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override {}
//////////////////////////////////////////////////////////////////////////
@@ -134,6 +138,7 @@ namespace UnitTest
// Adding this handler to allow utility functions access the serialize context
ComponentApplicationBus::Handler::BusConnect();
AZ::Interface<AZ::ComponentApplicationRequests>::Register(this);
AZ::AllocatorInstance<AZ::PoolAllocator>::Create();
AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Create();
@@ -212,6 +217,7 @@ namespace UnitTest
AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Destroy();
AZ::AllocatorInstance<AZ::PoolAllocator>::Destroy();
AZ::Interface<AZ::ComponentApplicationRequests>::Unregister(this);
ComponentApplicationBus::Handler::BusDisconnect();
AllocatorsBase::TeardownAllocator();
}
@@ -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"
}
]
}
@@ -15,6 +15,7 @@
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/NativeUI/NativeUIRequests.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/smart_ptr/make_shared.h>
@@ -166,6 +167,18 @@ namespace AZ
RPI::RPISystemInterface::Get()->InitializeSystemAssets();
if (!RPI::RPISystemInterface::Get()->IsInitialized())
{
AZ::OSString msgBoxMessage;
msgBoxMessage.append("RPI System could not initialize correctly. Check log for detail.");
AZ::NativeUI::NativeUIRequestBus::Broadcast(
&AZ::NativeUI::NativeUIRequestBus::Events::DisplayOkDialog, "O3DE Fatal Error", msgBoxMessage.c_str(), false);
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop);
return;
}
// In the case of the game we want to call create and register the scene as a soon as we can
// because a level could be loaded in autoexec.cfg and that will assert if there is no scene registered
// to get the feature processors for the components. So we can't wait until the tick (whereas the Editor wants to wait)
-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"
}
]
}
@@ -41,7 +41,8 @@ namespace AZ
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
// CameraControllerRequestBus::Handler overrides
void Enable(TypeId typeId) override final;
void Reset() override final;
@@ -69,6 +69,7 @@ namespace AZ
void CameraComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC("CameraService", 0x1dd1caa4));
incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
}
void CameraComponent::Activate()
@@ -32,12 +32,17 @@ namespace AZ
required.push_back(AZ_CRC("TransformService", 0x8ee22c50));
required.push_back(AZ_CRC("CameraService", 0x1dd1caa4));
}
void CameraControllerComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("CameraControllerService", 0xc35788f9));
}
void CameraControllerComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
}
void CameraControllerComponent::Enable(TypeId typeId)
{
// Enable this controller if type id matches, otherwise disable this controller
-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"
}
]
}
@@ -150,7 +150,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_depthFactor, MaterialSrg::m_depthOffset,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth, displacementIsClipped);
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth, IN.m_position.w, displacementIsClipped);
// Apply second part of the offset to the detail UV (see comment above)
IN.m_detailUv[MaterialSrg::m_parallaxUvIndex] -= IN.m_uv[MaterialSrg::m_parallaxUvIndex];
@@ -32,7 +32,7 @@ option bool prefix##o_useDepthMap;
void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float depthFactor, float depthOffset,
float4x4 objectWorldMatrix, float3x3 uvMatrix, float3x3 uvMatrixInverse,
inout float2 uv, inout float3 worldPosition, inout float depth, out bool isClipped)
inout float2 uv, inout float3 worldPosition, inout float depthNDC, inout float depthCS, out bool isClipped)
{
if(o_parallax_feature_enabled)
{
@@ -72,7 +72,8 @@ void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float dep
objectWorldMatrix,
ViewSrg::m_viewProjectionMatrix);
depth = pdo.m_depth;
depthCS = pdo.m_depthCS;
depthNDC = pdo.m_depthNDC;
worldPosition = pdo.m_worldPosition;
}
@@ -82,9 +83,17 @@ void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float dep
void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float depthFactor, float depthOffset,
float4x4 objectWorldMatrix, float3x3 uvMatrix, float3x3 uvMatrixInverse,
inout float2 uv, inout float3 worldPosition, inout float depth)
inout float2 uv, inout float3 worldPosition, inout float depthNDC, inout float depthCS)
{
bool isClipped;
GetParallaxInput(normal, tangent, bitangent, depthFactor, depthOffset, objectWorldMatrix, uvMatrix, uvMatrixInverse, uv, worldPosition, depth, isClipped);
GetParallaxInput(normal, tangent, bitangent, depthFactor, depthOffset, objectWorldMatrix, uvMatrix, uvMatrixInverse, uv, worldPosition, depthNDC, depthCS, isClipped);
}
void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float depthFactor, float depthOffset,
float4x4 objectWorldMatrix, float3x3 uvMatrix, float3x3 uvMatrixInverse,
inout float2 uv, inout float3 worldPosition, inout float depthNDC)
{
float depthCS;
GetParallaxInput(normal, tangent, bitangent, depthFactor, depthOffset, objectWorldMatrix, uvMatrix, uvMatrixInverse, uv, worldPosition, depthNDC, depthCS);
}
@@ -130,9 +130,9 @@ VSOutput ForwardPassVS(VSInput IN)
// ---------- Pixel Shader ----------
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth)
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depthNDC)
{
depth = IN.m_position.z;
depthNDC = IN.m_position.z;
// ------- Tangents & Bitangets -------
@@ -185,7 +185,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float parallaxOverallFactor = MaterialSrg::m_displacementMax - MaterialSrg::m_displacementMin;
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], parallaxOverallFactor, parallaxOverallOffset,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth, displacementIsClipped);
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depthNDC, IN.m_position.w, displacementIsClipped);
// Adjust directional light shadow coorinates for parallax correction
if(o_parallax_enablePixelDepthOffset)
@@ -109,7 +109,7 @@ PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace)
GetDepth_Setup(IN.m_blendMask);
float depth;
float depthNDC;
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
@@ -118,9 +118,9 @@ PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace)
float parallaxOverallFactor = MaterialSrg::m_displacementMax - MaterialSrg::m_displacementMin;
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], parallaxOverallFactor, parallaxOverallOffset,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth);
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depthNDC);
OUT.m_depth = depth;
OUT.m_depth = depthNDC;
}
return OUT;
@@ -107,7 +107,7 @@ VSOutput StandardPbr_ForwardPassVS(VSInput IN)
// ---------- Pixel Shader ----------
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth)
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depthNDC)
{
// ------- Tangents & Bitangets -------
@@ -127,7 +127,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
// ------- Depth & Parallax -------
depth = IN.m_position.z;
depthNDC = IN.m_position.z;
bool displacementIsClipped = false;
@@ -139,7 +139,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_depthFactor, MaterialSrg::m_depthOffset,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth, displacementIsClipped);
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depthNDC, IN.m_position.w, displacementIsClipped);
// Adjust directional light shadow coorinates for parallax correction
if(o_parallax_enablePixelDepthOffset)
@@ -37,8 +37,6 @@ float3 TextureBlend_Overlay(float3 target, float3 blend)
//! @return the resulting blended color
float3 ApplyTextureBlend(float3 color, float3 blendColor, float factor, TextureBlendMode blendMode)
{
// More info to help understand some of these blend modes: https://wiki.agscollab.com/pages/viewpage.action?pageId=15764930
if(blendMode == TextureBlendMode::Multiply)
{
return factor * color * blendColor;
@@ -25,7 +25,7 @@ class LightCullingTileIterator
float viewz = abs(svPosition.w);
// https://jira.agscollab.com/browse/ATOM-4198
// ATOM-4198
// Replace GetDimensions() with a cbuffer uint read. Reading it from a cbuffer should be faster
uint tileWidth, tileHeight;
tileLightDataTex.GetDimensions(tileWidth, tileHeight);
@@ -26,7 +26,7 @@
//
//----------------------------------------------------------------------------------
#define Depth_to_Z(d, unprojectZ) (unprojectZ.x / (d + unprojectZ.y))
#define DepthBufferToViewSpace(d, unprojectZ) (unprojectZ.x / (d + unprojectZ.y))
#define NVLC_MAX_POSSIBLE_LIGHTS_PER_BIN 256
@@ -187,7 +187,7 @@ float4 RemapZToUnit(float4 z, float2 minmaxz)
uint DepthSamplesToBinMask2x(float2 d, float2 minmaxz, float2 unprojectZ)
{
float2 z = Depth_to_Z(d, unprojectZ);
float2 z = DepthBufferToViewSpace(d, unprojectZ);
// Tile_UnitValueToBit will convert that 0 to 1 value into 0.0 to 31.99999
float2 bit = Tile_UnitValueToBit(RemapZToUnit(z, minmaxz));
@@ -207,7 +207,7 @@ uint DepthSamplesToBinMask2x(float2 d, float2 minmaxz, float2 unprojectZ)
uint DepthSamplesToBinMask4x(float4 d, float2 minmaxz, float2 unprojectZ)
{
float4 z = Depth_to_Z(d, unprojectZ);
float4 z = DepthBufferToViewSpace(d, unprojectZ);
// Tile_UnitValueToBit will convert that 0 to 1 value into 0.0 to 31.99999
float4 bit = Tile_UnitValueToBit(RemapZToUnit(z, minmaxz));
@@ -13,6 +13,49 @@
#pragma once
#include <Atom/Features/PBR/Lights/LightTypesCommon.azsli>
#include <Atom/Features/Shadow/ProjectedShadow.azsli>
// The order should match m_pointShadowTransforms in PointLightFeatureProcessor.h/.cpp
static const float3 PointLightShadowCubemapDirections[6] = {float3(-1,0,0), float3(1,0,0), float3(0,-1,0), float3(0,1,0), float3(0,0,-1), float3(0,0,1)};
int GetPointLightShadowCubemapFace(const float3 targetPos, const float3 lightPos)
{
const float3 toPoint = targetPos - lightPos;
const float maxElement = max(abs(toPoint.z), max(abs(toPoint.x), abs(toPoint.y)));
if (toPoint.x == -maxElement)
{
return 0;
}
else if (toPoint.x == maxElement)
{
return 1;
}
else if (toPoint.y == -maxElement)
{
return 2;
}
else if (toPoint.y == maxElement)
{
return 3;
}
else if (toPoint.z == -maxElement)
{
return 4;
}
else
{
return 5;
}
}
// PointLight::m_shadowIndices actually consists of uint16_t x 6 on the CPU, but visible as a uint32_t x 3 on the GPU.
// This function returns the proper uint16_t value given an input face in the range 0-5
int UnpackPointLightShadowIndex(const ViewSrg::PointLight light, const int face)
{
const int index = face >> 1;
const int shiftAmount = (face & 1) * 16;
return (light.m_shadowIndices[index] >> shiftAmount) & 0xFFFF;
}
void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingData lightingData)
{
@@ -31,11 +74,38 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD
d2 = max(0.001 * 0.001, d2); // clamp the light to at least 1mm away to avoid extreme values.
float3 lightIntensity = (light.m_rgbIntensityCandelas / d2) * radiusAttenuation;
// shadow
float litRatio = 1.0;
// How much is back face shadowed, it's set to the reverse of litRatio to share the same default value with thickness, which should be 0 if no shadow map available
float backShadowRatio = 0.0;
if (o_enableShadows)
{
const int shadowCubemapFace = GetPointLightShadowCubemapFace(surface.position, light.m_position);
const int shadowIndex = UnpackPointLightShadowIndex(light, shadowCubemapFace);
litRatio *= ProjectedShadow::GetVisibility(
shadowIndex,
light.m_position,
surface.position,
PointLightShadowCubemapDirections[shadowCubemapFace],
surface.normal);
// Use backShadowRatio to carry thickness from shadow map for thick mode
backShadowRatio = 1.0 - litRatio;
if (o_transmission_mode == TransmissionMode::ThickObject)
{
backShadowRatio = ProjectedShadow::GetThickness(
shadowIndex,
surface.position);
}
}
// Diffuse contribution
lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, normalize(posToLight));
lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, normalize(posToLight)) * litRatio;
// Tranmission contribution
lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), 0.0);
lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), backShadowRatio);
// Adjust the light direcion for specular based on bulb size
@@ -398,7 +398,8 @@ ParallaxOffset GetParallaxOffset( float depthFactor,
struct PixelDepthOffset
{
float m_depth;
float m_depthNDC; //!< The new depth value, in normalized device coordinates (used for final depth output)
float m_depthCS; //!< The new depth value, in clip space (can be used for other operations like light culling)
float3 m_worldPosition;
};
@@ -432,7 +433,8 @@ PixelDepthOffset CalcPixelDepthOffset( float depthFactor,
float4 clipOffsetPosition = mul(viewProjectionMatrix, float4(worldOffsetPosition, 1.0));
PixelDepthOffset pdo;
pdo.m_depth = clipOffsetPosition.z / clipOffsetPosition.w;
pdo.m_depthCS = clipOffsetPosition.z;
pdo.m_depthNDC = clipOffsetPosition.z / clipOffsetPosition.w;
pdo.m_worldPosition = worldOffsetPosition;
return pdo;
}
@@ -61,6 +61,8 @@ ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
float m_invAttenuationRadiusSquared;
float3 m_rgbIntensity;
float m_bulbRadius;
uint3 m_shadowIndices;
uint m_padding;
};
StructuredBuffer<PointLight> m_pointLights;
@@ -73,6 +73,8 @@ partial ShaderResourceGroup ViewSrg
float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2.
float3 m_rgbIntensityCandelas;
float m_bulbRadius;
uint3 m_shadowIndices;
uint m_padding;
};
StructuredBuffer<PointLight> m_pointLights;
@@ -17,7 +17,7 @@
#include <Atom/RPI/Math.azsli>
#include <Atom/Features/LightCulling/LightCullingShared.azsli>
enum QuadLightFlag // Copied from QuadLight.azsli. See https://jira.agscollab.com/browse/ATOM-3731
enum QuadLightFlag // Copied from QuadLight.azsli. See ATOM-3731
{
None = 0x00,
EmitsBothDirections = 0x01, // 1 << 0, // Quad should emit light from both sides
@@ -33,7 +33,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass
{
// Figure out how to remove duplicate struct definitions.
// These are also defined in View.srg
// https://jira.agscollab.com/browse/ATOM-3731
// ATOM-3731
struct SimplePointLight
{
@@ -59,6 +59,8 @@ ShaderResourceGroup PassSrg : SRG_PerPass
float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2.
float3 m_rgbIntensityCandelas;
float m_bulbRadius;
uint3 m_shadowIndices;
uint m_padding;
};
struct DiskLight
@@ -370,7 +372,7 @@ void CullDecals(uint groupIndex, TileLightData tileLightData, float3 aabb_center
float3 decalPosition = WorldToView_Point(decal.m_position);
// just wrapping a bounding sphere around a cube for now to get a minor perf boost. i.e. the sphere radius is sqrt(x*x + y*y + z*z)
// https://jira.agscollab.com/browse/ATOM-4224 - try AABB-AABB and implement depth binning for the decals
// ATOM-4224 - try AABB-AABB and implement depth binning for the decals
float maxHalfSize = max(max(decal.m_halfSize.x, decal.m_halfSize.y), decal.m_halfSize.z);
float boundingSphereRadiusSqr = maxHalfSize * maxHalfSize * 3;
@@ -378,7 +380,7 @@ void CullDecals(uint groupIndex, TileLightData tileLightData, float3 aabb_center
if (potentiallyIntersects)
{
// Implement and profile fine-grained light culling testing
// https://jira.agscollab.com/browse/ATOM-3732
// ATOM-3732
MarkLightAsVisibleInSharedMemory(decalIndex, 0xFFFF);
}
}
@@ -391,7 +393,7 @@ void CullPointLight(uint lightIndex, float3 lightPosition, float invLightRadius,
if (potentiallyIntersects)
{
// Implement and profile fine-grained light culling testing
// https://jira.agscollab.com/browse/ATOM-3732
// ATOM-3732
uint inside = 0;
float2 minmax = ComputePointLightMinMaxZ(rsqrt(invLightRadius), lightPosition);
@@ -432,7 +434,7 @@ void CullSimpleSpotLights(uint groupIndex, TileLightData tileLightData, float3 a
if (potentiallyIntersects)
{
// Implement and profile fine-grained light culling testing
// https://jira.agscollab.com/browse/ATOM-3732
// ATOM-3732
uint inside = 0;
float2 minmax = ComputeSimpleSpotLightMinMax(light, lightPosition);
@@ -477,7 +479,7 @@ void CullDiskLights(uint groupIndex, TileLightData tileLightData, float3 aabb_ce
if (potentiallyIntersects)
{
// Implement and profile fine-grained light culling testing
// https://jira.agscollab.com/browse/ATOM-3732
// ATOM-3732
uint inside = 0;
float2 minmax = ComputeDiskLightMinMax(light, lightPosition);
@@ -505,7 +507,7 @@ void CullCapsuleLights(uint groupIndex, TileLightData tileLightData, float3 aabb
if (potentiallyIntersects)
{
// Implement and profile fine-grained light culling testing
// https://jira.agscollab.com/browse/ATOM-3732
// ATOM-3732
uint inside = 0;
float2 minmax = ComputeCapsuleLightMinMax(light, lightMiddleView, lightFalloffRadius);
@@ -520,7 +522,7 @@ void CullCapsuleLights(uint groupIndex, TileLightData tileLightData, float3 aabb
void CullQuadLights(uint groupIndex, TileLightData tileLightData, float3 aabb_center, float3 aabb_extents)
{
// Implement and profile fine-grained light culling testing
// https://jira.agscollab.com/browse/ATOM-3732
// ATOM-3732
for (uint lightIndex = groupIndex ; lightIndex < PassSrg::m_quadLightCount ; lightIndex += TILE_DIM_X * TILE_DIM_Y)
{
@@ -242,7 +242,7 @@ PSOutput MainPS(VSOutput IN)
// Set this value to > 0 to actually see this pass. It is currently always active.
OUT.m_color.w = PassSrg::m_heatmapOpacity;
// https://jira.agscollab.com/browse/ATOM-3682 (improve heatmap integration with the pass system)
// ATOM-3682 (improve heatmap integration with the pass system)
return OUT;
}
@@ -186,7 +186,7 @@ void InitWriteIndices(uint3 groupID, uint baseBin, out uint writeIndices[NVLC_MA
// light indices until it hits an END_OF_X marker
// Note that this code could probably be made faster with wave intrinsics
// https://jira.agscollab.com/browse/ATOM-4104
// ATOM-4104
[numthreads(NUM_THREADS, 1, 1)]
void MainCS(
uint3 dispatchThreadID : SV_DispatchThreadID,
@@ -150,7 +150,7 @@ uint ComputeTransparentBitMask(float2 minmaxZ)
return 0;
}
float2 minmaxZ_transparent = Depth_to_Z(minmaxDepth_transparent, PassSrg::m_constantData.m_unprojectZ);
float2 minmaxZ_transparent = DepthBufferToViewSpace(minmaxDepth_transparent, PassSrg::m_constantData.m_unprojectZ);
float2 minmaxUnit_transparent = RemapZToUnit(minmaxZ_transparent, minmaxZ);
@@ -181,7 +181,7 @@ void WriteTileLightDataToMainMemory(uint groupIndex, uint3 groupID, float2 minma
// Note that Nvidia Light Culling framework has some additional code to better calculate this ratio
// See cb_perFrame.fRangeThreshold in their framework. This code might be something we want to port over.
// https://jira.agscollab.com/browse/ATOM-5554
// ATOM-5554
float ratio = tileZ / 1.0f;
float logMaxBins = clamp(log2(ratio), 0.0, LOG_MAX_BINS);
uint ulogMaxBins = uint(logMaxBins + 0.5);
@@ -295,7 +295,7 @@ void MainCS(
float2 minmaxDepth_opaque = ComputeDepthMinMaxFrom2Samples(opaqueDepthSamples);
minmaxDepth_both = ExpandMinMax(minmaxDepth_opaque, minmaxDepth_transparent);
UpdateMinMaxFromAllThreads(minmaxDepth_both, minmaxDepth_transparent, isPixelOnScreen);
minmaxDepth_both = Depth_to_Z(minmaxDepth_both, PassSrg::m_constantData.m_unprojectZ);
minmaxDepth_both = DepthBufferToViewSpace(minmaxDepth_both, PassSrg::m_constantData.m_unprojectZ);
// if zNear == zFar we want to map z == zNear to 0-bit, so we have to keep zNear without modifications
minmaxDepth_both.y = IncrementULP(minmaxDepth_both.y);
@@ -313,7 +313,7 @@ void MainCS(
float2 minmaxDepth_opaque = ComputeDepthMinMaxFrom4Samples(opaqueDepthSamples);
minmaxDepth_both = ExpandMinMax(minmaxDepth_opaque, minmaxDepth_transparent);
UpdateMinMaxFromAllThreads(minmaxDepth_both, minmaxDepth_transparent, isPixelOnScreen);
minmaxDepth_both = Depth_to_Z(minmaxDepth_both, PassSrg::m_constantData.m_unprojectZ);
minmaxDepth_both = DepthBufferToViewSpace(minmaxDepth_both, PassSrg::m_constantData.m_unprojectZ);
// if zNear == zFar we want to map z == zNear to 0-bit, so we have to keep zNear without modifications
minmaxDepth_both.y = IncrementULP(minmaxDepth_both.y);
@@ -41,7 +41,6 @@ ShaderResourceGroup PassSrg : SRG_PerDraw
// The number of points to sample.
// Sample 6 points around center pixel.
// Similarly, sample around it as 12,18,24 points.
// Please refer to “https://wiki.agscollab.com/display/ATOM/Pencil+Map” for details.
option enum class SampleNumber
{
Sample6, // 6
@@ -52,7 +51,6 @@ option enum class SampleNumber
o_sampleNumber = SampleNumber::Sample6;
// Get CocRadius from dofFactor.
// Please refer to https://wiki.agscollab.com/display/ATOM/Pencil+Map for CocRadius.
inline float GetCocRadius(float dofFactor)
{
float cocRadius = dofFactor * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f;
@@ -61,14 +59,12 @@ inline float GetCocRadius(float dofFactor)
}
// Calculate the texcoord U of the pencil map from cocRadius.
// Please refer to https://wiki.agscollab.com/display/ATOM/Pencil+Map for the pencil map.
inline float GetPencilMapTexcoordU(float cocRadius)
{
return cocRadius * ViewSrg::m_dof.m_pencilMapTexcoordToCocRadius + ViewSrg::m_dof.m_pencilMapFocusPointTexcoordU;
}
// Get the color from the coordinate array.
// Please refer to https://wiki.agscollab.com/display/ATOM/Pencil+Map for details of coordinates.
inline float4 SampleColorAndDofFactor(float2 centerTexCoord, float cocRadius, int sampleIndex)
{
float2 sampleTexcoordOffset = PassSrg::m_sampleTexcoordsRadius[sampleIndex].xy * cocRadius;
@@ -78,7 +74,6 @@ inline float4 SampleColorAndDofFactor(float2 centerTexCoord, float cocRadius, in
}
// Load the pencil map. Since the colors are square rooted, they are decoded (linearized). This is for accuracy.
// Please refer to https://wiki.agscollab.com/display/ATOM/Pencil+Map for the pencil map.
inline float4 SamplePencilMap(float lensCoordX, float radius)
{
float2 bokehTexcoord = float2(lensCoordX, radius);
@@ -77,7 +77,6 @@ PSOutput MainPS(VSOutput IN)
float3 colorSum = (float3)0;
// Combine from the back buffer to the front.
// Please refer to https://wiki.agscollab.com/pages/viewpage.action?spaceKey=ATOM&title=Dof+factor+and+Buffer+composition for details
////////////////////////////////////////////////////////////////////////
// Background
@@ -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...
@@ -1,19 +1,20 @@
/*
* 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.
*
*/
* 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 <Atom/RPI.Public/FeatureProcessor.h>
#include <Atom/Feature/CoreLights/PhotometricValue.h>
#include <Atom/Feature/CoreLights/ShadowConstants.h>
#include <Atom/RPI.Public/FeatureProcessor.h>
namespace AZ
{
@@ -22,9 +23,25 @@ namespace AZ
namespace Render
{
struct PointLightData
{
AZStd::array<float, 3> m_position = {{0.0f, 0.0f, 0.0f}};
// Inverse of the distance at which this light no longer has an effect, squared. Also used for falloff calculations.
float m_invAttenuationRadiusSquared = 0.0f;
AZStd::array<float, 3> m_rgbIntensity = {{0.0f, 0.0f, 0.0f}};
// Radius of spherical light in meters.
float m_bulbRadius = 0.0f;
static const int NumShadowFaces = 6;
AZStd::array<uint16_t, NumShadowFaces> m_shadowIndices = {{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}};
uint32_t m_padding;
};
//! PointLightFeatureProcessorInterface provides an interface to acquire, release, and update a point light.
class PointLightFeatureProcessorInterface
: public RPI::FeatureProcessor
class PointLightFeatureProcessorInterface : public RPI::FeatureProcessor
{
public:
AZ_RTTI(AZ::Render::PointLightFeatureProcessorInterface, "{D3E0B016-F3C6-4C7A-A29E-0B3A4FA87806}", AZ::RPI::FeatureProcessor);
@@ -33,7 +50,8 @@ namespace AZ
using LightHandle = RHI::Handle<uint16_t, class PointLight>;
static constexpr PhotometricUnit PhotometricUnitType = PhotometricUnit::Candela;
//! Creates a new point light which can be referenced by the returned LightHandle. Must be released via ReleaseLight() when no longer needed.
//! Creates a new point light which can be referenced by the returned LightHandle. Must be released via ReleaseLight() when no
//! longer needed.
virtual LightHandle AcquireLight() = 0;
//! Releases a LightHandle which removes the point light.
virtual bool ReleaseLight(LightHandle& handle) = 0;
@@ -48,6 +66,24 @@ namespace AZ
virtual void SetAttenuationRadius(LightHandle handle, float attenuationRadius) = 0;
//! Sets the bulb radius for the provided LightHandle. Values greater than zero effectively make it a spherical light.
virtual void SetBulbRadius(LightHandle handle, float bulbRadius) = 0;
//! Sets if shadows are enabled
virtual void SetShadowsEnabled(LightHandle handle, bool enabled) = 0;
//! Sets the shadowmap size (width and height) of the light.
virtual void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) = 0;
//! Specifies filter method of shadows.
virtual void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) = 0;
//! Specifies the width of boundary between shadowed area and lit area in radians. The degree ofshadowed gradually changes on
//! the boundary. 0 disables softening.
virtual void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) = 0;
//! Sets sample count to predict boundary of shadow (up to 16). It will be clamped to be less than or equal to the filtering
//! sample count.
virtual void SetPredictionSampleCount(LightHandle handle, uint16_t count) = 0;
//! Sets sample count for filtering of shadow boundary (up to 64)
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
//! Sets the shadowmap Pcf (percentage closer filtering) method.
virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0;
//! Sets all of the the point data for the provided LightHandle.
virtual void SetPointData(LightHandle handle, const PointLightData& data) = 0;
};
} // namespace Render
} // namespace AZ
@@ -1,21 +1,21 @@
/*
* 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.
*
*/
* 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 <Atom/RPI.Public/Material/Material.h>
#include <AzCore/std/containers/unordered_map.h>
#include <Atom/RPI.Public/Model/Model.h>
#include <Atom/Feature/Material/MaterialAssignmentId.h>
#include <Atom/RPI.Public/Material/Material.h>
#include <Atom/RPI.Public/Model/Model.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/std/containers/unordered_map.h>
namespace AZ
{
@@ -31,39 +31,19 @@ namespace AZ
MaterialAssignment() = default;
MaterialAssignment(const AZ::Data::AssetId& materialAssetId)
: m_materialInstance()
{
m_materialAsset.Create(materialAssetId);
}
MaterialAssignment(const AZ::Data::AssetId& materialAssetId);
MaterialAssignment(const Data::Asset<RPI::MaterialAsset>& asset)
: m_materialAsset(asset)
, m_materialInstance()
{
}
MaterialAssignment(const Data::Asset<RPI::MaterialAsset>& asset);
MaterialAssignment(const Data::Asset<RPI::MaterialAsset>& asset, const Data::Instance<RPI::Material>& instance)
: m_materialAsset(asset)
, m_materialInstance(instance)
{
}
MaterialAssignment(const Data::Asset<RPI::MaterialAsset>& asset, const Data::Instance<RPI::Material>& instance);
void RebuildInstance()
{
if (m_materialAsset.IsReady())
{
m_materialInstance = m_propertyOverrides.empty() ? RPI::Material::FindOrCreate(m_materialAsset) : RPI::Material::Create(m_materialAsset);
AZ_Error("MaterialAssignment", m_materialInstance, "Material instance not initialized");
}
}
//! Recreates the material instance from the asset if it has been loaded.
//! If amy property overrides have been specified then a unique instance will be created.
//! Otherwise an attempt will be made to find or create a shared instance.
void RebuildInstance();
AZStd::string ToString() const
{
AZStd::string assetPathString;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetPathString, &AZ::Data::AssetCatalogRequests::GetAssetPathById, m_materialAsset.GetId());
return assetPathString;
}
//! Returns a string composed of the asset path.
AZStd::string ToString() const;
Data::Asset<RPI::MaterialAsset> m_materialAsset;
Data::Instance<RPI::Material> m_materialInstance;
@@ -77,64 +57,15 @@ namespace AZ
static const MaterialAssignmentMap DefaultMaterialAssignmentMap;
//! Utility function for retrieving a material entry from a MaterialAssignmentMap
AZ_INLINE const MaterialAssignment& GetMaterialAssignmentFromMap(const MaterialAssignmentMap& materials, const MaterialAssignmentId& id)
{
const auto& materialItr = materials.find(id);
return materialItr != materials.end() ? materialItr->second : DefaultMaterialAssignment;
}
const MaterialAssignment& GetMaterialAssignmentFromMap(const MaterialAssignmentMap& materials, const MaterialAssignmentId& id);
//! Utility function for retrieving a material entry from a MaterialAssignmentMap, falling back to defaults for a particular asset or the entire model
AZ_INLINE const MaterialAssignment& GetMaterialAssignmentFromMapWithFallback(const MaterialAssignmentMap& materials, const MaterialAssignmentId& id)
{
const MaterialAssignment& lodAssignment = GetMaterialAssignmentFromMap(materials, id);
if (lodAssignment.m_materialInstance.get())
{
return lodAssignment;
}
const MaterialAssignment& assetAssignment = GetMaterialAssignmentFromMap(materials, MaterialAssignmentId::CreateFromAssetOnly(id.m_materialAssetId));
if (assetAssignment.m_materialInstance.get())
{
return assetAssignment;
}
const MaterialAssignment& defaultAssignment = GetMaterialAssignmentFromMap(materials, DefaultMaterialAssignmentId);
if (defaultAssignment.m_materialInstance.get())
{
return defaultAssignment;
}
return DefaultMaterialAssignment;
}
//! Utility function for retrieving a material entry from a MaterialAssignmentMap, falling back to defaults for a particular asset
//! or the entire model
const MaterialAssignment& GetMaterialAssignmentFromMapWithFallback(
const MaterialAssignmentMap& materials, const MaterialAssignmentId& id);
//! Utility function for generating a set of available material assignments in a model
AZ_INLINE MaterialAssignmentMap GetMaterialAssignmentsFromModel(Data::Instance<AZ::RPI::Model> model)
{
MaterialAssignmentMap materials;
materials[DefaultMaterialAssignmentId] = MaterialAssignment();
if (model)
{
size_t lodIndex = 0;
for (const Data::Instance<AZ::RPI::ModelLod>& lod : model->GetLods())
{
for (const AZ::RPI::ModelLod::Mesh& mesh : lod->GetMeshes())
{
if (mesh.m_material)
{
const MaterialAssignmentId generalId = MaterialAssignmentId::CreateFromAssetOnly(mesh.m_material->GetAssetId());
materials[generalId] = MaterialAssignment(mesh.m_material->GetAsset(), mesh.m_material);
const MaterialAssignmentId specificId = MaterialAssignmentId::CreateFromLodAndAsset(lodIndex, mesh.m_material->GetAssetId());
materials[specificId] = MaterialAssignment(mesh.m_material->GetAsset(), mesh.m_material);
}
}
++lodIndex;
}
}
return materials;
}
MaterialAssignmentMap GetMaterialAssignmentsFromModel(Data::Instance<AZ::RPI::Model> model);
} // namespace Render
} // namespace AZ
@@ -1,20 +1,20 @@
/*
* 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.
*
*/
* 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/Asset/AssetCommon.h>
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Memory/Memory.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/RTTI/ReflectContext.h>
@@ -26,6 +26,9 @@ namespace AZ
{
using MaterialAssignmentLodIndex = AZ::u64;
//! MaterialAssignmentId is used to address available and overridable material slots on a model.
//! The LOD and one of the model's original material asset IDs are used as coordinates that identify
//! a specific material slot or a set of slots matching either.
struct MaterialAssignmentId final
{
AZ_RTTI(AZ::Render::MaterialAssignmentId, "{EB603581-4654-4C17-B6DE-AE61E79EDA97}");
@@ -34,69 +37,37 @@ namespace AZ
MaterialAssignmentId() = default;
MaterialAssignmentId(MaterialAssignmentLodIndex lodIndex, const AZ::Data::AssetId& materialAssetId)
: m_lodIndex(lodIndex)
, m_materialAssetId(materialAssetId)
{
}
MaterialAssignmentId(MaterialAssignmentLodIndex lodIndex, const AZ::Data::AssetId& materialAssetId);
static MaterialAssignmentId CreateDefault()
{
return MaterialAssignmentId(NonLodIndex, AZ::Data::AssetId());
}
//! Create an ID that maps to all material slots, regardless of asset ID or LOD, effectively applying to an entire model.
static MaterialAssignmentId CreateDefault();
static MaterialAssignmentId CreateFromAssetOnly(AZ::Data::AssetId materialAssetId)
{
return MaterialAssignmentId(NonLodIndex, materialAssetId);
}
//! Create an ID that maps to all material slots with a corresponding asset ID, regardless of LOD.
static MaterialAssignmentId CreateFromAssetOnly(AZ::Data::AssetId materialAssetId);
static MaterialAssignmentId CreateFromLodAndAsset(MaterialAssignmentLodIndex lodIndex, AZ::Data::AssetId materialAssetId)
{
return MaterialAssignmentId(lodIndex, materialAssetId);
}
//! Create an ID that maps to a specific material slot with a corresponding asset ID and LOD.
static MaterialAssignmentId CreateFromLodAndAsset(MaterialAssignmentLodIndex lodIndex, AZ::Data::AssetId materialAssetId);
bool IsDefault() const
{
return m_lodIndex == NonLodIndex && !m_materialAssetId.IsValid();
}
//! Returns true if the asset ID and LOD are invalid
bool IsDefault() const;
bool IsAssetOnly() const
{
return m_lodIndex == NonLodIndex && m_materialAssetId.IsValid();
}
//! Returns true if the asset ID is valid and LOD is invalid
bool IsAssetOnly() const;
bool IsLodAndAsset() const
{
return m_lodIndex != NonLodIndex && m_materialAssetId.IsValid();
}
//! Returns true if the asset ID and LOD are both valid
bool IsLodAndAsset() const;
//! Creates a string composed of the asset path and LOD
AZStd::string ToString() const;
AZStd::string ToString() const
{
AZStd::string assetPathString;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetPathString, &AZ::Data::AssetCatalogRequests::GetAssetPathById, m_materialAssetId);
AZ::StringFunc::Path::StripPath(assetPathString);
AZ::StringFunc::Path::StripExtension(assetPathString);
return AZStd::string::format("%s:%llu", assetPathString.c_str(), m_lodIndex);
}
//! Creates a hash composed of the asset ID sub ID and LOD
size_t GetHash() const;
size_t GetHash() const
{
size_t seed = 0;
AZStd::hash_combine(seed, m_lodIndex);
AZStd::hash_combine(seed, m_materialAssetId);
return seed;
}
//! Returns true if both asset ID sub IDs and LODs match
bool operator==(const MaterialAssignmentId& rhs) const;
bool operator==(const MaterialAssignmentId& rhs) const
{
return m_lodIndex == rhs.m_lodIndex && m_materialAssetId == rhs.m_materialAssetId;
}
bool operator!=(const MaterialAssignmentId& rhs) const
{
return m_lodIndex != rhs.m_lodIndex || m_materialAssetId != rhs.m_materialAssetId;
}
//! Returns true if both asset ID sub IDs and LODs do not match
bool operator!=(const MaterialAssignmentId& rhs) const;
static constexpr MaterialAssignmentLodIndex NonLodIndex = -1;
MaterialAssignmentLodIndex m_lodIndex = NonLodIndex;
@@ -116,4 +87,4 @@ namespace AZStd
return id.GetHash();
}
};
} //namespace AZStd
} // namespace AZStd
@@ -53,6 +53,7 @@ namespace AZ
void SetBufferViewsOnShaderResourceGroup(const Data::Instance<RPI::ShaderResourceGroup>& perInstanceSRG);
private:
RHI::Ptr<RHI::BufferView> m_vertexDeltaBufferView;
Data::Instance<RPI::Buffer> m_vertexDeltaBuffer;
};
struct MorphTargetMetaData
@@ -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;
@@ -1487,7 +1487,6 @@ namespace AZ
float depthNear,
float depthFar) const
{
// For calculation, refer https://wiki.agscollab.com/display/ATOM/Cascaded+Shadowmaps
// This calculates the center of bounding sphere for a camera view frustum.
// By this, on the camera view (2D), the bounding sphere's center
// shifts to the remarkable point.
@@ -380,7 +380,7 @@ namespace AZ
const float invRadiusSquared = diskLight.m_invAttenuationRadiusSquared;
if (invRadiusSquared <= 0.f)
{
AZ_Assert(false, "Attenuation radius have to be set before use the light.");
AZ_Assert(false, "Attenuation radius must be set before using the light.");
return;
}
const float attenuationRadius = sqrtf(1.f / invRadiusSquared);
@@ -59,7 +59,7 @@ namespace AZ
void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) override;
void SetPredictionSampleCount(LightHandle handle, uint16_t count) override;
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
void SetPcfMethod(LightHandle handle, PcfMethod method);
void SetPcfMethod(LightHandle handle, PcfMethod method) override;
void SetDiskData(LightHandle handle, const DiskLightData& data) override;
@@ -84,7 +84,7 @@ namespace AZ
template <typename Functor, typename ParamType>
void SetShadowSetting(LightHandle handle, Functor&&, ParamType&& param);
ProjectedShadowFeatureProcessor* m_shadowFeatureProcessor;
ProjectedShadowFeatureProcessor* m_shadowFeatureProcessor = nullptr;
IndexedDataVector<DiskLightData> m_diskLightData;
GpuBufferHandler m_lightBufferHandler;
@@ -34,7 +34,7 @@ namespace AZ
const size_t NumBins = 8;
const size_t MaxLightsPerTile = 256;
// TODO convert this to R16_UINT. It just needs RHI support
// https://jira.agscollab.com/browse/ATOM-3975
// ATOM-3975
const RHI::Format LightListRemappedFormat = RHI::Format::R32_UINT;
RPI::Ptr<LightCullingRemap> LightCullingRemap::Create(const RPI::PassDescriptor& descriptor)
@@ -44,6 +44,13 @@ namespace AZ
PointLightFeatureProcessor::PointLightFeatureProcessor()
: PointLightFeatureProcessorInterface()
{
// Note must match PointShadowDirections in PointLight.azsli
m_pointShadowTransforms[0] = AZ::Transform::CreateLookAt(AZ::Vector3::CreateZero(), -AZ::Vector3::CreateAxisX());
m_pointShadowTransforms[1] = AZ::Transform::CreateLookAt(AZ::Vector3::CreateZero(), AZ::Vector3::CreateAxisX());
m_pointShadowTransforms[2] = AZ::Transform::CreateLookAt(AZ::Vector3::CreateZero(), -AZ::Vector3::CreateAxisY());
m_pointShadowTransforms[3] = AZ::Transform::CreateLookAt(AZ::Vector3::CreateZero(), AZ::Vector3::CreateAxisY());
m_pointShadowTransforms[4] = AZ::Transform::CreateLookAt(AZ::Vector3::CreateZero(), -AZ::Vector3::CreateAxisZ());
m_pointShadowTransforms[5] = AZ::Transform::CreateLookAt(AZ::Vector3::CreateZero(), AZ::Vector3::CreateAxisZ());
}
void PointLightFeatureProcessor::Activate()
@@ -54,6 +61,7 @@ namespace AZ
desc.m_elementCountSrgName = "m_pointLightCount";
desc.m_elementSize = sizeof(PointLightData);
desc.m_srgLayout = RPI::RPISystemInterface::Get()->GetViewSrgAsset()->GetLayout();
m_shadowFeatureProcessor = GetParentScene()->GetFeatureProcessor<ProjectedShadowFeatureProcessor>();
m_lightBufferHandler = GpuBufferHandler(desc);
}
@@ -83,6 +91,15 @@ namespace AZ
{
if (handle.IsValid())
{
for (int i = 0; i < PointLightData::NumShadowFaces; ++i)
{
ShadowId shadowId = ShadowId(m_pointLightData.GetData(handle.GetIndex()).m_shadowIndices[i]);
if (shadowId.IsValid())
{
m_shadowFeatureProcessor->ReleaseShadow(shadowId);
}
}
m_pointLightData.RemoveIndex(handle.GetIndex());
m_deviceBufferNeedsUpdate = true;
handle.Reset();
@@ -148,6 +165,7 @@ namespace AZ
lightPosition.StoreToFloat3(position.data());
m_deviceBufferNeedsUpdate = true;
UpdateShadow(handle);
}
void PointLightFeatureProcessor::SetAttenuationRadius(LightHandle handle, float attenuationRadius)
@@ -177,5 +195,122 @@ namespace AZ
return m_lightBufferHandler.GetElementCount();
}
void PointLightFeatureProcessor::SetShadowsEnabled(LightHandle handle, bool enabled)
{
auto& light = m_pointLightData.GetData(handle.GetIndex());
for (int i = 0; i < PointLightData::NumShadowFaces; ++i)
{
ShadowId shadowId = ShadowId(light.m_shadowIndices[i]);
if (shadowId.IsValid() && !enabled)
{
// Disable shadows
m_shadowFeatureProcessor->ReleaseShadow(shadowId);
shadowId.Reset();
light.m_shadowIndices[i] = shadowId.GetIndex();
m_deviceBufferNeedsUpdate = true;
}
else if (shadowId.IsNull() && enabled)
{
// Enable shadows
light.m_shadowIndices[i] = m_shadowFeatureProcessor->AcquireShadow().GetIndex();
UpdateShadow(handle);
m_deviceBufferNeedsUpdate = true;
}
}
}
void PointLightFeatureProcessor::SetPointData(LightHandle handle, const PointLightData& data)
{
AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to PointLightFeatureProcessor::SetPointData().");
m_pointLightData.GetData(handle.GetIndex()) = data;
m_deviceBufferNeedsUpdate = true;
UpdateShadow(handle);
}
void PointLightFeatureProcessor::UpdateShadow(LightHandle handle)
{
constexpr float SqrtHalf = 0.707106781187f; // sqrt(0.5);
const auto& pointLight = m_pointLightData.GetData(handle.GetIndex());
for (int i = 0; i < PointLightData::NumShadowFaces; ++i)
{
ShadowId shadowId = ShadowId(pointLight.m_shadowIndices[i]);
if (shadowId.IsNull())
{
// Early out if shadows are disabled.
return;
}
ProjectedShadowFeatureProcessorInterface::ProjectedShadowDescriptor desc = m_shadowFeatureProcessor->GetShadowProperties(shadowId);
// Make it slightly larger than 90 degrees to avoid artifacts on the boundary between 2 cubemap faces
desc.m_fieldOfViewYRadians = DegToRad(91.0f);
desc.m_transform = m_pointShadowTransforms[i];
desc.m_transform.SetTranslation(pointLight.m_position[0], pointLight.m_position[1], pointLight.m_position[2]);
desc.m_aspectRatio = 1.0f;
desc.m_nearPlaneDistance = SqrtHalf * pointLight.m_bulbRadius;
const float invRadiusSquared = pointLight.m_invAttenuationRadiusSquared;
if (invRadiusSquared <= 0.f)
{
AZ_Assert(false, "Attenuation radius must be set before using the light.");
return;
}
const float attenuationRadius = sqrtf(1.f / invRadiusSquared);
desc.m_farPlaneDistance = attenuationRadius + pointLight.m_bulbRadius;
m_shadowFeatureProcessor->SetShadowProperties(shadowId, desc);
}
}
template<typename Functor, typename ParamType>
void PointLightFeatureProcessor::SetShadowSetting(LightHandle handle, Functor&& functor, ParamType&& param)
{
AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to PointLightFeatureProcessor::SetShadowSetting().");
auto& light = m_pointLightData.GetData(handle.GetIndex());
for (int lightIndex = 0; lightIndex < PointLightData::NumShadowFaces; ++lightIndex)
{
ShadowId shadowId = ShadowId(light.m_shadowIndices[lightIndex]);
AZ_Assert(shadowId.IsValid(), "Attempting to set a shadow property when shadows are not enabled.");
if (shadowId.IsValid())
{
AZStd::invoke(AZStd::forward<Functor>(functor), m_shadowFeatureProcessor, shadowId, AZStd::forward<ParamType>(param));
}
}
}
void PointLightFeatureProcessor::SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution, shadowmapSize);
}
void PointLightFeatureProcessor::SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowFilterMethod, method);
}
void PointLightFeatureProcessor::SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetSofteningBoundaryWidthAngle, boundaryWidthRadians);
}
void PointLightFeatureProcessor::SetPredictionSampleCount(LightHandle handle, uint16_t count)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPredictionSampleCount, count);
}
void PointLightFeatureProcessor::SetFilteringSampleCount(LightHandle handle, uint16_t count)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetFilteringSampleCount, count);
}
void PointLightFeatureProcessor::SetPcfMethod(LightHandle handle, PcfMethod method)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method);
}
} // namespace Render
} // namespace AZ
@@ -16,6 +16,7 @@
#include <Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h>
#include <Atom/Feature/Utils/GpuBufferHandler.h>
#include <CoreLights/IndexedDataVector.h>
#include <Shadows/ProjectedShadowFeatureProcessor.h>
namespace AZ
{
@@ -24,15 +25,6 @@ namespace AZ
namespace Render
{
struct PointLightData
{
AZStd::array<float, 3> m_position = { { 0.0f, 0.0f, 0.0f } };
float m_invAttenuationRadiusSquared = 0.0f; // Inverse of the distance at which this light no longer has an effect, squared. Also used for falloff calculations.
AZStd::array<float, 3> m_rgbIntensity = { { 0.0f, 0.0f, 0.0f } };
float m_bulbRadius = 0.0f; // Radius of spherical light in meters.
};
class PointLightFeatureProcessor final
: public PointLightFeatureProcessorInterface
{
@@ -58,18 +50,34 @@ namespace AZ
void SetPosition(LightHandle handle, const AZ::Vector3& lightPosition) override;
void SetAttenuationRadius(LightHandle handle, float attenuationRadius) override;
void SetBulbRadius(LightHandle handle, float bulbRadius) override;
void SetShadowsEnabled(LightHandle handle, bool enabled) override;
void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) override;
void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override;
void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) override;
void SetPredictionSampleCount(LightHandle handle, uint16_t count) override;
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
void SetPcfMethod(LightHandle handle, PcfMethod method) override;
void SetPointData(LightHandle handle, const PointLightData& data) override;
const Data::Instance<RPI::Buffer> GetLightBuffer() const;
uint32_t GetLightCount()const;
private:
PointLightFeatureProcessor(const PointLightFeatureProcessor&) = delete;
using ShadowId = ProjectedShadowFeatureProcessor::ShadowId;
static constexpr const char* FeatureProcessorName = "PointLightFeatureProcessor";
void UpdateShadow(LightHandle handle);
// Convenience function for forwarding requests to the ProjectedShadowFeatureProcessor
template<typename Functor, typename ParamType>
void SetShadowSetting(LightHandle handle, Functor&&, ParamType&& param);
ProjectedShadowFeatureProcessor* m_shadowFeatureProcessor = nullptr;
IndexedDataVector<PointLightData> m_pointLightData;
GpuBufferHandler m_lightBufferHandler;
bool m_deviceBufferNeedsUpdate = false;
AZStd::array<AZ::Transform, PointLightData::NumShadowFaces> m_pointShadowTransforms;
};
} // namespace Render
} // namespace AZ
@@ -23,7 +23,9 @@ namespace AZ
{
public:
void TrackAssetLoad(const FeatureProcessorHandle handle, const AZ::Data::AssetId asset)
using MaterialAssetPtr = AZ::Data::Asset<AZ::RPI::MaterialAsset>;
void TrackAssetLoad(const FeatureProcessorHandle handle, const MaterialAssetPtr asset)
{
if (IsAssetLoading(handle))
{
@@ -77,12 +79,12 @@ namespace AZ
{
const auto asset = EraseFromInFlightHandles(handle);
AZ_Assert(m_inFlightHandlesByAsset.count(asset) > 0, "AsyncLoadTracker in a bad state");
auto& handleList = m_inFlightHandlesByAsset[asset];
AZ_Assert(m_inFlightHandlesByAsset.count(asset.GetId()) > 0, "AsyncLoadTracker in a bad state");
auto& handleList = m_inFlightHandlesByAsset[asset.GetId()];
EraseFromVector(handleList, handle);
if (handleList.empty())
{
m_inFlightHandlesByAsset.erase(asset);
m_inFlightHandlesByAsset.erase(asset.GetId());
}
}
@@ -104,14 +106,14 @@ namespace AZ
vec.pop_back();
}
void Add(const FeatureProcessorHandle handle, const AZ::Data::AssetId asset)
void Add(const FeatureProcessorHandle handle, const MaterialAssetPtr asset)
{
AZ_Assert(m_inFlightHandles.count(handle) == 0, "AsyncLoadTracker::Add() - told to add a handle that was already being tracked.");
m_inFlightHandlesByAsset[asset].push_back(handle);
m_inFlightHandlesByAsset[asset.GetId()].push_back(handle);
m_inFlightHandles[handle] = asset;
}
AZ::Data::AssetId EraseFromInFlightHandles(const FeatureProcessorHandle handle)
MaterialAssetPtr EraseFromInFlightHandles(const FeatureProcessorHandle handle)
{
const auto iter = m_inFlightHandles.find(handle);
AZ_Assert(iter != m_inFlightHandles.end(), "Told to remove handle that was not present");
@@ -125,7 +127,7 @@ namespace AZ
// Hash table that tracks the reverse of the m_inFlightHandlesByAsset hash table.
// i.e. for each object, it stores what asset that it needs.
AZStd::unordered_map<FeatureProcessorHandle, AZ::Data::AssetId> m_inFlightHandles;
AZStd::unordered_map<FeatureProcessorHandle, MaterialAssetPtr> m_inFlightHandles;
};
}
}
@@ -85,7 +85,6 @@ namespace AZ
m_decalData.Clear();
m_decalBufferHandler.Release();
m_materialAssets.clear();
}
DecalTextureArrayFeatureProcessor::DecalHandle DecalTextureArrayFeatureProcessor::AcquireDecal()
@@ -135,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;
@@ -410,7 +416,7 @@ namespace AZ
int iter = m_textureArrayList.begin();
while (iter != -1)
{
const auto packedTexture = m_textureArrayList[iter].second.GetPackedTexture();
const auto& packedTexture = m_textureArrayList[iter].second.GetPackedTexture();
view->GetShaderResourceGroup()->SetImage(m_decalTextureArrayIndices[iter], packedTexture);
iter = m_textureArrayList.next(iter);
}
@@ -482,22 +488,15 @@ namespace AZ
return material;
}
void DecalTextureArrayFeatureProcessor::QueueMaterialLoadForDecal(const AZ::Data::AssetId material, const DecalHandle handle)
void DecalTextureArrayFeatureProcessor::QueueMaterialLoadForDecal(const AZ::Data::AssetId materialId, const DecalHandle handle)
{
// Note that another decal might have already queued this material for loading
if (m_materialLoadTracker.IsAssetLoading(material))
{
m_materialLoadTracker.TrackAssetLoad(handle, material);
return;
}
const auto materialAsset = QueueMaterialAssetLoad(materialId);
const auto materialAsset = QueueMaterialAssetLoad(material);
m_materialAssets.emplace(material, materialAsset);
m_materialLoadTracker.TrackAssetLoad(handle, material);
m_materialLoadTracker.TrackAssetLoad(handle, materialAsset);
if (materialAsset.IsLoading())
{
AZ::Data::AssetBus::MultiHandler::BusConnect(material);
AZ::Data::AssetBus::MultiHandler::BusConnect(materialId);
}
else if (materialAsset.IsReady())
{
@@ -136,11 +136,8 @@ namespace AZ
GpuBufferHandler m_decalBufferHandler;
AsyncLoadTracker<DecalHandle> m_materialLoadTracker;
AZStd::unordered_map< AZ::Data::AssetId, DecalLocationAndUseCount> m_materialToTextureArrayLookupTable;
AZStd::unordered_map<AZ::Data::AssetId, AZ::Data::Asset<AZ::RPI::MaterialAsset>> m_materialAssets;
bool m_deviceBufferNeedsUpdate = false;
};
} // namespace Render
@@ -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;
@@ -11,8 +11,8 @@
*/
#include <Atom/Feature/Material/MaterialAssignment.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace AZ
{
@@ -67,5 +67,101 @@ namespace AZ
}
}
MaterialAssignment::MaterialAssignment(const AZ::Data::AssetId& materialAssetId)
: m_materialInstance()
{
m_materialAsset.Create(materialAssetId);
}
MaterialAssignment::MaterialAssignment(const Data::Asset<RPI::MaterialAsset>& asset)
: m_materialAsset(asset)
, m_materialInstance()
{
}
MaterialAssignment::MaterialAssignment(const Data::Asset<RPI::MaterialAsset>& asset, const Data::Instance<RPI::Material>& instance)
: m_materialAsset(asset)
, m_materialInstance(instance)
{
}
void MaterialAssignment::RebuildInstance()
{
if (m_materialAsset.IsReady())
{
m_materialInstance =
m_propertyOverrides.empty() ? RPI::Material::FindOrCreate(m_materialAsset) : RPI::Material::Create(m_materialAsset);
AZ_Error("MaterialAssignment", m_materialInstance, "Material instance not initialized");
}
}
AZStd::string MaterialAssignment::ToString() const
{
AZStd::string assetPathString;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
assetPathString, &AZ::Data::AssetCatalogRequests::GetAssetPathById, m_materialAsset.GetId());
return assetPathString;
}
const MaterialAssignment& GetMaterialAssignmentFromMap(const MaterialAssignmentMap& materials, const MaterialAssignmentId& id)
{
const auto& materialItr = materials.find(id);
return materialItr != materials.end() ? materialItr->second : DefaultMaterialAssignment;
}
const MaterialAssignment& GetMaterialAssignmentFromMapWithFallback(
const MaterialAssignmentMap& materials, const MaterialAssignmentId& id)
{
const MaterialAssignment& lodAssignment = GetMaterialAssignmentFromMap(materials, id);
if (lodAssignment.m_materialInstance.get())
{
return lodAssignment;
}
const MaterialAssignment& assetAssignment =
GetMaterialAssignmentFromMap(materials, MaterialAssignmentId::CreateFromAssetOnly(id.m_materialAssetId));
if (assetAssignment.m_materialInstance.get())
{
return assetAssignment;
}
const MaterialAssignment& defaultAssignment = GetMaterialAssignmentFromMap(materials, DefaultMaterialAssignmentId);
if (defaultAssignment.m_materialInstance.get())
{
return defaultAssignment;
}
return DefaultMaterialAssignment;
}
MaterialAssignmentMap GetMaterialAssignmentsFromModel(Data::Instance<AZ::RPI::Model> model)
{
MaterialAssignmentMap materials;
materials[DefaultMaterialAssignmentId] = MaterialAssignment();
if (model)
{
size_t lodIndex = 0;
for (const Data::Instance<AZ::RPI::ModelLod>& lod : model->GetLods())
{
for (const AZ::RPI::ModelLod::Mesh& mesh : lod->GetMeshes())
{
if (mesh.m_material)
{
const MaterialAssignmentId generalId = MaterialAssignmentId::CreateFromAssetOnly(mesh.m_material->GetAssetId());
materials[generalId] = MaterialAssignment(mesh.m_material->GetAsset(), mesh.m_material);
const MaterialAssignmentId specificId =
MaterialAssignmentId::CreateFromLodAndAsset(lodIndex, mesh.m_material->GetAssetId());
materials[specificId] = MaterialAssignment(mesh.m_material->GetAsset(), mesh.m_material);
}
}
++lodIndex;
}
}
return materials;
}
} // namespace Render
} // namespace AZ
@@ -11,8 +11,8 @@
*/
#include <Atom/Feature/Material/MaterialAssignmentId.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace AZ
{
@@ -47,5 +47,70 @@ namespace AZ
;
}
}
MaterialAssignmentId::MaterialAssignmentId(MaterialAssignmentLodIndex lodIndex, const AZ::Data::AssetId& materialAssetId)
: m_lodIndex(lodIndex)
, m_materialAssetId(materialAssetId)
{
}
MaterialAssignmentId MaterialAssignmentId::CreateDefault()
{
return MaterialAssignmentId(NonLodIndex, AZ::Data::AssetId());
}
MaterialAssignmentId MaterialAssignmentId::CreateFromAssetOnly(AZ::Data::AssetId materialAssetId)
{
return MaterialAssignmentId(NonLodIndex, materialAssetId);
}
MaterialAssignmentId MaterialAssignmentId::CreateFromLodAndAsset(
MaterialAssignmentLodIndex lodIndex, AZ::Data::AssetId materialAssetId)
{
return MaterialAssignmentId(lodIndex, materialAssetId);
}
bool MaterialAssignmentId::IsDefault() const
{
return m_lodIndex == NonLodIndex && !m_materialAssetId.IsValid();
}
bool MaterialAssignmentId::IsAssetOnly() const
{
return m_lodIndex == NonLodIndex && m_materialAssetId.IsValid();
}
bool MaterialAssignmentId::IsLodAndAsset() const
{
return m_lodIndex != NonLodIndex && m_materialAssetId.IsValid();
}
AZStd::string MaterialAssignmentId::ToString() const
{
AZStd::string assetPathString;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
assetPathString, &AZ::Data::AssetCatalogRequests::GetAssetPathById, m_materialAssetId);
AZ::StringFunc::Path::StripPath(assetPathString);
AZ::StringFunc::Path::StripExtension(assetPathString);
return AZStd::string::format("%s:%llu", assetPathString.c_str(), m_lodIndex);
}
size_t MaterialAssignmentId::GetHash() const
{
size_t seed = 0;
AZStd::hash_combine(seed, m_lodIndex);
AZStd::hash_combine(seed, m_materialAssetId.m_subId);
return seed;
}
bool MaterialAssignmentId::operator==(const MaterialAssignmentId& rhs) const
{
return m_lodIndex == rhs.m_lodIndex && m_materialAssetId.m_subId == rhs.m_materialAssetId.m_subId;
}
bool MaterialAssignmentId::operator!=(const MaterialAssignmentId& rhs) const
{
return !(*this == rhs);
}
} // namespace Render
} // namespace AZ
@@ -30,16 +30,18 @@ namespace AZ
{
MorphTargetInputBuffers::MorphTargetInputBuffers(const RPI::BufferAssetView& bufferAssetView, const AZStd::string& bufferNamePrefix)
{
auto buffer = RPI::Buffer::FindOrCreate(bufferAssetView.GetBufferAsset());
AZ::RHI::Ptr<AZ::RHI::BufferView> bufferView = RHI::Factory::Get().CreateBufferView();
m_vertexDeltaBuffer = RPI::Buffer::FindOrCreate(bufferAssetView.GetBufferAsset());
if (m_vertexDeltaBuffer)
{
bufferView->SetName(Name(bufferNamePrefix + "MorphTargetVertexDeltaView"));
[[maybe_unused]] RHI::ResultCode resultCode = bufferView->Init(*buffer->GetRHIBuffer(), bufferAssetView.GetBufferViewDescriptor());
AZ_Error("MorphTargetInputBuffers", resultCode == RHI::ResultCode::Success, "Failed to initialize buffer view for morph target.");
}
AZ::RHI::Ptr<AZ::RHI::BufferView> bufferView = RHI::Factory::Get().CreateBufferView();
{
bufferView->SetName(Name(bufferNamePrefix + "MorphTargetVertexDeltaView"));
[[maybe_unused]] RHI::ResultCode resultCode = bufferView->Init(*m_vertexDeltaBuffer->GetRHIBuffer(), bufferAssetView.GetBufferViewDescriptor());
AZ_Error("MorphTargetInputBuffers", resultCode == RHI::ResultCode::Success, "Failed to initialize buffer view for morph target.");
}
m_vertexDeltaBufferView = bufferView;
m_vertexDeltaBufferView = bufferView;
}
}
void MorphTargetInputBuffers::SetBufferViewsOnShaderResourceGroup(const Data::Instance<RPI::ShaderResourceGroup>& perInstanceSRG)
@@ -50,7 +50,7 @@ namespace AZ
static constexpr Quality QualitySet[DepthOfField::QualityLevelMax] =
{
// It is the radial division count of blur kernel. See "https://wiki.agscollab.com/display/ATOM/Pencil+Map" for details.
// It is the radial division count of blur kernel.
{2, 3, 4},
{4, 4, 4}
};
@@ -205,7 +205,6 @@ namespace AZ
float scaledDiameter = ScreenApertureDiameter * 0.25f;
// This is the conversion factor for calculating the blend ratio from DofFactor.
// Please refer to "https://wiki.agscollab.com/display/ATOM/Dof+factor+and+Buffer+composition" for blending of DofFactor and buffer.
// coc0 : Confusion circle diameter screen ratio
// coc1 : Confusion circle diameter screen ratio of one lower blur level;
@@ -139,7 +139,6 @@ namespace AZ
float m_minBokehRadiusDivision8 = 0.0f;
// Radial division count of bokeh blur kernel.
// See "https://wiki.agscollab.com/display/ATOM/Pencil+Map" for details.
uint32_t m_sampleRadialDivision2 = 0;
uint32_t m_sampleRadialDivision4 = 0;
uint32_t m_sampleRadialDivision8 = 0;
@@ -194,7 +194,6 @@ namespace AZ
// calculate sampling texcoords.
// sample 6 points around center pixel.
// Similarly, sample around it as 12,18,24 points.
// Please refer to "https://wiki.agscollab.com/display/ATOM/Pencil+Map" for details.
AZ_Assert(radialDivisionCount >= 1 && radialDivisionCount <= 4, "DepthOfFieldBokehBlurPass : radialDivisionCount is illegal value.");
@@ -18,8 +18,6 @@ namespace AZ
{
namespace PencilMap
{
// Please refer to "https://wiki.agscollab.com/display/ATOM/Pencil+Map" for details.
// PencilMap 35mm Film
static constexpr unsigned int TextureWidth = 128;
static constexpr unsigned int TextureHeight = 64;
@@ -120,13 +120,13 @@ namespace AZ
{
// stencil Srg
// Note: the stencil pass uses a slightly reduced inner AABB to avoid seams
Vector3 innerExtentsReduced = m_innerExtents * m_transform.GetScale() - Vector3(0.1f, 0.1f, 0.1f);
Vector3 innerExtentsReduced = m_innerExtents - Vector3(0.1f, 0.1f, 0.1f);
Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(innerExtentsReduced);
m_stencilSrg->SetConstant(m_reflectionRenderData->m_modelToWorldStencilConstantIndex, modelToWorldStencil);
m_stencilSrg->Compile();
// blend weight Srg
Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_outerExtents * m_transform.GetScale());
Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_outerExtents);
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldOuter);
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter());
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin());
@@ -149,7 +149,7 @@ namespace AZ
m_renderOuterSrg->Compile();
// render inner Srg
Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_innerExtents * m_transform.GetScale());
Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_innerExtents);
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldInner);
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter());
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin());
@@ -208,6 +208,12 @@ namespace AZ
void ReflectionProbe::SetTransform(const AZ::Transform& transform)
{
// retrieve previous scale and revert the scale on the inner/outer extents
AZ::Vector3 previousScale = m_transform.GetScale();
m_outerExtents /= previousScale;
m_innerExtents /= previousScale;
// store new transform
m_transform = transform;
// avoid scaling the visualization sphere
@@ -215,22 +221,26 @@ namespace AZ
visualizationTransform.ExtractScale();
m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, visualizationTransform);
m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents * m_transform.GetScale() / 2.0f);
m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents * m_transform.GetScale() / 2.0f);
// update the inner/outer extents with the new scale
m_outerExtents *= m_transform.GetScale();
m_innerExtents *= m_transform.GetScale();
m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents / 2.0f);
m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents / 2.0f);
m_updateSrg = true;
}
void ReflectionProbe::SetOuterExtents(const AZ::Vector3& outerExtents)
{
m_outerExtents = outerExtents;
m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents * m_transform.GetScale() / 2.0f);
m_outerExtents = outerExtents * m_transform.GetScale();
m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents / 2.0f);
m_updateSrg = true;
}
void ReflectionProbe::SetInnerExtents(const AZ::Vector3& innerExtents)
{
m_innerExtents = innerExtents;
m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents * m_transform.GetScale() / 2.0f);
m_innerExtents = innerExtents * m_transform.GetScale();
m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents / 2.0f);
m_updateSrg = true;
}
@@ -78,10 +78,10 @@ namespace AZ
const Vector3& GetPosition() const { return m_transform.GetTranslation(); }
void SetTransform(const AZ::Transform& transform);
AZ::Vector3 GetOuterExtents() const { return m_outerExtents * m_transform.GetScale(); }
const AZ::Vector3& GetOuterExtents() const { return m_outerExtents; }
void SetOuterExtents(const AZ::Vector3& outerExtents);
AZ::Vector3 GetInnerExtents() const { return m_innerExtents * m_transform.GetScale(); }
const AZ::Vector3& GetInnerExtents() const { return m_innerExtents; }
void SetInnerExtents(const AZ::Vector3& innerExtents);
const Aabb& GetOuterAabbWs() const { return m_outerAabbWs; }
@@ -27,8 +27,6 @@ set(FILES
Include/Atom/Feature/ImGui/SystemBus.h
Include/Atom/Feature/ImageBasedLights/ImageBasedLightFeatureProcessor.h
Include/Atom/Feature/LookupTable/LookupTableAsset.h
Include/Atom/Feature/Material/MaterialAssignment.h
Include/Atom/Feature/Material/MaterialAssignmentId.h
Include/Atom/Feature/Mesh/MeshFeatureProcessor.h
Include/Atom/Feature/PostProcessing/PostProcessingConstants.h
Include/Atom/Feature/PostProcessing/SMAAFeatureProcessorInterface.h
@@ -155,8 +153,6 @@ set(FILES
Source/LookupTable/LookupTableAsset.cpp
Source/Material/ConvertEmissiveUnitFunctor.cpp
Source/Material/ConvertEmissiveUnitFunctor.h
Source/Material/MaterialAssignment.cpp
Source/Material/MaterialAssignmentId.cpp
Source/Material/ShaderEnableFunctor.cpp
Source/Material/ShaderEnableFunctor.h
Source/Material/SubsurfaceTransmissionParameterFunctor.cpp
@@ -10,8 +10,12 @@
#
set(FILES
Include/Atom/Feature/Material/MaterialAssignment.h
Include/Atom/Feature/Material/MaterialAssignmentId.h
Include/Atom/Feature/Utils/LightingPreset.h
Include/Atom/Feature/Utils/ModelPreset.h
Source/Material/MaterialAssignment.cpp
Source/Material/MaterialAssignmentId.cpp
Source/Utils/LightingPreset.cpp
Source/Utils/ModelPreset.cpp
)
-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"
}
]
}
@@ -76,6 +76,9 @@ namespace AZ
//! Whether Ray Tracing support is available.
bool m_rayTracing = false;
//! Whether Unbounded Array support is available.
bool m_unboundedArrays = false;
/// Additional features here.
};
}
@@ -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
@@ -124,6 +124,8 @@ namespace AZ
// This lock will only be contested when the CpuProfiler's Shutdown() method has been called
AZStd::shared_mutex m_shutdownMutex;
bool m_initialized = false;
};
}; // namespace RPI
@@ -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)
{
@@ -82,10 +82,15 @@ namespace AZ
void CpuProfilerImpl::Init()
{
Interface<CpuProfiler>::Register(this);
m_initialized = true;
}
void CpuProfilerImpl::Shutdown()
{
if (!m_initialized)
{
return;
}
// When this call is made, no more thread profiling calls can be performed anymore
Interface<CpuProfiler>::Unregister(this);
@@ -97,6 +102,7 @@ namespace AZ
// Cleanup all TLS
m_registeredThreads.clear();
m_timeRegionMap.clear();
m_initialized = false;
}
void CpuProfilerImpl::BeginTimeRegion(TimeRegion& timeRegion)
@@ -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);
}
}
}
+10 -3
View File
@@ -200,9 +200,12 @@ namespace AZ
m_platformLimitsDescriptor = nullptr;
m_pipelineStateCache = nullptr;
m_device->PreShutdown();
AZ_Assert(m_device->use_count()==1, "The ref count for Device is %i but it should be 1 here to ensure all the resources are released", m_device->use_count());
m_device = nullptr;
if (m_device)
{
m_device->PreShutdown();
AZ_Assert(m_device->use_count()==1, "The ref count for Device is %i but it should be 1 here to ensure all the resources are released", m_device->use_count());
m_device = nullptr;
}
m_cpuProfiler.Shutdown();
}
@@ -287,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.");
}
}
}
@@ -90,12 +90,16 @@ namespace AZ
void AsyncUploadQueue::Shutdown()
{
m_copyQueue->Shutdown();
if (m_copyQueue)
{
m_copyQueue->Shutdown();
m_copyQueue = nullptr;
}
m_commandList = nullptr;
for (size_t i = 0; i < m_descriptor.m_frameCount; ++i)
for (auto& framePacket : m_framePackets)
{
m_framePackets[i].m_fence.Shutdown();
framePacket.m_fence.Shutdown();
}
m_framePackets.clear();
m_uploadFence.Shutdown();
@@ -267,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.
@@ -382,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
{
@@ -398,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());
@@ -109,7 +109,10 @@ namespace AZ
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
for (uint32_t hardwareQueueIdx = 0; hardwareQueueIdx < RHI::HardwareQueueClassCount; ++hardwareQueueIdx)
{
m_commandQueues[hardwareQueueIdx]->WaitForIdle();
if (m_commandQueues[hardwareQueueIdx])
{
m_commandQueues[hardwareQueueIdx]->WaitForIdle();
}
}
}
@@ -166,6 +166,8 @@ namespace AZ
m_features.m_rayTracing = false;
#endif
m_features.m_unboundedArrays = true;
m_limits.m_maxImageDimension1D = D3D12_REQ_TEXTURE1D_U_DIMENSION;
m_limits.m_maxImageDimension2D = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
m_limits.m_maxImageDimension3D = D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
@@ -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"
}
]
}
+1 -1
View File
@@ -89,7 +89,7 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
)
ly_add_target(
NAME Atom_RHI_Null.Builders MODULE
NAME Atom_RHI_Null.Builders GEM_MODULE
NAMESPACE Gem
FILES_CMAKE
atom_rhi_null_builders_shared_files.cmake
@@ -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;
@@ -239,7 +239,16 @@ namespace AZ
allocInfo.pSetLayouts = &nativeLayout;
VkResult result = vkAllocateDescriptorSets(descriptor.m_device->GetNativeDevice(), &allocInfo, &m_nativeDescriptorSet);
AssertSuccess(result);
if (result == VK_ERROR_FRAGMENTED_POOL)
{
// fragmented pool will be re-created subsequently in DescriptorSetAllocator, so warning only
AZ_Warning("Vulkan RHI", false, "Fragmented pool, will be recreated in DescriptorSetAllocator afterward");
}
else
{
AssertSuccess(result);
}
if (result != VK_SUCCESS)
{
return result;
@@ -720,6 +720,7 @@ namespace AZ
StringList deviceExtensions = physicalDevice.GetDeviceExtensionNames();
StringList::iterator itRayTracingExtension = AZStd::find(deviceExtensions.begin(), deviceExtensions.end(), VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
m_features.m_rayTracing = (itRayTracingExtension != deviceExtensions.end());
m_features.m_unboundedArrays = true;
const auto& deviceLimits = physicalDevice.GetDeviceLimits();
m_limits.m_maxImageDimension1D = deviceLimits.maxImageDimension1D;
@@ -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;
@@ -96,6 +96,8 @@ namespace AZ
return "Validation failed";
case VK_ERROR_OUT_OF_POOL_MEMORY:
return "Pool is out of memory";
case VK_ERROR_FRAGMENTED_POOL:
return "Fragmented pool";
default:
return "Unknown error";
}
-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,137 +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
{
// Array of textures
// NOTE: The size of the texture array has to match the number of textures in the example
Texture2D m_textureArray[8];
Sampler m_sampler
{
MaxAnisotropy = 16;
AddressU = Wrap;
AddressV = Wrap;
AddressW = Wrap;
};
}
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
)
@@ -45,6 +45,8 @@ namespace AZ
private:
RHI::Ptr<RHI::BufferPool> m_commonPools[static_cast<uint8_t>(CommonBufferPoolType::Count)];
bool m_initialized = false;
};
} // namespace RPI
} // namespace AZ

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