Merge branch 'development' of https://github.com/o3de/o3de into carlitosan/development

This commit is contained in:
chcurran
2021-09-10 11:49:13 -07:00
139 changed files with 2344 additions and 1904 deletions
-51
View File
@@ -1,51 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <viewsrg.srgi>
#include <Atom/RPI/Assets/ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultObjectSrg.azsli>
#include <Atom/RPI/Assets/ShaderLib/Atom/RPI/TangentSpace.azsli>
struct VertexInput
{
float3 m_position : POSITION;
float3 m_normal : NORMAL;
float4 m_tangent : TANGENT;
float3 m_bitangent : BITANGENT;
float2 m_uv : UV0;
};
struct VertexOutput
{
float4 m_position : SV_Position;
float3 m_normal : NORMAL;
float3 m_tangent : TANGENT;
float3 m_bitangent : BITANGENT;
float2 m_uv : UV0;
float3 m_view : VIEW;
};
VertexOutput CommonVS(VertexInput input)
{
float4x4 objectToWorld = ObjectSrg::GetWorldMatrix();
float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose();
VertexOutput output;
float3 worldPosition = mul(objectToWorld, float4(input.m_position, 1)).xyz;
output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0));
output.m_uv = input.m_uv;
output.m_view = worldPosition - ViewSrg::m_worldPosition;
ConstructTBN(input.m_normal, input.m_tangent, input.m_bitangent, objectToWorld, objectToWorldIT, output.m_normal, output.m_tangent, output.m_bitangent);
return output;
}
@@ -10,6 +10,7 @@
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace AZ {
struct Uuid;
@@ -8,14 +8,25 @@
#pragma once
// This is disabled by default because it puts in costly runtime checking of casted values.
// You can either change it here to enable it across the engine, or use push/pop_macro to enable per file/feature.
// Note that if using push/pop_macro, you may get some of the functions not inline and the definition coming from
// another compilation unit, in such case, you will have to push/pop_macro on that compilation unit as well.
// #define AZ_NUMERICCAST_ENABLED 1
#if !AZ_NUMERICCAST_ENABLED
#define aznumeric_cast static_cast
#else
#include <AzCore/Casting/numeric_cast_internal.h>
#include <AzCore/std/typetraits/is_arithmetic.h>
#include <AzCore/std/typetraits/is_class.h>
#include <AzCore/std/typetraits/is_enum.h>
#include <AzCore/std/typetraits/is_floating_point.h>
#include <AzCore/std/typetraits/is_integral.h>
#include <AzCore/std/typetraits/is_same.h>
#include <AzCore/std/typetraits/is_signed.h>
#include <AzCore/std/typetraits/is_unsigned.h>
#include <AzCore/std/typetraits/remove_cvref.h>
#include <AzCore/std/typetraits/underlying_type.h>
#include <AzCore/std/utils.h>
@@ -28,7 +39,7 @@
// enabled.
//
// Because we can't do partial function specialization, I'm using enable_if to chop up the implementation into one of these
// implementations. If none of these fit, then we will get a compile error because it is an unknown conversionr.
// implementations. If none of these fit, then we will get a compile error because it is an unknown conversion.
//
//--------------------------------------------
// TYPE <- TYPE DigitLoss
@@ -51,85 +62,7 @@
// (K) Floating Floating Y
*/
// This is disabled by default because it puts in costly runtime checking of casted values.
// You can either change it here to enable it across the engine, or use push/pop_macro to enable per file/feature.
// Note that if using push/pop_macro, you may get some of the functions not inline and the definition coming from
// another compilation unit, in such case, you will have to push/pop_macro on that compilation unit as well.
// #define AZ_NUMERICCAST_ENABLED 1
#if AZ_NUMERICCAST_ENABLED
#define AZ_NUMERIC_ASSERT(expr, ...) AZ_Assert(expr, __VA_ARGS__)
#else
#define AZ_NUMERIC_ASSERT(expr, ...) void(0)
#endif
#pragma push_macro("max")
#undef max
namespace NumericCastInternal
{
template <typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<
!AZStd::is_integral<FromType>::value || !AZStd::is_floating_point<ToType>::value
, bool> ::type UnderflowsToType(const FromType& value)
{
return (value < static_cast<FromType>(std::numeric_limits<ToType>::lowest()));
}
template <typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<
AZStd::is_integral<FromType>::value && AZStd::is_floating_point<ToType>::value
, bool> ::type UnderflowsToType(const FromType& value)
{
return (static_cast<ToType>(value) < std::numeric_limits<ToType>::lowest());
}
template <typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<
!AZStd::is_integral<FromType>::value || !AZStd::is_floating_point<ToType>::value
, bool> ::type OverflowsToType(const FromType& value)
{
return (value > static_cast<FromType>(std::numeric_limits<ToType>::max()));
}
template <typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<
AZStd::is_integral<FromType>::value && AZStd::is_floating_point<ToType>::value
, bool> ::type OverflowsToType(const FromType& value)
{
return (static_cast<ToType>(value) > std::numeric_limits<ToType>::max());
}
template <typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<
AZStd::is_integral<FromType>::value && AZStd::is_integral<ToType>::value
&& std::numeric_limits<FromType>::digits <= std::numeric_limits<ToType>::digits
&& AZStd::is_signed<FromType>::value && AZStd::is_unsigned<ToType>::value
, bool> ::type FitsInToType(const FromType& value)
{
return !NumericCastInternal::UnderflowsToType<ToType>(value);
}
template <typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<
AZStd::is_integral<FromType>::value && AZStd::is_integral<ToType>::value
&& (std::numeric_limits<FromType>::digits > std::numeric_limits<ToType>::digits)
&& AZStd::is_unsigned<FromType>::value
, bool> ::type FitsInToType(const FromType& value)
{
return !NumericCastInternal::OverflowsToType<ToType>(value);
}
template <typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<
(!AZStd::is_integral<FromType>::value || !AZStd::is_integral<ToType>::value)
|| ((std::numeric_limits<FromType>::digits <= std::numeric_limits<ToType>::digits) && (AZStd::is_unsigned<FromType>::value || AZStd::is_signed<ToType>::value))
|| ((std::numeric_limits<FromType>::digits > std::numeric_limits<ToType>::digits) && AZStd::is_signed<FromType>::value)
, bool> ::type FitsInToType(const FromType& value)
{
return !NumericCastInternal::OverflowsToType<ToType>(value) && !NumericCastInternal::UnderflowsToType<ToType>(value);
}
} // namespace AZ
// INTEGER -> INTEGER
// (A) Not losing digits or risking sign loss
@@ -276,8 +209,10 @@ inline constexpr auto aznumeric_cast(FromType&& value) ->
return static_cast<ToType>(value);
}
#endif
// This is a helper class that lets us induce the destination type of a numeric cast
// It should never be directly used by anything other than azlossy_caster.
// It should never be directly used by anything other than aznumeric_caster.
namespace AZ
{
template <typename FromType>
@@ -295,7 +230,7 @@ namespace AZ
FromType m_value;
};
}
} // namespace AZ
// This is the primary function we should use when doing numeric casting, since it induces the
// type we need to cast to from the code rather than requiring an explicit coupling in the source.
@@ -305,4 +240,3 @@ inline constexpr AZ::NumericCasted<FromType> aznumeric_caster(FromType value)
return AZ::NumericCasted<FromType>(value);
}
#pragma pop_macro("max")
@@ -0,0 +1,81 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/typetraits/conditional.h>
#include <AzCore/std/typetraits/is_floating_point.h>
#include <AzCore/std/typetraits/is_integral.h>
#include <AzCore/std/typetraits/is_signed.h>
#include <AzCore/std/typetraits/is_unsigned.h>
#include <limits>
namespace NumericCastInternal
{
template<typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<!AZStd::is_integral<FromType>::value || !AZStd::is_floating_point<ToType>::value, bool>::type
UnderflowsToType(const FromType& value)
{
return (value < static_cast<FromType>(std::numeric_limits<ToType>::lowest()));
}
template<typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<AZStd::is_integral<FromType>::value && AZStd::is_floating_point<ToType>::value, bool>::type
UnderflowsToType(const FromType& value)
{
return (static_cast<ToType>(value) < std::numeric_limits<ToType>::lowest());
}
template<typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<!AZStd::is_integral<FromType>::value || !AZStd::is_floating_point<ToType>::value, bool>::type
OverflowsToType(const FromType& value)
{
return (value > static_cast<FromType>(std::numeric_limits<ToType>::max()));
}
template<typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<AZStd::is_integral<FromType>::value && AZStd::is_floating_point<ToType>::value, bool>::type
OverflowsToType(const FromType& value)
{
return (static_cast<ToType>(value) > std::numeric_limits<ToType>::max());
}
template<typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<
AZStd::is_integral<FromType>::value && AZStd::is_integral<ToType>::value &&
std::numeric_limits<FromType>::digits <= std::numeric_limits<ToType>::digits && AZStd::is_signed<FromType>::value &&
AZStd::is_unsigned<ToType>::value,
bool>::type
FitsInToType(const FromType& value)
{
return !NumericCastInternal::UnderflowsToType<ToType>(value);
}
template<typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<
AZStd::is_integral<FromType>::value && AZStd::is_integral<ToType>::value &&
(std::numeric_limits<FromType>::digits > std::numeric_limits<ToType>::digits) && AZStd::is_unsigned<FromType>::value,
bool>::type
FitsInToType(const FromType& value)
{
return !NumericCastInternal::OverflowsToType<ToType>(value);
}
template<typename ToType, typename FromType>
inline constexpr typename AZStd::enable_if<
(!AZStd::is_integral<FromType>::value || !AZStd::is_integral<ToType>::value) ||
((std::numeric_limits<FromType>::digits <= std::numeric_limits<ToType>::digits) &&
(AZStd::is_unsigned<FromType>::value || AZStd::is_signed<ToType>::value)) ||
((std::numeric_limits<FromType>::digits > std::numeric_limits<ToType>::digits) && AZStd::is_signed<FromType>::value),
bool>::type
FitsInToType(const FromType& value)
{
return !NumericCastInternal::OverflowsToType<ToType>(value) && !NumericCastInternal::UnderflowsToType<ToType>(value);
}
}
@@ -84,8 +84,9 @@ namespace AZ
static TypeId genericComponentWrapperTypeId("{68D358CA-89B9-4730-8BA6-E181DEA28FDE}");
for (auto& [componentKey, component] : componentMap)
{
// if underlying type is genericComponentWrapperTypeId, the template is null and the component should not be addded
if (component->GetUnderlyingComponentType() != genericComponentWrapperTypeId)
// if the component didn't serialize (i.e. is null) or the underlying type is genericComponentWrapperTypeId, the
// template is null and the component should not be addded
if (component && (component->GetUnderlyingComponentType() != genericComponentWrapperTypeId))
{
entityInstance->m_components.emplace_back(component);
}
+20 -5
View File
@@ -256,8 +256,22 @@ namespace AZ::IO
template <typename PathResultType>
static constexpr void MakeRelativeTo(PathResultType& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base);
template <typename PathResultType>
static constexpr void LexicallyNormalInplace(PathResultType& pathResult, const AZ::IO::PathView& path);
struct PathIterable;
//! Returns a structure that provides a view of the path parts which can be used for iteration
//! Only the path parts that correspond to creating an normalized path is returned
//! This function is useful for returning a "view" into a normalized path without the need
//! to allocate memory for the heap
static constexpr PathIterable GetNormalPathParts(const AZ::IO::PathView& path) noexcept;
// joins the input path to the Path Iterable structure using similiar logic to Path::Append
// If the input path is absolute it will replace the current PathIterable otherwise
// the input path will be appended to the Path Iterable structure
// For example a PathIterable with parts = ['C:', '/', 'foo']
// If the path input = 'bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar']
// If the path input = 'C:/bar', then the new PathIterable parts = [C:', '/', 'bar']
// If the path input = 'C:bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar' ]
// If the path input = 'D:bar', then the new PathIterable parts = [D:, 'bar' ]
static constexpr void AppendNormalPathParts(PathIterable& pathIterableResult, const AZ::IO::PathView& path) noexcept;
constexpr int compare_string_view(AZStd::string_view other) const;
constexpr AZStd::string_view root_name_view() const;
@@ -442,14 +456,15 @@ namespace AZ::IO
constexpr void swap(BasicPath& rhs) noexcept;
// native format observers
constexpr const string_type& Native() const noexcept;
constexpr const string_type& Native() const& noexcept;
constexpr const string_type&& Native() const&& noexcept;
constexpr const value_type* c_str() const noexcept;
constexpr explicit operator string_type() const;
// Adds support for retrieving a modifiable copy of the underlying string
// Any modifications to the string invalidates existing PathIterators
constexpr string_type& Native() noexcept;
constexpr explicit operator string_type&() noexcept;
constexpr string_type& Native() & noexcept;
constexpr string_type&& Native() && noexcept;
//! The string and wstring functions cannot be constexpr until AZStd::basic_string is made constexpr.
//! This cannot occur until C++20 as operator new/delete cannot be used within constexpr functions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,162 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/containers/array.h>
#include <AzCore/IO/Path/PathParser.inl>
namespace AZ::IO
{
struct PathView::PathIterable
{
inline static constexpr size_t MaxPathParts = 64;
using PartKindPair = AZStd::pair<AZStd::string_view, AZ::IO::parser::PathPartKind>;
using PartKindArray = AZStd::array<PartKindPair, MaxPathParts>;
constexpr PathIterable() = default;
[[nodiscard]] constexpr bool empty() const noexcept;
constexpr auto size() const noexcept-> size_t;
constexpr auto begin() noexcept-> PartKindArray::iterator;
constexpr auto begin() const noexcept -> PartKindArray::const_iterator;
constexpr auto cbegin() const noexcept -> PartKindArray::const_iterator;
constexpr auto end() noexcept -> PartKindArray::iterator;
constexpr auto end() const noexcept -> PartKindArray::const_iterator;
constexpr auto cend() const noexcept -> PartKindArray::const_iterator;
constexpr auto rbegin() noexcept -> PartKindArray::reverse_iterator;
constexpr auto rbegin() const noexcept -> PartKindArray::const_reverse_iterator;
constexpr auto crbegin() const noexcept -> PartKindArray::const_reverse_iterator;
constexpr auto rend() noexcept -> PartKindArray::reverse_iterator;
constexpr auto rend() const noexcept -> PartKindArray::const_reverse_iterator;
constexpr auto crend() const noexcept -> PartKindArray::const_reverse_iterator;
[[nodiscard]] constexpr bool IsAbsolute() const noexcept;
private:
template <typename... Args>
constexpr PartKindPair& emplace_back(Args&&... args) noexcept;
constexpr void pop_back() noexcept;
constexpr const PartKindPair& back() const noexcept;
constexpr PartKindPair& back() noexcept;
constexpr const PartKindPair& front() const noexcept;
constexpr PartKindPair& front() noexcept;
constexpr void clear() noexcept;
friend constexpr auto PathView::GetNormalPathParts(const AZ::IO::PathView&) noexcept -> PathIterable;
friend constexpr auto PathView::AppendNormalPathParts(PathIterable& pathIterable, const AZ::IO::PathView&) noexcept -> void;
PartKindArray m_parts{};
size_t m_size{};
};
// public
[[nodiscard]] constexpr auto PathView::PathIterable::empty() const noexcept -> bool
{
return m_size == 0;
}
constexpr auto PathView::PathIterable::size() const noexcept -> size_t
{
return m_size;
}
constexpr auto PathView::PathIterable::begin() noexcept -> PartKindArray::iterator
{
return m_parts.begin();
}
constexpr auto PathView::PathIterable::begin() const noexcept -> PartKindArray::const_iterator
{
return m_parts.begin();
}
constexpr auto PathView::PathIterable::cbegin() const noexcept -> PartKindArray::const_iterator
{
return begin();
}
constexpr auto PathView::PathIterable::end() noexcept -> PartKindArray::iterator
{
return begin() + size();
}
constexpr auto PathView::PathIterable::end() const noexcept -> PartKindArray::const_iterator
{
return begin() + size();
}
constexpr auto PathView::PathIterable::cend() const noexcept -> PartKindArray::const_iterator
{
return end();
}
constexpr auto PathView::PathIterable::rbegin() noexcept -> PartKindArray::reverse_iterator
{
return PartKindArray::reverse_iterator(begin() + size());
}
constexpr auto PathView::PathIterable::rbegin() const noexcept -> PartKindArray::const_reverse_iterator
{
return PartKindArray::const_reverse_iterator(begin() + size());
}
constexpr auto PathView::PathIterable::crbegin() const noexcept -> PartKindArray::const_reverse_iterator
{
return rbegin();
}
constexpr auto PathView::PathIterable::rend() noexcept -> PartKindArray::reverse_iterator
{
return PartKindArray::reverse_iterator(begin());
}
constexpr auto PathView::PathIterable::rend() const noexcept -> PartKindArray::const_reverse_iterator
{
return PartKindArray::const_reverse_iterator(begin());
}
constexpr auto PathView::PathIterable::crend() const noexcept -> PartKindArray::const_reverse_iterator
{
return rend();
}
[[nodiscard]] constexpr auto PathView::PathIterable::IsAbsolute() const noexcept -> bool
{
return !empty() && (front().second == parser::PathPartKind::PK_RootSep
|| (size() > 1 && front().second == parser::PathPartKind::PK_RootName && m_parts[1].second == parser::PathPartKind::PK_RootSep));
}
// private
template <typename... Args>
constexpr auto PathView::PathIterable::emplace_back(Args&&... args) noexcept -> PartKindPair&
{
AZ_Assert(m_size < MaxPathParts, "PathIterable cannot be made out of a path with more than %zu parts", MaxPathParts);
m_parts[m_size++] = PartKindPair{ AZStd::forward<Args>(args)... };
return back();
}
constexpr auto PathView::PathIterable::pop_back() noexcept -> void
{
AZ_Assert(m_size > 0, "Cannot pop_back() from a PathIterable with 0 parts");
--m_size;
}
constexpr auto PathView::PathIterable::back() const noexcept -> const PartKindPair&
{
AZ_Assert(!empty(), "back() was invoked on PathIterable with 0 parts");
return m_parts[m_size - 1];
}
constexpr auto PathView::PathIterable::back() noexcept -> PartKindPair&
{
AZ_Assert(!empty(), "back() was invoked on PathIterable with 0 parts");
return m_parts[m_size - 1];
}
constexpr auto PathView::PathIterable::front() const noexcept -> const PartKindPair&
{
AZ_Assert(!empty(), "front() was invoked on PathIterable with 0 parts");
return m_parts[0];
}
constexpr auto PathView::PathIterable::front() noexcept -> PartKindPair&
{
AZ_Assert(!empty(), "front() was invoked on PathIterable with 0 parts");
return m_parts[0];
}
constexpr auto PathView::PathIterable::clear() noexcept -> void
{
m_size = 0;
}
}
@@ -0,0 +1,706 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/AzCore_Traits_Platform.h>
#include <AzCore/Casting/numeric_cast.h>
namespace AZ::IO::Internal
{
constexpr bool IsSeparator(const char elem)
{
return elem == '/' || elem == '\\';
}
template <typename InputIt, typename EndIt, typename = AZStd::enable_if_t<AZStd::Internal::is_input_iterator_v<InputIt>>>
static constexpr bool HasDrivePrefix(InputIt first, EndIt last)
{
size_t prefixSize = AZStd::distance(first, last);
if (prefixSize < 2 || *AZStd::next(first, 1) != ':')
{
// Drive prefix must be at least two characters and have a colon for the second character
return false;
}
constexpr size_t ValidDrivePrefixRange = 26;
// Uppercase the drive letter by bitwise and'ing out the the 2^5 bit
unsigned char driveLetter = static_cast<unsigned char>(*first);
driveLetter &= 0b1101'1111;
// normalize the character value in the range of A-Z -> 0-25
driveLetter -= 'A';
return driveLetter < ValidDrivePrefixRange;
}
static constexpr bool HasDrivePrefix(AZStd::string_view prefix)
{
return HasDrivePrefix(prefix.begin(), prefix.end());
}
//! Returns an iterator past the end of the consumed root name
//! Windows root names can have include drive letter within them
template <typename InputIt>
constexpr auto ConsumeRootName(InputIt entryBeginIter, InputIt entryEndIter, const char preferredSeparator)
-> AZStd::enable_if_t<AZStd::Internal::is_forward_iterator_v<InputIt>, InputIt>
{
if (preferredSeparator == PosixPathSeparator)
{
// If the preferred separator is forward slash the parser is in posix path
// parsing mode, which doesn't have a root name,
// unless we're on a posix platform that uses a custom path root separator
#if defined(AZ_TRAIT_CUSTOM_PATH_ROOT_SEPARATOR)
const AZStd::string_view path{ entryBeginIter, entryEndIter };
const auto positionOfPathSeparator = path.find(AZ_TRAIT_CUSTOM_PATH_ROOT_SEPARATOR);
if (positionOfPathSeparator != AZStd::string_view::npos)
{
return AZStd::next(entryBeginIter, positionOfPathSeparator + 1);
}
#endif
return entryBeginIter;
}
else
{
// Information for GetRootName has been gathered from Microsoft <filesystem> header
// Below are examples of paths and what there root-name will return
// "/" - returns ""
// "foo/" - returns ""
// "C:DriveRelative" - returns "C:"
// "C:\\DriveAbsolute" - returns "C:"
// "C://DriveAbsolute" - returns "C:"
// "\\server\share" - returns "\\server"
// The following paths are based on the UNC specification to work with paths longer than the 260 character path limit
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN#maximum-path-length-limitation
// \\?\device - returns "\\?"
// \??\device - returns "\??"
// \\.\device - returns "\\."
AZStd::string_view path{ entryBeginIter, entryEndIter };
if (path.size() < 2)
{
// A root name is either <drive letter><colon> or a network path
// therefore it has a least two characters
return entryBeginIter;
}
if (HasDrivePrefix(path))
{
// If the path has a drive prefix, then it has a root name of <driver letter><colon>
return AZStd::next(entryBeginIter, 2);
}
if (!Internal::IsSeparator(path[0]))
{
// At this point all other root names start with a path separator
return entryBeginIter;
}
// Check if the path has the form of "\\?\, "\??\" or "\\.\"
const bool pathInUncForm = path.size() >= 4 && Internal::IsSeparator(path[3])
&& (path.size() == 4 || !Internal::IsSeparator(path[4]));
if (pathInUncForm)
{
// \\?\<0 or more> or \\.\$<zero or more>
const bool slashQuestionMark = Internal::IsSeparator(path[1]) && (path[2] == '?' || path[2] == '.');
// \??\<0 or more>
const bool questionMarkTwice = path[1] == '?' && path[2] == '?';
if (slashQuestionMark || questionMarkTwice)
{
// Return the root value root slash - i.e "\\?"
return AZStd::next(entryBeginIter, 3);
}
}
if (path.size() >= 3 && Internal::IsSeparator(path[1]) && !Internal::IsSeparator(path[2]))
{
// Find the next path separator for network paths that have the form of \\server\share
constexpr AZStd::string_view PathSeparators = { "/\\" };
size_t nextPathSeparatorOffset = path.find_first_of(PathSeparators, 3);
return AZStd::next(entryBeginIter, nextPathSeparatorOffset != AZStd::string_view::npos ? nextPathSeparatorOffset : path.size());
}
return entryBeginIter;
}
}
//! Returns an iterator past the end of the consumed path separator(s)
template <typename InputIt>
constexpr InputIt ConsumeSeparator(InputIt entryBeginIter, InputIt entryEndIter) noexcept
{
return AZStd::find_if_not(entryBeginIter, entryEndIter, [](const char elem) { return Internal::IsSeparator(elem); });
}
//! Returns an iterator past the end of the consumed filename
template <typename InputIt>
constexpr InputIt ConsumeName(InputIt entryBeginIter, InputIt entryEndIter) noexcept
{
return AZStd::find_if(entryBeginIter, entryEndIter, [](const char elem) { return Internal::IsSeparator(elem); });
}
//! Check if a path is absolute on a OS basis
//! If the preferred separator is '/' just checks if the path starts with a '/
//! Otherwise a check for a Windows absolute path occurs
//! Windows absolute paths can include a RootName
template <typename InputIt, typename EndIt, typename = AZStd::enable_if_t<AZStd::Internal::is_input_iterator_v<InputIt>>>
static constexpr bool IsAbsolute(InputIt first, EndIt last, const char preferredSeparator)
{
size_t pathSize = AZStd::distance(first, last);
// If the preferred separator is a forward slash
// than an absolute path is simply one that starts with a forward slash,
// unless we're on a posix platform that uses a custom path root separator
if (preferredSeparator == PosixPathSeparator)
{
#if defined(AZ_TRAIT_CUSTOM_PATH_ROOT_SEPARATOR)
const AZStd::string_view path{ first, last };
return path.find(AZ_TRAIT_CUSTOM_PATH_ROOT_SEPARATOR) != AZStd::string_view::npos;
#else
return pathSize > 0 && IsSeparator(*first);
#endif
}
else
{
if (Internal::HasDrivePrefix(first, last))
{
// If a windows path ends starts with C:foo it is a root relative path
// A path is absolute root absolute on windows if it starts with <drive_letter><colon><path_separator>
return pathSize > 2 && Internal::IsSeparator(*AZStd::next(first, 2));
}
return first != ConsumeRootName(first, last, preferredSeparator);
}
}
static constexpr bool IsAbsolute(AZStd::string_view pathView, const char preferredSeparator)
{
// Uses the template preferred to branch on the absolute path check
// logic
return IsAbsolute(pathView.begin(), pathView.end(), preferredSeparator);
}
// Compares path segments using either Posix or Windows path rules based on the path separator in use
// Posix paths perform a case-sensitive comparison, while Windows paths perform a case-insensitive comparison
static int ComparePathSegment(AZStd::string_view left, AZStd::string_view right, char pathSeparator)
{
const size_t maxCharsToCompare = (AZStd::min)(left.size(), right.size());
int charCompareResult = pathSeparator == PosixPathSeparator
? maxCharsToCompare ? strncmp(left.data(), right.data(), maxCharsToCompare) : 0
: maxCharsToCompare ? azstrnicmp(left.data(), right.data(), maxCharsToCompare) : 0;
return charCompareResult == 0
? static_cast<int>(aznumeric_cast<ptrdiff_t>(left.size()) - aznumeric_cast<ptrdiff_t>(right.size()))
: charCompareResult;
}
}
//! PathParser implementation
//! For internal use only
namespace AZ::IO::parser
{
using parser_path_type = PathView;
using string_view_pair = AZStd::pair<AZStd::string_view, AZStd::string_view>;
using PosPtr = const typename parser_path_type::value_type*;
enum ParserState : uint8_t
{
// Zero is a special sentinel value used by default constructed iterators.
PS_BeforeBegin = PathIterator<PathView>::BeforeBegin,
PS_InRootName = PathIterator<PathView>::InRootName,
PS_InRootDir = PathIterator<PathView>::InRootDir,
PS_InFilenames = PathIterator<PathView>::InFilenames,
PS_AtEnd = PathIterator<PathView>::AtEnd
};
struct PathParser
{
AZStd::string_view m_path_view;
AZStd::string_view m_path_raw_entry;
ParserState m_parser_state{};
const char m_preferred_separator{ AZ_TRAIT_OS_PATH_SEPARATOR };
constexpr PathParser(AZStd::string_view path, ParserState state, const char preferredSeparator) noexcept
: m_path_view(path)
, m_parser_state(state)
, m_preferred_separator(preferredSeparator)
{
}
constexpr PathParser(AZStd::string_view path, AZStd::string_view entry, ParserState state, const char preferredSeparator) noexcept
: m_path_view(path)
, m_path_raw_entry(entry)
, m_parser_state(static_cast<ParserState>(state))
, m_preferred_separator(preferredSeparator)
{
}
constexpr static PathParser CreateBegin(AZStd::string_view path, const char preferredSeparator) noexcept
{
PathParser pathParser(path, PS_BeforeBegin, preferredSeparator);
pathParser.Increment();
return pathParser;
}
constexpr static PathParser CreateEnd(AZStd::string_view path, const char preferredSeparator) noexcept
{
PathParser pathParser(path, PS_AtEnd, preferredSeparator);
return pathParser;
}
constexpr PosPtr Peek() const noexcept
{
auto tokenEnd = getNextTokenStartPos();
auto End = m_path_view.end();
return tokenEnd == End ? nullptr : tokenEnd;
}
constexpr void Increment() noexcept
{
const PosPtr pathEnd = m_path_view.end();
const PosPtr currentPathEntry = getNextTokenStartPos();
if (currentPathEntry == pathEnd)
{
return MakeState(PS_AtEnd);
}
switch (m_parser_state)
{
case PS_BeforeBegin:
{
/*
* First the determine if the path contains only a root-name such as "C:" or is a filename such as "foo"
* root-relative path(Windows only) - C:foo
* root-absolute path - C:\foo
* root-absolute path - /foo
* relative path - foo
*
* Try to consume the root-name then the root directory to determine if path entry
* being parsed is a root-name or filename
* The State transitions from BeforeBegin are
* "C:", "\\server\", "\\?\", "\??\", "\\.\" -> Root Name
* "/", "\" -> Root Directory
* "path/foo", "foo" -> Filename
*/
auto rootNameEnd = Internal::ConsumeRootName(currentPathEntry, pathEnd, m_preferred_separator);
if (currentPathEntry != rootNameEnd)
{
// Transition to the Root Name state
return MakeState(PS_InRootName, currentPathEntry, rootNameEnd);
}
[[fallthrough]];
}
case PS_InRootName:
{
auto rootDirEnd = Internal::ConsumeSeparator(currentPathEntry, pathEnd);
if (currentPathEntry != rootDirEnd)
{
// Transition to Root Directory state
return MakeState(PS_InRootDir, currentPathEntry, rootDirEnd);
}
[[fallthrough]];
}
case PS_InRootDir:
{
auto filenameEnd = Internal::ConsumeName(currentPathEntry, pathEnd);
if (currentPathEntry != filenameEnd)
{
return MakeState(PS_InFilenames, currentPathEntry, filenameEnd);
}
[[fallthrough]];
}
case PS_InFilenames:
{
auto separatorEnd = Internal::ConsumeSeparator(currentPathEntry, pathEnd);
if (separatorEnd != pathEnd)
{
// find the end of the current filename entry
auto filenameEnd = Internal::ConsumeName(separatorEnd, pathEnd);
return MakeState(PS_InFilenames, separatorEnd, filenameEnd);
}
// If after consuming the separator that path entry is at the end iterator
// move the path state to AtEnd
return MakeState(PS_AtEnd);
}
case PS_AtEnd:
AZ_Assert(false, "Path Parser cannot be incremented when it is in the AtEnd state");
}
}
constexpr void Decrement() noexcept
{
auto pathStart = m_path_view.begin();
auto currentPathEntry = getCurrentTokenStartPos();
if (currentPathEntry == pathStart)
{
// we're decrementing the begin
return MakeState(PS_BeforeBegin);
}
switch (m_parser_state)
{
case PS_AtEnd:
{
/*
* First the determine if the path contains only a root-name such as "C:" or is a filename such as "foo"
* root-relative path(Windows only) - C:foo
* root-absolute path - C:\foo
* root-absolute path - /foo
* relative path - foo
* Try to consume the root-name then the root directory to determine if path entry
* being parsed is a root-name or filename
* The State transitions from AtEnd are
* "/path/foo/", "foo/", "C:foo\", "C:\foo\" -> Trailing Separator
* "/path/foo", "foo", "C:foo", "C:\foo" -> Filename
* "/", "C:\" or "\\server\" -> Root Directory
* "C:", "\\server", "\\?", "\??", "\\." -> Root Name
*/
auto rootNameEnd = Internal::ConsumeRootName(pathStart, currentPathEntry, m_preferred_separator);
if (pathStart != rootNameEnd && currentPathEntry == rootNameEnd)
{
// Transition to the Root Name state
return MakeState(PS_InRootName, pathStart, currentPathEntry);
}
auto rootDirEnd = Internal::ConsumeSeparator(rootNameEnd, currentPathEntry);
if (rootNameEnd != rootDirEnd && currentPathEntry == rootDirEnd)
{
// Transition to Root Directory state
return MakeState(PS_InRootDir, rootNameEnd, currentPathEntry);
}
auto filenameEnd = currentPathEntry;
if (Internal::IsSeparator(*(filenameEnd - 1)))
{
// The last character a path separator that isn't root directory
// consume all the preceding path separators
filenameEnd = Internal::ConsumeSeparator(AZStd::make_reverse_iterator(filenameEnd),
AZStd::make_reverse_iterator(rootDirEnd)).base();
}
// The previous state will be Filename, so the beginning of the filename is searched found
auto filenameBegin = Internal::ConsumeName(AZStd::make_reverse_iterator(filenameEnd),
AZStd::make_reverse_iterator(rootDirEnd)).base();
return MakeState(PS_InFilenames, filenameBegin, filenameEnd);
}
case PS_InFilenames:
{
/* The State transitions from Filename are
* "/path/foo" -> Filename
* ^
* "C:\foo" -> Root Directory
* ^
* "C:foo" -> Root Name
* ^
* "foo" -> This case has been taken care of by the current path entry != path start check
* ^
*/
auto rootNameEnd = Internal::ConsumeRootName(pathStart, currentPathEntry, m_preferred_separator);
if (pathStart != rootNameEnd && currentPathEntry == rootNameEnd)
{
// Transition to the Root Name state
return MakeState(PS_InRootName, pathStart, rootNameEnd);
}
auto rootDirEnd = Internal::ConsumeSeparator(rootNameEnd, currentPathEntry);
if (rootNameEnd != rootDirEnd && currentPathEntry == rootDirEnd)
{
// Transition to Root Directory state
return MakeState(PS_InRootDir, rootNameEnd, rootDirEnd);
}
// The previous state will be Filename again, so first the end of that filename is found
// proceeded by finding the beginning of that filename
auto filenameEnd = Internal::ConsumeSeparator(AZStd::make_reverse_iterator(currentPathEntry),
AZStd::make_reverse_iterator(rootDirEnd)).base();
auto filenameBegin = Internal::ConsumeName(AZStd::make_reverse_iterator(filenameEnd),
AZStd::make_reverse_iterator(rootDirEnd)).base();
return MakeState(PS_InFilenames, filenameBegin, filenameEnd);
}
case PS_InRootDir:
{
/* The State transitions from Root Directory are
* "C:\" "\\server\", "\\?\", "\??\", "\\.\" -> Root Name
* ^ ^ ^ ^ ^
* "/" -> This case has been taken care of by the current path entry != path start check
* ^
*/
return MakeState(PS_InRootName, pathStart, currentPathEntry);
}
case PS_InRootName:
// The only valid state transition from Root Name is BeforeBegin
return MakeState(PS_BeforeBegin);
case PS_BeforeBegin:
AZ_Assert(false, "Path Parser cannot be decremented when it is in the BeforeBegin State");
}
}
//! Return a view of the current element in the path processor state
constexpr AZStd::string_view operator*() const noexcept
{
switch (m_parser_state)
{
case PS_BeforeBegin:
[[fallthrough]];
case PS_AtEnd:
[[fallthrough]];
case PS_InRootDir:
return m_preferred_separator == '/' ? "/" : "\\";
case PS_InRootName:
case PS_InFilenames:
return m_path_raw_entry;
default:
AZ_Assert(false, "Path Parser is in an invalid state");
}
return {};
}
constexpr explicit operator bool() const noexcept
{
return m_parser_state != PS_BeforeBegin && m_parser_state != PS_AtEnd;
}
constexpr PathParser& operator++() noexcept
{
Increment();
return *this;
}
constexpr PathParser& operator--() noexcept
{
Decrement();
return *this;
}
constexpr bool AtEnd() const noexcept
{
return m_parser_state == PS_AtEnd;
}
constexpr bool InRootDir() const noexcept
{
return m_parser_state == PS_InRootDir;
}
constexpr bool InRootName() const noexcept
{
return m_parser_state == PS_InRootName;
}
constexpr bool InRootPath() const noexcept
{
return InRootName() || InRootDir();
}
private:
constexpr void MakeState(ParserState newState, typename AZStd::string_view::iterator start, typename AZStd::string_view::iterator end) noexcept
{
m_parser_state = newState;
m_path_raw_entry = AZStd::string_view(start, end);
}
constexpr void MakeState(ParserState newState) noexcept
{
m_parser_state = newState;
m_path_raw_entry = {};
}
//! Return a pointer to the first character after the currently lexed element.
constexpr typename AZStd::string_view::iterator getNextTokenStartPos() const noexcept
{
switch (m_parser_state)
{
case PS_BeforeBegin:
return m_path_view.begin();
case PS_InRootName:
case PS_InRootDir:
case PS_InFilenames:
return m_path_raw_entry.end();
case PS_AtEnd:
return m_path_view.end();
default:
AZ_Assert(false, "Path Parser is in an invalid state");
}
return m_path_view.end();
}
//! Return a pointer to the first character in the currently lexed element.
constexpr typename AZStd::string_view::iterator getCurrentTokenStartPos() const noexcept
{
switch (m_parser_state)
{
case PS_BeforeBegin:
case PS_InRootName:
return m_path_view.begin();
case PS_InRootDir:
case PS_InFilenames:
return m_path_raw_entry.begin();
case PS_AtEnd:
return m_path_view.end();
default:
AZ_Assert(false, "Path Parser is in an invalid state");
}
return m_path_view.end();
}
};
constexpr string_view_pair SeparateFilename(const AZStd::string_view& srcView)
{
if (srcView == "." || srcView == ".." || srcView.empty())
{
return string_view_pair{ srcView, "" };
}
auto pos = srcView.find_last_of('.');
if (pos == AZStd::string_view::npos || pos == 0)
{
return string_view_pair{ srcView, AZStd::string_view{} };
}
return string_view_pair{ srcView.substr(0, pos), srcView.substr(pos) };
}
// path part consumption
constexpr bool ConsumeRootName(PathParser* pathParser)
{
static_assert(PS_BeforeBegin == 1 && PS_InRootName == 2,
"PathParser must be in state before begin or in the root name in order to consume the root name");
while (pathParser->m_parser_state <= PS_InRootName)
{
++(*pathParser);
}
return pathParser->m_parser_state == PS_AtEnd;
}
constexpr bool ConsumeRootDir(PathParser* pathParser)
{
static_assert(PS_BeforeBegin == 1 && PS_InRootName == 2 && PS_InRootDir == 3,
"PathParser must be in state before begin, in the root name or in the root directory in order to consume the root directory");
while (pathParser->m_parser_state <= PS_InRootDir)
{
++(*pathParser);
}
return pathParser->m_parser_state == PS_AtEnd;
}
// path.comparisons
constexpr int CompareRootName(PathParser* lhsPathParser, PathParser* rhsPathParser)
{
if (!lhsPathParser->InRootName() && !rhsPathParser->InRootName())
{
return 0;
}
auto GetRootName = [](PathParser* pathParser) constexpr -> AZStd::string_view
{
return pathParser->InRootName() ? **pathParser : "";
};
int res = Internal::ComparePathSegment(GetRootName(lhsPathParser), GetRootName(rhsPathParser), lhsPathParser->m_preferred_separator);
ConsumeRootName(lhsPathParser);
ConsumeRootName(rhsPathParser);
return res;
}
constexpr int CompareRootDir(PathParser* lhsPathParser, PathParser* rhsPathParser)
{
if (!lhsPathParser->InRootDir() && rhsPathParser->InRootDir())
{
return -1;
}
else if (lhsPathParser->InRootDir() && !rhsPathParser->InRootDir())
{
return 1;
}
else
{
ConsumeRootDir(lhsPathParser);
ConsumeRootDir(rhsPathParser);
return 0;
}
}
constexpr int CompareRelative(PathParser* lhsPathParserPtr, PathParser* rhsPathParserPtr)
{
auto& lhsPathParser = *lhsPathParserPtr;
auto& rhsPathParser = *rhsPathParserPtr;
while (lhsPathParser && rhsPathParser)
{
if (int res = Internal::ComparePathSegment(*lhsPathParser, *rhsPathParser, lhsPathParser.m_preferred_separator);
res != 0)
{
return res;
}
++lhsPathParser;
++rhsPathParser;
}
return 0;
}
constexpr int CompareEndState(PathParser* lhsPathParser, PathParser* rhsPathParser)
{
if (lhsPathParser->AtEnd() && !rhsPathParser->AtEnd())
{
return -1;
}
else if (!lhsPathParser->AtEnd() && rhsPathParser->AtEnd())
{
return 1;
}
return 0;
}
constexpr int DetermineLexicalElementCount(PathParser pathParser)
{
int count = 0;
for (; pathParser; ++pathParser)
{
auto pathElement = *pathParser;
if (pathElement == "..")
{
--count;
}
else if (pathElement != "." && pathElement != "")
{
++count;
}
}
return count;
}
enum class PathPartKind : uint8_t
{
PK_None,
PK_RootName,
PK_RootSep,
PK_Filename,
PK_Dot,
PK_DotDot,
};
constexpr PathPartKind ClassifyPathPart(const PathParser& parser)
{
// Check each parser state to determine the PathPartKind
if (parser.m_parser_state == PS_InRootDir)
{
return PathPartKind::PK_RootSep;
}
if (parser.m_parser_state == PS_InRootName)
{
return PathPartKind::PK_RootName;
}
// Fallback to checking parser pathEntry view value
// to determine if the special "." or ".." values are being used
AZStd::string_view pathPart = *parser;
if (pathPart == ".")
{
return PathPartKind::PK_Dot;
}
if (pathPart == "..")
{
return PathPartKind::PK_DotDot;
}
// Return PathPartKind of PK_ilename if the parser state doesn't match
// the states of InRootDir or InRootName and the filename
// isn't made up of the special directory values of "." and ".."
return PathPartKind::PK_Filename;
}
}
@@ -7,18 +7,17 @@
*/
#pragma once
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/Script/ScriptContext.h>
#include <AzCore/Script/ScriptContextAttributes.h>
#include <AzCore/ScriptCanvas/ScriptCanvasAttributes.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/std/string/conversions.h>
#include <AzCore/std/string/tokenize.h>
#include <AzCore/ScriptCanvas/ScriptCanvasOnDemandNames.h>
#include <AzCore/RTTI/AzStdOnDemandPrettyName.inl>
#include <AzCore/RTTI/AzStdOnDemandReflectionLuaFunctions.inl>
#include <AzCore/EBus/Event.h>
#ifndef AZ_USE_CUSTOM_SCRIPT_BIND
struct lua_State;
struct lua_Debug;
#endif // AZ_USE_CUSTOM_SCRIPT_BIND
// forward declare specialized types
namespace AZStd
@@ -59,6 +58,26 @@ namespace AZ
class BehaviorContext;
class ScriptDataContext;
namespace OnDemandLuaFunctions
{
inline void AnyToLua(lua_State* lua, BehaviorValueParameter& param);
}
namespace ScriptCanvasOnDemandReflection
{
template<typename T>
struct OnDemandPrettyName;
template<typename T>
struct OnDemandToolTip;
template<typename T>
struct OnDemandCategoryName;
}
namespace CommonOnDemandReflections
{
void ReflectCommonString(ReflectContext* context);
void ReflectCommonStringView(ReflectContext* context);
void ReflectStdAny(ReflectContext* context);
void ReflectVoidOutcome(ReflectContext* context);
}
/// OnDemand reflection for AZStd::basic_string
template<class Element, class Traits, class Allocator>
struct OnDemandReflection< AZStd::basic_string<Element, Traits, Allocator> >
@@ -66,108 +85,16 @@ namespace AZ
using ContainerType = AZStd::basic_string<Element, Traits, Allocator>;
using SizeType = typename ContainerType::size_type;
using ValueType = typename ContainerType::value_type;
static void Reflect(ReflectContext* context)
{
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
constexpr bool is_string = AZStd::is_same_v<Element, char> && AZStd::is_same_v<Traits, AZStd::char_traits<char>>
&& AZStd::is_same_v<Allocator, AZStd::allocator>;
if constexpr(is_string)
{
behaviorContext->Class<ContainerType>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->template Constructor<typename ContainerType::value_type*>()
->Attribute(AZ::Script::Attributes::ConstructorOverride, &OnDemandLuaFunctions::ConstructBasicString<Element, Traits, Allocator>)
->Attribute(AZ::Script::Attributes::ReaderWriterOverride, ScriptContext::CustomReaderWriter(&OnDemandLuaFunctions::StringTypeToLua<ContainerType>, &OnDemandLuaFunctions::StringTypeFromLua<ContainerType>))
->template WrappingMember<const char*>(&ContainerType::c_str)
->Method("c_str", &ContainerType::c_str)
->Method("Length", [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->length()); })
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
->Method("Equal", [](const ContainerType& lhs, const ContainerType& rhs)
{
return lhs == rhs;
})
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Equal)
->Method("Find", [](ContainerType* thisPtr, const ContainerType& stringToFind, const int& startPos)
{
return aznumeric_cast<int>(thisPtr->find(stringToFind, startPos));
})
->Method("Substring", [](ContainerType* thisPtr, const int& pos, const int& len)
{
return thisPtr->substr(pos, len);
})
->Method("Replace", [](ContainerType* thisPtr, const ContainerType& stringToReplace, const ContainerType& replacementString)
{
SizeType startPos = 0;
while ((startPos = thisPtr->find(stringToReplace, startPos)) != ContainerType::npos && !stringToReplace.empty())
{
thisPtr->replace(startPos, stringToReplace.length(), replacementString);
startPos += replacementString.length();
}
return *thisPtr;
})
->Method("ReplaceByIndex", [](ContainerType* thisPtr, const int& beginIndex, const int& endIndex, const ContainerType& replacementString)
{
thisPtr->replace(beginIndex, endIndex - beginIndex + 1, replacementString);
return *thisPtr;
})
->Method("Add", [](ContainerType* thisPtr, const ContainerType& addend)
{
return *thisPtr + addend;
})
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Concat)
->Method("TrimLeft", [](ContainerType* thisPtr)
{
auto wsfront = AZStd::find_if_not(thisPtr->begin(), thisPtr->end(), [](char c) {return AZStd::is_space(c);});
thisPtr->erase(thisPtr->begin(), wsfront);
return *thisPtr;
})
->Method("TrimRight", [](ContainerType* thisPtr)
{
auto wsend = AZStd::find_if_not(thisPtr->rbegin(), thisPtr->rend(), [](char c) {return AZStd::is_space(c);});
thisPtr->erase(wsend.base(), thisPtr->end());
return *thisPtr;
})
->Method("ToLower", [](ContainerType* thisPtr)
{
ContainerType toLowerString;
for (auto itr = thisPtr->begin(); itr < thisPtr->end(); itr++)
{
toLowerString.push_back(static_cast<ValueType>(tolower(*itr)));
}
return toLowerString;
})
->Method("ToUpper", [](ContainerType* thisPtr)
{
ContainerType toUpperString;
for (auto itr = thisPtr->begin(); itr < thisPtr->end(); itr++)
{
toUpperString.push_back(static_cast<ValueType>(toupper(*itr)));
}
return toUpperString;
})
->Method("Join", [](AZStd::vector<ContainerType>* stringsToJoinPtr, const ContainerType& joinStr)
{
ContainerType joinString;
for (auto& stringToJoin : *stringsToJoinPtr)
{
joinString.append(stringToJoin).append(joinStr);
}
//Cut off the last join str
if (!stringsToJoinPtr->empty())
{
joinString = joinString.substr(0, joinString.length() - joinStr.length());
}
return joinString;
})
->Method("Split", [](ContainerType* thisPtr, const ContainerType& splitter)
{
AZStd::vector<ContainerType> splitStringList;
AZStd::tokenize(*thisPtr, splitter, splitStringList);
return splitStringList;
})
;
CommonOnDemandReflections::ReflectCommonString(context);
}
static_assert (is_string, "Unspecialized basic_string<> template reflection requested.");
}
};
@@ -181,44 +108,9 @@ namespace AZ
static void Reflect(ReflectContext* context)
{
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
{
behaviorContext->Class<ContainerType>()
->Attribute(AZ::Script::Attributes::Category, "Core")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->template Constructor<typename ContainerType::value_type*>()
->Attribute(AZ::Script::Attributes::ConstructorOverride, &OnDemandLuaFunctions::ConstructStringView<Element, Traits>)
->Attribute(AZ::Script::Attributes::ReaderWriterOverride, ScriptContext::CustomReaderWriter(&OnDemandLuaFunctions::StringTypeToLua<ContainerType>, &OnDemandLuaFunctions::StringTypeFromLua<ContainerType>))
->Method("ToString", [](const ContainerType& stringView) { return static_cast<AZStd::string>(stringView).c_str(); }, { { { "Reference", "String view object being converted to string" } } })
->Attribute(AZ::Script::Attributes::ToolTip, "Converts string_view to string")
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString)
->template WrappingMember<const char*>(&ContainerType::data)
->Method("data", &ContainerType::data)
->Attribute(AZ::Script::Attributes::ToolTip, "Returns reference to raw string data")
->Method("length", [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->length()); }, { { { "This", "Reference to the object the method is being performed on" } } })
->Attribute(AZ::Script::Attributes::ToolTip, "Returns length of string view")
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
->Method("size", [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->size()); }, { { { "This", "Reference to the object the method is being performed on" }} })
->Attribute(AZ::Script::Attributes::ToolTip, "Returns length of string view")
->Method("find", [](ContainerType* thisPtr, ContainerType stringToFind, int startPos)
{
return aznumeric_cast<int>(thisPtr->find(stringToFind, startPos));
}, { { { "This", "Reference to the object the method is being performed on" }, { "View", "View to search " }, { "Position", "Index in view to start search" }} })
->Attribute(AZ::Script::Attributes::ToolTip, "Searches for supplied string within this string")
->Method("substr", [](ContainerType* thisPtr, int pos, int len)
{
return thisPtr->substr(pos, len);
}, { {{"This", "Reference to the object the method is being performed on"}, {"Position", "Index in view that indicates the beginning of the sub string"}, {"Count", "Length of characters that sub string view occupies" }} })
->Attribute(AZ::Script::Attributes::ToolTip, "Creates a sub view of this string view. The string data is not actually modified")
->Method("remove_prefix", [](ContainerType* thisPtr, int n) {thisPtr->remove_prefix(n); },
{ { { "This", "Reference to the object the method is being performed on" }, { "Count", "Number of characters to remove from start of view" }} })
->Attribute(AZ::Script::Attributes::ToolTip, "Moves the supplied number of characters from the beginning of this sub view")
->Method("remove_suffix", [](ContainerType* thisPtr, int n) {thisPtr->remove_suffix(n); },
{ { { "This", "Reference to the object the method is being performed on" } ,{ "Count", "Number of characters to remove from end of view" }} })
->Attribute(AZ::Script::Attributes::ToolTip, "Moves the supplied number of characters from the end of this sub view")
;
}
constexpr bool is_common = AZStd::is_same_v<Element,char> && AZStd::is_same_v<Traits,AZStd::char_traits<char>>;
static_assert (is_common, "Unspecialized basic_string_view<> template reflection requested.");
CommonOnDemandReflections::ReflectCommonStringView(context);
}
};
@@ -228,7 +120,7 @@ namespace AZ
{
using ContainerType = AZStd::intrusive_ptr<T>;
// TODO: Count reflection types for a proper un-reflect
// TODO: Count reflection types for a proper un-reflect
static void CustomConstructor(ContainerType* thisPtr, ScriptDataContext& dc)
{
@@ -276,7 +168,7 @@ namespace AZ
{
using ContainerType = AZStd::shared_ptr<T>;
// TODO: Count reflection types for a proper un-reflect
// TODO: Count reflection types for a proper un-reflect
static void CustomConstructor(ContainerType* thisPtr, ScriptDataContext& dc)
{
@@ -435,7 +327,7 @@ namespace AZ
thisPtr[uindex] = value;
}
static bool EraseCheck_VM(ContainerType& thisPtr, AZ::u64 index)
{
if (index < thisPtr.size())
@@ -448,7 +340,7 @@ namespace AZ
return false;
}
}
static ContainerType& ErasePost_VM(ContainerType& thisPtr, AZ::u64 /*index*/)
{
return thisPtr;
@@ -604,7 +496,7 @@ namespace AZ
return AZ::Failure(AZStd::string::format("Index out of bounds: %zu (size: %zu)", index, thisContainer.size()));
}
}
static AZ::Outcome<void, void> Replace(ContainerType& thisContainer, size_t index, T& value)
{
if (index >= 0 && index < thisContainer.size())
@@ -634,7 +526,7 @@ namespace AZ
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Method(k_accessElementName, &At, {{ {}, { "Index", "The index to read from", nullptr, BehaviorParameter::Traits::TR_INDEX }}})
->Method(k_sizeName, [](ContainerType*) { return aznumeric_cast<int>(N); })
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
@@ -743,27 +635,8 @@ namespace AZ
template<> // in case someone has an issue with bool
struct OnDemandReflection<AZ::Outcome<void, void>>
{
using OutcomeType = AZ::Outcome<void, void>;
static void Reflect(ReflectContext* context)
{
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
{
// note we can reflect iterator types and support iterators, as of know we want to keep it simple
behaviorContext->Class<OutcomeType>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, true)
->Attribute(AZ::ScriptCanvasAttributes::PrettyName, &ScriptCanvasOnDemandReflection::OnDemandPrettyName<OutcomeType>::Get)
->Attribute(AZ::Script::Attributes::ToolTip, &ScriptCanvasOnDemandReflection::OnDemandToolTip<OutcomeType>::Get)
->Attribute(AZ::Script::Attributes::Category, &ScriptCanvasOnDemandReflection::OnDemandCategoryName<OutcomeType>::Get)
->Attribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, AttributeIsValid::IfPresent)
->Attribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden, AttributeIsValid::IfPresent)
->Method("Failure", []() -> OutcomeType { return AZ::Failure(); })
->Method("Success", []() -> OutcomeType { return AZ::Success(); })
->Method("IsSuccess", &OutcomeType::IsSuccess)
;
}
static void Reflect(ReflectContext* context) {
CommonOnDemandReflections::ReflectVoidOutcome(context);
}
};
@@ -1179,16 +1052,8 @@ namespace AZ
template <>
struct OnDemandReflection<AZStd::any>
{
static void Reflect(ReflectContext* context)
{
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
{
behaviorContext->Class<AZStd::any>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(Script::Attributes::Ignore, true) // Don't reflect any type to script (there should never be an any instance in script)
->Attribute(Script::Attributes::ReaderWriterOverride, ScriptContext::CustomReaderWriter(&AZ::OnDemandLuaFunctions::AnyToLua, &OnDemandLuaFunctions::AnyFromLua))
;
}
static void Reflect(ReflectContext* context) {
CommonOnDemandReflections::ReflectStdAny(context);
}
};
@@ -0,0 +1,208 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Math/Uuid.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/RTTI/TypeInfo.h>
#include <AzCore/std/string/alphanum.h>
#include <AzCore/std/string/conversions.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/string/tokenize.h>
#include <AzCore/RTTI/AzStdOnDemandReflection.inl>
#include <AzCore/RTTI/AzStdOnDemandReflectionLuaFunctions.inl>
namespace AZ::CommonOnDemandReflections
{
void ReflectCommonString(ReflectContext* context)
{
using ContainerType = AZStd::string;
using SizeType = typename ContainerType::size_type;
using ValueType = typename ContainerType::value_type;
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
{
behaviorContext->Class<ContainerType>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->template Constructor<typename ContainerType::value_type*>()
->Attribute(AZ::Script::Attributes::ConstructorOverride, &OnDemandLuaFunctions::ConstructBasicString<ContainerType::value_type, ContainerType::traits_type, ContainerType::allocator_type>)
->Attribute(AZ::Script::Attributes::ReaderWriterOverride, ScriptContext::CustomReaderWriter(&OnDemandLuaFunctions::StringTypeToLua<ContainerType>, &OnDemandLuaFunctions::StringTypeFromLua<ContainerType>))
->template WrappingMember<const char*>(&ContainerType::c_str)
->Method("c_str", &ContainerType::c_str)
->Method("Length", [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->length()); })
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
->Method("Equal", [](const ContainerType& lhs, const ContainerType& rhs)
{
return lhs == rhs;
})
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Equal)
->Method("Find", [](ContainerType* thisPtr, const ContainerType& stringToFind, const int& startPos)
{
return aznumeric_cast<int>(thisPtr->find(stringToFind, startPos));
})
->Method("Substring", [](ContainerType* thisPtr, const int& pos, const int& len)
{
return thisPtr->substr(pos, len);
})
->Method("Replace", [](ContainerType* thisPtr, const ContainerType& stringToReplace, const ContainerType& replacementString)
{
SizeType startPos = 0;
while ((startPos = thisPtr->find(stringToReplace, startPos)) != ContainerType::npos && !stringToReplace.empty())
{
thisPtr->replace(startPos, stringToReplace.length(), replacementString);
startPos += replacementString.length();
}
return *thisPtr;
})
->Method("ReplaceByIndex", [](ContainerType* thisPtr, const int& beginIndex, const int& endIndex, const ContainerType& replacementString)
{
thisPtr->replace(beginIndex, endIndex - beginIndex + 1, replacementString);
return *thisPtr;
})
->Method("Add", [](ContainerType* thisPtr, const ContainerType& addend)
{
return *thisPtr + addend;
})
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Concat)
->Method("TrimLeft", [](ContainerType* thisPtr)
{
auto wsfront = AZStd::find_if_not(thisPtr->begin(), thisPtr->end(), [](char c) {return AZStd::is_space(c);});
thisPtr->erase(thisPtr->begin(), wsfront);
return *thisPtr;
})
->Method("TrimRight", [](ContainerType* thisPtr)
{
auto wsend = AZStd::find_if_not(thisPtr->rbegin(), thisPtr->rend(), [](char c) {return AZStd::is_space(c);});
thisPtr->erase(wsend.base(), thisPtr->end());
return *thisPtr;
})
->Method("ToLower", [](ContainerType* thisPtr)
{
ContainerType toLowerString;
for (auto itr = thisPtr->begin(); itr < thisPtr->end(); itr++)
{
toLowerString.push_back(static_cast<ValueType>(tolower(*itr)));
}
return toLowerString;
})
->Method("ToUpper", [](ContainerType* thisPtr)
{
ContainerType toUpperString;
for (auto itr = thisPtr->begin(); itr < thisPtr->end(); itr++)
{
toUpperString.push_back(static_cast<ValueType>(toupper(*itr)));
}
return toUpperString;
})
->Method("Join", [](AZStd::vector<ContainerType>* stringsToJoinPtr, const ContainerType& joinStr)
{
ContainerType joinString;
for (auto& stringToJoin : *stringsToJoinPtr)
{
joinString.append(stringToJoin).append(joinStr);
}
//Cut off the last join str
if (!stringsToJoinPtr->empty())
{
joinString = joinString.substr(0, joinString.length() - joinStr.length());
}
return joinString;
})
->Method("Split", [](ContainerType* thisPtr, const ContainerType& splitter)
{
AZStd::vector<ContainerType> splitStringList;
AZStd::tokenize(*thisPtr, splitter, splitStringList);
return splitStringList;
})
;
}
}
void ReflectCommonStringView(ReflectContext* context)
{
using ContainerType = AZStd::string_view;
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
{
behaviorContext->Class<ContainerType>()
->Attribute(AZ::Script::Attributes::Category, "Core")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->template Constructor<typename ContainerType::value_type*>()
->Attribute(AZ::Script::Attributes::ConstructorOverride, &OnDemandLuaFunctions::ConstructStringView<ContainerType::value_type, ContainerType::traits_type>)
->Attribute(AZ::Script::Attributes::ReaderWriterOverride, ScriptContext::CustomReaderWriter(&OnDemandLuaFunctions::StringTypeToLua<ContainerType>, &OnDemandLuaFunctions::StringTypeFromLua<ContainerType>))
->Method("ToString", [](const ContainerType& stringView) { return static_cast<AZStd::string>(stringView).c_str(); }, { { { "Reference", "String view object being converted to string" } } })
->Attribute(AZ::Script::Attributes::ToolTip, "Converts string_view to string")
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString)
->template WrappingMember<const char*>(&ContainerType::data)
->Method("data", &ContainerType::data)
->Attribute(AZ::Script::Attributes::ToolTip, "Returns reference to raw string data")
->Method("length", [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->length()); }, { { { "This", "Reference to the object the method is being performed on" } } })
->Attribute(AZ::Script::Attributes::ToolTip, "Returns length of string view")
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
->Method("size", [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->size()); }, { { { "This", "Reference to the object the method is being performed on" }} })
->Attribute(AZ::Script::Attributes::ToolTip, "Returns length of string view")
->Method("find", [](ContainerType* thisPtr, ContainerType stringToFind, int startPos)
{
return aznumeric_cast<int>(thisPtr->find(stringToFind, startPos));
}, { { { "This", "Reference to the object the method is being performed on" }, { "View", "View to search " }, { "Position", "Index in view to start search" }} })
->Attribute(AZ::Script::Attributes::ToolTip, "Searches for supplied string within this string")
->Method("substr", [](ContainerType* thisPtr, int pos, int len)
{
return thisPtr->substr(pos, len);
}, { {{"This", "Reference to the object the method is being performed on"}, {"Position", "Index in view that indicates the beginning of the sub string"}, {"Count", "Length of characters that sub string view occupies" }} })
->Attribute(AZ::Script::Attributes::ToolTip, "Creates a sub view of this string view. The string data is not actually modified")
->Method("remove_prefix", [](ContainerType* thisPtr, int n) {thisPtr->remove_prefix(n); },
{ { { "This", "Reference to the object the method is being performed on" }, { "Count", "Number of characters to remove from start of view" }} })
->Attribute(AZ::Script::Attributes::ToolTip, "Moves the supplied number of characters from the beginning of this sub view")
->Method("remove_suffix", [](ContainerType* thisPtr, int n) {thisPtr->remove_suffix(n); },
{ { { "This", "Reference to the object the method is being performed on" } ,{ "Count", "Number of characters to remove from end of view" }} })
->Attribute(AZ::Script::Attributes::ToolTip, "Moves the supplied number of characters from the end of this sub view")
;
}
}
void ReflectVoidOutcome(ReflectContext* context)
{
using OutcomeType = AZ::Outcome<void, void>;
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
{
// note we can reflect iterator types and support iterators, as of know we want to keep it simple
behaviorContext->Class<OutcomeType>()
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, true)
->Attribute(AZ::ScriptCanvasAttributes::PrettyName, &ScriptCanvasOnDemandReflection::OnDemandPrettyName<OutcomeType>::Get)
->Attribute(AZ::Script::Attributes::ToolTip, &ScriptCanvasOnDemandReflection::OnDemandToolTip<OutcomeType>::Get)
->Attribute(AZ::Script::Attributes::Category, &ScriptCanvasOnDemandReflection::OnDemandCategoryName<OutcomeType>::Get)
->Attribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, AttributeIsValid::IfPresent)
->Attribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden, AttributeIsValid::IfPresent)
->Method("Failure", []() -> OutcomeType { return AZ::Failure(); })
->Method("Success", []() -> OutcomeType { return AZ::Success(); })
->Method("IsSuccess", &OutcomeType::IsSuccess)
;
}
}
void ReflectStdAny(ReflectContext* context)
{
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
{
behaviorContext->Class<AZStd::any>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(
Script::Attributes::Ignore, true) // Don't reflect any type to script (there should never be an any instance in script)
->Attribute(
Script::Attributes::ReaderWriterOverride,
ScriptContext::CustomReaderWriter(&AZ::OnDemandLuaFunctions::AnyToLua, &OnDemandLuaFunctions::AnyFromLua));
}
}
} // namespace AZ
@@ -8,14 +8,14 @@
#pragma once
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/Casting/numeric_cast_internal.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/std/string/string_view.h>
#include <AzCore/std/string/osstring.h>
namespace AZ
{
//! A helper function to casts between numeric types, and consider the data which is being converted comse from user data.
//! A helper function to casts between numeric types, and consider the data which is being converted comes from user data.
//! If a conversion from FromType to ToType will not cause overflow or underflow, the result is stored in result, and the function returns Success
//! Otherwise, the target is left untouched.
template <typename ToType, typename FromType>
@@ -24,9 +24,9 @@ namespace AZ
{
using namespace JsonSerializationResult;
if (NumericCastInternal::FitsInToType<ToType>(value))
if (NumericCastInternal::template FitsInToType<ToType>(value))
{
result = aznumeric_cast<ToType>(value);
result = static_cast<ToType>(value);
return reporting("Successfully cast number.", ResultCode(Tasks::Convert, Outcomes::Success), path);
}
else
@@ -6,6 +6,7 @@
*
*/
#include <AzCore/IO/ByteContainerStream.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
@@ -35,6 +35,7 @@ set(FILES
Asset/AssetInternal/WeakAsset.h
Casting/lossy_cast.h
Casting/numeric_cast.h
Casting/numeric_cast_internal.h
Component/Component.cpp
Component/Component.h
Component/ComponentApplication.cpp
@@ -176,6 +177,8 @@ set(FILES
IO/Path/Path.cpp
IO/Path/Path.h
IO/Path/Path.inl
IO/Path/PathIterable.inl
IO/Path/PathParser.inl
IO/Path/Path_fwd.h
IO/SystemFile.cpp
IO/SystemFile.h
@@ -440,6 +443,7 @@ set(FILES
RTTI/AttributeReader.h
RTTI/AzStdOnDemandPrettyName.inl
RTTI/AzStdOnDemandReflection.inl
RTTI/AzStdOnDemandReflectionSpecializations.cpp
RTTI/AzStdOnDemandReflectionLuaFunctions.inl
RTTI/BehaviorContext.cpp
RTTI/BehaviorContext.h
@@ -15,7 +15,7 @@ namespace AZStd
{
namespace Platform
{
void PostThreadRun();
unsigned __stdcall PostThreadRun();
HANDLE CreateThread(unsigned stackSize, unsigned (__stdcall* threadRunFunction)(void*), AZStd::Internal::thread_info* ti, unsigned int* id);
unsigned HardwareConcurrency();
void SetThreadName(HANDLE hThread, const char* threadName);
@@ -40,9 +40,7 @@ namespace AZStd
ThreadEventBus::Broadcast(&ThreadEventBus::Events::OnThreadExit, this_thread::get_id()); // goes to client listeners
ThreadDrillerEventBus::Broadcast(&ThreadDrillerEventBus::Events::OnThreadExit, this_thread::get_id()); // goes to the profiler.
Platform::PostThreadRun();
return 0;
return Platform::PostThreadRun();
}
/**
@@ -16,9 +16,10 @@ namespace AZStd
{
namespace Platform
{
void PostThreadRun()
unsigned __stdcall PostThreadRun()
{
_endthreadex(0);
return 0;
}
HANDLE CreateThread(unsigned stackSize, unsigned (__stdcall* threadRunFunction)(void*), AZStd::Internal::thread_info* ti, unsigned int* id)
@@ -56,7 +56,7 @@ namespace UnitTest
}
// filesystem::path::is_absolute test
// PathView::IsAbsolute test
TEST_F(PathFixture, IsAbsolute_ReturnsTrue)
{
using fixed_max_path = AZ::IO::FixedMaxPath;
@@ -88,7 +88,7 @@ namespace UnitTest
static_assert(IsAbsolute());
}
// filesystem::path::is_relative test
// PathView::isRelative test
TEST_F(PathFixture, IsRelative_ReturnsTrue)
{
using fixed_max_path = AZ::IO::FixedMaxPath;
@@ -573,7 +573,16 @@ namespace UnitTest
PathLexicallyNormalParams{ '/', "foo/./bar/..", "foo" },
PathLexicallyNormalParams{ '/', "foo/.///bar/../", "foo" },
PathLexicallyNormalParams{ '/', R"(/foo\./bar\..\)", "/foo" },
PathLexicallyNormalParams{ '\\', R"(C:/O3DE/dev/Cache\game/../pc)", R"(C:\O3DE\dev\Cache\pc)" }
PathLexicallyNormalParams{ '/', R"(/..)", "/" },
PathLexicallyNormalParams{ '\\', R"(C:/O3DE/dev/Cache\game/../pc)", R"(C:\O3DE\dev\Cache\pc)" },
PathLexicallyNormalParams{ '\\', R"(C:/foo/C:bar)", R"(C:\foo\bar)" },
PathLexicallyNormalParams{ '\\', R"(C:foo/C:bar)", R"(C:foo\bar)" },
PathLexicallyNormalParams{ '\\', R"(C:/foo/C:/bar)", R"(C:\bar)" },
PathLexicallyNormalParams{ '\\', R"(C:/foo/C:)", R"(C:\foo)" },
PathLexicallyNormalParams{ '\\', R"(C:/foo/C:/)", R"(C:\)" },
PathLexicallyNormalParams{ '\\', R"(C:/foo/D:bar)", R"(D:bar)" },
PathLexicallyNormalParams{ '\\', R"(..)", R"(..)" },
PathLexicallyNormalParams{ '\\', R"(foo/../../bar)", R"(..\bar)" }
)
);
@@ -641,7 +650,12 @@ namespace UnitTest
PathViewLexicallyProximateParams{ '\\', "C:\\a\\b", "C:\\a\\d\\c", "..\\..\\b", false },
PathViewLexicallyProximateParams{ '\\', "C:a\\b", "C:\\a\\b", "C:a\\b", false },
PathViewLexicallyProximateParams{ '\\', "C:\\a\\b", "C:a\\b", "C:\\a\\b", false },
PathViewLexicallyProximateParams{ '\\', "E:\\a\\b", "F:\\a\\b", "E:\\a\\b", false }
PathViewLexicallyProximateParams{ '\\', "E:\\a\\b", "F:\\a\\b", "E:\\a\\b", false },
PathViewLexicallyProximateParams{ '\\', "D:/o3de/proJECT/cache/asset.txt", "d:\\o3de\\Project\\Cache", "asset.txt", true },
PathViewLexicallyProximateParams{ '\\', "D:/o3de/proJECT/cache/pc/..", "d:\\o3de\\Project\\Cache", "pc\\..", true },
PathViewLexicallyProximateParams{ '\\', "D:/o3de/proJECT/cache/pc/asset.txt/..", "d:\\o3de\\Project\\Cache\\", "pc\\asset.txt\\..", true },
PathViewLexicallyProximateParams{ '\\', "D:/o3de/proJECT/cache\\", "D:\\o3de\\Project\\Cache/", ".", true },
PathViewLexicallyProximateParams{ '\\', "D:/o3de/proJECT/cache/../foo", "D:\\o3de\\Project\\Cache", "..\\foo", false }
)
);
@@ -10,11 +10,12 @@
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Settings/SettingsRegistryScriptUtils.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/std/containers/variant.h>
namespace SettingsRegistryScriptUtilsTests
{
static constexpr const char* SettingsRegistryScriptClassName = "SettingsRegistryInterface";
class SettingsRegistryBehaviorContextFixture
: public UnitTest::ScopedAllocatorSetupFixture
@@ -77,7 +78,7 @@ namespace SettingsRegistryScriptUtilsTests
// so the invoking the getter on global Settings Registry should succeed, but return nullptr
EXPECT_TRUE(globalSettingsRegistryGetter->InvokeResult(settingsRegistryObject));
EXPECT_EQ(nullptr, settingsRegistryObject.m_settingsRegistry);
// Register the Settings Registry stored on the fixture with the SettingsRegistry Interface<T>
AZ::SettingsRegistry::Register(m_registry.get());
EXPECT_TRUE(globalSettingsRegistryGetter->InvokeResult(settingsRegistryObject));
@@ -227,7 +228,7 @@ namespace SettingsRegistryScriptUtilsTests
R"( "intIndex": -55)" "\n"
R"( })" "\n"
R"(])";
// Populate the settings registry to match the expected json values
m_registry->Set("/TestObject/boolValue", false);
m_registry->Set("/TestObject/intValue", aznumeric_cast<AZ::s64>(17));
@@ -562,4 +563,4 @@ namespace SettingsRegistryScriptUtilsTests
SettingsRegistryBehaviorContextParams{ "/TestObject/stringValue", AZStd::string_view{"Hello World"}, "GetString", "SetString" }
)
);
}
}
@@ -18,6 +18,7 @@
#include <AzCore/std/functional.h>
#include <AzCore/std/parallel/thread.h>
#include <AzCore/std/string/string.h>
#include <AzCore/PlatformIncl.h>
#include <AzFramework/CommandLine/CommandLine.h>
@@ -689,9 +689,6 @@ namespace AZ::IO
return AZ::IO::InvalidHandle;
}
AZ_PROFILE_SCOPE(Game, "File: %.*s Archive: %p",
aznumeric_cast<int>(pName.size()), pName.data(), this);
SAutoCollectFileAccessTime accessTime(this);
AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
@@ -1915,7 +1912,7 @@ namespace AZ::IO
return m_pFileEntry->nFileDataOffset;
}
bool Archive::MakeDir(AZStd::string_view szPathIn, [[maybe_unused]] bool bGamePathMapping)
bool Archive::MakeDir(AZStd::string_view szPathIn)
{
AZ::IO::StackString pathStr{ szPathIn };
// Determine if there is a period ('.') after the last slash to determine if the path contains a file.
@@ -2330,7 +2327,9 @@ namespace AZ::IO
// we only want to record ASSET access
// assets are identified as things which start with no alias, or with the @assets@ alias
auto assetPath = AZ::IO::FileIOBase::GetInstance()->ConvertToAlias(szFilename);
if (assetPath && assetPath->Native().starts_with("@assets@"))
if (assetPath && (assetPath->Native().starts_with("@assets@")
|| assetPath->Native().starts_with("@root@")
|| assetPath->Native().starts_with("@projectplatformcache@")))
{
IResourceList* pList = GetResourceList(m_eRecordFileOpenList);
@@ -249,7 +249,7 @@ namespace AZ::IO
IArchive::SignedFileSize GetFileSizeOnDisk(AZStd::string_view filename) override;
// creates a directory
bool MakeDir(AZStd::string_view szPath, bool bGamePathMapping = false) override;
bool MakeDir(AZStd::string_view szPath) override;
// compresses the raw data into raw data. The buffer for compressed data itself with the heap passed. Uses method 8 (deflate)
// returns one of the Z_* errors (Z_OK upon success)
@@ -335,7 +335,7 @@ namespace AZ::IO
virtual IArchive::SignedFileSize GetFileSizeOnDisk(AZStd::string_view filename) = 0;
// creates a directory
virtual bool MakeDir(AZStd::string_view szPath, bool bGamePathMapping = false) = 0;
virtual bool MakeDir(AZStd::string_view szPath) = 0;
// open the physical archive file - creates if it doesn't exist
// returns NULL if it's invalid or can't open the file
@@ -287,11 +287,8 @@ namespace AZ
const char* assetAliasPath = GetAlias("@assets@");
if (path && assetAliasPath)
{
AZStd::string assetsAlias(assetAliasPath);
AZStd::string pathString = path;
AZStd::to_lower(assetsAlias.begin(), assetsAlias.end());
AZStd::to_lower(pathString.begin(), pathString.end());
if (AZ::IO::PathView(pathString.c_str()).IsRelativeTo(assetsAlias.c_str()))
const AZ::IO::PathView pathView(path);
if (pathView.IsRelativeTo(assetAliasPath))
{
AZ_Error("FileIO", false, "You may not alter data inside the asset cache. Please check the call stack and consider writing into the source asset folder instead.\n"
"Attempted write location: %s", path);
@@ -587,26 +584,11 @@ namespace AZ
// strings that are shorter than the alias's mapped path without checking.
if ((longestMatch == 0) || (resolvedAlias.size() > longestMatch) && (resolvedAlias.size() <= bufStringLength))
{
// custom strcmp that ignores slash directions
constexpr AZStd::string_view pathSeparators{ "/\\" };
bool allMatch = AZStd::equal(resolvedAlias.begin(), resolvedAlias.end(), inBuffer.begin(),
[&pathSeparators](const char lhs, const char rhs)
// Check if the input path is relative to the alias value
if (AZ::IO::PathView(inBuffer).IsRelativeTo(AZ::IO::PathView(resolvedAlias)))
{
const bool lhsIsSeparator = pathSeparators.find_first_of(lhs) != AZStd::string_view::npos;
const bool rhsIsSeparator = pathSeparators.find_first_of(lhs) != AZStd::string_view::npos;
return (lhsIsSeparator && rhsIsSeparator) || tolower(lhs) == tolower(rhs);
});
if (allMatch)
{
// Either the resolvedAlias path must match the path exactly or the path must have a path separator character
// right after the resolved alias
if (const size_t matchLen = resolvedAlias.size();
matchLen == bufStringLength || (pathSeparators.find_first_of(inBuffer[matchLen]) != AZStd::string_view::npos))
{
longestMatch = matchLen;
longestAlias = alias;
}
longestMatch = resolvedAlias.size();
longestAlias = alias;
}
}
}
@@ -712,6 +694,7 @@ namespace AZ
const char* assetAliasPath = GetAlias("@assets@");
const char* rootAliasPath = GetAlias("@root@");
const char* projectPlatformCacheAliasPath = GetAlias("@projectplatformcache@");
const bool lowercasePath = (assetAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, assetAliasPath)) ||
(rootAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, rootAliasPath)) ||
(projectPlatformCacheAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, projectPlatformCacheAliasPath));
@@ -83,7 +83,7 @@ namespace AzFramework::ProjectManager
return ProjectPathCheckResult::ProjectManagerLaunchFailed;
}
bool LaunchProjectManager(const AZStd::string& commandLineArgs)
bool LaunchProjectManager([[maybe_unused]]const AZStd::string& commandLineArgs)
{
bool launchSuccess = false;
#if (AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER)
@@ -7,6 +7,7 @@
*/
#include "TerrainDataRequestBus.h"
#include <AzCore/Serialization/SerializeContext.h>
namespace AzFramework
{
@@ -45,8 +45,6 @@ namespace AzFramework
void EntityVisibilityBoundsUnionSystem::OnEntityActivated(AZ::Entity* entity)
{
AZ_PROFILE_FUNCTION(AzFramework);
// ignore any entity that might activate which does not have a TransformComponent
if (entity->GetTransform() == nullptr)
{
@@ -68,8 +66,6 @@ namespace AzFramework
void EntityVisibilityBoundsUnionSystem::OnEntityDeactivated(AZ::Entity* entity)
{
AZ_PROFILE_FUNCTION(AzFramework);
// ignore any entity that might deactivate which does not have a TransformComponent
if (entity->GetTransform() == nullptr)
{
@@ -89,8 +85,6 @@ namespace AzFramework
void EntityVisibilityBoundsUnionSystem::UpdateVisibilitySystem(AZ::Entity* entity, EntityVisibilityBoundsUnionInstance& instance)
{
AZ_PROFILE_FUNCTION(AzFramework);
if (const auto& localEntityBoundsUnions = instance.m_localEntityBoundsUnion; localEntityBoundsUnions.IsValid())
{
// note: worldEntityBounds will not be a 'tight-fit' Aabb but that of a transformed local aabb
@@ -155,8 +149,6 @@ namespace AzFramework
void EntityVisibilityBoundsUnionSystem::OnTransformUpdated(AZ::Entity* entity)
{
AZ_PROFILE_FUNCTION(AzFramework);
// update the world transform of the visibility bounds union
if (auto instance_it = m_entityVisibilityBoundsUnionInstanceMapping.find(entity);
instance_it != m_entityVisibilityBoundsUnionInstanceMapping.end())
@@ -21,9 +21,6 @@ namespace AzFramework
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
#error "Linux Window Manager Wayland not supported."
return nullptr;
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB
#error "Linux Window Manager XLIB not supported."
return nullptr;
#else
#error "Linux Window Manager not recognized."
return nullptr;
@@ -5,6 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzFramework/API/ApplicationAPI_Platform.h>
#include <AzFramework/Application/Application.h>
@@ -17,9 +17,6 @@ namespace AzFramework
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
#error "Linux Window Manager Wayland not supported."
return nullptr;
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB
#error "Linux Window Manager XLIB not supported."
return nullptr;
#else
#error "Linux Window Manager not recognized."
return nullptr;
@@ -5,6 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzFramework/API/ApplicationAPI_Platform.h>
#include <AzFramework/Application/Application.h>
@@ -7,7 +7,7 @@
#
# Based on the linux window manager trait, perform the appropriate additional build configurations
# Only 'xcb', 'wayland', and 'xlib' are recognized
# Only 'xcb' and 'wayland' are recognized
if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb")
find_library(XCB_LIBRARY xcb)
@@ -23,10 +23,6 @@ elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "wayland")
set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND)
elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "xlib")
set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB)
else()
message(FATAL_ERROR, "Linux Window Manager ${PAL_TRAIT_LINUX_WINDOW_MANAGER} is not recognized")
@@ -608,6 +608,9 @@ namespace UnitTest
archive->ClosePack(genericArchiveFileName);
cpfio.Remove(genericArchiveFileName);
// create the asset alias directory
cpfio.CreatePath("@assets@");
// create generic file
HandleType normalFileHandle;
@@ -848,13 +851,17 @@ namespace UnitTest
const char *assetsPath = ioBase->GetAlias("@assets@");
ASSERT_NE(nullptr, assetsPath);
AZStd::string stringToAdd = AZStd::string::format("%s/textures/test.dds", assetsPath);
auto stringToAdd = AZ::IO::Path(assetsPath) / "textures" / "test.dds";
reslist->Clear();
reslist->Add(stringToAdd.c_str());
reslist->Add(stringToAdd.Native());
// it normalizes the string, so the slashes flip and everything is lowercased.
EXPECT_STREQ(reslist->GetFirst(), "@assets@/textures/test.dds");
AZ::IO::FixedMaxPath resolvedAddedPath;
AZ::IO::FixedMaxPath resolvedResourcePath;
EXPECT_TRUE(ioBase->ReplaceAlias(resolvedAddedPath, "@assets@/textures/test.dds"));
EXPECT_TRUE(ioBase->ReplaceAlias(resolvedResourcePath, reslist->GetFirst()));
EXPECT_EQ(resolvedAddedPath, resolvedResourcePath);
reslist->Clear();
}
@@ -9,6 +9,7 @@
#include <cmath>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/Debug/Trace.h>
#include <AzQtComponents/Components/DockTabBar.h>
#include <AzQtComponents/Components/FancyDocking.h>
@@ -114,7 +114,7 @@ void GradientSlider::mouseMoveEvent(QMouseEvent* event)
{
int intValue = Slider::valueFromPosition(this, event->pos(), width(), height(), rect().bottom());
qreal value = (aznumeric_cast<qreal, int>(intValue - minimum()) / aznumeric_cast<qreal, int>(maximum() - minimum()));
qreal value = (aznumeric_cast<qreal>(intValue - minimum()) / aznumeric_cast<qreal>(maximum() - minimum()));
const QString toolTipText = m_toolTipFunction(value);
@@ -312,8 +312,6 @@ namespace AzToolsFramework
void EditorVisibleEntityDataCache::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world)
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
const AZ::EntityId entityId = *AZ::TransformNotificationBus::GetCurrentBusId();
if (AZStd::optional<size_t> entityIndex = GetVisibleEntityIndexFromId(entityId))
+1 -1
View File
@@ -70,7 +70,7 @@ struct CryPakMock
MOCK_METHOD2(IsFileExist, bool(AZStd::string_view sFilename, EFileSearchLocation));
MOCK_METHOD1(IsFolder, bool(AZStd::string_view sPath));
MOCK_METHOD1(GetFileSizeOnDisk, AZ::IO::IArchive::SignedFileSize(AZStd::string_view filename));
MOCK_METHOD2(MakeDir, bool(AZStd::string_view szPath, bool bGamePathMapping));
MOCK_METHOD1(MakeDir, bool(AZStd::string_view szPath));
MOCK_METHOD4(OpenArchive, AZStd::intrusive_ptr<AZ::IO::INestedArchive> (AZStd::string_view szPath, AZStd::string_view bindRoot, uint32_t nFlags, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData));
MOCK_METHOD1(GetFileArchivePath, const char* (AZ::IO::HandleType f));
MOCK_METHOD5(RawCompress, int(const void* pUncompressed, size_t* pDestSize, void* pCompressed, size_t nSrcSize, int nLevel));
+3 -2
View File
@@ -6,9 +6,10 @@
*
*/
#include <AzCore/AzCore_Traits_Platform.h>
// Description : Linux/Mac port support for Win32API calls
#if !defined(WIN32)
#if AZ_TRAIT_LEGACY_CRYCOMMON_USE_WINDOWS_STUBS
#include "platform.h" // Note: This should be first to get consistent debugging definitions
@@ -1391,4 +1392,4 @@ __finddata64_t::~__finddata64_t()
}
#endif //defined(APPLE) || defined(LINUX)
#endif // !defined(WIN32)
#endif // AZ_TRAIT_LEGACY_CRYCOMMON_USE_WINDOWS_STUBS
-1
View File
@@ -131,7 +131,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
#include "SystemEventDispatcher.h"
#include "HMDBus.h"
#include "zlib.h"
#include "RemoteConsole/RemoteConsole.h"
#include <PNoise3.h>
-4
View File
@@ -273,11 +273,7 @@ static const char* GetLastSystemErrorMessage()
return szBuffer;
}
#else
return 0;
#endif //WIN32
return 0;
}
@@ -441,7 +441,7 @@ namespace O3DE::ProjectManager
return true;
}
bool ReplaceFile(const QString& origFile, const QString& newFile, QWidget* parent, bool interactive)
bool ReplaceProjectFile(const QString& origFile, const QString& newFile, QWidget* parent, bool interactive)
{
QFileInfo original(origFile);
if (original.exists())
@@ -25,7 +25,7 @@ namespace O3DE::ProjectManager
bool DeleteProjectFiles(const QString& path, bool force = false);
bool MoveProject(QString origPath, QString newPath, QWidget* parent, bool skipRegister = false);
bool ReplaceFile(const QString& origFile, const QString& newFile, QWidget* parent = nullptr, bool interactive = true);
bool ReplaceProjectFile(const QString& origFile, const QString& newFile, QWidget* parent = nullptr, bool interactive = true);
bool FindSupportedCompiler(QWidget* parent = nullptr);
AZ::Outcome<void, QString> FindSupportedCompilerForPlatform();
@@ -242,7 +242,7 @@ namespace O3DE::ProjectManager
if (!newProjectSettings.m_newPreviewImagePath.isEmpty())
{
if (!ProjectUtils::ReplaceFile(
if (!ProjectUtils::ReplaceProjectFile(
QDir(newProjectSettings.m_path).filePath(newProjectSettings.m_iconPath), newProjectSettings.m_newPreviewImagePath))
{
QMessageBox::critical(this, tr("File replace failed"), tr("Failed to replace project preview image."));
@@ -202,7 +202,7 @@ namespace O3DE::ProjectManager
TEST_F(ProjectManagerUtilsTests, ReplaceFile_Succeeds)
#endif // !AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS
{
EXPECT_TRUE(ReplaceFile(m_projectAOrigFilePath, m_projectAReplaceFilePath, nullptr, false));
EXPECT_TRUE(ReplaceProjectFile(m_projectAOrigFilePath, m_projectAReplaceFilePath, nullptr, false));
QFile origFile(m_projectAOrigFilePath);
EXPECT_TRUE(origFile.open(QIODevice::ReadOnly));
@@ -8,6 +8,7 @@
#include <SceneAPI/SceneCore/Events/ExportProductList.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/limits.h>
namespace AZ
+35 -10
View File
@@ -26,9 +26,6 @@ ly_add_target(
Gem::HttpRequestor
3rdParty::AWSNativeSDK::AWSClientAuth
3rdParty::AWSNativeSDK::Core
RUNTIME_DEPENDENCIES
Gem::AWSCore
Gem::HttpRequestor
)
ly_add_target(
@@ -48,17 +45,45 @@ ly_add_target(
3rdParty::AWSNativeSDK::Core
PUBLIC
Gem::AWSClientAuth.Static
RUNTIME_DEPENDENCIES
Gem::AWSCore
Gem::HttpRequestor
)
# Load the "Gem::AWSClientAuth" module in all types of applications.
ly_create_alias(NAME AWSClientAuth.Servers NAMESPACE Gem TARGETS Gem::AWSClientAuth)
ly_create_alias(NAME AWSClientAuth.Clients NAMESPACE Gem TARGETS Gem::AWSClientAuth)
ly_create_alias(
NAME AWSClientAuth.Servers
NAMESPACE Gem
TARGETS
Gem::AWSClientAuth
Gem::AWSCore.Servers
Gem::HttpRequestor.Servers
)
ly_create_alias(
NAME AWSClientAuth.Clients
NAMESPACE Gem
TARGETS
Gem::AWSClientAuth
Gem::AWSCore.Clients
Gem::HttpRequestor.Clients
)
if (PAL_TRAIT_BUILD_HOST_TOOLS)
ly_create_alias(NAME AWSClientAuth.Tools NAMESPACE Gem TARGETS Gem::AWSClientAuth)
ly_create_alias(NAME AWSClientAuth.Builders NAMESPACE Gem TARGETS Gem::AWSClientAuth)
ly_create_alias(
NAME AWSClientAuth.Tools
NAMESPACE Gem
TARGETS
Gem::AWSClientAuth
Gem::AWSCore.Tools
Gem::HttpRequestor.Tools
)
ly_create_alias(
NAME AWSClientAuth.Builders
NAMESPACE Gem
TARGETS
Gem::AWSClientAuth
Gem::AWSCore.Builders
Gem::HttpRequestor.Builders
)
endif()
################################################################################
@@ -8,11 +8,15 @@
#pragma once
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/std/string/string.h>
#include <aws/core/auth/AWSCredentialsProvider.h>
namespace AZ
{
class ReflectContext;
}
namespace AWSClientAuth
{
//! Client auth AWS Credentials object for serialization.
@@ -54,31 +58,8 @@ namespace AWSClientAuth
return m_sessionToken;
}
static void Reflect(AZ::ReflectContext* context)
{
auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<ClientAuthAWSCredentials>()
->Field("AWSAccessKeyId", &ClientAuthAWSCredentials::m_accessKeyId)
->Field("AWSSecretKey", &ClientAuthAWSCredentials::m_secretKey)
->Field("AWSSessionToken", &ClientAuthAWSCredentials::m_sessionToken);
}
static void Reflect(AZ::ReflectContext* context);
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<ClientAuthAWSCredentials>()
->Attribute(AZ::Script::Attributes::Category, "AWSClientAuth")
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Constructor()
->Constructor<const ClientAuthAWSCredentials&>()
->Property("AWSAccessKeyId", BehaviorValueGetter(&ClientAuthAWSCredentials::m_accessKeyId), BehaviorValueSetter(&ClientAuthAWSCredentials::m_accessKeyId))
->Property("AWSSecretKey", BehaviorValueGetter(&ClientAuthAWSCredentials::m_secretKey), BehaviorValueSetter(&ClientAuthAWSCredentials::m_secretKey))
->Property("AWSSessionToken", BehaviorValueGetter(&ClientAuthAWSCredentials::m_sessionToken), BehaviorValueSetter(&ClientAuthAWSCredentials::m_sessionToken));
}
}
private:
AZStd::string m_accessKeyId;
@@ -0,0 +1,50 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Authorization/ClientAuthAWSCredentials.h>
#include <AzCore/Outcome/Outcome.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/RTTI/AzStdOnDemandReflection.inl>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/AZStdContainers.inl>
namespace AWSClientAuth
{
void ClientAuthAWSCredentials::Reflect(AZ::ReflectContext* context)
{
auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<ClientAuthAWSCredentials>()
->Field("AWSAccessKeyId", &ClientAuthAWSCredentials::m_accessKeyId)
->Field("AWSSecretKey", &ClientAuthAWSCredentials::m_secretKey)
->Field("AWSSessionToken", &ClientAuthAWSCredentials::m_sessionToken);
}
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
behaviorContext->Class<ClientAuthAWSCredentials>()
->Attribute(AZ::Script::Attributes::Category, "AWSClientAuth")
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Constructor()
->Constructor<const ClientAuthAWSCredentials&>()
->Property(
"AWSAccessKeyId", BehaviorValueGetter(&ClientAuthAWSCredentials::m_accessKeyId),
BehaviorValueSetter(&ClientAuthAWSCredentials::m_accessKeyId))
->Property(
"AWSSecretKey", BehaviorValueGetter(&ClientAuthAWSCredentials::m_secretKey),
BehaviorValueSetter(&ClientAuthAWSCredentials::m_secretKey))
->Property(
"AWSSessionToken", BehaviorValueGetter(&ClientAuthAWSCredentials::m_sessionToken),
BehaviorValueSetter(&ClientAuthAWSCredentials::m_sessionToken));
}
}
} // namespace AWSClientAuth
@@ -42,6 +42,7 @@ set(FILES
Source/Authentication/LWAAuthenticationProvider.cpp
Source/Authentication/GoogleAuthenticationProvider.cpp
Source/Authorization/ClientAuthAWSCredentials.cpp
Source/Authorization/AWSCognitoAuthorizationController.cpp
Source/Authorization/AWSClientAuthPersistentCognitoIdentityProvider.cpp
+28 -6
View File
@@ -45,8 +45,19 @@ ly_add_target(
)
# clients and servers will use the above Gem::AWSCore module.
ly_create_alias(NAME AWSCore.Servers NAMESPACE Gem TARGETS Gem::AWSCore)
ly_create_alias(NAME AWSCore.Clients NAMESPACE Gem TARGETS Gem::AWSCore)
ly_create_alias(
NAME AWSCore.Servers
NAMESPACE Gem
TARGETS
Gem::AWSCore
)
ly_create_alias(
NAME AWSCore.Clients
NAMESPACE Gem
TARGETS
Gem::AWSCore
)
if (PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_target(
@@ -84,8 +95,6 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
PRIVATE
AZ::AzCore
Gem::AWSCore.Editor.Static
RUNTIME_DEPENDENCIES
Gem::AWSCore
)
# This target is not a real gem module
@@ -106,8 +115,21 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_dependencies(AWSCore.Editor AWSCore.ResourceMappingTool)
# Builders and Tools (such as the Editor use AWSCore.Editor) use the .Editor module above.
ly_create_alias(NAME AWSCore.Tools NAMESPACE Gem TARGETS Gem::AWSCore.Editor)
ly_create_alias(NAME AWSCore.Builders NAMESPACE Gem TARGETS Gem::AWSCore.Editor)
ly_create_alias(
NAME AWSCore.Tools
NAMESPACE Gem
TARGETS
Gem::AWSCore
Gem::AWSCore.Editor
)
ly_create_alias(
NAME AWSCore.Builders
NAMESPACE Gem
TARGETS
Gem::AWSCore
Gem::AWSCore.Editor
)
endif()
@@ -45,13 +45,26 @@ ly_add_target(
PUBLIC
Gem::AWSGameLift.Client.Static
RUNTIME_DEPENDENCIES
Gem::AWSCore
Gem::AWSCore.Clients
)
# Load the "Gem::AWSGameLift" module in all types of applications.
if (PAL_TRAIT_BUILD_HOST_TOOLS)
ly_create_alias(NAME AWSGameLift.Tools NAMESPACE Gem TARGETS Gem::AWSGameLift.Clients)
ly_create_alias(NAME AWSGameLift.Builders NAMESPACE Gem TARGETS Gem::AWSGameLift.Clients)
ly_create_alias(
NAME AWSGameLift.Tools
NAMESPACE Gem
TARGETS
Gem::AWSCore.Tools
Gem::AWSGameLift.Clients
)
ly_create_alias(
NAME AWSGameLift.Builders
NAMESPACE Gem
TARGETS
Gem::AWSCore.Builders
Gem::AWSGameLift.Clients
)
endif()
################################################################################
+31 -6
View File
@@ -40,16 +40,41 @@ ly_add_target(
AZ::AzCore
AZ::AzFramework
Gem::AWSMetrics.Static
RUNTIME_DEPENDENCIES
Gem::AWSCore
)
# Load the "Gem::AWSMetrics" module in all types of applications.
ly_create_alias(NAME AWSMetrics.Servers NAMESPACE Gem TARGETS Gem::AWSMetrics)
ly_create_alias(NAME AWSMetrics.Clients NAMESPACE Gem TARGETS Gem::AWSMetrics)
ly_create_alias(
NAME AWSMetrics.Servers
NAMESPACE Gem
TARGETS
Gem::AWSCore.Servers
Gem::AWSMetrics
)
ly_create_alias(
NAME AWSMetrics.Clients
NAMESPACE Gem
TARGETS
Gem::AWSCore.Clients
Gem::AWSMetrics
)
if (PAL_TRAIT_BUILD_HOST_TOOLS)
ly_create_alias(NAME AWSMetrics.Tools NAMESPACE Gem TARGETS Gem::AWSMetrics)
ly_create_alias(NAME AWSMetrics.Builders NAMESPACE Gem TARGETS Gem::AWSMetrics)
ly_create_alias(
NAME AWSMetrics.Tools
NAMESPACE Gem
TARGETS
Gem::AWSCore.Tools
Gem::AWSMetrics
)
ly_create_alias(
NAME AWSMetrics.Builders
NAMESPACE Gem
TARGETS
Gem::AWSCore.Builders
Gem::AWSMetrics
)
endif()
################################################################################
@@ -14,11 +14,11 @@
#include <AzCore/std/string/regex.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
@@ -56,7 +56,7 @@ namespace AZ
m_predefinedMacros.begin(), m_predefinedMacros.end(),
[&](const AZStd::string& predefinedMacro) {
// Haystack, needle, bCaseSensitive
if (!AzFramework::StringFunc::StartsWith(predefinedMacro, macroName, true))
if (!AZ::StringFunc::StartsWith(predefinedMacro, macroName, true))
{
return false;
}
@@ -117,11 +117,11 @@ namespace AZ
char localBuffer[DefaultFprintfBufferSize];
va_list args;
va_start(args, format);
int count = azvsnprintf(localBuffer, DefaultFprintfBufferSize, format, args);
va_end(args);
char* result = localBuffer;
// @result will be bound to @biggerData in case @localBuffer is not big enough.
@@ -134,7 +134,7 @@ namespace AZ
count++; // vsnprintf returns a size that doesn't include the null character.
biggerData.reset(new char[count]);
result = &biggerData[0];
// Remark: for MacOS & Linux it is important to call va_start again before
// each call to azvsnprintf. Not required for Windows.
va_start(args, format);
@@ -149,7 +149,7 @@ namespace AZ
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/vsnprintf-vsnprintf-vsnprintf-l-vsnwprintf-vsnwprintf-l?view=msvc-160
// In particular: "If the number of characters to write is greater than count,
// these functions return -1 indicating that output has been truncated."
// There wasn't enough space in the local store.
// Remark: for MacOS & Linux it is important to call va_start again before
// each call to azvsnprintf. Not required for Windows.
@@ -157,10 +157,10 @@ namespace AZ
count = azvscprintf(format, args);
count += 1; // vscprintf returns a size that doesn't include the null character.
va_end(args);
biggerData.reset(new char[count]);
result = &biggerData[0];
va_start(args, format);
count = azvsnprintf(result, count, format, args);
va_end(args);
@@ -191,7 +191,7 @@ namespace AZ
// definitions for the linker
AZStd::mutex McppBinder::s_mcppExclusiveProtection;
McppBinder* McppBinder::s_currentInstance = nullptr;
McppBinder* McppBinder::s_currentInstance = nullptr;
// McppBinder ends
///////////////////////////////////////////////////////////////////////
@@ -204,7 +204,7 @@ namespace AZ
// create the argc/argv
const char* processName = "builder";
const char* inputPath = fullPath.c_str();
const char* inputPath = fullPath.c_str();
// let's create the equivalent of that expression but in dynamic form:
//const char* argv[] = { processName, szInPath, "-C", "-+", "-D macro1"..., "-I path"..., NULL };
AZStd::vector< const char* > argv;
@@ -230,7 +230,7 @@ namespace AZ
argv.push_back(nullptr); // usual argv terminator
// output the command line:
AZStd::string stringifiedCommandLine;
AzFramework::StringFunc::Join(stringifiedCommandLine, argv.begin(), argv.end() - 1, " ");
AZ::StringFunc::Join(stringifiedCommandLine, argv.begin(), argv.end() - 1, " ");
AZ_TracePrintf("Preprocessor", "%s", stringifiedCommandLine.c_str());
// when we don't specify an -o outfile, mcpp uses stdout.
// the trick is that since we hijacked putc & puts, stdout will not be written.
@@ -238,17 +238,12 @@ namespace AZ
return result;
}
static void VerifySameFolder(const AZStd::string& path1, const AZStd::string& path2)
static void VerifySameFolder([[maybe_unused]] AZStd::string_view path1, [[maybe_unused]] AZStd::string_view path2)
{
AZStd::string folder1, folder2;
AzFramework::StringFunc::Path::GetFolderPath(path1.c_str(), folder1);
AzFramework::StringFunc::Path::GetFolderPath(path2.c_str(), folder2);
AzFramework::StringFunc::Path::Normalize(folder1);
AzFramework::StringFunc::Path::Normalize(folder2);
AZ_Warning("Preprocessing",
folder1 == folder2,
"The preprocessed file %s is in a different folder than its origin %s. Watch for #include problems with relative paths.",
path1.c_str(), path2.c_str()
AZ::IO::PathView(path1).ParentPath().LexicallyNormal() == AZ::IO::PathView(path2).ParentPath().LexicallyNormal(),
"The preprocessed file %.*s is in a different folder than its origin %.*s. Watch for #include problems with relative paths.",
AZ_STRING_ARG(path1), AZ_STRING_ARG(path2)
);
}
@@ -260,7 +255,7 @@ namespace AZ
// containing file names, to match the ORIGINAL source, and not the actual source in use by azslc.
// That gymnastic is better for error messages anyway, so instead of making the SRG layout builder more intelligent,
// we'll fake the origin of the file, by setting the original source as a filename
// note that it is not possible to build a file in a different folder and fake it to a file eslewhere because relative includes will fail.
// note that it is not possible to build a file in a different folder and fake it to a file elsewhere because relative includes will fail.
void MutateLineDirectivesFileOrigin(
AZStd::string& sourceCode,
AZStd::string newFileOrigin)
@@ -272,11 +267,11 @@ namespace AZ
// we will use that as the information of the source path to mutate.
if (sourceCode.starts_with("#line"))
{
auto firstQuote = sourceCode.find('"');
auto secondQuote = sourceCode.find('"', firstQuote + 1);
auto firstQuote = sourceCode.find('"');
auto secondQuote = firstQuote != AZStd::string::npos ? sourceCode.find('"', firstQuote + 1) : AZStd::string::npos;
auto originalFile = sourceCode.substr(firstQuote + 1, secondQuote - firstQuote - 1); // start +1, count -1 because we don't want the quotes included.
VerifySameFolder(originalFile, newFileOrigin);
[[maybe_unused]] bool didReplace = AzFramework::StringFunc::Replace(sourceCode, originalFile.c_str(), newFileOrigin.c_str(), true /*case sensitive*/);
[[maybe_unused]] bool didReplace = AZ::StringFunc::Replace(sourceCode, originalFile.c_str(), newFileOrigin.c_str(), true /*case sensitive*/);
AZ_Assert(didReplace, "Failed to replace %s for %s in preprocessed source.", originalFile.c_str(), newFileOrigin.c_str());
}
else
@@ -285,26 +280,6 @@ namespace AZ
}
}
namespace
{
template< typename Container1, typename Container2 >
void TransferContent(Container1& destination, Container2&& source)
{
destination.insert(AZStd::end(destination),
AZStd::make_move_iterator(AZStd::begin(source)),
AZStd::make_move_iterator(AZStd::end(source)));
}
void DeleteFromSet(const AZStd::string& string, AZStd::set<AZStd::string>& set)
{
auto iter = set.find(string);
if (iter != set.end())
{
set.erase(iter);
}
}
}
// populate options with scan folders and contents of parsing shader_global_build_options.json
void InitializePreprocessorOptions(
PreprocessorOptions& options, [[maybe_unused]] const char* builderName, const char* optionalIncludeFolder)
@@ -315,44 +290,61 @@ namespace AZ
bool success = true;
AZStd::vector<AZStd::string> scanFoldersVector;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(success,
&AzToolsFramework::AssetSystemRequestBus::Events::GetScanFolders,
scanFoldersVector);
&AzToolsFramework::AssetSystemRequestBus::Events::GetScanFolders,
scanFoldersVector);
AZ_Warning(builderName, success, "Preprocessor option: Could not acquire a list of scan folders from the database.");
// we transfer to a set, to order the folders, uniquify them, and ensure deterministic build behavior
AZStd::set<AZStd::string> scanFoldersSet;
// Add the project path to list of include paths
AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
scanFoldersSet.emplace(projectPath.c_str(), projectPath.size());
AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
auto FindPath = [](AZ::IO::PathView searchPath)
{
return [searchPath](AZStd::string_view includePathView)
{
return searchPath == AZ::IO::PathView(includePathView);
};
};
if (auto it = AZStd::find_if(options.m_projectIncludePaths.begin(), options.m_projectIncludePaths.end(), FindPath(projectPath));
it == options.m_projectIncludePaths.end())
{
options.m_projectIncludePaths.emplace_back(projectPath.c_str(), projectPath.Native().size());
}
if (optionalIncludeFolder)
{
scanFoldersSet.emplace(optionalIncludeFolder, strnlen(optionalIncludeFolder, AZ::IO::MaxPathLength));
if (auto it = AZStd::find_if(options.m_projectIncludePaths.begin(), options.m_projectIncludePaths.end(), FindPath(optionalIncludeFolder));
it == options.m_projectIncludePaths.end())
{
if (AZ::IO::SystemFile::Exists(optionalIncludeFolder))
{
options.m_projectIncludePaths.emplace_back(AZStd::move(AZ::IO::Path(optionalIncludeFolder).LexicallyNormal().Native()));
}
}
}
// but while we transfer to the set, we're going to keep only folders where +/ShaderLib exists
for (AZStd::string folder : scanFoldersVector)
for (AZ::IO::Path shaderScanFolder : scanFoldersVector)
{
AzFramework::StringFunc::Path::Join(folder.c_str(), "ShaderLib", folder);
if (AZ::IO::SystemFile::Exists(folder.c_str()))
shaderScanFolder /= "ShaderLib";
if (auto it = AZStd::find_if(options.m_projectIncludePaths.begin(), options.m_projectIncludePaths.end(), FindPath(shaderScanFolder));
it == options.m_projectIncludePaths.end())
{
scanFoldersSet.emplace(std::move(folder));
// the folders constructed this fashion constitute the base of automatic include search paths
if (AZ::IO::SystemFile::Exists(shaderScanFolder.c_str()))
{
options.m_projectIncludePaths.emplace_back(AZStd::move(shaderScanFolder.LexicallyNormal().Native()));
}
}
} // the folders constructed this fashion constitute the base of automatic include search paths
// get the engine root:
AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
// add optional additional options
for (AZStd::string& path : options.m_projectIncludePaths)
{
path = (engineRoot / path).String();
DeleteFromSet(path, scanFoldersSet); // no need to add a path two times.
}
// back-insert the default paths (after the config-read paths we just read)
TransferContent(/*to:*/options.m_projectIncludePaths, /*from:*/scanFoldersSet);
// finally the <engineroot>/Gems fallback
AZStd::string gemsFolder;
AzFramework::StringFunc::Path::Join(engineRoot.c_str(), "Gems", gemsFolder);
options.m_projectIncludePaths.push_back(gemsFolder);
AZ::IO::Path engineGemsFolder(AZStd::string_view{ AZ::Utils::GetEnginePath() });
engineGemsFolder /= "Gems";
if (auto it = AZStd::find_if(options.m_projectIncludePaths.begin(), options.m_projectIncludePaths.end(), FindPath(engineGemsFolder));
it == options.m_projectIncludePaths.end())
{
if (AZ::IO::SystemFile::Exists(engineGemsFolder.c_str()))
{
options.m_projectIncludePaths.emplace_back(AZStd::move(engineGemsFolder.Native()));
}
}
}
} // namespace ShaderBuilder
@@ -253,34 +253,6 @@ namespace AZ
RPI::SceneDescriptor sceneDesc;
AZ::RPI::ScenePtr atomScene = RPI::Scene::CreateScene(sceneDesc);
atomScene->EnableAllFeatureProcessors();
// Setup scene srg modification callback.
RPI::ShaderResourceGroupCallback callback = [this](RPI::ShaderResourceGroup* srg)
{
if (srg == nullptr)
{
return;
}
bool needCompile = false;
RHI::ShaderInputConstantIndex timeIndex = srg->FindShaderInputConstantIndex(Name{ "m_time" });
if (timeIndex.IsValid())
{
srg->SetConstant(timeIndex, m_simulateTime);
needCompile = true;
}
RHI::ShaderInputConstantIndex deltaTimeIndex = srg->FindShaderInputConstantIndex(Name{ "m_deltaTime" });
if (deltaTimeIndex.IsValid())
{
srg->SetConstant(deltaTimeIndex, m_deltaTime);
needCompile = true;
}
if (needCompile)
{
srg->Compile();
}
};
atomScene->SetShaderResourceGroupCallback(callback);
atomScene->Activate();
// Register scene to RPI system so it will be processed/rendered per tick
@@ -408,11 +380,8 @@ namespace AZ
m_renderPipelineId = "";
}
void BootstrapSystemComponent::OnTick(float deltaTime, [[maybe_unused]] ScriptTimePoint time)
void BootstrapSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] ScriptTimePoint time)
{
m_simulateTime += deltaTime;
m_deltaTime = deltaTime;
// Temp: When running in the launcher without the legacy renderer
// we need to call RenderTick on the viewport context each frame.
if (m_viewportContext)
@@ -105,9 +105,6 @@ namespace AZ
RPI::ScenePtr m_defaultScene = nullptr;
AZStd::shared_ptr<AzFramework::Scene> m_defaultFrameworkScene = nullptr;
float m_simulateTime = 0;
float m_deltaTime = 0.016f;
bool m_isAssetCatalogLoaded = false;
// The id of the render pipeline created by this component
@@ -11,6 +11,6 @@
// Please review README.md to understand how this file is used in SceneSrg.azsrg generation
#ifdef AZ_COLLECTING_PARTIAL_SRGS
#include <Atom/Feature/Common/Assets/ShaderResourceGroups/SceneTimeSrg.azsli>
#include <Atom/RPI/ShaderResourceGroups/DefaultSceneSrg.azsli>
#include <Atom/Feature/Common/Assets/ShaderResourceGroups/SceneSrg.azsli>
#endif
@@ -78,10 +78,12 @@ void MainCS(uint3 dispatch_id : SV_DispatchThreadID)
const float speed = exposureDifference > 0.0 ? ViewSrg::m_exposureControl.m_speedUp : ViewSrg::m_exposureControl.m_speedDown;
// Update the adjustment for this frame based on the frame deltaTime and speed
float exposureAdjustment = exposureDifference * SceneSrg::m_deltaTime * speed;
float deltaTime = clamp(SceneSrg::m_time - PassSrg::m_eyeAdaptationData[0].m_setValueTime, 0.0f, 1.0f);
float exposureAdjustment = exposureDifference * deltaTime * speed;
float newExposureLog2 = previousFrameExposureLog2 + exposureAdjustment;
// Store the linear exposure so it can be used by the look modification transform later.
// newExposureLog2 is negated because m_exposureValue is used to correct for a given exposure.
PassSrg::m_eyeAdaptationData[0].m_exposureValue = pow(2.0f, -newExposureLog2);
PassSrg::m_eyeAdaptationData[0].m_setValueTime = SceneSrg::m_time;
}
@@ -8,5 +8,6 @@
struct EyeAdaptation
{
float m_exposureValue; // current frame's exposure value in stops (logarithmic space)
float m_exposureValue; // current frame's exposure value in stops (logarithmic space)
float m_setValueTime; // the time when the m_exposureValue was set
};
@@ -289,7 +289,6 @@ set(FILES
ShaderLib/Atom/Features/Vertex/VertexHelper.azsli
ShaderResourceGroups/SceneSrg.azsli
ShaderResourceGroups/SceneSrgAll.azsli
ShaderResourceGroups/SceneTimeSrg.azsli
ShaderResourceGroups/ViewSrg.azsli
ShaderResourceGroups/ViewSrgAll.azsli
ShaderResourceGroups/CoreLights/SceneSrg.azsli
@@ -12,6 +12,7 @@
#include <Atom/RHI/Buffer.h>
#include <Atom/RHI/BufferPool.h>
#include <Atom/RPI.Public/FeatureProcessor.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
namespace AZ
@@ -36,8 +37,6 @@ namespace AZ
void Activate() override;
//! Releases GPU resources.
void Deactivate() override;
//! Binds buffers
void Render(const FeatureProcessor::RenderPacket& packet) override;
// RPI::SceneNotificationBus overrides ...
void OnBeginPrepareRender() override;
@@ -68,11 +67,13 @@ namespace AZ
// Prepare GPU buffers for object transformation matrices
// Create the buffers if they don't exist. Otherwise, resize them if they are not large enough for the matrices
void PrepareBuffers();
Data::Instance<RPI::ShaderResourceGroup> m_sceneSrg;
RHI::ShaderInputBufferIndex m_objectToWorldBufferIndex;
RHI::ShaderInputBufferIndex m_objectToWorldInverseTransposeBufferIndex;
RHI::ShaderInputBufferIndex m_objectToWorldHistoryBufferIndex;
void UpdateSceneSrg(RPI::ShaderResourceGroup *sceneSrg);
RPI::Scene::PrepareSceneSrgEvent::Handler m_updateSceneSrgHandler;
RHI::ShaderInputNameIndex m_objectToWorldBufferIndex = "m_objectToWorldBuffer";
RHI::ShaderInputNameIndex m_objectToWorldInverseTransposeBufferIndex = "m_objectToWorldInverseTransposeBuffer";
RHI::ShaderInputNameIndex m_objectToWorldHistoryBufferIndex = "m_objectToWorldHistoryBuffer";
// Stores transforms that are uploaded to a GPU buffer. Used slots have float12(matrix3x4) values, empty slots
// have a uint32_t that points to the next empty slot like a linked list. m_firstAvailableMeshTransformIndex stores the first
@@ -479,8 +479,6 @@ namespace AZ
: m_modelAsset(modelAsset)
, m_parent(parent)
{
AZ_PROFILE_FUNCTION(AzRender);
if (!m_modelAsset.GetId().IsValid())
{
AZ_Error("MeshDataInstance::MeshLoader", false, "Invalid model asset Id.");
@@ -508,7 +506,6 @@ namespace AZ
//! AssetBus::Handler overrides...
void MeshDataInstance::MeshLoader::OnAssetReady(Data::Asset<Data::AssetData> asset)
{
AZ_PROFILE_FUNCTION(AzRender);
Data::Asset<RPI::ModelAsset> modelAsset = asset;
// Assign the fully loaded asset back to the mesh handle to not only hold asset id, but the actual data as well.
@@ -580,8 +577,6 @@ namespace AZ
void MeshDataInstance::Init(Data::Instance<RPI::Model> model)
{
AZ_PROFILE_FUNCTION(AzRender);
m_model = model;
const size_t modelLodCount = m_model->GetLodCount();
m_drawPacketListsByLod.resize(modelLodCount);
@@ -612,8 +607,6 @@ namespace AZ
void MeshDataInstance::BuildDrawPacketList(size_t modelLodIndex)
{
AZ_PROFILE_FUNCTION(AzRender);
RPI::ModelLod& modelLod = *m_model->GetLods()[modelLodIndex];
const size_t meshCount = modelLod.GetMeshes().size();
@@ -36,8 +36,6 @@ namespace AZ
m_viewPtr = view;
m_viewSrg = view->GetShaderResourceGroup();
m_exposureControlBufferInputIndex = m_viewSrg->FindShaderInputBufferIndex(Name("m_exposureControl"));
m_eyeAdaptationBuffer.Init(m_viewSrg, idNumber);
}
@@ -109,14 +107,10 @@ namespace AZ
m_eyeAdaptationBuffer.UpdateSrg();
if (m_exposureControlBufferInputIndex.IsValid())
m_viewSrg->SetBufferView(m_exposureControlBufferInputIndex, m_buffer->GetBufferView());
if (m_viewPtr)
{
m_viewSrg->SetBufferView(m_exposureControlBufferInputIndex, m_buffer->GetBufferView());
if (m_viewPtr)
{
m_viewPtr->InvalidateSrg();
}
m_viewPtr->InvalidateSrg();
}
}
@@ -52,6 +52,7 @@ namespace AZ
struct ExposureCalculationData
{
float m_exposureValue = 1.0f;
float m_setValueTime = 0;
};
void BuildInternal() override;
@@ -36,11 +36,8 @@ namespace AZ
void TransformServiceFeatureProcessor::Activate()
{
m_sceneSrg = GetParentScene()->GetShaderResourceGroup();
m_objectToWorldBufferIndex = m_sceneSrg->FindShaderInputBufferIndex(Name{"m_objectToWorldBuffer"});
m_objectToWorldInverseTransposeBufferIndex = m_sceneSrg->FindShaderInputBufferIndex(Name{"m_objectToWorldInverseTransposeBuffer"});
m_objectToWorldHistoryBufferIndex = m_sceneSrg->FindShaderInputBufferIndex(Name{"m_objectToWorldHistoryBuffer"});
m_updateSceneSrgHandler = RPI::Scene::PrepareSceneSrgEvent::Handler([this](RPI::ShaderResourceGroup *sceneSrg) { this->UpdateSceneSrg(sceneSrg); });
GetParentScene()->ConnectEvent(m_updateSceneSrgHandler);
m_deviceBufferNeedsUpdate = true;
m_objectToWorldTransforms.reserve(BufferReserveCount);
@@ -62,9 +59,14 @@ namespace AZ
m_firstAvailableTransformIndex = NoAvailableTransformIndices;
m_objectToWorldBufferIndex.Reset();
m_objectToWorldInverseTransposeBufferIndex.Reset();
m_objectToWorldHistoryBufferIndex.Reset();
m_isWriteable = false;
RPI::SceneNotificationBus::Handler::BusDisconnect();
m_updateSceneSrgHandler.Disconnect();
}
void TransformServiceFeatureProcessor::PrepareBuffers()
@@ -131,16 +133,11 @@ namespace AZ
}
}
void TransformServiceFeatureProcessor::Render([[maybe_unused]] const FeatureProcessor::RenderPacket& packet)
void TransformServiceFeatureProcessor::UpdateSceneSrg(RPI::ShaderResourceGroup *sceneSrg)
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "TransformServiceFeatureProcessor: Render");
AZ_UNUSED(packet);
AZ_Assert(!m_isWriteable, "Must be called between OnBeginPrepareRender() and OnEndPrepareRender()");
m_sceneSrg->SetBufferView(m_objectToWorldBufferIndex, m_objectToWorldBuffer->GetBufferView());
m_sceneSrg->SetBufferView(m_objectToWorldInverseTransposeBufferIndex, m_objectToWorldInverseTransposeBuffer->GetBufferView());
m_sceneSrg->SetBufferView(m_objectToWorldHistoryBufferIndex, m_objectToWorldHistoryBuffer->GetBufferView());
sceneSrg->SetBufferView(m_objectToWorldBufferIndex, m_objectToWorldBuffer->GetBufferView());
sceneSrg->SetBufferView(m_objectToWorldInverseTransposeBufferIndex, m_objectToWorldInverseTransposeBuffer->GetBufferView());
sceneSrg->SetBufferView(m_objectToWorldHistoryBufferIndex, m_objectToWorldHistoryBuffer->GetBufferView());
}
void TransformServiceFeatureProcessor::OnBeginPrepareRender()
+1
View File
@@ -42,6 +42,7 @@ ly_add_target(
FILES_CMAKE
atom_rhi_public_files.cmake
${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
${pal_source_dir}/platform_private_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
Source
+54 -57
View File
@@ -50,24 +50,21 @@ namespace AZ
class RayTracingPipelineState;
class RayTracingShaderTable;
/* Priority of a Factory. The lower the number the higher the priority.
* Used when there's multiple factories available and the user hasn't define
* a priority.
*/
//! Priority of a Factory. The lower the number the higher the priority.
//! Used when there's multiple factories available and the user hasn't define
//! a priority.
using APIPriority = uint32_t;
static const APIPriority APITopPriority = 1;
static const APIPriority APILowPriority = 10;
static const APIPriority APIMiddlePriority = (APILowPriority - APITopPriority) / 2;
/**
* The factory is an interface for creating RHI data structures. The platform system should
* register itself with the factory by calling Register, and unregister on shutdown with
* Unregister.
*
* A call to Get will return the active instance. In the event that it's unclear whether
* a platform instance exists, you must call IsReady to determine whether it's safe to
* call Get. Calling Get without a registered platform will result in an assert.
*/
//! The factory is an interface for creating RHI data structures. The platform system should
//! register itself with the factory by calling Register, and unregister on shutdown with
//! Unregister.
//!
//! A call to Get will return the active instance. In the event that it's unclear whether
//! a platform instance exists, you must call IsReady to determine whether it's safe to
//! call Get. Calling Get without a registered platform will result in an assert.
class Factory
{
public:
@@ -79,78 +76,78 @@ namespace AZ
// Note that you have to delete these for safety reasons, you will trip a static_assert if you do not
AZ_DISABLE_COPY_MOVE(Factory);
/// Returns the component service name CRC used by the platform RHI system component.
//! Returns the component service name CRC used by the platform RHI system component.
static uint32_t GetComponentService();
/// Returns the component service name CRC used by the Factory manager component.
//! Returns the component service name CRC used by the Factory manager component.
static uint32_t GetManagerComponentService();
/// Returns the component service name CRC used by the platform RHI system component.
//! Returns the component service name CRC used by the platform RHI system component.
static uint32_t GetPlatformService();
/// Registers the global factory instance.
//! Registers the global factory instance.
static void Register(Factory* instance);
/// Unregisters the global factory instance.
//! Unregisters the global factory instance.
static void Unregister(Factory* instance);
/// Returns whether the factory is initialized and active in this module.
//! Returns whether the factory is initialized and active in this module.
static bool IsReady();
/// Access the global factory instance.
//! Access the global factory instance.
static Factory& Get();
#if defined(USE_RENDERDOC)
/// Access the RenderDoc API pointer if available.
/// The availability of the render doc API at runtime depends on the following:
/// - You must not be building a packaged game/product (LY_MONOLITHIC_GAME not enabled in CMake)
/// - A valid renderdoc installation was found, either by auto-discovery, or by supplying ATOM_RENDERDOC_PATH as an environment variable
/// - The module loaded successfully at runtime, and the API function pointer was retrieved successfully
//! Access the RenderDoc API pointer if available.
//! The availability of the render doc API at runtime depends on the following:
//! - You must not be building a packaged game/product (LY_MONOLITHIC_GAME not enabled in CMake)
//! - A valid renderdoc installation was found, either by auto-discovery, or by supplying ATOM_RENDERDOC_PATH as an environment variable
//! - The module loaded successfully at runtime, and the API function pointer was retrieved successfully
static RENDERDOC_API_1_1_2* GetRenderDocAPI();
#endif
//! Returns true if RenderDoc dll is loaded
static bool IsRenderDocModuleLoaded();
/// Returns the name of the Factory.
//! Returns true if Pix dll is loaded
static bool IsPixModuleLoaded();
//! Returns the name of the Factory.
virtual Name GetName() = 0;
/// Returns the APIType of the factory.
//! Returns the APIType of the factory.
virtual APIType GetType() = 0;
/// Returns the default priority of the factory in case there's no priorities set in the FactoryManager.
//! Returns the default priority of the factory in case there's no priorities set in the FactoryManager.
virtual APIPriority GetDefaultPriority() = 0;
/**
* Purpose: The API Unique Index will be encoded in the 2 Most Significant Bits of a ShaderVariantAsset ProductSubId (a 32bits integer).
* Returns a number in the range [0..3].
* In theory any given AssetBuilderSdk::PlatformInfo can support several RHI::APITypes.
* In reality "pc" only supports DX12 & Vulkan.
* "ios" supports only Metal.
* "mac" supports only Metal.
* "android" supports only Vulkan.
* So, for all practical purposes, a single PlatformInfo won't support more than 2 ShaderPlatformInterfaces, but for the sake of
* hedging our bets into the future We assume no more than 4 ShaderPlatformInterfaces will ever be supported for any given PlatformInfo.
* REMARK: It is the responsibility of the Factory subclass to return a unique number between 0...3.
* For example DX12 can return 0, while Vulkan should return 1 (Satisfies "pc", "android" and "linux").
* Metal can return 0 because it is the only ShaderPlatformInterface for "ios", "mac" and "appletv".
* See AZ::RHI::Limits::APIType::PerPlatformApiUniqueIndexMax.
*/
//! Purpose: The API Unique Index will be encoded in the 2 Most Significant Bits of a ShaderVariantAsset ProductSubId (a 32bits integer).
//! Returns a number in the range [0..3].
//! In theory any given AssetBuilderSdk::PlatformInfo can support several RHI::APITypes.
//! In reality "pc" only supports DX12 & Vulkan.
//! "ios" supports only Metal.
//! "mac" supports only Metal.
//! "android" supports only Vulkan.
//! So, for all practical purposes, a single PlatformInfo won't support more than 2 ShaderPlatformInterfaces, but for the sake of
//! hedging our bets into the future We assume no more than 4 ShaderPlatformInterfaces will ever be supported for any given PlatformInfo.
//! REMARK: It is the responsibility of the Factory subclass to return a unique number between 0...3.
//! For example DX12 can return 0, while Vulkan should return 1 (Satisfies "pc", "android" and "linux").
//! Metal can return 0 because it is the only ShaderPlatformInterface for "ios", "mac" and "appletv".
//! See AZ::RHI::Limits::APIType::PerPlatformApiUniqueIndexMax.
virtual uint32_t GetAPIUniqueIndex() const = 0;
/**
* Collects the set of physical devices on the system and returns a list of them. Physical
* devices represent the hardware attached to the system. Physical devices can be grouped
* into nodes for linked setups (e.g. SLI / Crossfire). They can also represent software
* reference implementations. Check the PhysicalDeviceType on the descriptor to inspect
* this information.
*/
//! Collects the set of physical devices on the system and returns a list of them. Physical
//! devices represent the hardware attached to the system. Physical devices can be grouped
//! into nodes for linked setups (e.g. SLI / Crossfire). They can also represent software
//! reference implementations. Check the PhysicalDeviceType on the descriptor to inspect
//! this information.
virtual PhysicalDeviceList EnumeratePhysicalDevices() = 0;
/**
* Factory Creation Methods:
*
* Returns the platform-specific derived variant of the RHI type. All instances are created
* in an uninitialized state; the operation simply allocates the memory for the appropriate
* platform type and returns the pointer.
*/
//! Factory Creation Methods:
//!
//! Returns the platform-specific derived variant of the RHI type. All instances are created
//! in an uninitialized state; the operation simply allocates the memory for the appropriate
//! platform type and returns the pointer.
virtual Ptr<Buffer> CreateBuffer() = 0;
@@ -0,0 +1,11 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(FILES
../Common/Unimplemented/Empty_Unimplemented.cpp
)
@@ -0,0 +1,21 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/std/string/string.h>
namespace AZ::RHI::Platform
{
bool IsPixDllInjected([[maybe_unused]] const char* dllName)
{
return false;
}
AZStd::wstring GetLatestWinPixGpuCapturerPath()
{
return L"";
}
}
@@ -0,0 +1,11 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(FILES
../Common/Unimplemented/Empty_Unimplemented.cpp
)
@@ -0,0 +1,11 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(FILES
../Common/Unimplemented/Empty_Unimplemented.cpp
)
@@ -8,3 +8,4 @@
#pragma once
#define AZ_TRAIT_RENDERDOC_MODULE "renderdoc.dll"
#define AZ_TRAIT_PIX_MODULE "WinPixGpuCapturer.dll"
@@ -0,0 +1,59 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <filesystem>
#include <shlobj.h>
#include <AzCore/base.h>
#include <AzCore/std/string/string.h>
namespace AZ::RHI::Platform
{
bool IsPixDllInjected(const char* dllName)
{
bool isDllLoaded = false;
wchar_t fileNameW[256];
size_t numCharsConverted;
errno_t wcharResult = mbstowcs_s(&numCharsConverted, fileNameW, dllName, AZ_ARRAY_SIZE(fileNameW) - 1);
if (wcharResult == 0)
{
isDllLoaded = NULL != GetModuleHandleW(fileNameW);
}
return isDllLoaded;
}
AZStd::wstring GetLatestWinPixGpuCapturerPath()
{
LPWSTR programFilesPath = nullptr;
SHGetKnownFolderPath(FOLDERID_ProgramFiles, KF_FLAG_DEFAULT, NULL, &programFilesPath);
std::filesystem::path pixInstallationPath = programFilesPath;
pixInstallationPath /= "Microsoft PIX";
std::wstring newestVersionFound;
for (auto const& directory_entry : std::filesystem::directory_iterator(pixInstallationPath))
{
if (directory_entry.is_directory())
{
if (newestVersionFound.empty() || newestVersionFound < directory_entry.path().filename().c_str())
{
newestVersionFound = directory_entry.path().filename().c_str();
}
}
}
if (newestVersionFound.empty())
{
return L"";
}
std::wstring finalPath = pixInstallationPath / newestVersionFound / L"WinPixGpuCapturer.dll";
return AZStd::wstring(finalPath.c_str());
}
}
@@ -0,0 +1,11 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(FILES
RHI/Factory_windows.cpp
)
@@ -0,0 +1,11 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(FILES
../Common/Unimplemented/Empty_Unimplemented.cpp
)
+65 -5
View File
@@ -11,20 +11,33 @@
#include <AzCore/Interface/Interface.h>
#include <AzCore/Component/TickBus.h>
#if defined(USE_RENDERDOC)
#if defined(USE_RENDERDOC) || defined(USE_PIX)
#include <AzCore/Module/DynamicModuleHandle.h>
#include <Atom/RHI/RHIUtils.h>
#include <Atom_RHI_Traits_Platform.h>
static AZStd::unique_ptr<AZ::DynamicModuleHandle> s_renderDocModule;
static RENDERDOC_API_1_1_2* s_renderDocApi = nullptr;
#endif
#if defined(USE_RENDERDOC)
static AZStd::unique_ptr<AZ::DynamicModuleHandle> s_renderDocModule;
static RENDERDOC_API_1_1_2* s_renderDocApi = nullptr;
static bool s_isRenderDocDllLoaded = false;
#endif
#if defined(USE_PIX)
static AZStd::unique_ptr<AZ::DynamicModuleHandle> s_pixModule;
static bool s_isPixGpuCaptureDllLoaded = false;
#endif
namespace AZ
{
namespace RHI
{
namespace Platform
{
bool IsPixDllInjected(const char* dllName);
AZStd::wstring GetLatestWinPixGpuCapturerPath();
}
uint32_t Factory::GetComponentService()
{
return AZ_CRC("RHIService", 0x45d8e053);
@@ -53,6 +66,7 @@ namespace AZ
{
if (s_renderDocModule->Load(false))
{
s_isRenderDocDllLoaded = true;
pRENDERDOC_GetAPI renderDocGetAPI = s_renderDocModule->GetFunction<pRENDERDOC_GetAPI>("RENDERDOC_GetAPI");
if (renderDocGetAPI)
{
@@ -78,8 +92,30 @@ namespace AZ
}
}
}
#endif // defined(USE_RENDERDOC)
#endif
#if defined(USE_PIX)
// If GPU capture is requested, we need to load the pix library as early as possible (before device queries/factories are made)
bool enablePixGPU = RHI::QueryCommandLineOption("enablePixGPU");
if (enablePixGPU && AZ_TRAIT_PIX_MODULE && !s_pixModule)
{
//Get the path to the latest pix install directory
AZStd::wstring pixGpuDllPath = Platform::GetLatestWinPixGpuCapturerPath();
AZStd::string dllPath;
AZStd::to_string(dllPath, pixGpuDllPath);
s_pixModule = DynamicModuleHandle::Create(dllPath.c_str());
if (s_pixModule)
{
if (!s_pixModule->Load(false))
{
AZ_Printf("RHISystem", "Pix capture requested but module failed to load.\n");
}
}
}
//Pix dll can still be injected even if we do not pass in enablePixGPU. This can be done if we launch the app from Pix.
s_isPixGpuCaptureDllLoaded = Platform::IsPixDllInjected(AZ_TRAIT_PIX_MODULE);
#endif
}
void Factory::Register(Factory* instance)
@@ -116,6 +152,12 @@ namespace AZ
{
s_renderDocModule->Unload();
}
#endif
#if defined(USE_PIX)
if (s_pixModule)
{
s_pixModule->Unload();
}
#endif
}
@@ -137,5 +179,23 @@ namespace AZ
return s_renderDocApi;
}
#endif
bool Factory::IsRenderDocModuleLoaded()
{
#if defined(USE_RENDERDOC)
return s_isRenderDocDllLoaded;
#else
return false;
#endif
}
bool Factory::IsPixModuleLoaded()
{
#if defined(USE_PIX)
return s_isPixGpuCaptureDllLoaded;
#else
return false;
#endif
}
}
}
@@ -417,7 +417,6 @@ namespace AZ
void FrameScheduler::ExecuteContextInternal(FrameGraphExecuteGroup& group, uint32_t index)
{
AZ_PROFILE_FUNCTION(RHI);
FrameGraphExecuteContext* executeContext = group.BeginContext(index);
{
@@ -278,8 +278,6 @@ namespace AZ
const PipelineState* PipelineStateCache::AcquirePipelineState(PipelineLibraryHandle handle, const PipelineStateDescriptor& descriptor)
{
AZ_PROFILE_FUNCTION(RHI);
if (handle.IsNull())
{
return nullptr;
@@ -258,6 +258,14 @@ namespace AZ
return RHI::ResultCode::Success;
}
RHI::ResultCode Device::CreateSwapChain(
[[maybe_unused]] const DXGI_SWAP_CHAIN_DESCX& swapChainDesc,
[[maybe_unused]] AZStd::array<RHI::Ptr<ID3D12Resource>, RHI::Limits::Device::FrameCountMax>& outSwapChainResources)
{
AZ_Assert(false, "Wrong Device::CreateSwapChain function called on Windows.");
return RHI::ResultCode::Fail;
}
AZStd::vector<RHI::Format> Device::GetValidSwapChainImageFormats(const RHI::WindowHandle& windowHandle) const
{
AZStd::vector<RHI::Format> formatsList;
@@ -317,5 +325,10 @@ namespace AZ
return formatsList;
}
void Device::BeginFrameInternal()
{
m_commandQueueContext.Begin();
}
}
}
@@ -0,0 +1,10 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <RHI/SwapChain_Windows.h>
@@ -5,15 +5,28 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <RHI/SwapChain.h>
#include <RHI/SwapChain_Windows.h>
#include <RHI/Device.h>
#include <RHI/Conversions.h>
#include <RHI/Image.h>
#include <RHI/NsightAftermath.h>
namespace AZ
{
namespace DX12
{
RHI::Ptr<SwapChain> SwapChain::Create()
{
return aznew SwapChain();
}
Device& SwapChain::GetDevice() const
{
return static_cast<Device&>(RHI::SwapChain::GetDevice());
}
RHI::ResultCode SwapChain::InitInternal(RHI::Device& deviceBase, const RHI::SwapChainDescriptor& descriptor, RHI::SwapChainDimensions* nativeDimensions)
{
// Check whether tearing support is available for full screen borderless windowed mode.
@@ -165,6 +178,47 @@ namespace AZ
return GetCurrentImageIndex();
}
RHI::ResultCode SwapChain::InitImageInternal(const InitImageRequest& request)
{
Device& device = GetDevice();
Microsoft::WRL::ComPtr<ID3D12Resource> resource;
DX12::AssertSuccess(m_swapChain->GetBuffer(request.m_imageIndex, IID_GRAPHICS_PPV_ARGS(resource.GetAddressOf())));
D3D12_RESOURCE_ALLOCATION_INFO allocationInfo;
device.GetImageAllocationInfo(request.m_descriptor, allocationInfo);
Name name(AZStd::string::format("SwapChainImage_%d", request.m_imageIndex));
Image& image = static_cast<Image&>(*request.m_image);
image.m_memoryView = MemoryView(resource.Get(), 0, allocationInfo.SizeInBytes, allocationInfo.Alignment, MemoryViewType::Image);
image.SetName(name);
image.GenerateSubresourceLayouts();
// Overwrite m_initialAttachmentState because Swapchain images are created with D3D12_RESOURCE_STATE_COMMON state
image.SetAttachmentState(D3D12_RESOURCE_STATE_COMMON);
RHI::HeapMemoryUsage& memoryUsage = m_memoryUsage.GetHeapMemoryUsage(RHI::HeapMemoryLevel::Device);
memoryUsage.m_reservedInBytes += allocationInfo.SizeInBytes;
memoryUsage.m_residentInBytes += allocationInfo.SizeInBytes;
return RHI::ResultCode::Success;
}
void SwapChain::ShutdownResourceInternal(RHI::Resource& resourceBase)
{
Image& image = static_cast<Image&>(resourceBase);
const size_t sizeInBytes = image.GetMemoryView().GetSize();
RHI::HeapMemoryUsage& memoryUsage = m_memoryUsage.GetHeapMemoryUsage(RHI::HeapMemoryLevel::Device);
memoryUsage.m_reservedInBytes -= sizeInBytes;
memoryUsage.m_residentInBytes -= sizeInBytes;
GetDevice().QueueForRelease(image.m_memoryView);
image.m_memoryView = {};
}
RHI::ResultCode SwapChain::ResizeInternal(const RHI::SwapChainDimensions& dimensions, RHI::SwapChainDimensions* nativeDimensions)
{
GetDevice().WaitForIdle();
@@ -0,0 +1,60 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Atom/RHI/SwapChain.h>
#include <RHI/DX12.h>
namespace AZ
{
namespace DX12
{
class Device;
class SwapChain
: public RHI::SwapChain
{
public:
AZ_RTTI(SwapChain, "{974AC6A9-5009-47BE-BD7E-61348BF623F0}", RHI::SwapChain);
AZ_CLASS_ALLOCATOR(SwapChain, AZ::SystemAllocator, 0);
static RHI::Ptr<SwapChain> Create();
Device& GetDevice() const;
private:
SwapChain() = default;
friend class SwapChainFactory;
//////////////////////////////////////////////////////////////////////////
// RHI::SwapChain
RHI::ResultCode InitInternal(RHI::Device& deviceBase, const RHI::SwapChainDescriptor& descriptor, RHI::SwapChainDimensions* nativeDimensions) override;
void ShutdownInternal() override;
uint32_t PresentInternal() override;
RHI::ResultCode InitImageInternal(const InitImageRequest& request) override;
void ShutdownResourceInternal(RHI::Resource& resourceBase) override;
RHI::ResultCode ResizeInternal(const RHI::SwapChainDimensions& dimensions, RHI::SwapChainDimensions* nativeDimensions) override;
bool IsExclusiveFullScreenPreferred() const override;
bool GetExclusiveFullScreenState() const override;
bool SetExclusiveFullScreenState(bool fullScreenState) override;
//////////////////////////////////////////////////////////////////////////
void ConfigureDisplayMode(const RHI::SwapChainDimensions& dimensions);
void EnsureColorSpace(const DXGI_COLOR_SPACE_TYPE& colorSpace);
void DisableHdr();
void SetHDRMetaData(float maxOutputNits, float minOutputNits, float maxContentLightLevel, float maxFrameAverageLightLevel);
static const uint32_t InvalidColorSpace = 0xFFFFFFFE;
DXGI_COLOR_SPACE_TYPE m_colorSpace = static_cast<DXGI_COLOR_SPACE_TYPE>(InvalidColorSpace);
RHI::Ptr<IDXGISwapChainX> m_swapChain;
bool m_isInFullScreenExclusiveState = false; //!< Was SetFullscreenState used to enter full screen exclusive state?
bool m_isTearingSupported = false; //!< Is tearing support available for full screen borderless windowed mode?
};
}
}
@@ -22,7 +22,9 @@ set(FILES
RHI/DX12_Windows.cpp
RHI/DX12_Windows.h
RHI/SystemComponent_Windows.cpp
RHI/SwapChain_Platform.h
RHI/SwapChain_Windows.cpp
RHI/SwapChain_Windows.h
RHI/NsightAftermathGpuCrashTracker_Windows.cpp
RHI/NsightAftermathGpuCrashTracker_Windows.h
RHI/NsightAftermath_Windows.cpp
@@ -41,6 +41,8 @@
#define DX12_COMMANDLIST_TIMER_DETAIL(id)
#endif
#define PIX_MARKER_CMDLIST_COL 0xFF0000FF
namespace AZ
{
namespace DX12
@@ -94,16 +96,22 @@ namespace AZ
{
SetName(name);
PIXBeginEvent(0xFF0000FF, name.GetCStr());
PIXBeginEvent(GetCommandList(), 0xFF0000FF, name.GetCStr());
PIXBeginEvent(PIX_MARKER_CMDLIST_COL, name.GetCStr());
if (RHI::Factory::Get().IsPixModuleLoaded() || RHI::Factory::Get().IsRenderDocModuleLoaded())
{
PIXBeginEvent(GetCommandList(), PIX_MARKER_CMDLIST_COL, name.GetCStr());
}
}
void CommandList::Close()
{
FlushBarriers();
PIXEndEvent(GetCommandList());
PIXEndEvent();
if (RHI::Factory::Get().IsPixModuleLoaded() || RHI::Factory::Get().IsRenderDocModuleLoaded())
{
PIXEndEvent(GetCommandList());
}
CommandListBase::Close();
}
@@ -189,11 +189,6 @@ namespace AZ
m_commandQueueContext.UpdateCpuTimingStatistics(cpuTimingStatistics);
}
void Device::BeginFrameInternal()
{
m_commandQueueContext.Begin();
}
void Device::EndFrameInternal()
{
AZ_TRACE_METHOD();
@@ -57,6 +57,10 @@ namespace AZ
const DXGI_SWAP_CHAIN_DESCX& swapChainDesc,
RHI::Ptr<IDXGISwapChainX>& swapChain);
RHI::ResultCode CreateSwapChain(
const DXGI_SWAP_CHAIN_DESCX& swapChainDesc,
AZStd::array<RHI::Ptr<ID3D12Resource>, RHI::Limits::Device::FrameCountMax>& outSwapChainResources);
void GetImageAllocationInfo(
const RHI::ImageDescriptor& descriptor,
D3D12_RESOURCE_ALLOCATION_INFO& info);
@@ -7,6 +7,7 @@
*/
#include <RHI/Device.h>
#include <RHI/PipelineLibrary.h>
#include <Atom/RHI/Factory.h>
namespace AZ
{
@@ -46,7 +47,16 @@ namespace AZ
#if defined (AZ_DX12_USE_PIPELINE_LIBRARY)
AZStd::array_view<uint8_t> bytes;
if (serializedData)
bool shouldCreateLibFromSerializedData = true;
if (RHI::Factory::Get().IsRenderDocModuleLoaded() || RHI::Factory::Get().IsPixModuleLoaded())
{
// CreatePipelineLibrary api does not function properly if Renderdoc or Pix is enabled
shouldCreateLibFromSerializedData = false;
}
if (serializedData && shouldCreateLibFromSerializedData)
{
bytes = serializedData->GetData();
}
@@ -205,10 +215,11 @@ namespace AZ
RHI::ResultCode PipelineLibrary::MergeIntoInternal([[maybe_unused]] AZStd::array_view<const RHI::PipelineLibrary*> pipelineLibraries)
{
#if defined(USE_PIX) || defined(USE_RENDERDOC)
// StorePipeline api does not function properly if Pix or RenderDoc is enabled
return RHI::ResultCode::Fail;
#else
if (RHI::Factory::Get().IsRenderDocModuleLoaded() || RHI::Factory::Get().IsPixModuleLoaded())
{
// StorePipeline api does not function properly if RenderDoc or Pix is enabled
return RHI::ResultCode::Fail;
}
#if defined (AZ_DX12_USE_PIPELINE_LIBRARY)
AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
@@ -226,8 +237,7 @@ namespace AZ
}
}
#endif
return RHI::ResultCode::Success;
#endif
return RHI::ResultCode::Success;
}
RHI::ConstPtr<RHI::PipelineLibraryData> PipelineLibrary::GetSerializedDataInternal() const
@@ -252,7 +262,11 @@ namespace AZ
bool PipelineLibrary::IsMergeRequired() const
{
#if defined (AZ_DX12_USE_PIPELINE_LIBRARY)
return !m_pipelineStates.empty();
#else
return false;
#endif
}
}
}
@@ -28,11 +28,11 @@ namespace AZ
}
#endif
RHI::ResultCode RayTracingPipelineState::InitInternal(RHI::Device& deviceBase, [[maybe_unused]]const RHI::RayTracingPipelineStateDescriptor* descriptor)
RHI::ResultCode RayTracingPipelineState::InitInternal([[maybe_unused]]RHI::Device& deviceBase, [[maybe_unused]]const RHI::RayTracingPipelineStateDescriptor* descriptor)
{
#ifdef AZ_DX12_DXR_SUPPORT
Device& device = static_cast<Device&>(deviceBase);
#ifdef AZ_DX12_DXR_SUPPORT
size_t dxilLibraryCount = descriptor->GetShaderLibraries().size();
size_t hitGroupCount = descriptor->GetHitGroups().size();
+9 -2
View File
@@ -18,6 +18,7 @@
#include <Atom/RHI/ResourcePool.h>
#include <Atom/RHI/ImageScopeAttachment.h>
#include <Atom/RHI/BufferScopeAttachment.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RHI/ResolveScopeAttachment.h>
#include <AzCore/Debug/EventTrace.h>
@@ -309,8 +310,11 @@ namespace AZ
commandList.GetValidator().BeginScope(*this);
PIXBeginEvent(0xFFFF00FF, GetId().GetCStr());
PIXBeginEvent(commandList.GetCommandList(), 0xFFFF00FF, GetId().GetCStr());
if (RHI::Factory::Get().IsPixModuleLoaded() || RHI::Factory::Get().IsRenderDocModuleLoaded())
{
PIXBeginEvent(commandList.GetCommandList(), 0xFFFF00FF, GetId().GetCStr());
}
commandList.SetAftermathEventMarker(GetId().GetCStr());
@@ -424,7 +428,10 @@ namespace AZ
}
}
PIXEndEvent(commandList.GetCommandList());
if (RHI::Factory::Get().IsPixModuleLoaded() || RHI::Factory::Get().IsRenderDocModuleLoaded())
{
PIXEndEvent(commandList.GetCommandList());
}
PIXEndEvent();
commandList.GetValidator().EndScope();
@@ -1,73 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <RHI/SwapChain.h>
#include <RHI/Device.h>
#include <RHI/Conversions.h>
#include <RHI/Image.h>
#include <Atom/RHI/MemoryStatisticsBuilder.h>
#include <Atom/RHI.Reflect/AttachmentEnums.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/string/conversions.h>
namespace AZ
{
namespace DX12
{
RHI::Ptr<SwapChain> SwapChain::Create()
{
return aznew SwapChain();
}
Device& SwapChain::GetDevice() const
{
return static_cast<Device&>(Base::GetDevice());
}
RHI::ResultCode SwapChain::InitImageInternal(const InitImageRequest& request)
{
Device& device = GetDevice();
Microsoft::WRL::ComPtr<ID3D12Resource> resource;
DX12::AssertSuccess(m_swapChain->GetBuffer(request.m_imageIndex, IID_GRAPHICS_PPV_ARGS(resource.GetAddressOf())));
D3D12_RESOURCE_ALLOCATION_INFO allocationInfo;
device.GetImageAllocationInfo(request.m_descriptor, allocationInfo);
Name name(AZStd::string::format("SwapChainImage_%d", request.m_imageIndex));
Image& image = static_cast<Image&>(*request.m_image);
image.m_memoryView = MemoryView(resource.Get(), 0, allocationInfo.SizeInBytes, allocationInfo.Alignment, MemoryViewType::Image);
image.SetName(name);
image.GenerateSubresourceLayouts();
// Overwrite m_initialAttachmentState because Swapchain images are created with D3D12_RESOURCE_STATE_COMMON state
image.SetAttachmentState(D3D12_RESOURCE_STATE_COMMON);
RHI::HeapMemoryUsage& memoryUsage = m_memoryUsage.GetHeapMemoryUsage(RHI::HeapMemoryLevel::Device);
memoryUsage.m_reservedInBytes += allocationInfo.SizeInBytes;
memoryUsage.m_residentInBytes += allocationInfo.SizeInBytes;
return RHI::ResultCode::Success;
}
void SwapChain::ShutdownResourceInternal(RHI::Resource& resourceBase)
{
Image& image = static_cast<Image&>(resourceBase);
const size_t sizeInBytes = image.GetMemoryView().GetSize();
RHI::HeapMemoryUsage& memoryUsage = m_memoryUsage.GetHeapMemoryUsage(RHI::HeapMemoryLevel::Device);
memoryUsage.m_reservedInBytes -= sizeInBytes;
memoryUsage.m_residentInBytes -= sizeInBytes;
GetDevice().QueueForRelease(image.m_memoryView);
image.m_memoryView = {};
}
}
}
+1 -53
View File
@@ -7,56 +7,4 @@
*/
#pragma once
#include <Atom/RHI/SwapChain.h>
#include <RHI/DX12.h>
namespace AZ
{
namespace DX12
{
class Device;
class Image;
class CommandQueue;
class SwapChain
: public RHI::SwapChain
{
using Base = RHI::SwapChain;
public:
AZ_RTTI(SwapChain, "{974AC6A9-5009-47BE-BD7E-61348BF623F0}", Base);
AZ_CLASS_ALLOCATOR(SwapChain, AZ::SystemAllocator, 0);
static RHI::Ptr<SwapChain> Create();
Device& GetDevice() const;
private:
SwapChain() = default;
//////////////////////////////////////////////////////////////////////////
// RHI::SwapChain
RHI::ResultCode InitInternal(RHI::Device& deviceBase, const RHI::SwapChainDescriptor& descriptor, RHI::SwapChainDimensions* nativeDimensions) override;
void ShutdownInternal() override;
uint32_t PresentInternal() override;
RHI::ResultCode InitImageInternal(const InitImageRequest& request) override;
void ShutdownResourceInternal(RHI::Resource& resourceBase) override;
RHI::ResultCode ResizeInternal(const RHI::SwapChainDimensions& dimensions, RHI::SwapChainDimensions* nativeDimensions) override;
bool IsExclusiveFullScreenPreferred() const override;
bool GetExclusiveFullScreenState() const override;
bool SetExclusiveFullScreenState(bool fullScreenState) override;
//////////////////////////////////////////////////////////////////////////
void ConfigureDisplayMode(const RHI::SwapChainDimensions& dimensions);
void EnsureColorSpace(const DXGI_COLOR_SPACE_TYPE& colorSpace);
void DisableHdr();
void SetHDRMetaData(float maxOutputNits, float minOutputNits, float maxContentLightLevel, float maxFrameAverageLightLevel);
static const uint32_t InvalidColorSpace = 0xFFFFFFFE;
DXGI_COLOR_SPACE_TYPE m_colorSpace = static_cast<DXGI_COLOR_SPACE_TYPE>(InvalidColorSpace);
RHI::Ptr<IDXGISwapChainX> m_swapChain;
bool m_isInFullScreenExclusiveState = false; //!< Was SetFullscreenState used to enter full screen exclusive state?
bool m_isTearingSupported = false; //!< Is tearing support available for full screen borderless windowed mode?
};
}
}
#include <RHI/SwapChain_Platform.h>
@@ -95,7 +95,6 @@ set(FILES
Source/RHI/ShaderResourceGroup.h
Source/RHI/ShaderResourceGroupPool.cpp
Source/RHI/ShaderResourceGroupPool.h
Source/RHI/SwapChain.cpp
Source/RHI/SwapChain.h
Source/RHI/DX12.cpp
Source/RHI/DX12.h
@@ -14,10 +14,6 @@ elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "wayland")
set(GLAD_VULKAN_COMPILE_DEFINITIONS
VK_USE_PLATFORM_WAYLAND_KHR
)
elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "xlib")
set(GLAD_VULKAN_COMPILE_DEFINITIONS
VK_USE_PLATFORM_XLIB_KHR
)
else()
message(FATAL_ERROR, "Linux Window Manager ${PAL_TRAIT_LINUX_WINDOW_MANAGER} is not recognized")
endif()
+3
View File
@@ -19,9 +19,12 @@ if(NOT PAL_TRAIT_ATOM_RHI_VULKAN_SUPPORTED)
NAMESPACE Gem
FILES_CMAKE
atom_rhi_vulkan_stub_module.cmake
atom_rhi_vulkan_reflect_common_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
Include
Source
${pal_include_dir}
Include/Atom/RHI.Loader/Glad
BUILD_DEPENDENCIES
PRIVATE
@@ -5,6 +5,8 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/RHI.Reflect/Vulkan/ReflectSystemComponent.h>
#include <AzCore/Module/Module.h>
namespace AZ
@@ -17,7 +19,12 @@ namespace AZ
public:
AZ_RTTI(PlatformModule, "{958CB096-796C-42C7-9B29-17C6FE792C30}", Module);
PlatformModule() = default;
PlatformModule()
{
m_descriptors.insert(m_descriptors.end(), {
ReflectSystemComponent::CreateDescriptor()
});
}
~PlatformModule() override = default;
AZ::ComponentTypeList GetRequiredSystemComponents() const override
@@ -41,9 +41,6 @@ namespace AZ
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
#error "Linux Window Manager Wayland not supported."
return RHI::ResultCode::Unimplemented;
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB
#error "Linux Window Manager XLIB not supported."
return RHI::ResultCode::Unimplemented;
#else
#error "Linux Window Manager not recognized."
return RHI::ResultCode::Unimplemented;
@@ -13,6 +13,5 @@
partial ShaderResourceGroup SceneSrg
{
float m_time;
float m_deltaTime;
}
@@ -129,10 +129,6 @@ namespace AZ
void RemoveRenderPipeline(const RenderPipelineId& pipelineId);
//! Set a callback function to set values for scene's srg.
//! The callback function is usually defined by the one who create the scene since it knows how the layout look like.
void SetShaderResourceGroupCallback(ShaderResourceGroupCallback callback);
const RHI::ShaderResourceGroup* GetRHIShaderResourceGroup() const;
Data::Instance<ShaderResourceGroup> GetShaderResourceGroup() const;
@@ -166,9 +162,13 @@ namespace AZ
RenderPipelinePtr FindRenderPipelineForWindow(AzFramework::NativeWindowHandle windowHandle);
using PrepareSceneSrgEvent = AZ::Event<RPI::ShaderResourceGroup*>;
//! Connect a handler to listen to the event that the Scene is ready to update and compile its scene srg
//! User should use this event to update the part scene srg they know of
void ConnectEvent(PrepareSceneSrgEvent::Handler& handler);
protected:
// SceneFinder overrides...
Scene* FindSelf();
void OnSceneNotifictaionHandlerConnected(SceneNotification* handler);
// Cpu simulation which runs all active FeatureProcessor Simulate() functions.
@@ -183,7 +183,7 @@ namespace AZ
// Function called when the current frame is finished rendering.
void OnFrameEnd();
// Update and compile view srgs
// Update and compile scene and view srgs
// This is called after PassSystem's FramePrepare so passes can still modify view srgs in its FramePrepareIntenal function before they are submitted to command list
void UpdateSrgs();
@@ -200,6 +200,10 @@ namespace AZ
// Add a created feature processor to this scene
void AddFeatureProcessor(FeatureProcessorPtr fp);
// Send out event to PrepareSceneSrgEvent::Handlers so they can update scene srg as needed
// This happens in UpdateSrgs()
void PrepareSceneSrg();
// List of feature processors that are active for this scene
AZStd::vector<FeatureProcessorPtr> m_featureProcessors;
@@ -215,9 +219,10 @@ namespace AZ
AZ::RPI::FeatureProcessor::SimulatePacket m_simulatePacket;
AZ::RPI::FeatureProcessor::RenderPacket m_renderPacket;
// Scene's srg and its set function
// Scene's srg
Data::Instance<ShaderResourceGroup> m_srg;
ShaderResourceGroupCallback m_srgCallback;
// Event to for prepare scene srg
PrepareSceneSrgEvent m_prepareSrgEvent;
// The uuid to identify this scene.
SceneId m_id;
@@ -234,6 +239,8 @@ namespace AZ
// Registry which allocates draw filter tag for RenderPipeline
RHI::Ptr<RHI::DrawFilterTagRegistry> m_drawFilterTagRegistry;
float m_simulationTime;
};
// --- Template functions ---
@@ -80,7 +80,6 @@ namespace AZ
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
using BusIdType = SceneId;
virtual Scene* FindSelf() = 0;
virtual void OnSceneNotifictaionHandlerConnected(SceneNotification* handler) = 0;
};
@@ -124,7 +124,6 @@ namespace AZ
bool MeshDrawPacket::DoUpdate(const Scene& parentScene)
{
AZ_PROFILE_FUNCTION(RPI);
const ModelLod::Mesh& mesh = m_modelLod->GetMeshes()[m_modelLodMeshIndex];
if (!m_material)
@@ -155,8 +154,6 @@ namespace AZ
auto appendShader = [&](const ShaderCollection::Item& shaderItem)
{
AZ_PROFILE_SCOPE(RPI, "appendShader()");
// Skip the shader item without creating the shader instance
// if the mesh is not going to be rendered based on the draw tag
RHI::RHISystemInterface* rhiSystem = RHI::RHISystemInterface::Get();
@@ -256,7 +253,6 @@ namespace AZ
Data::Instance<ShaderResourceGroup> drawSrg;
if (drawSrgLayout)
{
AZ_PROFILE_SCOPE(RPI, "create drawSrg");
// If the DrawSrg exists we must create and bind it, otherwise the CommandList will fail validation for SRG being null
drawSrg = RPI::ShaderResourceGroup::Create(shader->GetAsset(), shader->GetSupervariantIndex(), drawSrgLayout->GetName());
@@ -264,8 +264,6 @@ namespace AZ
const MaterialModelUvOverrideMap& materialModelUvMap,
const MaterialUvNameMap& materialUvNameMap) const
{
AZ_PROFILE_FUNCTION(RPI);
streamBufferViewsOut.clear();
RHI::InputStreamLayoutBuilder layoutBuilder;
@@ -366,8 +364,6 @@ namespace AZ
const MaterialModelUvOverrideMap& materialModelUvMap,
const MaterialUvNameMap& materialUvNameMap) const
{
AZ_PROFILE_FUNCTION(RPI);
const Mesh& mesh = m_meshes[meshIndex];
auto defaultUv = FindDefaultUvStream(meshIndex, materialUvNameMap);
@@ -308,10 +308,10 @@ namespace AZ
// The fix is to clear the buffer outside of the callback.
for (int32_t i = 0; i < RHI::Limits::Device::FrameCountMax; i++)
{
if (m_isReadbackComplete[m_readbackBufferCurrentIndex])
if (m_isReadbackComplete[i])
{
m_isReadbackComplete[m_readbackBufferCurrentIndex] = false;
m_readbackBufferArray[m_readbackBufferCurrentIndex] = nullptr;
m_isReadbackComplete[i] = false;
m_readbackBufferArray[i] = nullptr;
}
}
// Loop the triple buffer index and cache the current index to the callback.

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