Merge branch 'development' of https://github.com/o3de/o3de into carlitosan/development
commit
5e91be38ba
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
)
|
||||
@ -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
|
||||
)
|
||||
@ -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>
|
||||
@ -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?
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -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 = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue