Merge branch 'development' of https://github.com/o3de/o3de into carlitosan/development
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-4
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-1
@@ -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
|
||||
{
|
||||
|
||||
-8
@@ -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())
|
||||
|
||||
-3
@@ -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;
|
||||
|
||||
+1
@@ -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;
|
||||
|
||||
+1
@@ -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);
|
||||
|
||||
|
||||
-2
@@ -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))
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -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
|
||||
|
||||
+8
-7
@@ -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;
|
||||
|
||||
+11
-14
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
)
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
+8
-1
@@ -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;
|
||||
|
||||
-1
@@ -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
Reference in New Issue
Block a user