Merge branch 'main' into Atom/antonmic/lowEnd
This commit is contained in:
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
+2
-1
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -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)
|
||||
|
||||
+3
-3
@@ -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;
|
||||
|
||||
+1
-1
@@ -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));
|
||||
|
||||
+72
-2
@@ -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;
|
||||
}
|
||||
|
||||
+2
@@ -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...
|
||||
+50
-14
@@ -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
|
||||
|
||||
+36
-65
@@ -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
|
||||
|
||||
+1
@@ -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
|
||||
|
||||
+36
-69
@@ -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)
|
||||
|
||||
+1
-2
@@ -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
|
||||
)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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;}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
-137
@@ -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
Reference in New Issue
Block a user