Merge main
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>
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -101,7 +101,7 @@ struct VSOutput
|
||||
float2 m_uv[UvSetCount] : UV1;
|
||||
float2 m_detailUv : UV3;
|
||||
|
||||
float4 m_blendMask : UV8;
|
||||
float4 m_wrinkleBlendFactors : UV8;
|
||||
};
|
||||
|
||||
#include <Atom/Features/Vertex/VertexHelper.azsli>
|
||||
@@ -132,11 +132,11 @@ VSOutput SkinVS(VSInput IN)
|
||||
|
||||
if(o_blendMask_isBound)
|
||||
{
|
||||
OUT.m_blendMask = IN.m_optional_blendMask;
|
||||
OUT.m_wrinkleBlendFactors = IN.m_optional_blendMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
OUT.m_blendMask = float4(0,1,0,0);
|
||||
OUT.m_wrinkleBlendFactors = float4(0,0,0,0);
|
||||
}
|
||||
|
||||
VertexHelper(IN, OUT, worldPosition, false);
|
||||
@@ -214,7 +214,22 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
|
||||
|
||||
float2 normalUv = IN.m_uv[MaterialSrg::m_normalMapUvIndex];
|
||||
float detailLayerNormalFactor = MaterialSrg::m_detail_normal_factor * detailLayerBlendFactor;
|
||||
|
||||
|
||||
// ------- Wrinkle Map Setup -------
|
||||
|
||||
// Combine the optional per-morph target wrinkle masks
|
||||
float4 wrinkleBlendFactors = float4(0.0, 0.0, 0.0, 0.0);
|
||||
for(uint wrinkleMaskIndex = 0; wrinkleMaskIndex < ObjectSrg::m_wrinkle_mask_count; ++wrinkleMaskIndex)
|
||||
{
|
||||
wrinkleBlendFactors += ObjectSrg::m_wrinkle_masks[wrinkleMaskIndex].Sample(MaterialSrg::m_sampler, normalUv) * ObjectSrg::GetWrinkleMaskWeight(wrinkleMaskIndex);
|
||||
}
|
||||
|
||||
// If texture based morph target driven masks are being used, use those values instead of the per-vertex colors
|
||||
if(ObjectSrg::m_wrinkle_mask_count)
|
||||
{
|
||||
IN.m_wrinkleBlendFactors = saturate(wrinkleBlendFactors);
|
||||
}
|
||||
|
||||
// Since the wrinkle normal maps should all be in the same tangent space as the main normal map, we should be able to blend the raw normal map
|
||||
// texture values before doing all the tangent space transforms, so we only have to do the transforms once, for better performance.
|
||||
|
||||
@@ -223,12 +238,12 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
|
||||
{
|
||||
normalMapSample = SampleNormalXY(MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY);
|
||||
}
|
||||
if(o_wrinkleLayers_enabled && o_blendMask_isBound && o_wrinkleLayers_normal_enabled)
|
||||
if(o_wrinkleLayers_enabled && o_wrinkleLayers_normal_enabled)
|
||||
{
|
||||
normalMapSample = ApplyNormalWrinkleMap(o_wrinkleLayers_normal_useTexture1, normalMapSample, MaterialSrg::m_wrinkle_normal_texture1, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, IN.m_blendMask.r);
|
||||
normalMapSample = ApplyNormalWrinkleMap(o_wrinkleLayers_normal_useTexture2, normalMapSample, MaterialSrg::m_wrinkle_normal_texture2, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, IN.m_blendMask.g);
|
||||
normalMapSample = ApplyNormalWrinkleMap(o_wrinkleLayers_normal_useTexture3, normalMapSample, MaterialSrg::m_wrinkle_normal_texture3, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, IN.m_blendMask.b);
|
||||
normalMapSample = ApplyNormalWrinkleMap(o_wrinkleLayers_normal_useTexture4, normalMapSample, MaterialSrg::m_wrinkle_normal_texture4, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, IN.m_blendMask.a);
|
||||
normalMapSample = ApplyNormalWrinkleMap(o_wrinkleLayers_normal_useTexture1, normalMapSample, MaterialSrg::m_wrinkle_normal_texture1, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, IN.m_wrinkleBlendFactors.r);
|
||||
normalMapSample = ApplyNormalWrinkleMap(o_wrinkleLayers_normal_useTexture2, normalMapSample, MaterialSrg::m_wrinkle_normal_texture2, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, IN.m_wrinkleBlendFactors.g);
|
||||
normalMapSample = ApplyNormalWrinkleMap(o_wrinkleLayers_normal_useTexture3, normalMapSample, MaterialSrg::m_wrinkle_normal_texture3, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, IN.m_wrinkleBlendFactors.b);
|
||||
normalMapSample = ApplyNormalWrinkleMap(o_wrinkleLayers_normal_useTexture4, normalMapSample, MaterialSrg::m_wrinkle_normal_texture4, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, IN.m_wrinkleBlendFactors.a);
|
||||
}
|
||||
|
||||
if(o_detail_normal_useTexture)
|
||||
@@ -255,7 +270,7 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
|
||||
float3 baseColor = GetBaseColorInput(MaterialSrg::m_baseColorMap, MaterialSrg::m_sampler, baseColorUv, MaterialSrg::m_baseColor, o_baseColor_useTexture);
|
||||
|
||||
bool useSampledBaseColor = o_baseColor_useTexture;
|
||||
if(o_wrinkleLayers_enabled && o_blendMask_isBound && o_wrinkleLayers_baseColor_enabled)
|
||||
if(o_wrinkleLayers_enabled && o_wrinkleLayers_baseColor_enabled)
|
||||
{
|
||||
// If any of the wrinkle maps are applied, we will use the Base Color blend settings to apply the MaterialSrg::m_baseColor tint to the wrinkle maps,
|
||||
// even if the main base color map is not used.
|
||||
@@ -272,10 +287,10 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
|
||||
baseColor = float3(1,1,1);
|
||||
}
|
||||
|
||||
baseColor = ApplyBaseColorWrinkleMap(o_wrinkleLayers_baseColor_useTexture1, baseColor, MaterialSrg::m_wrinkle_baseColor_texture1, MaterialSrg::m_sampler, baseColorUv, IN.m_blendMask.r);
|
||||
baseColor = ApplyBaseColorWrinkleMap(o_wrinkleLayers_baseColor_useTexture2, baseColor, MaterialSrg::m_wrinkle_baseColor_texture2, MaterialSrg::m_sampler, baseColorUv, IN.m_blendMask.g);
|
||||
baseColor = ApplyBaseColorWrinkleMap(o_wrinkleLayers_baseColor_useTexture3, baseColor, MaterialSrg::m_wrinkle_baseColor_texture3, MaterialSrg::m_sampler, baseColorUv, IN.m_blendMask.b);
|
||||
baseColor = ApplyBaseColorWrinkleMap(o_wrinkleLayers_baseColor_useTexture4, baseColor, MaterialSrg::m_wrinkle_baseColor_texture4, MaterialSrg::m_sampler, baseColorUv, IN.m_blendMask.a);
|
||||
baseColor = ApplyBaseColorWrinkleMap(o_wrinkleLayers_baseColor_useTexture1, baseColor, MaterialSrg::m_wrinkle_baseColor_texture1, MaterialSrg::m_sampler, baseColorUv, IN.m_wrinkleBlendFactors.r);
|
||||
baseColor = ApplyBaseColorWrinkleMap(o_wrinkleLayers_baseColor_useTexture2, baseColor, MaterialSrg::m_wrinkle_baseColor_texture2, MaterialSrg::m_sampler, baseColorUv, IN.m_wrinkleBlendFactors.g);
|
||||
baseColor = ApplyBaseColorWrinkleMap(o_wrinkleLayers_baseColor_useTexture3, baseColor, MaterialSrg::m_wrinkle_baseColor_texture3, MaterialSrg::m_sampler, baseColorUv, IN.m_wrinkleBlendFactors.b);
|
||||
baseColor = ApplyBaseColorWrinkleMap(o_wrinkleLayers_baseColor_useTexture4, baseColor, MaterialSrg::m_wrinkle_baseColor_texture4, MaterialSrg::m_sampler, baseColorUv, IN.m_wrinkleBlendFactors.a);
|
||||
|
||||
}
|
||||
|
||||
@@ -283,13 +298,13 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
|
||||
|
||||
baseColor = ApplyTextureOverlay(o_detail_baseColor_useTexture, baseColor, MaterialSrg::m_detail_baseColor_texture, MaterialSrg::m_sampler, IN.m_detailUv, detailLayerBaseColorFactor);
|
||||
|
||||
if(o_wrinkleLayers_enabled && o_wrinkleLayers_showBlendMaskValues && o_blendMask_isBound)
|
||||
if(o_wrinkleLayers_enabled && o_wrinkleLayers_showBlendMaskValues)
|
||||
{
|
||||
// Overlay debug colors to highlight the different blend weights coming from the vertex color stream.
|
||||
if(o_wrinkleLayers_count > 0) { baseColor = lerp(baseColor, float3(1,0,0), IN.m_blendMask.r); }
|
||||
if(o_wrinkleLayers_count > 1) { baseColor = lerp(baseColor, float3(0,1,0), IN.m_blendMask.g); }
|
||||
if(o_wrinkleLayers_count > 2) { baseColor = lerp(baseColor, float3(0,0,1), IN.m_blendMask.b); }
|
||||
if(o_wrinkleLayers_count > 3) { baseColor = lerp(baseColor, float3(1,1,1), IN.m_blendMask.a); }
|
||||
if(o_wrinkleLayers_count > 0) { baseColor = lerp(baseColor, float3(1,0,0), IN.m_wrinkleBlendFactors.r); }
|
||||
if(o_wrinkleLayers_count > 1) { baseColor = lerp(baseColor, float3(0,1,0), IN.m_wrinkleBlendFactors.g); }
|
||||
if(o_wrinkleLayers_count > 2) { baseColor = lerp(baseColor, float3(0,0,1), IN.m_wrinkleBlendFactors.b); }
|
||||
if(o_wrinkleLayers_count > 3) { baseColor = lerp(baseColor, float3(1,1,1), IN.m_wrinkleBlendFactors.a); }
|
||||
}
|
||||
|
||||
// ------- Specular -------
|
||||
|
||||
@@ -987,15 +987,6 @@
|
||||
{
|
||||
"file": "Shaders/MotionVector/SkinnedMeshMotionVector.shader",
|
||||
"tag": "SkinnedMeshMotionVector"
|
||||
},
|
||||
// Used by the light culling system to produce accurate depth bounds for this object when it uses blended transparency
|
||||
{
|
||||
"file": "Shaders/Depth/DepthPassTransparentMin.shader",
|
||||
"tag": "DepthPassTransparentMin"
|
||||
},
|
||||
{
|
||||
"file": "Shaders/Depth/DepthPassTransparentMax.shader",
|
||||
"tag": "DepthPassTransparentMax"
|
||||
}
|
||||
],
|
||||
"functors": [
|
||||
|
||||
@@ -1199,6 +1199,14 @@
|
||||
"file": "./StandardPBR_ForwardPass_EDS.shader",
|
||||
"tag": "ForwardPass_EDS"
|
||||
},
|
||||
{
|
||||
"file": "./StandardPBR_LowEndForward.shader",
|
||||
"tag": "LowEndForward"
|
||||
},
|
||||
{
|
||||
"file": "./StandardPBR_LowEndForward_EDS.shader",
|
||||
"tag": "LowEndForward_EDS"
|
||||
},
|
||||
{
|
||||
"file": "Shaders/Shadow/Shadowmap.shader",
|
||||
"tag": "Shadowmap"
|
||||
@@ -1289,10 +1297,6 @@
|
||||
"textureProperty": "baseColor.textureMap",
|
||||
"useTextureProperty": "baseColor.useTexture",
|
||||
"dependentProperties": ["baseColor.textureMapUv", "baseColor.textureBlendMode"],
|
||||
"shaderTags": [
|
||||
"ForwardPass",
|
||||
"ForwardPass_EDS"
|
||||
],
|
||||
"shaderOption": "o_baseColor_useTexture"
|
||||
}
|
||||
},
|
||||
@@ -1302,10 +1306,6 @@
|
||||
"textureProperty": "metallic.textureMap",
|
||||
"useTextureProperty": "metallic.useTexture",
|
||||
"dependentProperties": ["metallic.textureMapUv"],
|
||||
"shaderTags": [
|
||||
"ForwardPass",
|
||||
"ForwardPass_EDS"
|
||||
],
|
||||
"shaderOption": "o_metallic_useTexture"
|
||||
}
|
||||
},
|
||||
@@ -1315,10 +1315,6 @@
|
||||
"textureProperty": "specularF0.textureMap",
|
||||
"useTextureProperty": "specularF0.useTexture",
|
||||
"dependentProperties": ["specularF0.textureMapUv"],
|
||||
"shaderTags": [
|
||||
"ForwardPass",
|
||||
"ForwardPass_EDS"
|
||||
],
|
||||
"shaderOption": "o_specularF0_useTexture"
|
||||
}
|
||||
},
|
||||
@@ -1328,10 +1324,6 @@
|
||||
"textureProperty": "normal.textureMap",
|
||||
"useTextureProperty": "normal.useTexture",
|
||||
"dependentProperties": ["normal.textureMapUv", "normal.factor", "normal.flipX", "normal.flipY"],
|
||||
"shaderTags": [
|
||||
"ForwardPass",
|
||||
"ForwardPass_EDS"
|
||||
],
|
||||
"shaderOption": "o_normal_useTexture"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Atom/Features/ShaderQualityOptions.azsli"
|
||||
|
||||
#include "StandardPBR_Common.azsli"
|
||||
|
||||
// SRGs
|
||||
@@ -317,13 +319,18 @@ ForwardPassOutputWithDepth StandardPbr_ForwardPassPS(VSOutput IN, bool isFrontFa
|
||||
|
||||
PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth);
|
||||
|
||||
#ifdef UNIFIED_FORWARD_OUTPUT
|
||||
OUT.m_color.rgb = lightingOutput.m_diffuseColor.rgb + lightingOutput.m_specularColor.rgb;
|
||||
OUT.m_color.a = lightingOutput.m_diffuseColor.a;
|
||||
OUT.m_depth = depth;
|
||||
#else
|
||||
OUT.m_diffuseColor = lightingOutput.m_diffuseColor;
|
||||
OUT.m_specularColor = lightingOutput.m_specularColor;
|
||||
OUT.m_specularF0 = lightingOutput.m_specularF0;
|
||||
OUT.m_albedo = lightingOutput.m_albedo;
|
||||
OUT.m_normal = lightingOutput.m_normal;
|
||||
OUT.m_depth = depth;
|
||||
|
||||
#endif
|
||||
return OUT;
|
||||
}
|
||||
|
||||
@@ -335,12 +342,16 @@ ForwardPassOutput StandardPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace :
|
||||
|
||||
PbrLightingOutput lightingOutput = ForwardPassPS_Common(IN, isFrontFace, depth);
|
||||
|
||||
#ifdef UNIFIED_FORWARD_OUTPUT
|
||||
OUT.m_color.rgb = lightingOutput.m_diffuseColor.rgb + lightingOutput.m_specularColor.rgb;
|
||||
OUT.m_color.a = lightingOutput.m_diffuseColor.a;
|
||||
#else
|
||||
OUT.m_diffuseColor = lightingOutput.m_diffuseColor;
|
||||
OUT.m_specularColor = lightingOutput.m_specularColor;
|
||||
OUT.m_specularF0 = lightingOutput.m_specularF0;
|
||||
OUT.m_albedo = lightingOutput.m_albedo;
|
||||
OUT.m_normal = lightingOutput.m_normal;
|
||||
|
||||
#endif
|
||||
return OUT;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// NOTE: This file is a temporary workaround until .shader files can #define macros for their .azsl files
|
||||
|
||||
#define QUALITY_LOW_END 1
|
||||
|
||||
#include "StandardPBR_ForwardPass.azsl"
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
// Note: "LowEnd" shaders are for supporting the low end pipeline
|
||||
// These shaders can be safely added to materials without incurring additional runtime draw
|
||||
// items as draw items for shaders are only created if the scene has a pass with a matching
|
||||
// DrawListTag. If your pipeline doesn't have a "lowEndForward" DrawListTag, no draw items
|
||||
// for this shader will be created.
|
||||
|
||||
"Source" : "./StandardPBR_LowEndForward.azsl",
|
||||
|
||||
"DepthStencilState" :
|
||||
{
|
||||
"Depth" :
|
||||
{
|
||||
"Enable" : true,
|
||||
"CompareFunc" : "GreaterEqual"
|
||||
},
|
||||
"Stencil" :
|
||||
{
|
||||
"Enable" : true,
|
||||
"ReadMask" : "0x00",
|
||||
"WriteMask" : "0xFF",
|
||||
"FrontFace" :
|
||||
{
|
||||
"Func" : "Always",
|
||||
"DepthFailOp" : "Keep",
|
||||
"FailOp" : "Keep",
|
||||
"PassOp" : "Replace"
|
||||
},
|
||||
"BackFace" :
|
||||
{
|
||||
"Func" : "Always",
|
||||
"DepthFailOp" : "Keep",
|
||||
"FailOp" : "Keep",
|
||||
"PassOp" : "Replace"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"CompilerHints" : {
|
||||
"DisableOptimizations" : false
|
||||
},
|
||||
|
||||
"ProgramSettings":
|
||||
{
|
||||
"EntryPoints":
|
||||
[
|
||||
{
|
||||
"name": "StandardPbr_ForwardPassVS",
|
||||
"type": "Vertex"
|
||||
},
|
||||
{
|
||||
"name": "StandardPbr_ForwardPassPS",
|
||||
"type": "Fragment"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"DrawList" : "lowEndForward"
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
// Note: "LowEnd" shaders are for supporting the low end pipeline
|
||||
// These shaders can be safely added to materials without incurring additional runtime draw
|
||||
// items as draw items for shaders are only created if the scene has a pass with a matching
|
||||
// DrawListTag. If your pipeline doesn't have a "lowEndForward" DrawListTag, no draw items
|
||||
// for this shader will be created.
|
||||
|
||||
"Source" : "./StandardPBR_LowEndForward.azsl",
|
||||
|
||||
"DepthStencilState" :
|
||||
{
|
||||
"Depth" :
|
||||
{
|
||||
"Enable" : true,
|
||||
"CompareFunc" : "GreaterEqual"
|
||||
},
|
||||
"Stencil" :
|
||||
{
|
||||
"Enable" : true,
|
||||
"ReadMask" : "0x00",
|
||||
"WriteMask" : "0xFF",
|
||||
"FrontFace" :
|
||||
{
|
||||
"Func" : "Always",
|
||||
"DepthFailOp" : "Keep",
|
||||
"FailOp" : "Keep",
|
||||
"PassOp" : "Replace"
|
||||
},
|
||||
"BackFace" :
|
||||
{
|
||||
"Func" : "Always",
|
||||
"DepthFailOp" : "Keep",
|
||||
"FailOp" : "Keep",
|
||||
"PassOp" : "Replace"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"CompilerHints" : {
|
||||
"DisableOptimizations" : false
|
||||
},
|
||||
|
||||
"ProgramSettings":
|
||||
{
|
||||
"EntryPoints":
|
||||
[
|
||||
{
|
||||
"name": "StandardPbr_ForwardPassVS",
|
||||
"type": "Vertex"
|
||||
},
|
||||
{
|
||||
"name": "StandardPbr_ForwardPassPS_EDS",
|
||||
"type": "Fragment"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"DrawList" : "lowEndForward"
|
||||
}
|
||||
@@ -29,26 +29,33 @@ function Process(context)
|
||||
local depthPass = context:GetShaderByTag("DepthPass")
|
||||
local shadowMap = context:GetShaderByTag("Shadowmap")
|
||||
local forwardPassEDS = context:GetShaderByTag("ForwardPass_EDS")
|
||||
local lowEndForwardEDS = context:GetShaderByTag("LowEndForward_EDS")
|
||||
|
||||
local depthPassWithPS = context:GetShaderByTag("DepthPass_WithPS")
|
||||
local shadowMapWitPS = context:GetShaderByTag("Shadowmap_WithPS")
|
||||
local forwardPass = context:GetShaderByTag("ForwardPass")
|
||||
local lowEndForward = context:GetShaderByTag("LowEndForward")
|
||||
|
||||
if parallaxEnabled and parallaxPdoEnabled then
|
||||
depthPass:SetEnabled(false)
|
||||
shadowMap:SetEnabled(false)
|
||||
forwardPassEDS:SetEnabled(false)
|
||||
lowEndForwardEDS:SetEnabled(false)
|
||||
|
||||
depthPassWithPS:SetEnabled(true)
|
||||
shadowMapWitPS:SetEnabled(true)
|
||||
forwardPass:SetEnabled(true)
|
||||
lowEndForward:SetEnabled(true)
|
||||
else
|
||||
depthPass:SetEnabled(opacityMode == OpacityMode_Opaque)
|
||||
shadowMap:SetEnabled(opacityMode == OpacityMode_Opaque)
|
||||
forwardPassEDS:SetEnabled((opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent))
|
||||
lowEndForwardEDS:SetEnabled((opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent))
|
||||
|
||||
depthPassWithPS:SetEnabled(opacityMode == OpacityMode_Cutout)
|
||||
shadowMapWitPS:SetEnabled(opacityMode == OpacityMode_Cutout)
|
||||
forwardPass:SetEnabled(opacityMode == OpacityMode_Cutout)
|
||||
lowEndForward:SetEnabled(opacityMode == OpacityMode_Cutout)
|
||||
end
|
||||
|
||||
context:GetShaderByTag("DepthPassTransparentMin"):SetEnabled((opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent))
|
||||
|
||||
@@ -148,22 +148,6 @@
|
||||
},
|
||||
"LoadAction": "Clear"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "ScatterDistanceOutput",
|
||||
"SlotType": "Output",
|
||||
"ScopeAttachmentUsage": "RenderTarget",
|
||||
"LoadStoreAction": {
|
||||
"ClearValue": {
|
||||
"Value": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
},
|
||||
"LoadAction": "Clear"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ImageAttachments": [
|
||||
@@ -238,19 +222,6 @@
|
||||
"AssetRef": {
|
||||
"FilePath": "Textures/BRDFTexture.attimage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "ScatterDistanceImage",
|
||||
"SizeSource": {
|
||||
"Source": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
},
|
||||
"ImageDescriptor": {
|
||||
"Format": "R11G11B10_FLOAT",
|
||||
"SharedQueueMask": "Graphics"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Connections": [
|
||||
@@ -295,13 +266,6 @@
|
||||
"Pass": "This",
|
||||
"Attachment": "BRDFTexture"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "ScatterDistanceOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "This",
|
||||
"Attachment": "ScatterDistanceImage"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "PassAsset",
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "LightAdaptationParentTemplate",
|
||||
"PassClass": "ParentPass",
|
||||
"Slots": [
|
||||
// Inputs...
|
||||
{
|
||||
"Name": "LightingInput",
|
||||
"SlotType": "Input"
|
||||
},
|
||||
// SwapChain here is only used to reference the frame height and format
|
||||
{
|
||||
"Name": "SwapChainOutput",
|
||||
"SlotType": "InputOutput"
|
||||
},
|
||||
// Outputs...
|
||||
{
|
||||
"Name": "Output",
|
||||
"SlotType": "Output"
|
||||
},
|
||||
// Debug Outputs...
|
||||
{
|
||||
"Name": "LuminanceMipChainOutput",
|
||||
"SlotType": "Output"
|
||||
}
|
||||
],
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Output",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DisplayMapperPass",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "LuminanceMipChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DownsampleLuminanceMipChain",
|
||||
"Attachment": "MipChainInputOutput"
|
||||
}
|
||||
}
|
||||
],
|
||||
"PassRequests": [
|
||||
{
|
||||
"Name": "DownsampleLuminanceMinAvgMax",
|
||||
"TemplateName": "DownsampleLuminanceMinAvgMaxCS",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Input",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "LightingInput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "DownsampleLuminanceMipChain",
|
||||
"TemplateName": "DownsampleMipChainTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "MipChainInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DownsampleLuminanceMinAvgMax",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
}
|
||||
],
|
||||
"PassData": {
|
||||
"$type": "DownsampleMipChainPassData",
|
||||
"ShaderAsset": {
|
||||
"FilePath": "Shaders/PostProcessing/DownsampleMinAvgMaxCS.shader"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "EyeAdaptationPass",
|
||||
"TemplateName": "EyeAdaptationTemplate",
|
||||
"Enabled": false,
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SceneLuminanceInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DownsampleLuminanceMipChain",
|
||||
"Attachment": "MipChainInputOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "LookModificationTransformPass",
|
||||
"TemplateName": "LookModificationTransformTemplate",
|
||||
"Enabled": true,
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Input",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "LightingInput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "EyeAdaptationDataInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "EyeAdaptationPass",
|
||||
"Attachment": "EyeAdaptationDataInputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "DisplayMapperPass",
|
||||
"TemplateName": "DisplayMapperTemplate",
|
||||
"Enabled": true,
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Input",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LookModificationTransformPass",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "PassAsset",
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "LowEndForwardPassTemplate",
|
||||
"PassClass": "RasterPass",
|
||||
"Slots": [
|
||||
// Inputs...
|
||||
{
|
||||
"Name": "BRDFTextureInput",
|
||||
"ShaderInputName": "m_brdfMap",
|
||||
"SlotType": "Input",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "DirectionalLightShadowmap",
|
||||
"ShaderInputName": "m_directionalLightShadowmap",
|
||||
"SlotType": "Input",
|
||||
"ScopeAttachmentUsage": "Shader",
|
||||
"ImageViewDesc": {
|
||||
"IsArray": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "ExponentialShadowmapDirectional",
|
||||
"ShaderInputName": "m_directionalLightExponentialShadowmap",
|
||||
"SlotType": "Input",
|
||||
"ScopeAttachmentUsage": "Shader",
|
||||
"ImageViewDesc": {
|
||||
"IsArray": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "ProjectedShadowmap",
|
||||
"ShaderInputName": "m_projectedShadowmaps",
|
||||
"SlotType": "Input",
|
||||
"ScopeAttachmentUsage": "Shader",
|
||||
"ImageViewDesc": {
|
||||
"IsArray": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "ExponentialShadowmapProjected",
|
||||
"ShaderInputName": "m_projectedExponentialShadowmap",
|
||||
"SlotType": "Input",
|
||||
"ScopeAttachmentUsage": "Shader",
|
||||
"ImageViewDesc": {
|
||||
"IsArray": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "TileLightData",
|
||||
"SlotType": "Input",
|
||||
"ShaderInputName": "m_tileLightData",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "LightListRemapped",
|
||||
"SlotType": "Input",
|
||||
"ShaderInputName": "m_lightListRemapped",
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
// Input/Outputs...
|
||||
{
|
||||
"Name": "DepthStencilInputOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "DepthStencil"
|
||||
},
|
||||
// Outputs...
|
||||
{
|
||||
"Name": "LightingOutput",
|
||||
"SlotType": "Output",
|
||||
"ScopeAttachmentUsage": "RenderTarget",
|
||||
"LoadStoreAction": {
|
||||
"ClearValue": {
|
||||
"Value": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
},
|
||||
"LoadAction": "Clear"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ImageAttachments": [
|
||||
{
|
||||
"Name": "LightingAttachment",
|
||||
"SizeSource": {
|
||||
"Source": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
},
|
||||
"MultisampleSource": {
|
||||
"Pass": "This",
|
||||
"Attachment": "DepthStencilInputOutput"
|
||||
},
|
||||
"ImageDescriptor": {
|
||||
"Format": "R16G16B16A16_FLOAT",
|
||||
"SharedQueueMask": "Graphics"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "BRDFTexture",
|
||||
"Lifetime": "Imported",
|
||||
"AssetRef": {
|
||||
"FilePath": "Textures/BRDFTexture.attimage"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "LightingOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "This",
|
||||
"Attachment": "LightingAttachment"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "BRDFTextureInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "This",
|
||||
"Attachment": "BRDFTexture"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "PassAsset",
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "LowEndPipelineTemplate",
|
||||
"PassClass": "ParentPass",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "SwapChainOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "RenderTarget"
|
||||
}
|
||||
],
|
||||
"PassRequests": [
|
||||
{
|
||||
"Name": "MorphTargetPass",
|
||||
"TemplateName": "MorphTargetPassTemplate"
|
||||
},
|
||||
{
|
||||
"Name": "SkinningPass",
|
||||
"TemplateName": "SkinningPassTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SkinnedMeshOutputStream",
|
||||
"AttachmentRef": {
|
||||
"Pass": "MorphTargetPass",
|
||||
"Attachment": "MorphTargetDeltaOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "DepthPrePass",
|
||||
"TemplateName": "DepthMSAAParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SkinnedMeshes",
|
||||
"AttachmentRef": {
|
||||
"Pass": "SkinningPass",
|
||||
"Attachment": "SkinnedMeshOutputStream"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "LightCullingPass",
|
||||
"TemplateName": "LightCullingParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SkinnedMeshes",
|
||||
"AttachmentRef": {
|
||||
"Pass": "SkinningPass",
|
||||
"Attachment": "SkinnedMeshOutputStream"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthMSAA",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "DepthMSAA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "ShadowPass",
|
||||
"TemplateName": "ShadowParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SkinnedMeshes",
|
||||
"AttachmentRef": {
|
||||
"Pass": "SkinningPass",
|
||||
"Attachment": "SkinnedMeshOutputStream"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "ForwardPass",
|
||||
"TemplateName": "LowEndForwardPassTemplate",
|
||||
"Connections": [
|
||||
// Inputs...
|
||||
{
|
||||
"LocalSlot": "DirectionalLightShadowmap",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "DirectionalShadowmap"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "ExponentialShadowmapDirectional",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "DirectionalESM"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "ProjectedShadowmap",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "ProjectedShadowmap"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "ExponentialShadowmapProjected",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "ProjectedESM"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "TileLightData",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "TileLightData"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "LightListRemapped",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "LightListRemapped"
|
||||
}
|
||||
},
|
||||
// Input/Outputs...
|
||||
{
|
||||
"LocalSlot": "DepthStencilInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "DepthMSAA"
|
||||
}
|
||||
}
|
||||
],
|
||||
"PassData": {
|
||||
"$type": "RasterPassData",
|
||||
"DrawListTag": "lowEndForward",
|
||||
"PipelineViewTag": "MainCamera",
|
||||
"PassSrgAsset": {
|
||||
"FilePath": "shaderlib/atom/features/pbr/forwardpasssrg.azsli:PassSrg"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "SkyBoxPass",
|
||||
"TemplateName": "SkyBoxTemplate",
|
||||
"Enabled": true,
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SpecularInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ForwardPass",
|
||||
"Attachment": "LightingOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SkyBoxDepth",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ForwardPass",
|
||||
"Attachment": "DepthStencilInputOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "MSAAResolvePass",
|
||||
"TemplateName": "MSAAResolveColorTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Input",
|
||||
"AttachmentRef": {
|
||||
"Pass": "SkyBoxPass",
|
||||
"Attachment": "SpecularInputOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "TransparentPass",
|
||||
"TemplateName": "TransparentParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "DirectionalShadowmap",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "DirectionalShadowmap"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DirectionalESM",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "DirectionalESM"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "ProjectedShadowmap",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "ProjectedShadowmap"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "ProjectedESM",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "ProjectedESM"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "TileLightData",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "TileLightData"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "LightListRemapped",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "LightListRemapped"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthStencil",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "Depth"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "InputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "MSAAResolvePass",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "LightAdaptation",
|
||||
"TemplateName": "LightAdaptationParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "LightingInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "TransparentPass",
|
||||
"Attachment": "InputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "AuxGeomPass",
|
||||
"TemplateName": "AuxGeomPassTemplate",
|
||||
"Enabled": true,
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "ColorInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightAdaptation",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "Depth"
|
||||
}
|
||||
}
|
||||
],
|
||||
"PassData": {
|
||||
"$type": "RasterPassData",
|
||||
"DrawListTag": "auxgeom",
|
||||
"PipelineViewTag": "MainCamera"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "UIPass",
|
||||
"TemplateName": "UIParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "InputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "AuxGeomPass",
|
||||
"Attachment": "ColorInputOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "CopyToSwapChain",
|
||||
"TemplateName": "FullscreenCopyTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Input",
|
||||
"AttachmentRef": {
|
||||
"Pass": "UIPass",
|
||||
"Attachment": "InputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "Output",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,7 +305,7 @@
|
||||
},
|
||||
{
|
||||
"Name": "SkyBoxPass",
|
||||
"TemplateName": "SkyBoxTemplate",
|
||||
"TemplateName": "SkyBoxTwoOutputsTemplate",
|
||||
"Enabled": true,
|
||||
"Connections": [
|
||||
{
|
||||
|
||||
@@ -92,6 +92,10 @@
|
||||
"Name": "SkyBoxTemplate",
|
||||
"Path": "Passes/SkyBox.pass"
|
||||
},
|
||||
{
|
||||
"Name": "SkyBoxTwoOutputsTemplate",
|
||||
"Path": "Passes/SkyBox_TwoOutputs.pass"
|
||||
},
|
||||
{
|
||||
"Name": "UIPassTemplate",
|
||||
"Path": "Passes/UI.pass"
|
||||
@@ -483,6 +487,18 @@
|
||||
{
|
||||
"Name": "UIParentTemplate",
|
||||
"Path": "Passes/UIParent.pass"
|
||||
},
|
||||
{
|
||||
"Name": "LightAdaptationParentTemplate",
|
||||
"Path": "Passes/LightAdaptationParent.pass"
|
||||
},
|
||||
{
|
||||
"Name": "LowEndForwardPassTemplate",
|
||||
"Path": "Passes/LowEndForward.pass"
|
||||
},
|
||||
{
|
||||
"Name": "LowEndPipelineTemplate",
|
||||
"Path": "Passes/LowEndPipeline.pass"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
{
|
||||
"LocalSlot": "Output",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DisplayMapperPass",
|
||||
"Pass": "LightAdaptation",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
},
|
||||
@@ -54,8 +54,8 @@
|
||||
{
|
||||
"LocalSlot": "LuminanceMipChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DownsampleLuminanceMipChain",
|
||||
"Attachment": "MipChainInputOutput"
|
||||
"Pass": "LightAdaptation",
|
||||
"Attachment": "LuminanceMipChainOutput"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -115,94 +115,16 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
// Everything before this point deals in raw lighting values
|
||||
// ---------------------------------------------------------
|
||||
// Everything after starts to map to values we see on screen
|
||||
{
|
||||
"Name": "DownsampleLuminanceMinAvgMax",
|
||||
"TemplateName": "DownsampleLuminanceMinAvgMaxCS",
|
||||
"Name": "LightAdaptation",
|
||||
"TemplateName": "LightAdaptationParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Input",
|
||||
"LocalSlot": "LightingInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "BloomPass",
|
||||
"Attachment": "InputOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "DownsampleLuminanceMipChain",
|
||||
"TemplateName": "DownsampleMipChainTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "MipChainInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DownsampleLuminanceMinAvgMax",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
}
|
||||
],
|
||||
"PassData": {
|
||||
"$type": "DownsampleMipChainPassData",
|
||||
"ShaderAsset": {
|
||||
"FilePath": "Shaders/PostProcessing/DownsampleMinAvgMaxCS.shader"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "EyeAdaptationPass",
|
||||
"TemplateName": "EyeAdaptationTemplate",
|
||||
"Enabled": false,
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SceneLuminanceInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DownsampleLuminanceMipChain",
|
||||
"Attachment": "MipChainInputOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "LookModificationTransformPass",
|
||||
"TemplateName": "LookModificationTransformTemplate",
|
||||
"Enabled": true,
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Input",
|
||||
"AttachmentRef": {
|
||||
"Pass": "BloomPass",
|
||||
"Attachment": "InputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "EyeAdaptationDataInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "EyeAdaptationPass",
|
||||
"Attachment": "EyeAdaptationDataInputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "DisplayMapperPass",
|
||||
"TemplateName": "DisplayMapperTemplate",
|
||||
"Enabled": true,
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Input",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LookModificationTransformPass",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
|
||||
@@ -12,11 +12,6 @@
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "RenderTarget"
|
||||
},
|
||||
{
|
||||
"Name": "ReflectionInputOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "RenderTarget"
|
||||
},
|
||||
{
|
||||
"Name": "SkyBoxDepth",
|
||||
"SlotType": "InputOutput",
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "PassAsset",
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "SkyBoxTwoOutputsTemplate",
|
||||
"PassClass": "FullScreenTriangle",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "SpecularInputOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "RenderTarget"
|
||||
},
|
||||
{
|
||||
"Name": "ReflectionInputOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "RenderTarget"
|
||||
},
|
||||
{
|
||||
"Name": "SkyBoxDepth",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "DepthStencil"
|
||||
}
|
||||
],
|
||||
"PassData": {
|
||||
"$type": "FullscreenTrianglePassData",
|
||||
"ShaderAsset": {
|
||||
"FilePath": "shaders/skybox/skybox_twooutputs.shader"
|
||||
},
|
||||
"PipelineViewTag": "MainCamera",
|
||||
"ShaderDataMappings": {
|
||||
"FloatMappings": [
|
||||
{
|
||||
"Name": "m_sunIntensityMultiplier",
|
||||
"Value": 1.0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -31,6 +31,16 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
|
||||
return SceneSrg::GetObjectToWorldInverseTransposeMatrix(m_objectId);
|
||||
}
|
||||
|
||||
//[GFX TODO][ATOM-15280] Move wrinkle mask data from the default object srg into something specific to the Skin shader
|
||||
uint m_wrinkle_mask_count;
|
||||
float4 m_wrinkle_mask_weights[4];
|
||||
Texture2D m_wrinkle_masks[16];
|
||||
|
||||
float GetWrinkleMaskWeight(uint index)
|
||||
{
|
||||
return m_wrinkle_mask_weights[index / 4][index % 4];
|
||||
}
|
||||
|
||||
//! Reflection Probe (smallest probe volume that overlaps the object position)
|
||||
struct ReflectionProbeData
|
||||
{
|
||||
|
||||
@@ -10,6 +10,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef UNIFIED_FORWARD_OUTPUT
|
||||
|
||||
struct ForwardPassOutput
|
||||
{
|
||||
float4 m_color : SV_Target0;
|
||||
};
|
||||
|
||||
struct ForwardPassOutputWithDepth
|
||||
{
|
||||
float4 m_color : SV_Target0;
|
||||
float m_depth : SV_Depth;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
struct ForwardPassOutput
|
||||
{
|
||||
float4 m_diffuseColor : SV_Target0; //!< RGB = Diffuse Lighting, A = Blend Alpha (for blended surfaces) OR A = special encoding of surfaceScatteringFactor, m_subsurfaceScatteringQuality, o_enableSubsurfaceScattering
|
||||
@@ -30,3 +45,5 @@ struct ForwardPassOutputWithDepth
|
||||
float4 m_normal : SV_Target4;
|
||||
float m_depth : SV_Depth;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,38 +12,39 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// --- Static Options Available ---
|
||||
// FORCE_IBL_IN_FORWARD_PASS - forces IBL lighting to be run in the forward pass, used in pipelines that don't have a reflection pass
|
||||
|
||||
#include <Atom/Features/PBR/LightingOptions.azsli>
|
||||
|
||||
#include <Atom/RPI/Math.azsli>
|
||||
#include <Atom/Features/PBR/Lights/LightTypesCommon.azsli>
|
||||
#include <Atom/Features/PBR/LightingUtils.azsli>
|
||||
|
||||
void ApplyIblDiffuse(
|
||||
float3 GetIblDiffuse(
|
||||
float3 normal,
|
||||
float3 albedo,
|
||||
float3 diffuseResponse,
|
||||
out float3 outDiffuse)
|
||||
float3 diffuseResponse)
|
||||
{
|
||||
float3 irradianceDir = MultiplyVectorQuaternion(normal, SceneSrg::m_iblOrientation);
|
||||
float3 diffuseSample = SceneSrg::m_diffuseEnvMap.Sample(SceneSrg::m_samplerEnv, GetCubemapCoords(irradianceDir)).rgb;
|
||||
|
||||
outDiffuse = diffuseResponse * albedo * diffuseSample;
|
||||
return diffuseResponse * albedo * diffuseSample;
|
||||
}
|
||||
|
||||
void ApplyIblSpecular(
|
||||
float3 GetIblSpecular(
|
||||
float3 position,
|
||||
float3 normal,
|
||||
float3 specularF0,
|
||||
float roughnessLinear,
|
||||
float3 dirToCamera,
|
||||
float2 brdf,
|
||||
out float3 outSpecular)
|
||||
float2 brdf)
|
||||
{
|
||||
float3 reflectDir = reflect(-dirToCamera, normal);
|
||||
reflectDir = MultiplyVectorQuaternion(reflectDir, SceneSrg::m_iblOrientation);
|
||||
|
||||
// global
|
||||
outSpecular = SceneSrg::m_specularEnvMap.SampleLevel(SceneSrg::m_samplerEnv, GetCubemapCoords(reflectDir), GetRoughnessMip(roughnessLinear)).rgb;
|
||||
float3 outSpecular = SceneSrg::m_specularEnvMap.SampleLevel(SceneSrg::m_samplerEnv, GetCubemapCoords(reflectDir), GetRoughnessMip(roughnessLinear)).rgb;
|
||||
outSpecular *= (specularF0 * brdf.x + brdf.y);
|
||||
|
||||
// reflection probe
|
||||
@@ -72,86 +73,55 @@ void ApplyIblSpecular(
|
||||
|
||||
outSpecular = lerp(outSpecular, probeSpecular, blendAmount);
|
||||
}
|
||||
return outSpecular;
|
||||
}
|
||||
|
||||
void ApplyIBL(Surface surface, inout LightingData lightingData)
|
||||
{
|
||||
if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent)
|
||||
#ifdef FORCE_IBL_IN_FORWARD_PASS
|
||||
bool useDiffuseIbl = true;
|
||||
bool useSpecularIbl = true;
|
||||
bool useIbl = o_enableIBL;
|
||||
#else
|
||||
bool isTransparent = (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent);
|
||||
bool useDiffuseIbl = isTransparent;
|
||||
bool useSpecularIbl = (isTransparent || o_meshUseForwardPassIBLSpecular || o_materialUseForwardPassIBLSpecular);
|
||||
bool useIbl = o_enableIBL && (useDiffuseIbl || useSpecularIbl);
|
||||
#endif
|
||||
|
||||
if(useIbl)
|
||||
{
|
||||
// transparencies currently require IBL in the forward pass
|
||||
if (o_enableIBL)
|
||||
float iblExposureFactor = pow(2.0, SceneSrg::m_iblExposure);
|
||||
|
||||
if(useDiffuseIbl)
|
||||
{
|
||||
float3 iblDiffuse = 0.0f;
|
||||
ApplyIblDiffuse(
|
||||
surface.normal,
|
||||
surface.albedo,
|
||||
lightingData.diffuseResponse,
|
||||
iblDiffuse);
|
||||
|
||||
float3 iblSpecular = 0.0f;
|
||||
ApplyIblSpecular(
|
||||
surface.position,
|
||||
surface.normal,
|
||||
surface.specularF0,
|
||||
surface.roughnessLinear,
|
||||
lightingData.dirToCamera,
|
||||
lightingData.brdf,
|
||||
iblSpecular);
|
||||
|
||||
// Adjust IBL lighting by exposure.
|
||||
float iblExposureFactor = pow(2.0, SceneSrg::m_iblExposure);
|
||||
float3 iblDiffuse = GetIblDiffuse(surface.normal, surface.albedo, lightingData.diffuseResponse);
|
||||
lightingData.diffuseLighting += (iblDiffuse * iblExposureFactor * lightingData.diffuseAmbientOcclusion);
|
||||
lightingData.specularLighting += (iblSpecular * iblExposureFactor);
|
||||
}
|
||||
}
|
||||
else if (o_meshUseForwardPassIBLSpecular || o_materialUseForwardPassIBLSpecular)
|
||||
{
|
||||
if (o_enableIBL)
|
||||
{
|
||||
float3 iblSpecular = 0.0f;
|
||||
ApplyIblSpecular(
|
||||
surface.position,
|
||||
surface.normal,
|
||||
surface.specularF0,
|
||||
surface.roughnessLinear,
|
||||
lightingData.dirToCamera,
|
||||
lightingData.brdf,
|
||||
iblSpecular);
|
||||
|
||||
if(useSpecularIbl)
|
||||
{
|
||||
float3 iblSpecular = GetIblSpecular(surface.position, surface.normal, surface.specularF0, surface.roughnessLinear, lightingData.dirToCamera, lightingData.brdf);
|
||||
iblSpecular *= lightingData.multiScatterCompensation;
|
||||
|
||||
if (o_clearCoat_feature_enabled)
|
||||
if (o_clearCoat_feature_enabled && surface.clearCoat.factor > 0.0f)
|
||||
{
|
||||
if (surface.clearCoat.factor > 0.0f)
|
||||
{
|
||||
float clearCoatNdotV = saturate(dot(surface.clearCoat.normal, lightingData.dirToCamera));
|
||||
clearCoatNdotV = max(clearCoatNdotV, 0.01f); // [GFX TODO][ATOM-4466] This is a current band-aid for specular noise at grazing angles.
|
||||
float2 clearCoatBrdf = PassSrg::m_brdfMap.Sample(PassSrg::LinearSampler, GetBRDFTexCoords(surface.clearCoat.roughness, clearCoatNdotV)).rg;
|
||||
float clearCoatNdotV = saturate(dot(surface.clearCoat.normal, lightingData.dirToCamera));
|
||||
clearCoatNdotV = max(clearCoatNdotV, 0.01f); // [GFX TODO][ATOM-4466] This is a current band-aid for specular noise at grazing angles.
|
||||
float2 clearCoatBrdf = PassSrg::m_brdfMap.Sample(PassSrg::LinearSampler, GetBRDFTexCoords(surface.clearCoat.roughness, clearCoatNdotV)).rg;
|
||||
|
||||
// clear coat uses fixed IOR = 1.5 represents polyurethane which is the most common material for gloss clear coat
|
||||
// coat layer assumed to be dielectric thus don't need multiple scattering compensation
|
||||
float3 clearCoatSpecularF0 = float3(0.04f, 0.04f, 0.04f);
|
||||
float3 clearCoatIblSpecular = 0.0f;
|
||||
// clear coat uses fixed IOR = 1.5 represents polyurethane which is the most common material for gloss clear coat
|
||||
// coat layer assumed to be dielectric thus don't need multiple scattering compensation
|
||||
float3 clearCoatSpecularF0 = float3(0.04f, 0.04f, 0.04f);
|
||||
float3 clearCoatIblSpecular = GetIblSpecular(surface.position, surface.clearCoat.normal, clearCoatSpecularF0, surface.clearCoat.roughness, lightingData.dirToCamera, clearCoatBrdf);
|
||||
|
||||
ApplyIblSpecular(
|
||||
surface.position,
|
||||
surface.clearCoat.normal,
|
||||
clearCoatSpecularF0,
|
||||
surface.clearCoat.roughness,
|
||||
lightingData.dirToCamera,
|
||||
clearCoatBrdf,
|
||||
clearCoatIblSpecular);
|
||||
|
||||
clearCoatIblSpecular *= surface.clearCoat.factor;
|
||||
clearCoatIblSpecular *= surface.clearCoat.factor;
|
||||
|
||||
// attenuate base layer energy
|
||||
float3 clearCoatResponse = FresnelSchlickWithRoughness(clearCoatNdotV, clearCoatSpecularF0, surface.clearCoat.roughness) * surface.clearCoat.factor;
|
||||
iblSpecular = iblSpecular * (1.0 - clearCoatResponse) * (1.0 - clearCoatResponse) + clearCoatIblSpecular;
|
||||
}
|
||||
// attenuate base layer energy
|
||||
float3 clearCoatResponse = FresnelSchlickWithRoughness(clearCoatNdotV, clearCoatSpecularF0, surface.clearCoat.roughness) * surface.clearCoat.factor;
|
||||
iblSpecular = iblSpecular * (1.0 - clearCoatResponse) * (1.0 - clearCoatResponse) + clearCoatIblSpecular;
|
||||
}
|
||||
|
||||
|
||||
float iblExposureFactor = pow(2.0f, SceneSrg::m_iblExposure);
|
||||
lightingData.specularLighting += (iblSpecular * iblExposureFactor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
// This file translates quality option macros like QUALITY_LOW_END to their relevant settings
|
||||
|
||||
#ifdef QUALITY_LOW_END
|
||||
|
||||
// Unifies the forward output into a single lighting buffer instead of splitting it into a GBuffer
|
||||
#define UNIFIED_FORWARD_OUTPUT 1
|
||||
|
||||
// Forces IBL lighting to be executed in the forward pass instead of subsequent refleciton passes
|
||||
#define FORCE_IBL_IN_FORWARD_PASS 1
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// --- Static Options Available ---
|
||||
// SKYBOX_TWO_OUTPUTS - Skybox renders to two rendertargets instead of one (SkyBox_TwoOutputs.pass writes to specular and reflection targets)
|
||||
|
||||
#include <Atom/Features/ColorManagement/TransformColor.azsli>
|
||||
#include <Atom/Features/PostProcessing/FullscreenVertexUtil.azsli>
|
||||
#include <Atom/Features/MatrixUtility.azsli>
|
||||
@@ -102,7 +105,9 @@ float3 GetCubemapCoords(float3 original)
|
||||
struct PSOutput
|
||||
{
|
||||
float4 m_specular : SV_Target0;
|
||||
#ifdef SKYBOX_TWO_OUTPUTS
|
||||
float4 m_reflection : SV_Target1;
|
||||
#endif
|
||||
};
|
||||
|
||||
PSOutput MainPS(VSOutput input)
|
||||
@@ -163,6 +168,8 @@ PSOutput MainPS(VSOutput input)
|
||||
|
||||
PSOutput OUT;
|
||||
OUT.m_specular = float4(color, 1.0);
|
||||
#ifdef SKYBOX_TWO_OUTPUTS
|
||||
OUT.m_reflection = float4(color, 1.0);
|
||||
#endif
|
||||
return OUT;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// NOTE: This file is a temporary workaround until .shader files can #define macros for their .azsl files
|
||||
|
||||
#define SKYBOX_TWO_OUTPUTS
|
||||
|
||||
#include "SkyBox.azsl"
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"Source" : "SkyBox_TwoOutputs",
|
||||
|
||||
"DepthStencilState" : {
|
||||
"Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" }
|
||||
},
|
||||
|
||||
"ProgramSettings":
|
||||
{
|
||||
"EntryPoints":
|
||||
[
|
||||
{
|
||||
"name": "MainVS",
|
||||
"type": "Vertex"
|
||||
},
|
||||
{
|
||||
"name": "MainPS",
|
||||
"type": "Fragment"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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...
|
||||
@@ -38,6 +38,7 @@ set(FILES
|
||||
Materials/Types/StandardMultilayerPBR_ForwardPass_EDS.shader
|
||||
Materials/Types/StandardMultilayerPBR_Parallax.lua
|
||||
Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua
|
||||
Materials/Types/StandardMultilayerPBR_ShaderEnable.lua
|
||||
Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl
|
||||
Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.shader
|
||||
Materials/Types/StandardPBR.materialtype
|
||||
@@ -52,6 +53,9 @@ set(FILES
|
||||
Materials/Types/StandardPBR_ForwardPass_EDS.shader
|
||||
Materials/Types/StandardPBR_HandleOpacityDoubleSided.lua
|
||||
Materials/Types/StandardPBR_HandleOpacityMode.lua
|
||||
Materials/Types/StandardPBR_LowEndForward.azsl
|
||||
Materials/Types/StandardPBR_LowEndForward.shader
|
||||
Materials/Types/StandardPBR_LowEndForward_EDS.shader
|
||||
Materials/Types/StandardPBR_ParallaxState.lua
|
||||
Materials/Types/StandardPBR_Roughness.lua
|
||||
Materials/Types/StandardPBR_ShaderEnable.lua
|
||||
@@ -116,6 +120,7 @@ set(FILES
|
||||
Passes/DiffuseProbeGridBlendDistance.pass
|
||||
Passes/DiffuseProbeGridBlendIrradiance.pass
|
||||
Passes/DiffuseProbeGridBorderUpdate.pass
|
||||
Passes/DiffuseProbeGridClassification.pass
|
||||
Passes/DiffuseProbeGridDownsample.pass
|
||||
Passes/DiffuseProbeGridRayTracing.pass
|
||||
Passes/DiffuseProbeGridRelocation.pass
|
||||
@@ -144,6 +149,7 @@ set(FILES
|
||||
Passes/FullscreenCopy.pass
|
||||
Passes/FullscreenOutputOnly.pass
|
||||
Passes/ImGui.pass
|
||||
Passes/LightAdaptationParent.pass
|
||||
Passes/LightCulling.pass
|
||||
Passes/LightCullingHeatmap.pass
|
||||
Passes/LightCullingParent.pass
|
||||
@@ -152,6 +158,8 @@ set(FILES
|
||||
Passes/LightCullingTilePrepareMSAA.pass
|
||||
Passes/LookModificationComposite.pass
|
||||
Passes/LookModificationTransform.pass
|
||||
Passes/LowEndForward.pass
|
||||
Passes/LowEndPipeline.pass
|
||||
Passes/LuminanceHeatmap.pass
|
||||
Passes/LuminanceHistogramGenerator.pass
|
||||
Passes/MainPipeline.pass
|
||||
@@ -179,13 +187,16 @@ set(FILES
|
||||
Passes/ReflectionScreenSpace.pass
|
||||
Passes/ReflectionScreenSpaceBlur.pass
|
||||
Passes/ReflectionScreenSpaceBlurHorizontal.pass
|
||||
Passes/ReflectionScreenSpaceBlurMobile.pass
|
||||
Passes/ReflectionScreenSpaceBlurVertical.pass
|
||||
Passes/ReflectionScreenSpaceComposite.pass
|
||||
Passes/ReflectionScreenSpaceMobile.pass
|
||||
Passes/ReflectionScreenSpaceTrace.pass
|
||||
Passes/Reflections_nomsaa.pass
|
||||
Passes/ShadowParent.pass
|
||||
Passes/Skinning.pass
|
||||
Passes/SkyBox.pass
|
||||
Passes/SkyBox_TwoOutputs.pass
|
||||
Passes/SMAA1xApplyLinearHDRColor.pass
|
||||
Passes/SMAA1xApplyPerceptualColor.pass
|
||||
Passes/SMAABlendingWeightCalculation.pass
|
||||
@@ -205,6 +216,7 @@ set(FILES
|
||||
ShaderLib/Atom/Features/IndirectRendering.azsli
|
||||
ShaderLib/Atom/Features/MatrixUtility.azsli
|
||||
ShaderLib/Atom/Features/ParallaxMapping.azsli
|
||||
ShaderLib/Atom/Features/ShaderQualityOptions.azsli
|
||||
ShaderLib/Atom/Features/SphericalHarmonicsUtility.azsli
|
||||
ShaderLib/Atom/Features/SrgSemantics.azsli
|
||||
ShaderLib/Atom/Features/ColorManagement/TransformColor.azsli
|
||||
@@ -272,6 +284,7 @@ set(FILES
|
||||
ShaderLib/Atom/Features/PostProcessing/GlyphData.azsli
|
||||
ShaderLib/Atom/Features/PostProcessing/GlyphRender.azsli
|
||||
ShaderLib/Atom/Features/PostProcessing/PostProcessUtil.azsli
|
||||
ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli
|
||||
ShaderLib/Atom/Features/ScreenSpace/ScreenSpaceUtil.azsli
|
||||
ShaderLib/Atom/Features/Shadow/BicubicPcfFilters.azsli
|
||||
ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli
|
||||
@@ -471,4 +484,6 @@ set(FILES
|
||||
Shaders/SkinnedMesh/LinearSkinningPassSRG.azsli
|
||||
Shaders/SkyBox/SkyBox.azsl
|
||||
Shaders/SkyBox/SkyBox.shader
|
||||
Shaders/SkyBox/SkyBox_TwoOutputs.azsl
|
||||
Shaders/SkyBox/SkyBox_TwoOutputs.shader
|
||||
)
|
||||
|
||||
@@ -148,6 +148,8 @@ namespace AZ
|
||||
|
||||
Data::Instance<RPI::Model> GetModel(const MeshHandle& meshHandle) const override;
|
||||
Data::Asset<RPI::ModelAsset> GetModelAsset(const MeshHandle& meshHandle) const override;
|
||||
Data::Instance<RPI::ShaderResourceGroup> GetObjectSrg(const MeshHandle& meshHandle) const override;
|
||||
void QueueObjectSrgForCompile(const MeshHandle& meshHandle) const override;
|
||||
void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const Data::Instance<RPI::Material>& material) override;
|
||||
void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const MaterialAssignmentMap& materials) override;
|
||||
const MaterialAssignmentMap& GetMaterialAssignmentMap(const MeshHandle& meshHandle) const override;
|
||||
|
||||
+8
@@ -61,6 +61,14 @@ namespace AZ
|
||||
virtual Data::Instance<RPI::Model> GetModel(const MeshHandle& meshHandle) const = 0;
|
||||
//! Gets the underlying RPI::ModelAsset for a meshHandle.
|
||||
virtual Data::Asset<RPI::ModelAsset> GetModelAsset(const MeshHandle& meshHandle) const = 0;
|
||||
//! Gets the ObjectSrg for a meshHandle.
|
||||
//! Updating the ObjectSrg should be followed by a call to QueueObjectSrgForCompile,
|
||||
//! instead of compiling the srg directly. This way, if the srg has already been queued for compile,
|
||||
//! it will not be queued twice in the same frame. The ObjectSrg should not be updated during
|
||||
//! Simulate, or it will create a race between updating the data and the call to Compile
|
||||
virtual Data::Instance<RPI::ShaderResourceGroup> GetObjectSrg(const MeshHandle& meshHandle) const = 0;
|
||||
//! Queues the object srg for compile.
|
||||
virtual void QueueObjectSrgForCompile(const MeshHandle& meshHandle) const = 0;
|
||||
//! Sets the MaterialAssignmentMap for a meshHandle, using just a single material for the DefaultMaterialAssignmentId.
|
||||
//! Note if there is already a material assignment map, this will replace the entire map with just a single material.
|
||||
virtual void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const Data::Instance<RPI::Material>& material) = 0;
|
||||
|
||||
+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
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace UnitTest
|
||||
MOCK_METHOD1(CloneMesh, MeshHandle(const MeshHandle&));
|
||||
MOCK_CONST_METHOD1(GetModel, AZStd::intrusive_ptr<AZ::RPI::Model>(const MeshHandle&));
|
||||
MOCK_CONST_METHOD1(GetModelAsset, AZ::Data::Asset<AZ::RPI::ModelAsset>(const MeshHandle&));
|
||||
MOCK_CONST_METHOD1(GetObjectSrg, AZStd::intrusive_ptr<AZ::RPI::ShaderResourceGroup>(const MeshHandle&));
|
||||
MOCK_CONST_METHOD1(QueueObjectSrgForCompile, void(const MeshHandle&));
|
||||
MOCK_CONST_METHOD1(GetMaterialAssignmentMap, const AZ::Render::MaterialAssignmentMap&(const MeshHandle&));
|
||||
MOCK_METHOD2(ConnectModelChangeEventHandler, void(const MeshHandle&, ModelChangedEvent::Handler&));
|
||||
MOCK_METHOD3(SetTransform, void(const MeshHandle&, const AZ::Transform&, const AZ::Vector3&));
|
||||
|
||||
@@ -274,6 +274,10 @@ namespace AZ
|
||||
passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurPass"), &Render::ReflectionScreenSpaceBlurPass::Create);
|
||||
passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurChildPass"), &Render::ReflectionScreenSpaceBlurChildPass::Create);
|
||||
passSystem->AddPassCreator(Name("ReflectionCopyFrameBufferPass"), &Render::ReflectionCopyFrameBufferPass::Create);
|
||||
|
||||
// setup handler for load pass template mappings
|
||||
m_loadTemplatesHandler = RPI::PassSystemInterface::OnReadyLoadTemplatesEvent::Handler([this]() { this->LoadPassTemplateMappings(); });
|
||||
RPI::PassSystemInterface::Get()->ConnectEvent(m_loadTemplatesHandler);
|
||||
}
|
||||
|
||||
void CommonSystemComponent::Deactivate()
|
||||
@@ -292,5 +296,12 @@ namespace AZ
|
||||
AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor<TransformServiceFeatureProcessor>();
|
||||
AZ::RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor<AuxGeomFeatureProcessor>();
|
||||
}
|
||||
|
||||
void CommonSystemComponent::LoadPassTemplateMappings()
|
||||
{
|
||||
const char* passTemplatesFile = "Passes/PassTemplates.azasset";
|
||||
RPI::PassSystemInterface::Get()->LoadPassTemplateMappings(passTemplatesFile);
|
||||
}
|
||||
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <Atom_Feature_Traits_Platform.h>
|
||||
|
||||
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
|
||||
|
||||
#if AZ_TRAIT_LUXCORE_SUPPORTED
|
||||
#include "LuxCore/LuxCoreRenderer.h"
|
||||
#endif
|
||||
@@ -41,6 +43,11 @@ namespace AZ
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
|
||||
// Load pass template mappings for this gem
|
||||
void LoadPassTemplateMappings();
|
||||
|
||||
RPI::PassSystemInterface::OnReadyLoadTemplatesEvent::Handler m_loadTemplatesHandler;
|
||||
|
||||
#if AZ_TRAIT_LUXCORE_SUPPORTED
|
||||
// LuxCore
|
||||
LuxCoreRenderer m_luxCore;
|
||||
|
||||
@@ -134,7 +134,14 @@ namespace AZ
|
||||
{
|
||||
m_decalData.GetData(decal.GetIndex()) = m_decalData.GetData(sourceDecal.GetIndex());
|
||||
const auto materialAsset = GetMaterialUsedByDecal(sourceDecal);
|
||||
m_materialToTextureArrayLookupTable.at(materialAsset).m_useCount++;
|
||||
if (materialAsset.IsValid())
|
||||
{
|
||||
m_materialToTextureArrayLookupTable.at(materialAsset).m_useCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("DecalTextureArrayFeatureProcessor", false, "CloneDecal called on a decal with no material set.");
|
||||
}
|
||||
m_deviceBufferNeedsUpdate = true;
|
||||
}
|
||||
return decal;
|
||||
|
||||
+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;
|
||||
|
||||
@@ -231,6 +231,19 @@ namespace AZ
|
||||
return {};
|
||||
}
|
||||
|
||||
Data::Instance<RPI::ShaderResourceGroup> MeshFeatureProcessor::GetObjectSrg(const MeshHandle& meshHandle) const
|
||||
{
|
||||
return meshHandle.IsValid() ? meshHandle->m_shaderResourceGroup : nullptr;
|
||||
}
|
||||
|
||||
void MeshFeatureProcessor::QueueObjectSrgForCompile(const MeshHandle& meshHandle) const
|
||||
{
|
||||
if (meshHandle.IsValid())
|
||||
{
|
||||
meshHandle->m_objectSrgNeedsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MeshFeatureProcessor::SetMaterialAssignmentMap(const MeshHandle& meshHandle, const Data::Instance<RPI::Material>& material)
|
||||
{
|
||||
Render::MaterialAssignmentMap materials;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
|
||||
#include <MorphTargets/MorphTargetComputePass.h>
|
||||
#include <SkinnedMesh/SkinnedMeshFeatureProcessor.h>
|
||||
#include <Atom/Feature/SkinnedMesh/SkinnedMeshOutputStreamManagerInterface.h>
|
||||
|
||||
#include <Atom/RPI.Public/Shader/Shader.h>
|
||||
@@ -38,6 +39,11 @@ namespace AZ
|
||||
return m_shader;
|
||||
}
|
||||
|
||||
void MorphTargetComputePass::SetFeatureProcessor(SkinnedMeshFeatureProcessor* skinnedMeshFeatureProcessor)
|
||||
{
|
||||
m_skinnedMeshFeatureProcessor = skinnedMeshFeatureProcessor;
|
||||
}
|
||||
|
||||
void MorphTargetComputePass::BuildAttachmentsInternal()
|
||||
{
|
||||
// The same buffer that skinning writes to is used to manage the computed vertex deltas that are passed from the
|
||||
@@ -45,30 +51,16 @@ namespace AZ
|
||||
AttachBufferToSlot(Name{ "MorphTargetDeltaOutput" }, SkinnedMeshOutputStreamManagerInterface::Get()->GetBuffer());
|
||||
}
|
||||
|
||||
void MorphTargetComputePass::AddDispatchItem(const RHI::DispatchItem* dispatchItem)
|
||||
{
|
||||
AZ_Assert(dispatchItem != nullptr, "invalid dispatchItem");
|
||||
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
|
||||
//using an unordered_set here to prevent redundantly adding the same dispatchItem to the submission queue
|
||||
//(i.e. if the same morph target exists in multiple views, it can call AddDispatchItem multiple times with the same item)
|
||||
m_dispatches.insert(dispatchItem);
|
||||
}
|
||||
|
||||
void MorphTargetComputePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
|
||||
{
|
||||
RHI::CommandList* commandList = context.GetCommandList();
|
||||
|
||||
SetSrgsForDispatch(commandList);
|
||||
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
|
||||
for (const RHI::DispatchItem* dispatchItem : m_dispatches)
|
||||
if (m_skinnedMeshFeatureProcessor)
|
||||
{
|
||||
commandList->Submit(*dispatchItem);
|
||||
}
|
||||
RHI::CommandList* commandList = context.GetCommandList();
|
||||
|
||||
// Clear the dispatch items. They will need to be re-populated next frame
|
||||
m_dispatches.clear();
|
||||
SetSrgsForDispatch(commandList);
|
||||
|
||||
m_skinnedMeshFeatureProcessor->SubmitMorphTargetDispatchItems(commandList);
|
||||
}
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -18,6 +18,8 @@ namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
class SkinnedMeshFeatureProcessor;
|
||||
|
||||
//! The morph target compute pass submits dispatch items for morph targets. The dispatch items are cleared every frame, so it needs to be re-populated.
|
||||
class MorphTargetComputePass
|
||||
: public RPI::ComputePass
|
||||
@@ -31,16 +33,14 @@ namespace AZ
|
||||
|
||||
static RPI::Ptr<MorphTargetComputePass> Create(const RPI::PassDescriptor& descriptor);
|
||||
|
||||
//! Thread-safe function for adding a dispatch item to the current frame.
|
||||
void AddDispatchItem(const RHI::DispatchItem* dispatchItem);
|
||||
Data::Instance<RPI::Shader> GetShader() const;
|
||||
|
||||
void SetFeatureProcessor(SkinnedMeshFeatureProcessor* m_skinnedMeshFeatureProcessor);
|
||||
private:
|
||||
void BuildAttachmentsInternal() override;
|
||||
void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
|
||||
|
||||
AZStd::mutex m_mutex;
|
||||
AZStd::unordered_set<const RHI::DispatchItem*> m_dispatches;
|
||||
SkinnedMeshFeatureProcessor* m_skinnedMeshFeatureProcessor = nullptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
#include <MorphTargets/MorphTargetDispatchItem.h>
|
||||
#include <MorphTargets/MorphTargetComputePass.h>
|
||||
#include <SkinnedMesh/SkinnedMeshFeatureProcessor.h>
|
||||
|
||||
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
|
||||
#include <Atom/RPI.Public/Shader/Shader.h>
|
||||
@@ -30,7 +30,7 @@ namespace AZ
|
||||
MorphTargetDispatchItem::MorphTargetDispatchItem(
|
||||
const AZStd::intrusive_ptr<MorphTargetInputBuffers> inputBuffers,
|
||||
const MorphTargetMetaData& morphTargetMetaData,
|
||||
RPI::Ptr<MorphTargetComputePass> morphTargetComputePass,
|
||||
SkinnedMeshFeatureProcessor* skinnedMeshFeatureProcessor,
|
||||
MorphTargetInstanceMetaData morphInstanceMetaData,
|
||||
float morphDeltaIntegerEncoding)
|
||||
: m_inputBuffers(inputBuffers)
|
||||
@@ -38,7 +38,7 @@ namespace AZ
|
||||
, m_morphInstanceMetaData(morphInstanceMetaData)
|
||||
, m_accumulatedDeltaIntegerEncoding(morphDeltaIntegerEncoding)
|
||||
{
|
||||
m_morphTargetShader = morphTargetComputePass->GetShader();
|
||||
m_morphTargetShader = skinnedMeshFeatureProcessor->GetMorphTargetShader();
|
||||
RPI::ShaderReloadNotificationBus::Handler::BusConnect(m_morphTargetShader->GetAssetId());
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace AZ
|
||||
|
||||
namespace Render
|
||||
{
|
||||
class MorphTargetComputePass;
|
||||
class SkinnedMeshFeatureProcessor;
|
||||
|
||||
//! Holds and manages an RHI DispatchItem for a specific morph target, and the resources that are needed to build and maintain it.
|
||||
class MorphTargetDispatchItem
|
||||
@@ -51,7 +51,7 @@ namespace AZ
|
||||
explicit MorphTargetDispatchItem(
|
||||
const AZStd::intrusive_ptr<MorphTargetInputBuffers> inputBuffers,
|
||||
const MorphTargetMetaData& morphTargetMetaData,
|
||||
RPI::Ptr<MorphTargetComputePass> morphTargetComputePass,
|
||||
SkinnedMeshFeatureProcessor* skinnedMeshFeatureProcessor,
|
||||
MorphTargetInstanceMetaData morphInstanceMetaData,
|
||||
float accumulatedDeltaRange
|
||||
);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
|
||||
#include <SkinnedMesh/SkinnedMeshComputePass.h>
|
||||
#include <SkinnedMesh/SkinnedMeshFeatureProcessor.h>
|
||||
#include <Atom/Feature/SkinnedMesh/SkinnedMeshOutputStreamManagerInterface.h>
|
||||
|
||||
#include <Atom/RPI.Public/Shader/Shader.h>
|
||||
@@ -22,11 +23,9 @@ namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
|
||||
SkinnedMeshComputePass::SkinnedMeshComputePass(const RPI::PassDescriptor& descriptor)
|
||||
: RPI::ComputePass(descriptor)
|
||||
{
|
||||
m_cachedShaderOptions.SetShader(m_shader);
|
||||
}
|
||||
|
||||
RPI::Ptr<SkinnedMeshComputePass> SkinnedMeshComputePass::Create(const RPI::PassDescriptor& descriptor)
|
||||
@@ -40,42 +39,30 @@ namespace AZ
|
||||
return m_shader;
|
||||
}
|
||||
|
||||
RPI::ShaderOptionGroup SkinnedMeshComputePass::CreateShaderOptionGroup(const SkinnedMeshShaderOptions shaderOptions, SkinnedMeshShaderOptionNotificationBus::Handler& shaderReinitializedHandler)
|
||||
void SkinnedMeshComputePass::SetFeatureProcessor(SkinnedMeshFeatureProcessor* skinnedMeshFeatureProcessor)
|
||||
{
|
||||
m_cachedShaderOptions.ConnectToShaderReinitializedEvent(shaderReinitializedHandler);
|
||||
return m_cachedShaderOptions.CreateShaderOptionGroup(shaderOptions);
|
||||
}
|
||||
|
||||
void SkinnedMeshComputePass::AddDispatchItem(const RHI::DispatchItem* dispatchItem)
|
||||
{
|
||||
AZ_Assert(dispatchItem != nullptr, "invalid dispatchItem");
|
||||
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
|
||||
//using an unordered_set here to prevent redundantly adding the same dispatchItem to the submission queue
|
||||
//(i.e. if the same skinnedMesh exists in multiple views, it can call AddDispatchItem multiple times with the same item)
|
||||
m_dispatches.insert(dispatchItem);
|
||||
m_skinnedMeshFeatureProcessor = skinnedMeshFeatureProcessor;
|
||||
}
|
||||
|
||||
void SkinnedMeshComputePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
|
||||
{
|
||||
RHI::CommandList* commandList = context.GetCommandList();
|
||||
|
||||
SetSrgsForDispatch(commandList);
|
||||
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
|
||||
for (const RHI::DispatchItem* dispatchItem : m_dispatches)
|
||||
if (m_skinnedMeshFeatureProcessor)
|
||||
{
|
||||
commandList->Submit(*dispatchItem);
|
||||
}
|
||||
RHI::CommandList* commandList = context.GetCommandList();
|
||||
|
||||
// Clear the dispatch items. They will need to be re-populated next frame
|
||||
m_dispatches.clear();
|
||||
SetSrgsForDispatch(commandList);
|
||||
|
||||
m_skinnedMeshFeatureProcessor->SubmitSkinningDispatchItems(commandList);
|
||||
}
|
||||
}
|
||||
|
||||
void SkinnedMeshComputePass::OnShaderReinitialized(const RPI::Shader& shader)
|
||||
{
|
||||
ComputePass::OnShaderReinitialized(shader);
|
||||
m_cachedShaderOptions.SetShader(m_shader);
|
||||
if (m_skinnedMeshFeatureProcessor)
|
||||
{
|
||||
m_skinnedMeshFeatureProcessor->OnSkinningShaderReinitialized(m_shader);
|
||||
}
|
||||
}
|
||||
|
||||
void SkinnedMeshComputePass::OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId&, RPI::ShaderVariantStableId)
|
||||
|
||||
@@ -20,6 +20,8 @@ namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
class SkinnedMeshFeatureProcessor;
|
||||
|
||||
//! The skinned mesh compute pass submits dispatch items for skinning. The dispatch items are cleared every frame, so it needs to be re-populated.
|
||||
class SkinnedMeshComputePass
|
||||
: public RPI::ComputePass
|
||||
@@ -33,10 +35,9 @@ namespace AZ
|
||||
|
||||
static RPI::Ptr<SkinnedMeshComputePass> Create(const RPI::PassDescriptor& descriptor);
|
||||
|
||||
//! Thread-safe function for adding a dispatch item to the current frame.
|
||||
void AddDispatchItem(const RHI::DispatchItem* dispatchItem);
|
||||
Data::Instance<RPI::Shader> GetShader() const;
|
||||
RPI::ShaderOptionGroup CreateShaderOptionGroup(const SkinnedMeshShaderOptions shaderOptions, SkinnedMeshShaderOptionNotificationBus::Handler& shaderReinitializedHandler);
|
||||
|
||||
void SetFeatureProcessor(SkinnedMeshFeatureProcessor* m_skinnedMeshFeatureProcessor);
|
||||
|
||||
private:
|
||||
void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
|
||||
@@ -45,9 +46,7 @@ namespace AZ
|
||||
void OnShaderReinitialized(const RPI::Shader& shader) override;
|
||||
void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override;
|
||||
|
||||
AZStd::mutex m_mutex;
|
||||
AZStd::unordered_set<const RHI::DispatchItem*> m_dispatches;
|
||||
CachedSkinnedMeshShaderOptions m_cachedShaderOptions;
|
||||
SkinnedMeshFeatureProcessor* m_skinnedMeshFeatureProcessor = nullptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#include <SkinnedMesh/SkinnedMeshDispatchItem.h>
|
||||
#include <SkinnedMesh/SkinnedMeshOutputStreamManager.h>
|
||||
#include <SkinnedMesh/SkinnedMeshComputePass.h>
|
||||
#include <SkinnedMesh/SkinnedMeshFeatureProcessor.h>
|
||||
|
||||
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
|
||||
#include <Atom/RPI.Public/Shader/Shader.h>
|
||||
@@ -34,7 +34,7 @@ namespace AZ
|
||||
size_t lodIndex,
|
||||
Data::Instance<RPI::Buffer> boneTransforms,
|
||||
const SkinnedMeshShaderOptions& shaderOptions,
|
||||
RPI::Ptr<SkinnedMeshComputePass> skinnedMeshComputePass,
|
||||
SkinnedMeshFeatureProcessor* skinnedMeshFeatureProcessor,
|
||||
MorphTargetInstanceMetaData morphTargetInstanceMetaData,
|
||||
float morphTargetDeltaIntegerEncoding)
|
||||
: m_inputBuffers(inputBuffers)
|
||||
@@ -45,7 +45,7 @@ namespace AZ
|
||||
, m_morphTargetInstanceMetaData(morphTargetInstanceMetaData)
|
||||
, m_morphTargetDeltaIntegerEncoding(morphTargetDeltaIntegerEncoding)
|
||||
{
|
||||
m_skinningShader = skinnedMeshComputePass->GetShader();
|
||||
m_skinningShader = skinnedMeshFeatureProcessor->GetSkinningShader();
|
||||
|
||||
// Shader options are generally set per-skinned mesh instance, but morph targets may only exist on some lods. Override the option for applying morph targets here
|
||||
if (m_morphTargetInstanceMetaData.m_accumulatedPositionDeltaOffsetInBytes != MorphTargetConstants::s_invalidDeltaOffset)
|
||||
@@ -58,7 +58,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
// CreateShaderOptionGroup will also connect to the SkinnedMeshShaderOptionNotificationBus
|
||||
m_shaderOptionGroup = skinnedMeshComputePass->CreateShaderOptionGroup(m_shaderOptions, *this);
|
||||
m_shaderOptionGroup = skinnedMeshFeatureProcessor->CreateSkinningShaderOptionGroup(m_shaderOptions, *this);
|
||||
}
|
||||
|
||||
SkinnedMeshDispatchItem::~SkinnedMeshDispatchItem()
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace AZ
|
||||
|
||||
namespace Render
|
||||
{
|
||||
class SkinnedMeshComputePass;
|
||||
class SkinnedMeshFeatureProcessor;
|
||||
|
||||
//! Holds and manages an RHI DispatchItem for a specific skinned mesh, and the resources that are needed to build and maintain it.
|
||||
class SkinnedMeshDispatchItem
|
||||
@@ -55,7 +55,7 @@ namespace AZ
|
||||
size_t lodIndex,
|
||||
Data::Instance<RPI::Buffer> skinningMatrices,
|
||||
const SkinnedMeshShaderOptions& shaderOptions,
|
||||
RPI::Ptr<SkinnedMeshComputePass> skinnedMeshComputePass,
|
||||
SkinnedMeshFeatureProcessor* skinnedMeshFeatureProcessor,
|
||||
MorphTargetInstanceMetaData morphTargetInstanceMetaData,
|
||||
float morphTargetDeltaIntegerEncoding
|
||||
);
|
||||
|
||||
@@ -24,8 +24,10 @@
|
||||
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
|
||||
#include <Atom/RPI.Public/RPIUtils.h>
|
||||
#include <Atom/RPI.Public/Shader/Shader.h>
|
||||
#include <Atom/RPI.Public/RenderPipeline.h>
|
||||
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RHI/CommandList.h>
|
||||
|
||||
#include <AzCore/Debug/EventTrace.h>
|
||||
#include <AzCore/Jobs/JobCompletion.h>
|
||||
@@ -69,26 +71,11 @@ namespace AZ
|
||||
|
||||
}
|
||||
|
||||
void SkinnedMeshFeatureProcessor::Simulate(const FeatureProcessor::SimulatePacket& packet)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
|
||||
AZ_ATOM_PROFILE_FUNCTION("SkinnedMesh", "SkinnedMeshFeatureProcessor: Simulate");
|
||||
AZ_UNUSED(packet);
|
||||
|
||||
SkinnedMeshFeatureProcessorNotificationBus::Broadcast(&SkinnedMeshFeatureProcessorNotificationBus::Events::OnUpdateSkinningMatrices);
|
||||
|
||||
}
|
||||
|
||||
void SkinnedMeshFeatureProcessor::Render(const FeatureProcessor::RenderPacket& packet)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
|
||||
AZ_ATOM_PROFILE_FUNCTION("SkinnedMesh", "SkinnedMeshFeatureProcessor: Render");
|
||||
|
||||
if (!m_skinningPass)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0 //[GFX_TODO][ATOM-13564] Temporarily disable skinning culling until we figure out how to hook up visibility & lod selection with skinning:
|
||||
//Setup the culling workgroup (it will be re-used for each view)
|
||||
{
|
||||
@@ -132,7 +119,7 @@ namespace AZ
|
||||
//Dispatch the workgroup to each view
|
||||
for (const RPI::ViewPtr& viewPtr : packet.m_views)
|
||||
{
|
||||
Job *processWorkgroupJob = AZ::CreateJobFunction(
|
||||
Job* processWorkgroupJob = AZ::CreateJobFunction(
|
||||
[this, cullingSystem, viewPtr](AZ::Job& thisJob)
|
||||
{
|
||||
AZ_PROFILE_SCOPE_DYNAMIC(Debug::ProfileCategory::AzRender, "skinningMeshFP processWorkgroupJob - View: %s", viewPtr->GetName().GetCStr());
|
||||
@@ -167,7 +154,16 @@ namespace AZ
|
||||
float maxScreenPercentage(lod.m_range.m_max);
|
||||
if (approxScreenPercentage >= minScreenPercentage && approxScreenPercentage <= maxScreenPercentage)
|
||||
{
|
||||
m_skinningPass->AddDispatchItem(&renderProxy->m_dispatchItemsByLod[lodIndex]->GetRHIDispatchItem());
|
||||
AZStd::lock_guard lock(m_dispatchItemMutex);
|
||||
m_skinningDispatches.insert(&renderProxy->m_dispatchItemsByLod[lodIndex]->GetRHIDispatchItem());
|
||||
for (size_t morphTargetIndex = 0; morphTargetIndex < renderProxy->m_morphTargetDispatchItemsByLod[lodIndex].size(); morphTargetIndex++)
|
||||
{
|
||||
const MorphTargetDispatchItem* dispatchItem = renderProxy->m_morphTargetDispatchItemsByLod[lodIndex][morphTargetIndex].get();
|
||||
if (dispatchItem && dispatchItem->GetWeight() > AZ::Constants::FloatEpsilon)
|
||||
{
|
||||
m_morphTargetDispatches.insert(&dispatchItem->GetRHIDispatchItem());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -232,13 +228,14 @@ namespace AZ
|
||||
//Note that this supports overlapping lod ranges (to support cross-fading lods, for example)
|
||||
if (approxScreenPercentage >= lod.m_screenCoverageMin && approxScreenPercentage <= lod.m_screenCoverageMax)
|
||||
{
|
||||
m_skinningPass->AddDispatchItem(&renderProxy.m_dispatchItemsByLod[lodIndex]->GetRHIDispatchItem());
|
||||
AZStd::lock_guard lock(m_dispatchItemMutex);
|
||||
m_skinningDispatches.insert(&renderProxy.m_dispatchItemsByLod[lodIndex]->GetRHIDispatchItem());
|
||||
for (size_t morphTargetIndex = 0; morphTargetIndex < renderProxy.m_morphTargetDispatchItemsByLod[lodIndex].size(); morphTargetIndex++)
|
||||
{
|
||||
const MorphTargetDispatchItem* dispatchItem = renderProxy.m_morphTargetDispatchItemsByLod[lodIndex][morphTargetIndex].get();
|
||||
if (dispatchItem && dispatchItem->GetWeight() > AZ::Constants::FloatEpsilon)
|
||||
{
|
||||
m_morphTargetPass->AddDispatchItem(&dispatchItem->GetRHIDispatchItem());
|
||||
m_morphTargetDispatches.insert(&dispatchItem->GetRHIDispatchItem());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,29 +245,32 @@ namespace AZ
|
||||
#endif
|
||||
}
|
||||
|
||||
void SkinnedMeshFeatureProcessor::OnRenderPipelineAdded([[maybe_unused]] RPI::RenderPipelinePtr pipeline)
|
||||
void SkinnedMeshFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline)
|
||||
{
|
||||
InitSkinningAndMorphPass();
|
||||
InitSkinningAndMorphPass(pipeline->GetRootPass());
|
||||
}
|
||||
|
||||
void SkinnedMeshFeatureProcessor::OnRenderPipelineRemoved([[maybe_unused]] RPI::RenderPipeline* pipeline)
|
||||
void SkinnedMeshFeatureProcessor::OnRenderPipelinePassesChanged(RPI::RenderPipeline* renderPipeline)
|
||||
{
|
||||
InitSkinningAndMorphPass();
|
||||
}
|
||||
|
||||
void SkinnedMeshFeatureProcessor::OnRenderPipelinePassesChanged([[maybe_unused]] RPI::RenderPipeline* renderPipeline)
|
||||
{
|
||||
InitSkinningAndMorphPass();
|
||||
InitSkinningAndMorphPass(renderPipeline->GetRootPass());
|
||||
}
|
||||
|
||||
void SkinnedMeshFeatureProcessor::OnBeginPrepareRender()
|
||||
{
|
||||
m_renderProxiesChecker.soft_lock();
|
||||
|
||||
SkinnedMeshFeatureProcessorNotificationBus::Broadcast(&SkinnedMeshFeatureProcessorNotificationBus::Events::OnUpdateSkinningMatrices);
|
||||
}
|
||||
|
||||
void SkinnedMeshFeatureProcessor::OnEndPrepareRender()
|
||||
void SkinnedMeshFeatureProcessor::OnRenderEnd()
|
||||
{
|
||||
m_renderProxiesChecker.soft_unlock();
|
||||
|
||||
// Clear any dispatch items that were added but never submitted
|
||||
// in case there were no passes that submitted this frame
|
||||
// because they execute at a lower frequency
|
||||
m_skinningDispatches.clear();
|
||||
m_morphTargetDispatches.clear();
|
||||
}
|
||||
|
||||
SkinnedMeshRenderProxyHandle SkinnedMeshFeatureProcessor::AcquireRenderProxy(const SkinnedMeshRenderProxyDesc& desc)
|
||||
@@ -295,61 +295,73 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
void SkinnedMeshFeatureProcessor::InitSkinningAndMorphPass()
|
||||
void SkinnedMeshFeatureProcessor::InitSkinningAndMorphPass(const RPI::Ptr<RPI::ParentPass> pipelineRootPass)
|
||||
{
|
||||
m_skinningPass = nullptr; //reset it to null, just in case it fails to load the assets properly
|
||||
m_morphTargetPass = nullptr;
|
||||
|
||||
RPI::PassSystemInterface* passSystem = RPI::PassSystemInterface::Get();
|
||||
if (passSystem->HasPassesForTemplateName(AZ::Name{ "SkinningPassTemplate" }))
|
||||
RPI::Ptr<RPI::Pass> skinningPass = pipelineRootPass->FindPassByNameRecursive(AZ::Name{ "SkinningPass" });
|
||||
if (skinningPass)
|
||||
{
|
||||
auto& skinningPasses = passSystem->GetPassesForTemplateName(AZ::Name{ "SkinningPassTemplate" });
|
||||
SkinnedMeshComputePass* skinnedMeshComputePass = azdynamic_cast<SkinnedMeshComputePass*>(skinningPass.get());
|
||||
skinnedMeshComputePass->SetFeatureProcessor(this);
|
||||
|
||||
// For now, assume one skinning pass
|
||||
if (!skinningPasses.empty() && skinningPasses[0])
|
||||
// There may be multiple skinning passes in the scene due to multiple pipelines, but there is only one skinning shader
|
||||
m_skinningShader = skinnedMeshComputePass->GetShader();
|
||||
|
||||
if (!m_skinningShader)
|
||||
{
|
||||
m_skinningPass = static_cast<SkinnedMeshComputePass*>(skinningPasses[0]);
|
||||
const Data::Instance<RPI::Shader> shader = m_skinningPass->GetShader();
|
||||
|
||||
if (!shader)
|
||||
{
|
||||
AZ_Error(s_featureProcessorName, false, "Failed to get skinning pass shader. It may need to finish processing.");
|
||||
}
|
||||
AZ_Error(s_featureProcessorName, false, "Failed to get skinning pass shader. It may need to finish processing.");
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(s_featureProcessorName, false, "\"SkinningPassTemplate\" does not have any valid passes. Check your game project's .pass assets.");
|
||||
m_cachedSkinningShaderOptions.SetShader(m_skinningShader);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(s_featureProcessorName, false, "Failed to find passes for \"SkinningPassTemplate\". Check your game project's .pass assets.");
|
||||
}
|
||||
|
||||
if (passSystem->HasPassesForTemplateName(AZ::Name{ "MorphTargetPassTemplate" }))
|
||||
RPI::Ptr<RPI::Pass> morphTargetPass = pipelineRootPass->FindPassByNameRecursive(AZ::Name{ "MorphTargetPass" });
|
||||
if (morphTargetPass)
|
||||
{
|
||||
auto& morphTargetPasses = passSystem->GetPassesForTemplateName(AZ::Name{ "MorphTargetPassTemplate" });
|
||||
MorphTargetComputePass* morphTargetComputePass = azdynamic_cast<MorphTargetComputePass*>(morphTargetPass.get());
|
||||
morphTargetComputePass->SetFeatureProcessor(this);
|
||||
|
||||
// For now, assume one skinning pass
|
||||
if (!morphTargetPasses.empty() && morphTargetPasses[0])
|
||||
// There may be multiple morph target passes in the scene due to multiple pipelines, but there is only one morph target shader
|
||||
m_morphTargetShader = morphTargetComputePass->GetShader();
|
||||
|
||||
if (!m_morphTargetShader)
|
||||
{
|
||||
m_morphTargetPass = static_cast<MorphTargetComputePass*>(morphTargetPasses[0]);
|
||||
const Data::Instance<RPI::Shader> shader = m_morphTargetPass->GetShader();
|
||||
AZ_Error(s_featureProcessorName, false, "Failed to get morph target pass shader. It may need to finish processing.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!shader)
|
||||
{
|
||||
AZ_Error(s_featureProcessorName, false, "Failed to get morph target pass shader. It may need to finish processing.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(s_featureProcessorName, false, "\"MorphTargetPassTemplate\" does not have any valid passes. Check your game project's .pass assets.");
|
||||
}
|
||||
}
|
||||
else
|
||||
RPI::ShaderOptionGroup SkinnedMeshFeatureProcessor::CreateSkinningShaderOptionGroup(const SkinnedMeshShaderOptions shaderOptions, SkinnedMeshShaderOptionNotificationBus::Handler& shaderReinitializedHandler)
|
||||
{
|
||||
m_cachedSkinningShaderOptions.ConnectToShaderReinitializedEvent(shaderReinitializedHandler);
|
||||
return m_cachedSkinningShaderOptions.CreateShaderOptionGroup(shaderOptions);
|
||||
}
|
||||
|
||||
void SkinnedMeshFeatureProcessor::OnSkinningShaderReinitialized(const Data::Instance<RPI::Shader> skinningShader)
|
||||
{
|
||||
m_skinningShader = skinningShader;
|
||||
m_cachedSkinningShaderOptions.SetShader(m_skinningShader);
|
||||
}
|
||||
|
||||
void SkinnedMeshFeatureProcessor::SubmitSkinningDispatchItems(RHI::CommandList* commandList)
|
||||
{
|
||||
AZStd::lock_guard lock(m_dispatchItemMutex);
|
||||
for (const RHI::DispatchItem* dispatchItem : m_skinningDispatches)
|
||||
{
|
||||
AZ_Error(s_featureProcessorName, false, "Failed to find passes for \"MorphTargetPassTemplate\". Check your game project's .pass assets.");
|
||||
commandList->Submit(*dispatchItem);
|
||||
}
|
||||
m_skinningDispatches.clear();
|
||||
}
|
||||
|
||||
void SkinnedMeshFeatureProcessor::SubmitMorphTargetDispatchItems(RHI::CommandList* commandList)
|
||||
{
|
||||
AZStd::lock_guard lock(m_dispatchItemMutex);
|
||||
for (const RHI::DispatchItem* dispatchItem : m_morphTargetDispatches)
|
||||
{
|
||||
commandList->Submit(*dispatchItem);
|
||||
}
|
||||
m_morphTargetDispatches.clear();
|
||||
}
|
||||
|
||||
SkinnedMeshRenderProxyInterfaceHandle SkinnedMeshFeatureProcessor::AcquireRenderProxyInterface(const SkinnedMeshRenderProxyDesc& desc)
|
||||
@@ -363,14 +375,14 @@ namespace AZ
|
||||
return ReleaseRenderProxy(handle);
|
||||
}
|
||||
|
||||
RPI::Ptr<SkinnedMeshComputePass> SkinnedMeshFeatureProcessor::GetSkinningPass() const
|
||||
Data::Instance<RPI::Shader> SkinnedMeshFeatureProcessor::GetSkinningShader() const
|
||||
{
|
||||
return m_skinningPass;
|
||||
return m_skinningShader;
|
||||
}
|
||||
|
||||
RPI::Ptr<MorphTargetComputePass> SkinnedMeshFeatureProcessor::GetMorphTargetPass() const
|
||||
Data::Instance<RPI::Shader> SkinnedMeshFeatureProcessor::GetMorphTargetShader() const
|
||||
{
|
||||
return m_morphTargetPass;
|
||||
return m_morphTargetShader;
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -49,37 +49,47 @@ namespace AZ
|
||||
// FeatureProcessor overrides ...
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
void Simulate(const FeatureProcessor::SimulatePacket& packet) override;
|
||||
void Render(const FeatureProcessor::RenderPacket& packet) override;
|
||||
void OnRenderEnd() override;
|
||||
|
||||
// RPI::SceneNotificationBus overrides ...
|
||||
void OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline) override;
|
||||
void OnRenderPipelineRemoved(RPI::RenderPipeline* pipeline) override;
|
||||
void OnRenderPipelinePassesChanged(RPI::RenderPipeline* renderPipeline) override;
|
||||
void OnBeginPrepareRender() override;
|
||||
void OnEndPrepareRender() override;
|
||||
|
||||
SkinnedMeshRenderProxyHandle AcquireRenderProxy(const SkinnedMeshRenderProxyDesc& desc);
|
||||
bool ReleaseRenderProxy(SkinnedMeshRenderProxyHandle& handle);
|
||||
|
||||
RPI::Ptr<SkinnedMeshComputePass> GetSkinningPass() const;
|
||||
RPI::Ptr<MorphTargetComputePass> GetMorphTargetPass() const;
|
||||
Data::Instance<RPI::Shader> GetSkinningShader() const;
|
||||
RPI::ShaderOptionGroup CreateSkinningShaderOptionGroup(const SkinnedMeshShaderOptions shaderOptions, SkinnedMeshShaderOptionNotificationBus::Handler& shaderReinitializedHandler);
|
||||
void OnSkinningShaderReinitialized(const Data::Instance<RPI::Shader> skinningShader);
|
||||
void SubmitSkinningDispatchItems(RHI::CommandList* commandList);
|
||||
|
||||
Data::Instance<RPI::Shader> GetMorphTargetShader() const;
|
||||
void SubmitMorphTargetDispatchItems(RHI::CommandList* commandList);
|
||||
private:
|
||||
AZ_DISABLE_COPY_MOVE(SkinnedMeshFeatureProcessor);
|
||||
|
||||
void InitSkinningAndMorphPass();
|
||||
void InitSkinningAndMorphPass(const RPI::Ptr<RPI::ParentPass> pipelineRootPass);
|
||||
|
||||
SkinnedMeshRenderProxyInterfaceHandle AcquireRenderProxyInterface(const SkinnedMeshRenderProxyDesc& desc) override;
|
||||
bool ReleaseRenderProxyInterface(SkinnedMeshRenderProxyInterfaceHandle& handle) override;
|
||||
|
||||
static const char* s_featureProcessorName;
|
||||
RPI::Ptr<SkinnedMeshComputePass> m_skinningPass;
|
||||
RPI::Ptr<MorphTargetComputePass> m_morphTargetPass;
|
||||
|
||||
Data::Instance<RPI::Shader> m_skinningShader;
|
||||
CachedSkinnedMeshShaderOptions m_cachedSkinningShaderOptions;
|
||||
|
||||
Data::Instance<RPI::Shader> m_morphTargetShader;
|
||||
|
||||
AZStd::concurrency_checker m_renderProxiesChecker;
|
||||
StableDynamicArray<SkinnedMeshRenderProxy> m_renderProxies;
|
||||
AZStd::unique_ptr<SkinnedMeshStatsCollector> m_statsCollector;
|
||||
|
||||
MeshFeatureProcessor* m_meshFeatureProcessor = nullptr;
|
||||
AZStd::unordered_set<const RHI::DispatchItem*> m_skinningDispatches;
|
||||
AZStd::unordered_set<const RHI::DispatchItem*> m_morphTargetDispatches;
|
||||
AZStd::mutex m_dispatchItemMutex;
|
||||
|
||||
};
|
||||
} // namespace Render
|
||||
|
||||
@@ -60,13 +60,7 @@ namespace AZ
|
||||
|
||||
bool SkinnedMeshRenderProxy::BuildDispatchItem([[maybe_unused]] const RPI::Scene& scene, size_t modelLodIndex, [[maybe_unused]] const SkinnedMeshShaderOptions& shaderOptions)
|
||||
{
|
||||
if (!m_featureProcessor->GetSkinningPass())
|
||||
{
|
||||
AZ_Error("Skinned Mesh Feature Processor", false, "Failed to get Skinning Pass. Make sure the project has a skinning pass.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Data::Instance<RPI::Shader> skinningShader = m_featureProcessor->GetSkinningPass()->GetShader();
|
||||
Data::Instance<RPI::Shader> skinningShader = m_featureProcessor->GetSkinningShader();
|
||||
if (!skinningShader)
|
||||
{
|
||||
AZ_Error("Skinned Mesh Feature Processor", false, "Failed to get skinning shader from skinning pass");
|
||||
@@ -89,7 +83,7 @@ namespace AZ
|
||||
m_instance->m_outputStreamOffsetsInBytes[modelLodIndex],
|
||||
modelLodIndex, m_boneTransforms,
|
||||
m_shaderOptions,
|
||||
m_featureProcessor->GetSkinningPass(),
|
||||
m_featureProcessor,
|
||||
m_instance->m_morphTargetInstanceMetaData[modelLodIndex],
|
||||
morphDeltaIntegerEncoding });
|
||||
|
||||
@@ -100,7 +94,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
// Get the data needed to create a morph target dispatch item
|
||||
Data::Instance<RPI::Shader> morphTargetShader = m_featureProcessor->GetMorphTargetPass()->GetShader();
|
||||
Data::Instance<RPI::Shader> morphTargetShader = m_featureProcessor->GetMorphTargetShader();
|
||||
const AZStd::vector<AZStd::intrusive_ptr<MorphTargetInputBuffers>>& morphTargetInputBuffersVector = m_inputBuffers->GetMorphTargetInputBuffers(modelLodIndex);
|
||||
AZ_Assert(morphTargetMetaDatas.size() == morphTargetInputBuffersVector.size(), "Skinned Mesh Feature Processor - Mismatch in morph target metadata count and morph target input buffer count");
|
||||
|
||||
@@ -118,7 +112,7 @@ namespace AZ
|
||||
aznew MorphTargetDispatchItem{
|
||||
morphTargetInputBuffersVector[morphTargetIndex],
|
||||
morphTargetMetaDatas[morphTargetIndex],
|
||||
m_featureProcessor->GetMorphTargetPass(),
|
||||
m_featureProcessor,
|
||||
m_instance->m_morphTargetInstanceMetaData[modelLodIndex],
|
||||
morphDeltaIntegerEncoding });
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"gem_name": "Atom_Feature_Common",
|
||||
"Dependencies": [
|
||||
{
|
||||
"Uuid": "a218db9eb2114477b46600fea4441a6c",
|
||||
"VersionConstraints": [
|
||||
"~>0.1.0"
|
||||
],
|
||||
"_comment": "Atom RPI"
|
||||
}
|
||||
],
|
||||
"GemFormatVersion": 4,
|
||||
"Uuid": "b58e5eed0901428ca78544b04dbd61bd",
|
||||
"Name": "Atom_Feature_Common",
|
||||
"DisplayName": "Atom.Feature.Common",
|
||||
"Version": "0.1.0",
|
||||
"LinkType": "Dynamic",
|
||||
"Summary": "Provides commonly used render features.",
|
||||
"Tags": [ "Atom", "Feature", "Common" ],
|
||||
"IconPath": "preview.png",
|
||||
"Modules": [
|
||||
{
|
||||
"Type": "GameModule"
|
||||
},
|
||||
{
|
||||
"Name": "Builders",
|
||||
"Type": "EditorModule"
|
||||
},
|
||||
{
|
||||
"Name": "Public",
|
||||
"Type": "StaticLib"
|
||||
},
|
||||
{
|
||||
"Name": "Editor",
|
||||
"Type": "EditorModule",
|
||||
"Extends": "GameModule"
|
||||
},
|
||||
{
|
||||
"Name": "StaticLibrary",
|
||||
"Type": "StaticLib"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -100,7 +100,9 @@ namespace AZ
|
||||
Size size,
|
||||
uint32_t rowCount,
|
||||
uint32_t bytesPerRow,
|
||||
uint32_t bytesPerImage);
|
||||
uint32_t bytesPerImage,
|
||||
uint32_t numBlocksWidth,
|
||||
uint32_t numBlocksHeight);
|
||||
|
||||
/// The size of the image subresource in pixels. Certain formats have alignment requirements.
|
||||
/// Block compressed formats are 4 pixel aligned. Other non-standard formats may be 2 pixel aligned.
|
||||
@@ -114,6 +116,13 @@ namespace AZ
|
||||
|
||||
/// The number of bytes in a single image slice. 3D textures are comprised of m_size.m_depth image slices.
|
||||
uint32_t m_bytesPerImage = 0;
|
||||
|
||||
/// The number of blocks in width based on the texture fomat
|
||||
uint32_t m_blockElementWidth = 1;
|
||||
|
||||
/// The number of blocks in height based on the texture fomat
|
||||
uint32_t m_blockElementHeight = 1;
|
||||
|
||||
};
|
||||
|
||||
struct ImageSubresourceLayoutPlaced : ImageSubresourceLayout
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <Atom/RHI/FrameGraphExecuter.h>
|
||||
#include <Atom/RHI/FrameGraphCompiler.h>
|
||||
#include <Atom/RHI/FrameGraph.h>
|
||||
#include <Atom/RHI/RayTracingShaderTable.h>
|
||||
#include <Atom/RHI/ScopeProducer.h>
|
||||
#include <Atom/RHI/ScopeProducerEmpty.h>
|
||||
#include <Atom/RHI/TransientAttachmentPool.h>
|
||||
@@ -181,6 +182,9 @@ namespace AZ
|
||||
|
||||
const TransientAttachmentPoolDescriptor* GetTransientAttachmentPoolDescriptor() const;
|
||||
|
||||
//! Adds a RayTracingShaderTable to be built this frame
|
||||
void QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable);
|
||||
|
||||
private:
|
||||
const ScopeId m_rootScopeId{"Root"};
|
||||
|
||||
@@ -190,6 +194,7 @@ namespace AZ
|
||||
void PrepareProducers();
|
||||
void CompileProducers();
|
||||
void CompileShaderResourceGroups();
|
||||
void BuildRayTracingShaderTables();
|
||||
|
||||
ScopeProducer* FindScopeProducer(const ScopeId& scopeId);
|
||||
|
||||
@@ -224,6 +229,9 @@ namespace AZ
|
||||
AZStd::unique_ptr<ScopeProducerEmpty> m_rootScopeProducer;
|
||||
AZStd::vector<ScopeProducer*> m_scopeProducers;
|
||||
AZStd::unordered_map<ScopeId, ScopeProducer*> m_scopeProducerLookup;
|
||||
|
||||
// list of RayTracingShaderTables that should be built this frame
|
||||
AZStd::vector<RHI::Ptr<RayTracingShaderTable>> m_rayTracingShaderTablesToBuild;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace AZ
|
||||
const RHI::TransientAttachmentStatistics* GetTransientAttachmentStatistics() const override;
|
||||
const RHI::TransientAttachmentPoolDescriptor* GetTransientAttachmentPoolDescriptor() const override;
|
||||
ConstPtr<PlatformLimitsDescriptor> GetPlatformLimitsDescriptor() const override;
|
||||
void QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable) override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace AZ
|
||||
class PipelineState;
|
||||
class PipelineStateCache;
|
||||
class PlatformLimitsDescriptor;
|
||||
class RayTracingShaderTable;
|
||||
struct CpuTimingStatistics;
|
||||
struct FrameSchedulerCompileRequest;
|
||||
struct TransientAttachmentStatistics;
|
||||
@@ -61,6 +62,8 @@ namespace AZ
|
||||
virtual const RHI::TransientAttachmentPoolDescriptor* GetTransientAttachmentPoolDescriptor() const = 0;
|
||||
|
||||
virtual ConstPtr<PlatformLimitsDescriptor> GetPlatformLimitsDescriptor() const = 0;
|
||||
|
||||
virtual void QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable) = 0;
|
||||
};
|
||||
|
||||
//! This bus exists to give RHI samples the ability to slot in scopes manually
|
||||
|
||||
@@ -97,18 +97,30 @@ namespace AZ
|
||||
virtual ~RayTracingShaderTable() = default;
|
||||
|
||||
static RHI::Ptr<RHI::RayTracingShaderTable> CreateRHIRayTracingShaderTable();
|
||||
void Init(Device& device, const RayTracingBufferPools& rayTracingBufferPools);
|
||||
|
||||
ResultCode Init(Device& device, const RayTracingShaderTableDescriptor* descriptor, const RayTracingBufferPools& rayTracingBufferPools);
|
||||
//! Queues this RayTracingShaderTable to be built by the FrameScheduler.
|
||||
//! Note that the descriptor must be heap allocated, preferably using make_shared.
|
||||
void Build(const AZStd::shared_ptr<RayTracingShaderTableDescriptor> descriptor);
|
||||
|
||||
protected:
|
||||
|
||||
AZStd::shared_ptr<RayTracingShaderTableDescriptor> m_descriptor;
|
||||
const RayTracingBufferPools* m_bufferPools = nullptr;
|
||||
|
||||
private:
|
||||
|
||||
// explicit shutdown is not allowed for this type
|
||||
void Shutdown() override final;
|
||||
friend class FrameScheduler;
|
||||
|
||||
/// Called by the FrameScheduler to validate the state prior to building
|
||||
void Validate();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Platform API
|
||||
virtual RHI::ResultCode InitInternal(RHI::Device& deviceBase, const RHI::RayTracingShaderTableDescriptor* descriptor, const RayTracingBufferPools& bufferPools) = 0;
|
||||
virtual RHI::ResultCode BuildInternal() = 0;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool m_isQueuedForBuild = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,11 +102,13 @@ namespace AZ
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<ImageSubresourceLayout>()
|
||||
->Version(0)
|
||||
->Version(1)
|
||||
->Field("m_size", &ImageSubresourceLayout::m_size)
|
||||
->Field("m_rowCount", &ImageSubresourceLayout::m_rowCount)
|
||||
->Field("m_bytesPerRow", &ImageSubresourceLayout::m_bytesPerRow)
|
||||
->Field("m_bytesPerImage", &ImageSubresourceLayout::m_bytesPerImage)
|
||||
->Field("m_blockElementWidth", &ImageSubresourceLayout::m_blockElementWidth)
|
||||
->Field("m_blockElementHeight", &ImageSubresourceLayout::m_blockElementHeight)
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -115,11 +117,15 @@ namespace AZ
|
||||
Size size,
|
||||
uint32_t rowCount,
|
||||
uint32_t bytesPerRow,
|
||||
uint32_t bytesPerImage)
|
||||
uint32_t bytesPerImage,
|
||||
uint32_t blockElementWidth,
|
||||
uint32_t blockElementHeight)
|
||||
: m_size{size}
|
||||
, m_rowCount{rowCount}
|
||||
, m_bytesPerRow{bytesPerRow}
|
||||
, m_bytesPerImage{bytesPerImage}
|
||||
, m_blockElementWidth{blockElementWidth}
|
||||
, m_blockElementHeight{blockElementHeight}
|
||||
{}
|
||||
|
||||
ImageSubresourceLayoutPlaced::ImageSubresourceLayoutPlaced(const ImageSubresourceLayout& subresourceLayout, size_t offset)
|
||||
@@ -296,8 +302,22 @@ namespace AZ
|
||||
numBlocks = 4;
|
||||
break;
|
||||
|
||||
case RHI::Format::EAC_R11_UNORM:
|
||||
case RHI::Format::EAC_R11_SNORM:
|
||||
isBlockCompressed = true;
|
||||
bytesPerElement = 8;
|
||||
numBlocks = 4;
|
||||
break;
|
||||
|
||||
case RHI::Format::EAC_RG11_UNORM:
|
||||
case RHI::Format::EAC_RG11_SNORM:
|
||||
isBlockCompressed = true;
|
||||
bytesPerElement = 16;
|
||||
numBlocks = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
AZ_Assert(false, "Unimplemented esoteric format.");
|
||||
AZ_Assert(false, "Unimplemented esoteric format %i.", static_cast<int>(imageFormat));
|
||||
}
|
||||
|
||||
if (isBlockCompressed)
|
||||
@@ -316,6 +336,8 @@ namespace AZ
|
||||
subresourceLayout.m_rowCount = numBlocksHigh;
|
||||
subresourceLayout.m_size.m_width = imageSize.m_width;
|
||||
subresourceLayout.m_size.m_height = imageSize.m_height;
|
||||
subresourceLayout.m_blockElementWidth = numBlocks;
|
||||
subresourceLayout.m_blockElementHeight = numBlocks;
|
||||
}
|
||||
else if (isPacked)
|
||||
{
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <Atom/RHI/ShaderResourceGroupPool.h>
|
||||
#include <Atom/RHI/TransientAttachmentPool.h>
|
||||
#include <Atom/RHI/ResourcePoolDatabase.h>
|
||||
#include <Atom/RHI/RayTracingShaderTable.h>
|
||||
|
||||
#include <AzCore/Debug/EventTrace.h>
|
||||
#include <AzCore/Jobs/Algorithms.h>
|
||||
@@ -204,6 +205,9 @@ namespace AZ
|
||||
|
||||
// Compile all invalidated shader resource groups.
|
||||
CompileShaderResourceGroups();
|
||||
|
||||
// Build RayTracingShaderTables
|
||||
BuildRayTracingShaderTables();
|
||||
}
|
||||
return outcome;
|
||||
}
|
||||
@@ -314,6 +318,25 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void FrameScheduler::BuildRayTracingShaderTables()
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
|
||||
AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameScheduler: BuildRayTracingShaderTables");
|
||||
|
||||
for (auto rayTracingShaderTable : m_rayTracingShaderTablesToBuild)
|
||||
{
|
||||
rayTracingShaderTable->Validate();
|
||||
|
||||
[[maybe_unused]] ResultCode resultCode = rayTracingShaderTable->BuildInternal();
|
||||
AZ_Assert(resultCode == ResultCode::Success, "RayTracingShaderTable build failed");
|
||||
|
||||
rayTracingShaderTable->m_isQueuedForBuild = false;
|
||||
}
|
||||
|
||||
// clear the list now that all RayTracingShaderTables have been built for this frame
|
||||
m_rayTracingShaderTablesToBuild.clear();
|
||||
}
|
||||
|
||||
ResultCode FrameScheduler::BeginFrame()
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
|
||||
@@ -528,5 +551,10 @@ namespace AZ
|
||||
{
|
||||
return m_transientAttachmentPool ? &m_transientAttachmentPool->GetDescriptor() : nullptr;
|
||||
}
|
||||
|
||||
void FrameScheduler::QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable)
|
||||
{
|
||||
m_rayTracingShaderTablesToBuild.push_back(rayTracingShaderTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,5 +290,9 @@ namespace AZ
|
||||
return m_platformLimitsDescriptor;
|
||||
}
|
||||
|
||||
void RHISystem::QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable)
|
||||
{
|
||||
m_frameScheduler.QueueRayTracingShaderTableForBuild(rayTracingShaderTable);
|
||||
}
|
||||
} //namespace RPI
|
||||
} //namespace AZ
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <Atom/RHI/Factory.h>
|
||||
#include <Atom/RHI/RayTracingShaderTable.h>
|
||||
#include <Atom/RHI/RHISystemInterface.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -77,21 +78,28 @@ namespace AZ
|
||||
return rayTracingShaderTable;
|
||||
}
|
||||
|
||||
ResultCode RayTracingShaderTable::Init(Device& device, const RayTracingShaderTableDescriptor* descriptor, const RayTracingBufferPools& bufferPools)
|
||||
void RayTracingShaderTable::Init(Device& device, const RayTracingBufferPools& bufferPools)
|
||||
{
|
||||
#if defined (AZ_RHI_ENABLE_VALIDATION)
|
||||
// [GFX TODO][ATOM-5217] Validate shaders in the ray tracing shader table are present in the pipeline state
|
||||
#endif
|
||||
ResultCode resultCode = InitInternal(device, descriptor, bufferPools);
|
||||
if (resultCode == ResultCode::Success)
|
||||
{
|
||||
DeviceObject::Init(device);
|
||||
}
|
||||
return resultCode;
|
||||
DeviceObject::Init(device);
|
||||
m_bufferPools = &bufferPools;
|
||||
}
|
||||
|
||||
void RayTracingShaderTable::Shutdown()
|
||||
void RayTracingShaderTable::Build(const AZStd::shared_ptr<RayTracingShaderTableDescriptor> descriptor)
|
||||
{
|
||||
AZ_Assert(!m_isQueuedForBuild, "Attempting to build a RayTracingShaderTable that's already been queued. Only build once per frame.")
|
||||
m_descriptor = descriptor;
|
||||
|
||||
RHI::RHISystemInterface::Get()->QueueRayTracingShaderTableForBuild(this);
|
||||
m_isQueuedForBuild = true;
|
||||
}
|
||||
|
||||
void RayTracingShaderTable::Validate()
|
||||
{
|
||||
AZ_Assert(m_isQueuedForBuild, "Attempting to build a RayTracingShaderTable that is not queued.");
|
||||
AZ_Assert(m_bufferPools, "RayTracingBufferPools pointer is null.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ namespace AZ
|
||||
// Staging sizes
|
||||
uint32_t stagingRowPitch = RHI::AlignUp(subresourceLayout.m_bytesPerRow, DX12_TEXTURE_DATA_PITCH_ALIGNMENT);
|
||||
uint32_t stagingSlicePitch = RHI::AlignUp(subresourceLayout.m_rowCount*stagingRowPitch, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
|
||||
const uint32_t compressedTexelBlockSizeHeight = subresourceLayout.m_size.m_height / subresourceLayout.m_rowCount;
|
||||
const uint32_t compressedTexelBlockSizeHeight = subresourceLayout.m_blockElementHeight;
|
||||
|
||||
// ImageHeight must be bigger than or equal to the Image's row count. Images with a RowCount that is less than the ImageHeight indicates a block compression.
|
||||
// Images with a RowCount which is higher than the ImageHeight indicates a planar image, which is not supported for streaming images.
|
||||
@@ -386,7 +386,7 @@ namespace AZ
|
||||
const uint32_t numRowsToCopy = endRow - startRow;
|
||||
|
||||
// Calculate the blocksize for BC formatted images; the copy command works in texels.
|
||||
const uint32_t heightToCopy = (endRow - startRow) * compressedTexelBlockSizeHeight;
|
||||
uint32_t heightToCopy = (endRow - startRow) * compressedTexelBlockSizeHeight;
|
||||
|
||||
// Copy subresource data to staging memory
|
||||
{
|
||||
@@ -402,6 +402,14 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
//Clamp heightToCopy to match subresourceLayout.m_size.m_height as it is possible to go over
|
||||
//if subresourceLayout.m_size.m_height is not perfectly divisible by compressedTexelBlockSizeHeight
|
||||
if(destHeight+heightToCopy > subresourceLayout.m_size.m_height)
|
||||
{
|
||||
uint32_t HeightDiff = (destHeight + heightToCopy) - subresourceLayout.m_size.m_height;
|
||||
heightToCopy -= HeightDiff;
|
||||
}
|
||||
|
||||
// Add copy command to copy image subresource from staging memory to image gpu resource
|
||||
|
||||
// Source location
|
||||
|
||||
@@ -415,7 +415,7 @@ namespace AZ
|
||||
|
||||
// this assert typically happens when a shader needs a particular Srg (e.g., the ViewSrg) but the code did not bind it,
|
||||
// check the pass code in this callstack to determine why it was not bound
|
||||
AZ_Assert(false, "ShaderResourceGroup in slot '%d' is null at DrawItem submit time. This is not valid and means the shader is expecting an Srg that is not currently bound in the pipeline. Current bindings: %s",
|
||||
AZ_Assert(false, "ShaderResourceGroup in slot '%d' is null at DrawItem submit time. This is not valid and means the shader is expecting an Srg that isF not currently bound in the pipeline. Current bindings: %s",
|
||||
srgSlot,
|
||||
slotSrgString.c_str());
|
||||
|
||||
|
||||
@@ -121,15 +121,15 @@ namespace AZ
|
||||
}
|
||||
#endif
|
||||
|
||||
RHI::ResultCode RayTracingShaderTable::InitInternal([[maybe_unused]] RHI::Device& deviceBase, [[maybe_unused]] const RHI::RayTracingShaderTableDescriptor* descriptor, [[maybe_unused]] const RHI::RayTracingBufferPools& bufferPools)
|
||||
RHI::ResultCode RayTracingShaderTable::BuildInternal()
|
||||
{
|
||||
#ifdef AZ_DX12_DXR_SUPPORT
|
||||
// advance to the next buffer
|
||||
m_currentBufferIndex = (m_currentBufferIndex + 1) % BufferCount;
|
||||
ShaderTableBuffers& buffers = m_buffers[m_currentBufferIndex];
|
||||
|
||||
// clear the shader table if a null descriptor was passed in
|
||||
if (!descriptor)
|
||||
// clear the shader table if the descriptor has no ray generation shader
|
||||
if (m_descriptor->GetRayGenerationRecord().empty())
|
||||
{
|
||||
buffers.m_rayGenerationTable = nullptr;
|
||||
buffers.m_rayGenerationTableSize = 0;
|
||||
@@ -144,7 +144,7 @@ namespace AZ
|
||||
|
||||
// retrieve the ID3D12StateObjectProperties interface from the raytracing pipeline state object
|
||||
// this is needed to get the shader identifiers to put in the table
|
||||
const RayTracingPipelineState* rayTracingPipelineState = static_cast<const RayTracingPipelineState*>(descriptor->GetPipelineState().get());
|
||||
const RayTracingPipelineState* rayTracingPipelineState = static_cast<const RayTracingPipelineState*>(m_descriptor->GetPipelineState().get());
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12StateObjectProperties> stateObjectProperties;
|
||||
[[maybe_unused]] HRESULT hr = rayTracingPipelineState->Get()->QueryInterface(IID_GRAPHICS_PPV_ARGS(stateObjectProperties.GetAddressOf()));
|
||||
@@ -153,28 +153,28 @@ namespace AZ
|
||||
// ray generation shader table
|
||||
{
|
||||
// RayGeneration table must have one and only one record
|
||||
AZ_Assert(descriptor->GetRayGenerationRecord().size() == 1, "Descriptor must contain one and only one RayGeneration record");
|
||||
uint32_t shaderRecordSize = RHI::AlignUp(FindLargestRecordSize(descriptor->GetRayGenerationRecord()), D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
|
||||
AZ_Assert(m_descriptor->GetRayGenerationRecord().size() == 1, "Descriptor must contain one and only one RayGeneration record");
|
||||
uint32_t shaderRecordSize = RHI::AlignUp(FindLargestRecordSize(m_descriptor->GetRayGenerationRecord()), D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
|
||||
|
||||
buffers.m_rayGenerationTable = BuildTable(deviceBase, bufferPools, descriptor->GetRayGenerationRecord(), shaderRecordSize, L"Ray Generation Shader Table", stateObjectProperties);
|
||||
buffers.m_rayGenerationTable = BuildTable(GetDevice(), *m_bufferPools, m_descriptor->GetRayGenerationRecord(), shaderRecordSize, L"Ray Generation Shader Table", stateObjectProperties);
|
||||
buffers.m_rayGenerationTableSize = shaderRecordSize;
|
||||
}
|
||||
|
||||
// miss shader table
|
||||
{
|
||||
uint32_t shaderRecordSize = RHI::AlignUp(FindLargestRecordSize(descriptor->GetMissRecords()), D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
|
||||
uint32_t shaderRecordSize = RHI::AlignUp(FindLargestRecordSize(m_descriptor->GetMissRecords()), D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
|
||||
|
||||
buffers.m_missTable = BuildTable(deviceBase, bufferPools, descriptor->GetMissRecords(), shaderRecordSize, L"Miss Shader Table", stateObjectProperties);
|
||||
buffers.m_missTableSize = shaderRecordSize * static_cast<uint32_t>(descriptor->GetMissRecords().size());
|
||||
buffers.m_missTable = BuildTable(GetDevice(), *m_bufferPools, m_descriptor->GetMissRecords(), shaderRecordSize, L"Miss Shader Table", stateObjectProperties);
|
||||
buffers.m_missTableSize = shaderRecordSize * static_cast<uint32_t>(m_descriptor->GetMissRecords().size());
|
||||
buffers.m_missTableStride = shaderRecordSize;
|
||||
}
|
||||
|
||||
// hit group shader table
|
||||
{
|
||||
uint32_t shaderRecordSize = RHI::AlignUp(FindLargestRecordSize(descriptor->GetHitGroupRecords()), D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
|
||||
uint32_t shaderRecordSize = RHI::AlignUp(FindLargestRecordSize(m_descriptor->GetHitGroupRecords()), D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
|
||||
|
||||
buffers.m_hitGroupTable = BuildTable(deviceBase, bufferPools, descriptor->GetHitGroupRecords(), shaderRecordSize, L"HitGroup Shader Table", stateObjectProperties);
|
||||
buffers.m_hitGroupTableSize = shaderRecordSize * static_cast<uint32_t>(descriptor->GetHitGroupRecords().size());
|
||||
buffers.m_hitGroupTable = BuildTable(GetDevice(), *m_bufferPools, m_descriptor->GetHitGroupRecords(), shaderRecordSize, L"HitGroup Shader Table", stateObjectProperties);
|
||||
buffers.m_hitGroupTableSize = shaderRecordSize * static_cast<uint32_t>(m_descriptor->GetHitGroupRecords().size());
|
||||
buffers.m_hitGroupTableStride = shaderRecordSize;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -61,8 +61,8 @@ namespace AZ
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// RHI::PipelineState
|
||||
RHI::ResultCode InitInternal(RHI::Device& deviceBase, const RHI::RayTracingShaderTableDescriptor* descriptor, const RHI::RayTracingBufferPools& bufferPools) override;
|
||||
// RHI::RayTracingShaderTable
|
||||
RHI::ResultCode BuildInternal() override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const uint32_t BufferCount = 3;
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
-136
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// NOTE: Nest this array, so Azslc will output a size of the bindingslot to 1
|
||||
struct FloatBuffer
|
||||
{
|
||||
float buffer;
|
||||
};
|
||||
|
||||
// Listed on update frequency
|
||||
ShaderResourceGroupSemantic FrequencyPerScene
|
||||
{
|
||||
FrequencyId = 6;
|
||||
};
|
||||
|
||||
ShaderResourceGroupSemantic FloatBufferSemanticId
|
||||
{
|
||||
FrequencyId = 7;
|
||||
};
|
||||
|
||||
ShaderResourceGroup ImageSrg : FrequencyPerScene
|
||||
{
|
||||
Sampler m_sampler
|
||||
{
|
||||
MaxAnisotropy = 16;
|
||||
AddressU = Wrap;
|
||||
AddressV = Wrap;
|
||||
AddressW = Wrap;
|
||||
};
|
||||
|
||||
// Array of textures
|
||||
Texture2D m_textureArray[];
|
||||
}
|
||||
|
||||
ShaderResourceGroup FloatBufferSrg : FloatBufferSemanticId
|
||||
{
|
||||
StructuredBuffer<FloatBuffer> m_floatBuffer;
|
||||
};
|
||||
|
||||
// Helper functions to read data from the FloatBuffer. The FloatBuffer is accessed with a descriptor and a index.
|
||||
// The descriptor holds the initial offset within the FloatBuffer, and the index is a sub-index, which increments with each property that is being read.
|
||||
// The data needs to be read in the same order as it is allocated on the host.
|
||||
|
||||
// All float setters
|
||||
void SetFloat(out float outFloat, in uint desc, inout uint index)
|
||||
{
|
||||
outFloat = FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer;
|
||||
index += 1;
|
||||
}
|
||||
|
||||
void SetFloat2(out float2 outFloat, in uint desc, inout uint index)
|
||||
{
|
||||
outFloat.x = FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer;
|
||||
outFloat.y = FloatBufferSrg::m_floatBuffer[desc + index + 1].buffer;
|
||||
index += 2;
|
||||
}
|
||||
|
||||
void SetFloat3(out float3 outFloat, in uint desc, inout uint index)
|
||||
{
|
||||
outFloat.x = FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer;
|
||||
outFloat.y = FloatBufferSrg::m_floatBuffer[desc + index + 1].buffer;
|
||||
outFloat.z = FloatBufferSrg::m_floatBuffer[desc + index + 2].buffer;
|
||||
index += 3;
|
||||
}
|
||||
|
||||
void SetFloat4(out float4 outFloat, in uint desc, inout uint index)
|
||||
{
|
||||
outFloat.x = FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer;
|
||||
outFloat.y = FloatBufferSrg::m_floatBuffer[desc + index + 1].buffer;
|
||||
outFloat.z = FloatBufferSrg::m_floatBuffer[desc + index + 2].buffer;
|
||||
outFloat.w = FloatBufferSrg::m_floatBuffer[desc + index + 3].buffer;
|
||||
index += 4;
|
||||
}
|
||||
|
||||
// All matrix setters
|
||||
void SetFloat4x4(out float4x4 outFloat, in uint desc, inout uint index)
|
||||
{
|
||||
[unroll(4)]
|
||||
for(uint i = 0; i < 4; i++)
|
||||
{
|
||||
SetFloat4(outFloat[i], desc, index);
|
||||
}
|
||||
}
|
||||
|
||||
// All uint setters
|
||||
void SetUint(out uint outUInt, in uint desc, inout uint index)
|
||||
{
|
||||
outUInt = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer);
|
||||
index += 1;
|
||||
}
|
||||
|
||||
void SetUint2(out uint2 outUInt, in uint desc, inout uint index)
|
||||
{
|
||||
outUInt.x = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer);
|
||||
outUInt.y = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 1].buffer);
|
||||
index += 2;
|
||||
}
|
||||
|
||||
void SetUint3(out uint3 outUInt, in uint desc, inout uint index)
|
||||
{
|
||||
outUInt.x = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer);
|
||||
outUInt.y = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 1].buffer);
|
||||
outUInt.z = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 2].buffer);
|
||||
index += 3;
|
||||
}
|
||||
|
||||
void SetUint4(out uint4 outUInt, in uint desc, inout uint index)
|
||||
{
|
||||
outUInt.x = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 0].buffer);
|
||||
outUInt.y = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 1].buffer);
|
||||
outUInt.z = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 2].buffer);
|
||||
outUInt.w = asuint(FloatBufferSrg::m_floatBuffer[desc + index + 3].buffer);
|
||||
index += 4;
|
||||
}
|
||||
|
||||
// All double setters
|
||||
void SetDouble(out double outDouble, in uint desc, inout uint index)
|
||||
{
|
||||
uint lowBits;
|
||||
uint highBits;
|
||||
SetUint(highBits, desc, index);
|
||||
SetUint(lowBits, desc, index);
|
||||
|
||||
outDouble = asdouble(lowBits, highBits);
|
||||
}
|
||||
@@ -21,7 +21,6 @@ set(FILES
|
||||
Shader/ImagePreview.shader
|
||||
ShaderLib/Atom/RPI/Math.azsli
|
||||
ShaderLib/Atom/RPI/TangentSpace.azsli
|
||||
ShaderLib/Atom/RPI/ShaderResourceGroups/BindlessPrototypeSrg.azsli
|
||||
ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli
|
||||
ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultObjectSrg.azsli
|
||||
)
|
||||
|
||||
@@ -381,6 +381,7 @@ namespace AZ
|
||||
uint64_t m_createdByPassRequest : 1;
|
||||
uint64_t m_initialized : 1;
|
||||
uint64_t m_enabled : 1;
|
||||
uint64_t m_parentEnabled : 1;
|
||||
uint64_t m_alreadyCreated : 1;
|
||||
uint64_t m_alreadyReset : 1;
|
||||
uint64_t m_alreadyPrepared : 1;
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace AZ
|
||||
// --- Members ---
|
||||
|
||||
// Cached pointer to the pass library to simplify code
|
||||
PassLibrary* m_passLibary = nullptr;
|
||||
PassLibrary* m_passLibrary = nullptr;
|
||||
|
||||
// ClassNames are used to look up PassCreators. This list is 1-to-1 with the PassCreator list
|
||||
AZStd::vector<Name> m_passClassNames;
|
||||
|
||||
@@ -56,6 +56,9 @@ namespace AZ
|
||||
|
||||
// The list of passes created from this template
|
||||
AZStd::vector<Pass*> m_passes;
|
||||
|
||||
// The pass templates mapping asset id which this template is coming from.
|
||||
Data::AssetId m_mappingAssetId;
|
||||
};
|
||||
|
||||
typedef AZStd::unordered_map<Name, TemplateEntry> TemplateEntriesByName;
|
||||
@@ -105,7 +108,7 @@ namespace AZ
|
||||
bool LoadPassAsset(const Name& name, const Data::Asset<PassAsset>& passAsset, bool hotReloading = false);
|
||||
|
||||
// Find asset with specified pass template asset id and load pass template from the asset.
|
||||
void LoadPassAsset(const Name& name, const Data::AssetId& passAssetId);
|
||||
bool LoadPassAsset(const Name& name, const Data::AssetId& passAssetId);
|
||||
|
||||
// Data::AssetBus::Handler overrides...
|
||||
void OnAssetReloaded(Data::Asset<Data::AssetData> asset) override;
|
||||
|
||||
@@ -55,6 +55,10 @@ namespace AZ
|
||||
//! Initializes the PassSystem and the Root Pass and creates the Pass InstanceDatabase
|
||||
void Init();
|
||||
|
||||
//! Initialize and load pass templates
|
||||
//! This function need to be called after Init()
|
||||
void InitPassTemplates();
|
||||
|
||||
//! Deletes the Root Pass and shuts down the PassSystem
|
||||
void Shutdown();
|
||||
|
||||
@@ -74,6 +78,7 @@ namespace AZ
|
||||
void SetHotReloading(bool hotReloading) override;
|
||||
void SetTargetedPassDebuggingName(const AZ::Name& targetPassName) override;
|
||||
const AZ::Name& GetTargetedPassDebuggingName() const override;
|
||||
void ConnectEvent(OnReadyLoadTemplatesEvent::Handler& handler) override;
|
||||
|
||||
// PassSystemInterface factory related functions...
|
||||
void AddPassCreator(Name className, PassCreator createFunction) override;
|
||||
@@ -139,6 +144,9 @@ namespace AZ
|
||||
|
||||
// Counts the number of passes
|
||||
int32_t m_passCounter = 0;
|
||||
|
||||
// Events
|
||||
OnReadyLoadTemplatesEvent m_loadTemplatesEvent;
|
||||
};
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
|
||||
@@ -64,7 +64,10 @@ namespace AZ
|
||||
//! initializing a scene;
|
||||
virtual void ProcessQueuedChanges() = 0;
|
||||
|
||||
//! Load pass templates listed in a name-assetid mapping asset
|
||||
//! Load pass templates listed in a name-assetid mapping asset
|
||||
//! This function should be called before the render pipelines which use templates from this mappings are created.
|
||||
//! To load pass template mapping before any render pipelines are created, use OnReadyLoadTemplatesEvent::Handler to
|
||||
//! load desired pass template mappings
|
||||
virtual bool LoadPassTemplateMappings(const AZStd::string& templateMappingPath) = 0;
|
||||
|
||||
//! Writes a pass template to a .pass file which can then be used as a pass asset. Useful for
|
||||
@@ -148,6 +151,12 @@ namespace AZ
|
||||
//! Find the SwapChainPass associated with window Handle
|
||||
virtual SwapChainPass* FindSwapChainPass(AzFramework::NativeWindowHandle windowHandle) const = 0;
|
||||
|
||||
using OnReadyLoadTemplatesEvent = AZ::Event<>;
|
||||
//! Connect a handler to listen to the event that the pass system is ready to load pass templates
|
||||
//! The event is triggered when pass system is initialized and asset system is ready.
|
||||
//! The handler can add new pass templates or load pass template mappings from assets
|
||||
virtual void ConnectEvent(OnReadyLoadTemplatesEvent::Handler& handler) = 0;
|
||||
|
||||
private:
|
||||
// These functions are only meant to be used by the Pass class
|
||||
|
||||
@@ -164,17 +173,10 @@ namespace AZ
|
||||
virtual void UnregisterPass(Pass* pass) = 0;
|
||||
|
||||
};
|
||||
|
||||
//! Notifications of the pass system such attachments were rebuilt, pass tree changes
|
||||
class PassSystemNotificiations
|
||||
: public AZ::EBusTraits
|
||||
|
||||
namespace PassSystemEvents
|
||||
{
|
||||
public:
|
||||
}
|
||||
|
||||
//! Notify when any pass's attachment was rebuilt
|
||||
virtual void OnPassAttachmentsBuilt() = 0;
|
||||
};
|
||||
|
||||
using PassSystemNotificiationBus = AZ::EBus<PassSystemNotificiations>;
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
|
||||
@@ -91,6 +91,8 @@ namespace AZ
|
||||
const AZ::Matrix4x4& GetViewToWorldMatrix() const;
|
||||
const AZ::Matrix4x4& GetViewToClipMatrix() const;
|
||||
const AZ::Matrix4x4& GetWorldToClipMatrix() const;
|
||||
//! Get the camera's world transform, converted from the viewToWorld matrix's native y-up to z-up
|
||||
AZ::Transform GetCameraTransform() const;
|
||||
|
||||
//! Finalize draw lists in this view. This function should only be called when all
|
||||
//! draw packets for current frame are added.
|
||||
|
||||
@@ -92,6 +92,8 @@ namespace AZ
|
||||
virtual ViewPtr GetCurrentView(const Name& contextName) const = 0;
|
||||
};
|
||||
|
||||
using ViewportContextRequests = AZ::Interface<ViewportContextRequestsInterface>;
|
||||
|
||||
class ViewportContextManagerNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
|
||||
@@ -137,13 +137,19 @@ namespace AZ
|
||||
template<typename AssetDataT>
|
||||
Data::Asset<AssetDataT> LoadCriticalAsset(const AZStd::string& assetFilePath, TraceLevel reporting)
|
||||
{
|
||||
AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown;
|
||||
AzFramework::AssetSystemRequestBus::BroadcastResult(status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, assetFilePath);
|
||||
|
||||
if (status != AzFramework::AssetSystem::AssetStatus_Compiled)
|
||||
bool apConnected = false;
|
||||
AzFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
apConnected, &AzFramework::AssetSystemRequestBus::Events::ConnectedWithAssetProcessor);
|
||||
if (apConnected)
|
||||
{
|
||||
AssetUtilsInternal::ReportIssue(reporting, AZStd::string::format("Could not compile asset '%s'", assetFilePath.c_str()).c_str());
|
||||
return {};
|
||||
AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown;
|
||||
AzFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, assetFilePath);
|
||||
if (status != AzFramework::AssetSystem::AssetStatus_Compiled)
|
||||
{
|
||||
AssetUtilsInternal::ReportIssue(reporting, AZStd::string::format("Could not compile asset '%s'", assetFilePath.c_str()).c_str());
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return LoadAssetByProductPath<AssetDataT>(assetFilePath.c_str(), reporting);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <Atom/RPI.Reflect/Asset/AssetHandler.h>
|
||||
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
|
||||
|
||||
namespace AZ::RPI
|
||||
{
|
||||
@@ -56,6 +57,9 @@ namespace AZ::RPI
|
||||
float m_minPositionDelta;
|
||||
float m_maxPositionDelta;
|
||||
|
||||
//! Reference to the wrinkle mask, if it exists
|
||||
AZ::Data::Asset<AZ::RPI::StreamingImageAsset> m_wrinkleMask;
|
||||
|
||||
//! Boolean to indicate the presence or absence of color deltas
|
||||
bool m_hasColorDeltas = false;
|
||||
|
||||
|
||||
@@ -44,9 +44,6 @@ namespace AZ
|
||||
//! The path of the only one view srg asset for the RPI system. This is used to create any RPI::View.
|
||||
AZStd::string m_viewSrgAssetPath = "shaderlib/viewsrg_viewsrg.azsrg";
|
||||
|
||||
//! Path of pass templates' name-assetid mapping file.
|
||||
AZStd::string m_passTemplatesMappingPath = "Passes/PassTemplates.azasset";
|
||||
|
||||
ImageSystemDescriptor m_imageSystemDescriptor;
|
||||
GpuQuerySystemDescriptor m_gpuQuerySystemDescriptor;
|
||||
DynamicDrawSystemDescriptor m_dynamicDrawSystemDescriptor;
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Views/SceneGraphDownwardsIterator.h>
|
||||
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
|
||||
namespace AZ::RPI
|
||||
{
|
||||
using namespace AZ::SceneAPI;
|
||||
@@ -114,7 +117,7 @@ namespace AZ::RPI
|
||||
meshNodeName, sourceMesh.m_name.GetCStr());
|
||||
|
||||
const DataTypes::MatrixType globalTransform = Utilities::BuildWorldTransform(sceneGraph, sceneNodeIndex);
|
||||
BuildMorphTargetMesh(vertexOffset, sourceMesh, productMesh, metaAssetCreator, blendShapeName, blendShapeData, globalTransform, coordSysConverter);
|
||||
BuildMorphTargetMesh(vertexOffset, sourceMesh, productMesh, metaAssetCreator, blendShapeName, blendShapeData, globalTransform, coordSysConverter, scene.GetSourceFilename());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -157,7 +160,8 @@ namespace AZ::RPI
|
||||
const AZStd::string& blendShapeName,
|
||||
const AZStd::shared_ptr<const DataTypes::IBlendShapeData>& blendShapeData,
|
||||
const DataTypes::MatrixType& globalTransform,
|
||||
const AZ::SceneAPI::CoordinateSystemConverter& coordSysConverter)
|
||||
const AZ::SceneAPI::CoordinateSystemConverter& coordSysConverter,
|
||||
const AZStd::string& sourceSceneFilename)
|
||||
{
|
||||
const float tolerance = CalcPositionDeltaTolerance(sourceMesh);
|
||||
AZ::Aabb deltaPositionAabb = AZ::Aabb::CreateNull();
|
||||
@@ -288,6 +292,8 @@ namespace AZ::RPI
|
||||
metaData.m_maxPositionDelta = maxValue;
|
||||
}
|
||||
|
||||
metaData.m_wrinkleMask = GetWrinkleMask(sourceSceneFilename, blendShapeName);
|
||||
|
||||
metaAssetCreator.AddMorphTarget(metaData);
|
||||
|
||||
AZ_Assert(uncompressedPositionDeltas.size() == compressedDeltas.size(), "Number of uncompressed (%d) and compressed position delta components (%d) do not match.",
|
||||
@@ -312,4 +318,47 @@ namespace AZ::RPI
|
||||
AZ_Assert((packedCompressedMorphTargetVertexData.size() - metaData.m_startIndex) == numMorphedVertices, "Vertex index range (%d) in morph target meta data does not match number of morphed vertices (%d).",
|
||||
packedCompressedMorphTargetVertexData.size() - metaData.m_startIndex, numMorphedVertices);
|
||||
}
|
||||
|
||||
Data::Asset<RPI::StreamingImageAsset> MorphTargetExporter::GetWrinkleMask(const AZStd::string& sourceSceneFullFilePath, const AZStd::string& blendShapeName) const
|
||||
{
|
||||
AZ::Data::Asset<AZ::RPI::StreamingImageAsset> imageAsset;
|
||||
|
||||
// See if there is a wrinkle map mask for this mesh
|
||||
AZStd::string sceneRelativeFilePath;
|
||||
bool relativePathFound = true;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(relativePathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetRelativeProductPathFromFullSourceOrProductPath, sourceSceneFullFilePath, sceneRelativeFilePath);
|
||||
|
||||
if (relativePathFound)
|
||||
{
|
||||
AZ::StringFunc::Path::StripFullName(sceneRelativeFilePath);
|
||||
|
||||
// Get the folder the masks are supposed to be in
|
||||
AZStd::string folderName;
|
||||
AZ::StringFunc::Path::GetFileName(sourceSceneFullFilePath.c_str(), folderName);
|
||||
folderName += "_wrinklemasks";
|
||||
|
||||
// Note: for now, we're assuming the mask is always authored as a .tif
|
||||
AZStd::string blendMaskFileName = blendShapeName + "_wrinklemask.tif.streamingimage";
|
||||
|
||||
AZStd::string maskFolderAndFile;
|
||||
AZ::StringFunc::Path::Join(folderName.c_str(), blendMaskFileName.c_str(), maskFolderAndFile);
|
||||
|
||||
AZStd::string maskRelativePath;
|
||||
AZ::StringFunc::Path::Join(sceneRelativeFilePath.c_str(), maskFolderAndFile.c_str(), maskRelativePath);
|
||||
AZ::StringFunc::Path::Normalize(maskRelativePath);
|
||||
|
||||
// Now see if the file exists
|
||||
AZ::Data::AssetId maskAssetId;
|
||||
Data::AssetCatalogRequestBus::BroadcastResult(maskAssetId, &Data::AssetCatalogRequests::GetAssetIdByPath, maskRelativePath.c_str(), AZ::Data::s_invalidAssetType, false);
|
||||
|
||||
if (maskAssetId.IsValid())
|
||||
{
|
||||
// Flush asset manager events to ensure no asset references are held by closures queued on Ebuses.
|
||||
AZ::Data::AssetManager::Instance().DispatchEvents();
|
||||
|
||||
imageAsset.Create(maskAssetId, AZ::Data::AssetLoadBehavior::PreLoad, false);
|
||||
}
|
||||
}
|
||||
return imageAsset;
|
||||
}
|
||||
} // namespace AZ::RPI
|
||||
|
||||
@@ -64,7 +64,11 @@ namespace AZ
|
||||
const AZStd::string& blendShapeName,
|
||||
const AZStd::shared_ptr<const AZ::SceneAPI::DataTypes::IBlendShapeData>& blendShapeData,
|
||||
const AZ::SceneAPI::DataTypes::MatrixType& globalTransform,
|
||||
const AZ::SceneAPI::CoordinateSystemConverter& coordSysConverter);
|
||||
const AZ::SceneAPI::CoordinateSystemConverter& coordSysConverter,
|
||||
const AZStd::string& sourceSceneFilename);
|
||||
|
||||
// Find a wrinkle mask for this morph target, if it exists
|
||||
Data::Asset<RPI::StreamingImageAsset> GetWrinkleMask(const AZStd::string& sourceSceneFullFilePath, const AZStd::string& blendShapeName) const;
|
||||
};
|
||||
} // 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