Files
o3de/Gems/Atom/Feature/Common/Code/Source/Decals/DecalFeatureProcessor.cpp
T
galibzon cc615a8f32 [ATOM-15472] Shader Build Pipeline: Remove Deprecated Files And Funct… (#1079)
* [ATOM-15472] Shader Build Pipeline: Remove Deprecated Files And Functions That
Predate The Shader Supervariants

These are the essential impactful changes as a result of deprecating the
ShaderResourceGroupAsset.

* Addressed feedback by @moudgils. Better comments in header files.

* More updates related with deprecation of ShaderResourceGroupAsset

* Deleted the temporary version 2 classes.

* Updated version of the shader asset builders.

* Updated version of all the shader related classes impacted
by the Supervariant concept and deprecation of ShaderResourceGroupAsset

* Changes to *.pass and DGI, Reflections and RayTracing.

* changes to material related assets

* changes to core lights

* Changes to auxgeom/dynamic draw.

* changes to decals, lyshine, imguipass

* changes to RPI Pass classes

* Shader for SceneSrg, ViewSrg and ForwardPass Srgs.

* changes to mesh, skinned mesh, Morphtarget.

* Fixes to RayTracingPass.cpp & now allow empty srg in shaders.

* Updated Atom_RPI.Tests

* Simplified InstanceDatabase by removing AddHandler

------------------------------------------------------------------------------------
* Updated DiffuseGI precompiled shaders.
Added RayTracingSceneSrg and RayTracingMaterialSrg shader asset.
Updated ShaderAssetCreator::Clone to handle the supervariant when processing root variants.
Co-authored-by: Doug McDiarmid <dmcdiar@amazon.com>
------------------------------------------------------------------------------------

* Changed semantics for some PassSrg to SRG_PerPass_WithFallback.

AuxGeom/FixedShapeProcessor.cpp requires SRG_PerDraw on ObjectSrg.

Removed names of SceneSrg and ViewSrg from RPISystemDescriptor.cpp

* Moved ShaderLib/Atom/Features/DummyEntryFunctions.azsli
To  Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/DummyEntryFunctions.azsli

Removed redundant checking for finalization in
ShaderResourceGroupLayout.cpp

* Fixed race condition bug for Shader::FindOrCreate.
InstanceDatabase<>::CreateInstance() needs to be atomic
for instance creation and initialization.

Added optional InstanceHandler::CreateFunctionWithParams to accomodate
to the needs of Instances that need more than an asset reference
to be able to be created an initialzed.

Removed ShaderResourceGroup::FindOrCreate() only ::Create is available
now.

* Renamed scene_and_view_srgs.* as SceneAndViewSrgs.*

Changed GetAzslFileOfOrigin for GetUniqueId

* Fixed unit tests.

* Reverted the serialization name of m_uniqueId back to
"m_azslFileOfOrigin" so precompiled shaders don't fail
in layout comparison.

* Fixed AtomCore.Tests
Removed non-applicable test. InstanceDatabase.AddHandler() is not
available anymore.

* The Null rhi is re-enabled for shader compilation.

Signed-off-by: garrieta <garrieta@amazon.com>
2021-06-11 07:48:23 -05:00

344 lines
14 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Decals/DecalFeatureProcessor.h>
#include <AzCore/Debug/EventTrace.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <Atom/RPI.Public/Material/Material.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/View.h>
#include <AzCore/Math/Quaternion.h>
#include <AtomCore/std/containers/array_view.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
namespace AZ
{
namespace Render
{
DecalFeatureProcessor::DecalFeatureProcessor()
: m_baseColorMapShaderName("m_decalBaseColorMaps")
, m_opacityMapShaderName("m_opacityMaps")
, m_baseColorMapPropertyName("baseColor.textureMap")
, m_opacityMapPropertyName("opacity.textureMap")
{
}
void DecalFeatureProcessor::Reflect(ReflectContext* context)
{
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
{
serializeContext
->Class<DecalFeatureProcessor, RPI::FeatureProcessor>()
->Version(0);
}
}
void DecalFeatureProcessor::Activate()
{
GpuBufferHandler::Descriptor desc;
desc.m_bufferName = "DecalBuffer";
desc.m_bufferSrgName = "m_decals";
desc.m_elementCountSrgName = "m_decalCount";
desc.m_elementSize = sizeof(DecalData);
desc.m_srgLayout = RPI::RPISystemInterface::Get()->GetViewSrgLayout().get();
m_decalBufferHandler = GpuBufferHandler(desc);
CacheShaderIndices();
}
void DecalFeatureProcessor::Deactivate()
{
m_decalData.Clear();
m_decalBufferHandler.Release();
}
DecalFeatureProcessor::DecalHandle DecalFeatureProcessor::AcquireDecal()
{
uint16_t id = m_decalData.GetFreeSlotIndex();
if (id == DataVector::NoFreeSlot)
{
return DecalHandle(DecalHandle::NullIndex);
}
else
{
m_deviceBufferNeedsUpdate = true;
return DecalHandle(id);
}
}
bool DecalFeatureProcessor::ReleaseDecal(DecalHandle decal)
{
if (decal.IsValid())
{
m_decalData.RemoveIndex(decal.GetIndex());
m_deviceBufferNeedsUpdate = true;
return true;
}
return false;
}
DecalFeatureProcessor::DecalHandle DecalFeatureProcessor::CloneDecal(DecalHandle sourceDecal)
{
AZ_Assert(sourceDecal.IsValid(), "Invalid DecalHandle passed to DecalFeatureProcessor::CloneDecal().");
DecalHandle decal = AcquireDecal();
if (decal.IsValid())
{
m_decalData.GetData<0>(decal.GetIndex()) = m_decalData.GetData<0>(sourceDecal.GetIndex());
m_decalData.GetData<1>(decal.GetIndex()) = m_decalData.GetData<1>(sourceDecal.GetIndex());
m_deviceBufferNeedsUpdate = true;
}
return decal;
}
void DecalFeatureProcessor::Simulate(const RPI::FeatureProcessor::SimulatePacket& packet)
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "DecalFeatureProcessor: Simulate");
AZ_UNUSED(packet);
if (m_deviceBufferNeedsUpdate)
{
[[maybe_unused]] bool success = m_decalBufferHandler.UpdateBuffer(m_decalData.GetDataVector<0>());
AZ_Error(FeatureProcessorName, success, "Unable to update buffer during Simulate().");
m_deviceBufferNeedsUpdate = false;
}
}
AZStd::array_view<Data::Instance<RPI::Image>> DecalFeatureProcessor::GetImageArray() const
{
// [GFX TODO][ATOM-4445] Replace this hardcoded constant with atlasing / bindless so we can have far more than 8 decal textures
// Note this constant also is defined in View.srg
const size_t MaxDecals = 8;
size_t numImages = AZStd::min(MaxDecals, m_decalData.GetDataCount());
AZStd::array_view<ImagePtr> imageArrayView(m_decalData.GetDataVector<1>().begin(), m_decalData.GetDataVector<1>().begin() + numImages);
return imageArrayView;
}
void DecalFeatureProcessor::Render(const RPI::FeatureProcessor::RenderPacket& packet)
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "DecalFeatureProcessor: Render");
AZStd::array_view<Data::Instance<RPI::Image>> baseMaps = GetImagesFromDecalData<1>();
AZStd::array_view<Data::Instance<RPI::Image>> opacityMaps = GetImagesFromDecalData<2>();
for (const RPI::ViewPtr& view : packet.m_views)
{
m_decalBufferHandler.UpdateSrg(view->GetShaderResourceGroup().get());
if (baseMaps.empty() == false)
{
view->GetShaderResourceGroup()->SetImageArray(m_baseColorMapsIndex, baseMaps);
}
if (opacityMaps.empty() == false)
{
view->GetShaderResourceGroup()->SetImageArray(m_opacityMapsIndex, opacityMaps);
}
}
}
void DecalFeatureProcessor::SetDecalData(DecalHandle handle, const DecalData& data)
{
if (handle.IsValid())
{
m_decalData.GetData<0>(handle.GetIndex()) = data;
m_deviceBufferNeedsUpdate = true;
}
else
{
AZ_Warning("DecalFeatureProcessor", false, "Invalid handle passed to DecalFeatureProcessor::SetDecalData().");
}
}
const Data::Instance<RPI::Buffer> DecalFeatureProcessor::GetDecalBuffer()const
{
return m_decalBufferHandler.GetBuffer();
}
uint32_t DecalFeatureProcessor::GetDecalCount() const
{
return m_decalBufferHandler.GetElementCount();
}
void DecalFeatureProcessor::SetDecalPosition(DecalHandle handle, const AZ::Vector3& position)
{
if (handle.IsValid())
{
AZStd::array<float, 3>& writePos = m_decalData.GetData<0>(handle.GetIndex()).m_position;
position.StoreToFloat3(writePos.data());
m_deviceBufferNeedsUpdate = true;
}
else
{
AZ_Warning("DecalFeatureProcessor", false, "Invalid handle passed to DecalFeatureProcessor::SetDecalPosition().");
}
}
void DecalFeatureProcessor::SetDecalOrientation(DecalHandle handle, const AZ::Quaternion& orientation)
{
if (handle.IsValid())
{
orientation.StoreToFloat4(m_decalData.GetData<0>(handle.GetIndex()).m_quaternion.data());
m_deviceBufferNeedsUpdate = true;
}
else
{
AZ_Warning("DecalFeatureProcessor", false, "Invalid handle passed to DecalFeatureProcessor::SetDecalOrientation().");
}
}
void DecalFeatureProcessor::SetDecalHalfSize(DecalHandle handle, const Vector3& halfSize)
{
if (handle.IsValid())
{
halfSize.StoreToFloat3(m_decalData.GetData<0>(handle.GetIndex()).m_halfSize.data());
m_deviceBufferNeedsUpdate = true;
}
else
{
AZ_Warning("DecalFeatureProcessor", false, "Invalid handle passed to DecalFeatureProcessor::SetDecalHalfSize().");
}
}
void DecalFeatureProcessor::SetDecalAttenuationAngle(DecalHandle handle, float angleAttenuation)
{
if (handle.IsValid())
{
m_decalData.GetData<0>(handle.GetIndex()).m_angleAttenuation = angleAttenuation;
m_deviceBufferNeedsUpdate = true;
}
else
{
AZ_Warning("DecalFeatureProcessor", handle.IsValid(), "Invalid handle passed to DecalFeatureProcessor::SetDecalAttenuationAngle().");
}
}
void DecalFeatureProcessor::SetDecalOpacity(DecalHandle handle, float opacity)
{
if (handle.IsValid())
{
m_decalData.GetData<0>(handle.GetIndex()).m_opacity = opacity;
m_deviceBufferNeedsUpdate = true;
}
else
{
AZ_Warning("DecalFeatureProcessor", false, "Invalid handle passed to DecalFeatureProcessor::SetDecalOpacity().");
}
}
void DecalFeatureProcessor::SetDecalSortKey(DecalHandle handle, uint8_t sortKey)
{
if (handle.IsValid())
{
m_decalData.GetData<0>(handle.GetIndex()).m_sortKey = sortKey;
m_deviceBufferNeedsUpdate = true;
}
else
{
AZ_Warning("DecalFeatureProcessor", false, "Invalid handle passed to DecalFeatureProcessor::SetDecalSortKey().");
}
}
void DecalFeatureProcessor::SetDecalTransform(DecalHandle handle, const AZ::Transform& world)
{
SetDecalTransform(handle, world, AZ::Vector3::CreateOne());
}
void DecalFeatureProcessor::SetDecalTransform(DecalHandle handle, const AZ::Transform& world, const AZ::Vector3& nonUniformScale)
{
// ATOM-4330
// Original Open 3D Engine uploads a 4x4 matrix rather than quaternion, rotation, scale.
// That is more memory but less calculation because it is doing a matrix inverse rather than a polar decomposition
// I've done some experiments and uploading a 3x4 transform matrix with 3x3 matrix inverse should be possible
// I am putting it as part of a separate Jira because I would have to upload different data to the light culling system
// (not a bad thing, but it would make this commit quite a bit more complex)
if (handle.IsValid())
{
Quaternion orientation = world.GetRotation();
Vector3 scale = world.GetUniformScale() * nonUniformScale;
SetDecalHalfSize(handle, scale);
SetDecalPosition(handle, world.GetTranslation());
SetDecalOrientation(handle, orientation);
m_deviceBufferNeedsUpdate = true;
}
else
{
AZ_Warning("DecalFeatureProcessor", false, "Invalid handle passed to DecalFeatureProcessor::SetTransform().");
}
}
Data::Instance<RPI::Image> DecalFeatureProcessor::GetImageFromMaterial(const AZ::Name& materialPropertyName, Data::Instance<RPI::Material> materialInstance) const
{
Data::Instance<RPI::Image> image;
RPI::MaterialPropertyIndex index = materialInstance->FindPropertyIndex(materialPropertyName);
if (index.IsValid())
{
image = materialInstance->GetPropertyValue<Data::Instance<RPI::Image>>(index);
}
else
{
AZ_Warning("DecalFeatureProcessor", false, "Unable to find %s in material.", materialPropertyName.GetCStr());
}
return image;
}
void DecalFeatureProcessor::SetDecalMaterial(DecalHandle handle, const AZ::Data::AssetId materialAssetId)
{
if (handle.IsNull())
{
AZ_Warning("DecalFeatureProcessor", false, "Invalid handle passed to DecalFeatureProcessor::SetMaterial().");
return;
}
if (materialAssetId.IsValid())
{
const auto materialAsset = AZ::RPI::AssetUtils::LoadAssetById<AZ::RPI::MaterialAsset>(materialAssetId);
Data::Instance<RPI::Material> materialInstance = AZ::RPI::Material::FindOrCreate(materialAsset);
if (materialInstance)
{
const auto baseColorImage = GetImageFromMaterial(m_baseColorMapPropertyName, materialInstance);
const auto opacityImage = GetImageFromMaterial(m_opacityMapPropertyName, materialInstance);
m_decalData.GetData<1>(handle.GetIndex()) = baseColorImage;
m_decalData.GetData<2>(handle.GetIndex()) = opacityImage;
}
}
}
void DecalFeatureProcessor::CacheShaderIndices()
{
const RHI::ShaderResourceGroupLayout* viewSrgLayout = RPI::RPISystemInterface::Get()->GetViewSrgLayout().get();
m_baseColorMapsIndex = viewSrgLayout->FindShaderInputImageIndex(m_baseColorMapShaderName);
AZ_Warning("DecalFeatureProcessor", m_baseColorMapsIndex.IsValid(), "Unable to find baseColorMaps in decal shader.");
m_opacityMapsIndex = viewSrgLayout->FindShaderInputImageIndex(m_opacityMapShaderName);
AZ_Warning("DecalFeatureProcessor", m_opacityMapsIndex.IsValid(), "Unable to find opacityMaps in decal shader.");
}
} // namespace Render
} // namespace AZ