Update amdgpu-windows-interop with latest changes 20251105 (#1728)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
کامیت شده توسط
GitHub
والد
ea31a0bf18
کامیت
27f85500f8
@@ -1,92 +1,92 @@
|
||||
##
|
||||
#######################################################################################################################
|
||||
#
|
||||
# Copyright (c) 2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
#######################################################################################################################
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
project(PAL LANGUAGES CXX)
|
||||
add_library(pal INTERFACE)
|
||||
set_target_properties(pal PROPERTIES
|
||||
CXX_STANDARD 20
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CXX_EXTENSIONS OFF
|
||||
POSITION_INDEPENDENT_CODE TRUE
|
||||
)
|
||||
target_compile_features(pal INTERFACE cxx_std_20)
|
||||
if (NOT PAL_CLIENT_INTERFACE_MAJOR_VERSION EQUAL 932)
|
||||
message(WARNING "PAL: PAL_CLIENT_INTERFACE_MAJOR_VERSION ${PAL_CLIENT_INTERFACE_MAJOR_VERSION} not supported !!!")
|
||||
endif()
|
||||
target_link_libraries(pal
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/pal.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/palCompilerDeps.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/palUtil.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/pal_uuid.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/cwpack.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/pal_lz4.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/addrlib.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/amdrdf.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/zstd.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/vam.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/UberTraceService.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/DriverUtilsService.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/dd_settings.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/SettingsRpcService2.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddRpcServer.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddNet.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddRpcShared.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddSocket.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/devdriver.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/dd_common.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddCommon.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddCore.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/dd_libyaml.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/mpack.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/metrohash.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/stb_sprintf.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddRpcClient.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddEventStreamer.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddEventClient.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddEventParser.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddEventServer.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddYaml.lib
|
||||
SetupAPI.Lib
|
||||
)
|
||||
target_compile_definitions(pal
|
||||
INTERFACE
|
||||
PAL_CLIENT_INTERFACE_MAJOR_VERSION=932
|
||||
GPUOPEN_CLIENT_INTERFACE_MAJOR_VERSION=42
|
||||
PAL_BUILD_RDF=1
|
||||
PAL_DEVELOPER_BUILD=0
|
||||
PAL_KMT_BUILD=1
|
||||
)
|
||||
target_include_directories(pal
|
||||
INTERFACE
|
||||
inc
|
||||
inc/core
|
||||
inc/gpuUtil
|
||||
inc/util
|
||||
shared/inc
|
||||
shared/devdriver/shared/legacy/inc
|
||||
shared/devdriver/third_party/dd_crc32/inc
|
||||
shared/metrohash/src
|
||||
)
|
||||
##
|
||||
#######################################################################################################################
|
||||
#
|
||||
# Copyright (c) 2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
#######################################################################################################################
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
project(PAL LANGUAGES CXX)
|
||||
add_library(pal INTERFACE)
|
||||
set_target_properties(pal PROPERTIES
|
||||
CXX_STANDARD 20
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CXX_EXTENSIONS OFF
|
||||
POSITION_INDEPENDENT_CODE TRUE
|
||||
)
|
||||
target_compile_features(pal INTERFACE cxx_std_20)
|
||||
if (NOT PAL_CLIENT_INTERFACE_MAJOR_VERSION EQUAL 932)
|
||||
message(WARNING "PAL: PAL_CLIENT_INTERFACE_MAJOR_VERSION ${PAL_CLIENT_INTERFACE_MAJOR_VERSION} not supported !!!")
|
||||
endif()
|
||||
target_link_libraries(pal
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/pal.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/palCompilerDeps.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/palUtil.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/pal_uuid.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/cwpack.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/pal_lz4.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/addrlib.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/amdrdf.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/zstd.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/vam.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/UberTraceService.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/DriverUtilsService.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/dd_settings.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/SettingsRpcService2.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddRpcServer.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddNet.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddRpcShared.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddSocket.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/devdriver.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/dd_common.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddCommon.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddCore.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/dd_libyaml.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/mpack.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/metrohash.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/stb_sprintf.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddRpcClient.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddEventStreamer.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddEventClient.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddEventParser.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddEventServer.lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/x64/ddYaml.lib
|
||||
SetupAPI.Lib
|
||||
)
|
||||
target_compile_definitions(pal
|
||||
INTERFACE
|
||||
PAL_CLIENT_INTERFACE_MAJOR_VERSION=932
|
||||
GPUOPEN_CLIENT_INTERFACE_MAJOR_VERSION=42
|
||||
PAL_BUILD_RDF=1
|
||||
PAL_DEVELOPER_BUILD=0
|
||||
PAL_KMT_BUILD=1
|
||||
)
|
||||
target_include_directories(pal
|
||||
INTERFACE
|
||||
inc
|
||||
inc/core
|
||||
inc/gpuUtil
|
||||
inc/util
|
||||
shared/inc
|
||||
shared/devdriver/shared/legacy/inc
|
||||
shared/devdriver/third_party/dd_crc32/inc
|
||||
shared/metrohash/src
|
||||
)
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,204 +1,204 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palCmdAllocator.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) ICmdAllocator interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palDestroyable.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
struct GpuMemSubAllocInfo;
|
||||
class IGpuMemory;
|
||||
|
||||
/// Flags controlling the creation of ICmdAllocator objects.
|
||||
union CmdAllocatorCreateFlags
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 threadSafe : 1; ///< If set, the allocator will acquire a lock each time it is accessed;
|
||||
/// otherwise it will not attempt to protect itself from multithreaded
|
||||
/// access.
|
||||
uint32 autoMemoryReuse : 1; ///< If set, the allocator will track when the GPU finishes accessing
|
||||
/// each piece of command memory and attempt to reuse memory which the
|
||||
/// GPU is done with before allocating more memory from the OS. If not
|
||||
/// set, memory will only be recycled after a call to
|
||||
/// @ref ICmdAllocator::Reset().
|
||||
uint32 disableBusyChunkTracking : 1; ///< If set, the allocator will not do any GPU-side tracking of which
|
||||
/// command chunks are still in use. It will be the client's (or the
|
||||
/// application's) responsibility to guarantee that command chunks are
|
||||
/// not returned to the allocator before the GPU has finished processing
|
||||
/// them. Failure to guarantee this will result in undefined behavior.
|
||||
/// This flag has no effect if @ref autoMemoryReuse is not set.
|
||||
uint32 autoTrimMemory : 1; ///< If set the allocator will automatically trim down the allocations
|
||||
/// (where all chunks are idle on the freeList). A minimum of
|
||||
/// allocFreeThreshold allocations are kept for fast reuse.
|
||||
uint32 reserved : 28; ///< Reserved for future use.
|
||||
};
|
||||
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
};
|
||||
|
||||
/// Different type of allocation data that an ICmdAllocator allocates and distributes to command buffers.
|
||||
enum CmdAllocType : uint32
|
||||
{
|
||||
CommandDataAlloc = 0, ///< Data allocated is for executable commands.
|
||||
EmbeddedDataAlloc, ///< Data allocated is for embedded data.
|
||||
LargeEmbeddedDataAlloc, ///< Data allocated is for embedded data, allocation is >32kb
|
||||
GpuScratchMemAlloc, ///< Data allocated is GPU-only accessible at command buffer execution-time. Possible
|
||||
/// uses like GPU events.
|
||||
CmdAllocatorTypeCount ///< Number of allocation types for ICmdAllocator's.
|
||||
};
|
||||
|
||||
/// Specifies properties for creation of an ICmdAllocator object. Input structure to IDevice::CreateCmdAllocator().
|
||||
struct CmdAllocatorCreateInfo
|
||||
{
|
||||
CmdAllocatorCreateFlags flags; ///< Flags controlling command allocator creation.
|
||||
|
||||
struct
|
||||
{
|
||||
GpuHeap allocHeap; ///< Preferred allocation heap. For @ref GpuScratchMemAlloc, this field is
|
||||
/// ignored and the allocation will always be in GPU-invisible memory. For
|
||||
/// all other allocation types, this must be CPU-mappable.
|
||||
/// For best performance, command allocators that will be used by the
|
||||
/// UVD engine should prefer the Local heap
|
||||
gpusize allocSize; ///< Size, in bytes, of the GPU memory allocations this allocator will create.
|
||||
/// It must be an integer multiple of suballocSize.
|
||||
gpusize suballocSize; ///< Size, in bytes, of the chunks of GPU memory this allocator will give to
|
||||
/// command buffers. It must be an integer multiple of 4096.
|
||||
/// Must be greater than zero even if the client doesn't plan on using this
|
||||
/// allocation type.
|
||||
uint32 allocFreeThreshold; ///< Minimum count of free allocations that the allocator should keep around
|
||||
/// for fast reuse. It is used when the autoTrimMemory flag is set.
|
||||
} allocInfo[CmdAllocatorTypeCount]; ///< Information for each allocation type.
|
||||
};
|
||||
|
||||
/// Output structure for QueryUtilizationInfo().
|
||||
/// The CmdAllocator utilization data can be queried by PAL clients in order to decide whether to trim the allocations.
|
||||
struct CmdAllocatorUtilizationInfo
|
||||
{
|
||||
uint32 numAllocations; ///< Number of allocations owned by the allocator.
|
||||
uint32 numFreeChunks; ///< Number of chunks that are reset and not in use.
|
||||
uint32 numBusyChunks; ///< Number of chunks that in use by the GPU.
|
||||
uint32 numReuseChunks; ///< Number of chunks that have been 'returned' to the allocator for reuse.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface ICmdAllocator
|
||||
* @brief Allocates and distributes GPU memory to command buffers on the client's behalf.
|
||||
*
|
||||
* All ICmdBuffer objects must be associated with an ICmdAllocator at creation. Command buffers may switch command
|
||||
* allocators when ICmdBuffer::Reset() is called. The set of command buffers associated with a given command allocator
|
||||
* will query that allocator for additional GPU memory as they are building commands.
|
||||
*
|
||||
* To protect against race conditions the client must ask for a thread safe command allocator unless its can guarantee
|
||||
* that all command buffers associated with a given command allocator will be built, reset, and destroyed in a thread-
|
||||
* safe manner. It is illegal to destroy a command allocator while it still has command buffers associated with it.
|
||||
*
|
||||
* @see IDevice::CreateCmdAllocator()
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class ICmdAllocator : public IDestroyable
|
||||
{
|
||||
public:
|
||||
/// Explicitly resets a command allocator, marking all internal GPU memory allocations as unused.
|
||||
///
|
||||
/// The client is responsible for guaranteeing that all command buffers associated with this allocator have finished
|
||||
/// GPU execution and have been explicitly reset before calling this function.
|
||||
///
|
||||
/// @param [in] freeMemory If the all GPU and CPU memory allocations should be returned to the OS.
|
||||
///
|
||||
/// @returns Success if the command allocator was successfully reset. Otherwise, one of the following errors may be
|
||||
/// returned:
|
||||
/// + ErrorUnknown if an internal PAL error occurs.
|
||||
virtual Result Reset(bool freeMemory) = 0;
|
||||
|
||||
/// Explicitly trims a command allocator, deleting as many unused internal GPU memory allocations as possible.
|
||||
///
|
||||
/// @returns Success if the command allocator was successfully trimmed.
|
||||
///
|
||||
/// @param [in] allocTypeMask Gives control whether trimming will be applied for each CmdAllocType.
|
||||
/// Use (1 << CmdAllocatorTypeCount) - 1 to apply trimming to all types.
|
||||
/// When trimming only the embedded date use (1 << EmbeddedDataAlloc).
|
||||
/// @param [in] dynamicThreshold Minimum count of free allocations that the allocator should keep around
|
||||
|
||||
virtual Result Trim(uint32 allocTypeMask, uint32 dynamicThreshold) = 0;
|
||||
|
||||
/// Query the numbers of allocations and chunks of the given CmdAllocator type.
|
||||
/// This may help clients to decide whether they may apply trimming or not.
|
||||
///
|
||||
/// @returns Success if valid values can be reported.
|
||||
///
|
||||
/// @param [in] type CmdAllocType that is being queried
|
||||
/// @param [out] pUtilizationInfo The allocation and chunk counts will be stored here.
|
||||
|
||||
virtual Result QueryUtilizationInfo(CmdAllocType type, CmdAllocatorUtilizationInfo* pUtilizationInfo) const = 0;
|
||||
|
||||
/// Returns the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @returns Pointer to client data.
|
||||
void* GetClientData() const
|
||||
{
|
||||
return m_pClientData;
|
||||
}
|
||||
|
||||
/// Sets the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @param [in] pClientData A pointer to arbitrary client data.
|
||||
void SetClientData(
|
||||
void* pClientData)
|
||||
{
|
||||
m_pClientData = pClientData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @internal Constructor. Prevent use of new operator on this interface. Client must create objects by explicitly
|
||||
/// called the proper create method.
|
||||
ICmdAllocator() : m_pClientData(nullptr) {}
|
||||
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~ICmdAllocator() { }
|
||||
|
||||
private:
|
||||
/// @internal Client data pointer. This can have an arbitrary value and can be returned by calling GetClientData()
|
||||
/// and set via SetClientData().
|
||||
/// For non-top-layer objects, this will point to the layer above the current object.
|
||||
void* m_pClientData;
|
||||
};
|
||||
|
||||
} // Pal
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palCmdAllocator.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) ICmdAllocator interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palDestroyable.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
struct GpuMemSubAllocInfo;
|
||||
class IGpuMemory;
|
||||
|
||||
/// Flags controlling the creation of ICmdAllocator objects.
|
||||
union CmdAllocatorCreateFlags
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 threadSafe : 1; ///< If set, the allocator will acquire a lock each time it is accessed;
|
||||
/// otherwise it will not attempt to protect itself from multithreaded
|
||||
/// access.
|
||||
uint32 autoMemoryReuse : 1; ///< If set, the allocator will track when the GPU finishes accessing
|
||||
/// each piece of command memory and attempt to reuse memory which the
|
||||
/// GPU is done with before allocating more memory from the OS. If not
|
||||
/// set, memory will only be recycled after a call to
|
||||
/// @ref ICmdAllocator::Reset().
|
||||
uint32 disableBusyChunkTracking : 1; ///< If set, the allocator will not do any GPU-side tracking of which
|
||||
/// command chunks are still in use. It will be the client's (or the
|
||||
/// application's) responsibility to guarantee that command chunks are
|
||||
/// not returned to the allocator before the GPU has finished processing
|
||||
/// them. Failure to guarantee this will result in undefined behavior.
|
||||
/// This flag has no effect if @ref autoMemoryReuse is not set.
|
||||
uint32 autoTrimMemory : 1; ///< If set the allocator will automatically trim down the allocations
|
||||
/// (where all chunks are idle on the freeList). A minimum of
|
||||
/// allocFreeThreshold allocations are kept for fast reuse.
|
||||
uint32 reserved : 28; ///< Reserved for future use.
|
||||
};
|
||||
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
};
|
||||
|
||||
/// Different type of allocation data that an ICmdAllocator allocates and distributes to command buffers.
|
||||
enum CmdAllocType : uint32
|
||||
{
|
||||
CommandDataAlloc = 0, ///< Data allocated is for executable commands.
|
||||
EmbeddedDataAlloc, ///< Data allocated is for embedded data.
|
||||
LargeEmbeddedDataAlloc, ///< Data allocated is for embedded data, allocation is >32kb
|
||||
GpuScratchMemAlloc, ///< Data allocated is GPU-only accessible at command buffer execution-time. Possible
|
||||
/// uses like GPU events.
|
||||
CmdAllocatorTypeCount ///< Number of allocation types for ICmdAllocator's.
|
||||
};
|
||||
|
||||
/// Specifies properties for creation of an ICmdAllocator object. Input structure to IDevice::CreateCmdAllocator().
|
||||
struct CmdAllocatorCreateInfo
|
||||
{
|
||||
CmdAllocatorCreateFlags flags; ///< Flags controlling command allocator creation.
|
||||
|
||||
struct
|
||||
{
|
||||
GpuHeap allocHeap; ///< Preferred allocation heap. For @ref GpuScratchMemAlloc, this field is
|
||||
/// ignored and the allocation will always be in GPU-invisible memory. For
|
||||
/// all other allocation types, this must be CPU-mappable.
|
||||
/// For best performance, command allocators that will be used by the
|
||||
/// UVD engine should prefer the Local heap
|
||||
gpusize allocSize; ///< Size, in bytes, of the GPU memory allocations this allocator will create.
|
||||
/// It must be an integer multiple of suballocSize.
|
||||
gpusize suballocSize; ///< Size, in bytes, of the chunks of GPU memory this allocator will give to
|
||||
/// command buffers. It must be an integer multiple of 4096.
|
||||
/// Must be greater than zero even if the client doesn't plan on using this
|
||||
/// allocation type.
|
||||
uint32 allocFreeThreshold; ///< Minimum count of free allocations that the allocator should keep around
|
||||
/// for fast reuse. It is used when the autoTrimMemory flag is set.
|
||||
} allocInfo[CmdAllocatorTypeCount]; ///< Information for each allocation type.
|
||||
};
|
||||
|
||||
/// Output structure for QueryUtilizationInfo().
|
||||
/// The CmdAllocator utilization data can be queried by PAL clients in order to decide whether to trim the allocations.
|
||||
struct CmdAllocatorUtilizationInfo
|
||||
{
|
||||
uint32 numAllocations; ///< Number of allocations owned by the allocator.
|
||||
uint32 numFreeChunks; ///< Number of chunks that are reset and not in use.
|
||||
uint32 numBusyChunks; ///< Number of chunks that in use by the GPU.
|
||||
uint32 numReuseChunks; ///< Number of chunks that have been 'returned' to the allocator for reuse.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface ICmdAllocator
|
||||
* @brief Allocates and distributes GPU memory to command buffers on the client's behalf.
|
||||
*
|
||||
* All ICmdBuffer objects must be associated with an ICmdAllocator at creation. Command buffers may switch command
|
||||
* allocators when ICmdBuffer::Reset() is called. The set of command buffers associated with a given command allocator
|
||||
* will query that allocator for additional GPU memory as they are building commands.
|
||||
*
|
||||
* To protect against race conditions the client must ask for a thread safe command allocator unless its can guarantee
|
||||
* that all command buffers associated with a given command allocator will be built, reset, and destroyed in a thread-
|
||||
* safe manner. It is illegal to destroy a command allocator while it still has command buffers associated with it.
|
||||
*
|
||||
* @see IDevice::CreateCmdAllocator()
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class ICmdAllocator : public IDestroyable
|
||||
{
|
||||
public:
|
||||
/// Explicitly resets a command allocator, marking all internal GPU memory allocations as unused.
|
||||
///
|
||||
/// The client is responsible for guaranteeing that all command buffers associated with this allocator have finished
|
||||
/// GPU execution and have been explicitly reset before calling this function.
|
||||
///
|
||||
/// @param [in] freeMemory If the all GPU and CPU memory allocations should be returned to the OS.
|
||||
///
|
||||
/// @returns Success if the command allocator was successfully reset. Otherwise, one of the following errors may be
|
||||
/// returned:
|
||||
/// + ErrorUnknown if an internal PAL error occurs.
|
||||
virtual Result Reset(bool freeMemory) = 0;
|
||||
|
||||
/// Explicitly trims a command allocator, deleting as many unused internal GPU memory allocations as possible.
|
||||
///
|
||||
/// @returns Success if the command allocator was successfully trimmed.
|
||||
///
|
||||
/// @param [in] allocTypeMask Gives control whether trimming will be applied for each CmdAllocType.
|
||||
/// Use (1 << CmdAllocatorTypeCount) - 1 to apply trimming to all types.
|
||||
/// When trimming only the embedded date use (1 << EmbeddedDataAlloc).
|
||||
/// @param [in] dynamicThreshold Minimum count of free allocations that the allocator should keep around
|
||||
|
||||
virtual Result Trim(uint32 allocTypeMask, uint32 dynamicThreshold) = 0;
|
||||
|
||||
/// Query the numbers of allocations and chunks of the given CmdAllocator type.
|
||||
/// This may help clients to decide whether they may apply trimming or not.
|
||||
///
|
||||
/// @returns Success if valid values can be reported.
|
||||
///
|
||||
/// @param [in] type CmdAllocType that is being queried
|
||||
/// @param [out] pUtilizationInfo The allocation and chunk counts will be stored here.
|
||||
|
||||
virtual Result QueryUtilizationInfo(CmdAllocType type, CmdAllocatorUtilizationInfo* pUtilizationInfo) const = 0;
|
||||
|
||||
/// Returns the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @returns Pointer to client data.
|
||||
void* GetClientData() const
|
||||
{
|
||||
return m_pClientData;
|
||||
}
|
||||
|
||||
/// Sets the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @param [in] pClientData A pointer to arbitrary client data.
|
||||
void SetClientData(
|
||||
void* pClientData)
|
||||
{
|
||||
m_pClientData = pClientData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @internal Constructor. Prevent use of new operator on this interface. Client must create objects by explicitly
|
||||
/// called the proper create method.
|
||||
ICmdAllocator() : m_pClientData(nullptr) {}
|
||||
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~ICmdAllocator() { }
|
||||
|
||||
private:
|
||||
/// @internal Client data pointer. This can have an arbitrary value and can be returned by calling GetClientData()
|
||||
/// and set via SetClientData().
|
||||
/// For non-top-layer objects, this will point to the layer above the current object.
|
||||
void* m_pClientData;
|
||||
};
|
||||
|
||||
} // Pal
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,370 +1,370 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palCmdTracking.h
|
||||
* @brief Defines a number of support classes used for construction and storage of struct TrackedCmdLocation
|
||||
* defined in trackedCmdLocation.h
|
||||
*
|
||||
* - struct TrackingEventInfo: A single from uint8 to name, used for logging
|
||||
* - class TrackedCmdSupportBase A set of TrackingEventInfo, maintained outside of Pal
|
||||
* - class TrackedCmdLocationArray The arrays for TrackedCmdLocation's used for reporting
|
||||
* correlation data through ICmdBufferReporting::CorrelationReportOnSubmit
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palVector.h"
|
||||
|
||||
#include "trackedCmdLocation.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
// forward decl
|
||||
class Platform;
|
||||
|
||||
namespace CmdDisassembly
|
||||
{
|
||||
|
||||
// forward definition
|
||||
class TrackedCmdLocationArray;
|
||||
|
||||
/**
|
||||
************************************************************************************************************************
|
||||
* @brief class TrackedCmdLocationRef
|
||||
* A copyable reference to a member in a TrackedCmdLocationArray, invariant to that array be
|
||||
* re-allocated.
|
||||
*
|
||||
* @detail Is simply a pointer to a TrackedCmdLocationArray, and an index in to that array
|
||||
*
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
class TrackedCmdLocationRef
|
||||
{
|
||||
public:
|
||||
TrackedCmdLocationRef()
|
||||
: m_pSourceArray(nullptr),
|
||||
m_index(0)
|
||||
{
|
||||
}
|
||||
|
||||
TrackedCmdLocationRef(
|
||||
TrackedCmdLocationArray* pSourceArray,
|
||||
Util::uint32 index)
|
||||
: m_pSourceArray(pSourceArray),
|
||||
m_index(index)
|
||||
{
|
||||
}
|
||||
|
||||
TrackedCmdLocationRef(
|
||||
TrackedCmdLocationRef&& other) = default;
|
||||
TrackedCmdLocationRef(
|
||||
TrackedCmdLocationRef const& other) = default;
|
||||
TrackedCmdLocationRef& operator=(
|
||||
TrackedCmdLocationRef&& other) = default;
|
||||
TrackedCmdLocationRef& operator=(
|
||||
TrackedCmdLocationRef const& other) = default;
|
||||
|
||||
bool operator==(
|
||||
TrackedCmdLocationRef const& other) const
|
||||
{ return (this->m_pSourceArray == other.m_pSourceArray) && (this->m_index == other.m_index); }
|
||||
bool operator!=(
|
||||
TrackedCmdLocationRef const& other) const
|
||||
{ return (this->m_pSourceArray != other.m_pSourceArray) || (this->m_index != other.m_index); }
|
||||
|
||||
TrackedCmdLocation* Use();
|
||||
const TrackedCmdLocation* Get() const;
|
||||
|
||||
Util::uint32 GetIndex() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
/// Helper functions
|
||||
///
|
||||
|
||||
/// Clears the TrackedCmdLocation referred to by this TrackedCmdLocationRef
|
||||
///
|
||||
/// @returns
|
||||
/// Result::ErrorInvalidPointer if (IsValid() == false)
|
||||
/// Result::Success if successful
|
||||
Result Clear();
|
||||
|
||||
/// @returns
|
||||
/// TrackedCmdLocationMode::Invalid if (IsValid() == false)
|
||||
/// Get()->m_mode otherwise
|
||||
TrackedCmdLocationMode GetMode() const;
|
||||
|
||||
/// Sets the TrackedCmdLocation referred to by this TrackedCmdLocationRef
|
||||
/// to mode TrackedCmdLocationMode::Before
|
||||
///
|
||||
/// @param [in] eventId Refers to an uint8 event that has a begin and/or an end associated with it
|
||||
/// Most likely, a value registered to a TrackedCmdSupportBase
|
||||
/// @param [in] beforePtr The end pointer for the cmdList being tracked before the event referred to by eventId
|
||||
/// Only 48-bits of beforePtr are used
|
||||
///
|
||||
/// @returns
|
||||
/// Result::ErrorInvalidPointer if (IsValid() == false)
|
||||
/// Result::Success if successful
|
||||
Result SetAsBefore(
|
||||
uint8 eventId,
|
||||
uint64 beforePtr);
|
||||
|
||||
/// Sets the TrackedCmdLocation referred to by this TrackedCmdLocationRef
|
||||
/// to mode TrackedCmdLocationMode::After
|
||||
///
|
||||
/// @param [in] eventId Refers to an uint8 event that has a begin and/or an end associated with it
|
||||
/// Most likely, a value registered to a TrackedCmdSupportBase
|
||||
/// @param [in] afterPtr The end pointer for the cmdList being tracked after the event referred to by eventId
|
||||
/// Only 48-bits of afterPtr are used
|
||||
///
|
||||
/// @returns
|
||||
/// Result::ErrorInvalidPointer if (IsValid() == false)
|
||||
/// Result::Success if successful
|
||||
Result SetAsAfter(
|
||||
uint8 eventId,
|
||||
uint64 afterPtr);
|
||||
|
||||
/// Sets the TrackedCmdLocation referred to by this TrackedCmdLocationRef
|
||||
/// to mode TrackedCmdLocationMode::Delta, with no begin or end (ie, no data can be written to
|
||||
/// the cmdList being tracked "during" the event referred to be eventId
|
||||
///
|
||||
/// @param [in] eventId Refers to an uint8 event that does not have a begin and/or an end associated with it
|
||||
/// Such as Pal::CmdDisassembly::TrackedCmdLocation::PostClientEvent
|
||||
/// @param [in] ptr The end pointer for the cmdList being tracked after the event referred to by eventId
|
||||
/// Only 48-bits of ptr are used
|
||||
///
|
||||
/// @returns
|
||||
/// Result::ErrorInvalidPointer if (IsValid() == false)
|
||||
/// Result::Success if successful
|
||||
Result SetAsEmptyDelta(
|
||||
uint8 eventId,
|
||||
uint64 ptr);
|
||||
|
||||
/// Sets the TrackedCmdLocation referred to by this TrackedCmdLocationRef
|
||||
/// to mode TrackedCmdLocationMode::ClientId
|
||||
///
|
||||
/// @param [in] clientId A 61-bit bit value used by the client application to identify which cmdList is being
|
||||
/// tracked
|
||||
///
|
||||
/// @returns
|
||||
/// Result::ErrorInvalidPointer if (IsValid() == false)
|
||||
/// Result::Success if successful
|
||||
Result SetAsClientId(
|
||||
uint64 clientId);
|
||||
|
||||
/// Sets the TrackedCmdLocation referred to by this TrackedCmdLocationRef
|
||||
/// to mode TrackedCmdLocationMode::ClientEventId
|
||||
///
|
||||
/// @param [in] clientEventId A 61-bit bit value used by the client application to identify
|
||||
/// a client event relative to the current end position of the cmdList being tracked
|
||||
///
|
||||
/// @returns
|
||||
/// Result::ErrorInvalidPointer if (IsValid() == false)
|
||||
/// Result::Success if successful
|
||||
Result SetAsClientEvent(
|
||||
uint64 clientEventId);
|
||||
|
||||
/// @brief bool TrackedCmdLocation::TrySetAsDelta(uint64 afterPtr)
|
||||
/// Will attempt to set this TrackedCmdLocation to type TrackedCmdLocationMode::Delta
|
||||
///
|
||||
/// @detail If GetMode() == TrackedCmdLocationMode::Before and afterPtr - m_correlateInternal.m_ptr is small
|
||||
/// enough to be encoded in m_correlateInternal.m_deltaInDWords, the mode will be altered to
|
||||
/// TrackedCmdLocationMode::Delta, with afterPtr - m_correlateInternal.m_ptr encoded in
|
||||
/// m_correlateInternal.m_deltaInDWords.
|
||||
/// If this attempt fails, the calling function should instead create a TrackedCmdLocationMode::After
|
||||
/// TrackedCmdLocation
|
||||
///
|
||||
/// @param [in] afterPtr, the value a TrackedCmdLocationMode::After would have for m_correlateInternal.m_ptr
|
||||
/// @return Result::Success if it was possible to set this TrackedCmdLocation to type
|
||||
/// TrackedCmdLocationMode::Delta
|
||||
/// Result::Unsupported if the conditions described above are not met.
|
||||
Result TrySetAsDelta(
|
||||
uint64 afterPtr);
|
||||
|
||||
private:
|
||||
TrackedCmdLocationArray* m_pSourceArray;
|
||||
Util::uint32 m_index;
|
||||
|
||||
Result SetMode(
|
||||
TrackedCmdLocationMode mode);
|
||||
};
|
||||
|
||||
/// @brief struct TrackingEventInfo
|
||||
/// Essentially just a name, plus a boolean to indicate whether the name is valid / has been set
|
||||
struct TrackingEventInfo
|
||||
{
|
||||
Util::StringView<char> name;
|
||||
bool isValid;
|
||||
|
||||
TrackingEventInfo()
|
||||
: isValid(false)
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
************************************************************************************************************************
|
||||
* @brief class TrackedCmdSupportBase translates eventId's to strings for internal correlation events
|
||||
*
|
||||
* @detail For use in Pal::Queue when dumping to text files. Corresponds to
|
||||
* TrackedCmdLocation::m_correlateInternal.m_event for the cases where TrackedCmdLocation::m_mode
|
||||
* is not TrackedCmdLocationMode::ClientEvent
|
||||
*
|
||||
* The implementation for this is in whatever client of Pal that is creating the internal correlation events,
|
||||
*
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
class TrackedCmdSupportBase
|
||||
{
|
||||
public:
|
||||
virtual ~TrackedCmdSupportBase() = default;
|
||||
|
||||
void SetEventIdName(
|
||||
uint8 eventId,
|
||||
const char* name)
|
||||
{
|
||||
PAL_ASSERT(static_cast<uint32>(eventId) < NumUInt8Values);
|
||||
m_allEventsMap[eventId].name = name;
|
||||
m_allEventsMap[eventId].isValid = true;
|
||||
}
|
||||
|
||||
TrackingEventInfo const& GetEventInfo(
|
||||
uint8 eventId) const
|
||||
{
|
||||
PAL_ASSERT(static_cast<uint32>(eventId) < NumUInt8Values);
|
||||
return m_allEventsMap[eventId];
|
||||
}
|
||||
|
||||
protected:
|
||||
static constexpr uint32 NumUInt8Values = UINT8_MAX + 1;
|
||||
|
||||
TrackingEventInfo m_allEventsMap[NumUInt8Values];
|
||||
|
||||
TrackedCmdSupportBase() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
************************************************************************************************************************
|
||||
* @brief class TrackedCmdLocationArray is simple a TrackedCmdLocationVec together with a clientId
|
||||
* and some helpers. TrackedCmdLocationArray live on Pal::GfxCmdBuffer
|
||||
*
|
||||
* @detail Each Pal::GfxCmdBuffer has at most CmdDisassembly::MaxNumSubCmdBuffers TrackedCmdLocationArray's
|
||||
* corresponding to Pal::GfxCmdBuffer::NumCmdStreams();
|
||||
*
|
||||
* The clientId used for TrackedCmdLocationArray::m_clientId, corresponds to the client Id used in
|
||||
* TrackedCmdLocation::m_clientId.m_clientId
|
||||
*
|
||||
* For the moment, the underlying implementation used is
|
||||
* Util::Vector<TrackedCmdLocation, DefaultCapacity, Pal::Platform>, but could be changed to use a Chunk
|
||||
* scheme, especially as sizes of cmdLists can become very large.
|
||||
* The only requirement to a change, is for TrackedCmdLocationRef continues to function as an accessor
|
||||
*
|
||||
* Note that the functions in TrackedCmdLocationArray are not designed for thread-safety, as they are
|
||||
* issued from command-list-building functions that are, in their turn, not thread safe. Adding mutex
|
||||
* behavior here would potentially hide issues relating to thread-safety.
|
||||
*
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
class TrackedCmdLocationArray
|
||||
{
|
||||
public:
|
||||
static constexpr uint32 DefaultCapacity = 1024;
|
||||
static constexpr uint32 BadIndex = UINT32_MAX;
|
||||
static constexpr uint64 InvalidClientId = UINT64_MAX;
|
||||
|
||||
typedef Util::Vector<TrackedCmdLocation, DefaultCapacity, Pal::Platform> TrackedCmdLocationVec;
|
||||
|
||||
static uint32 GetTrackedCmdLocationArraySizeInBytes()
|
||||
{
|
||||
return sizeof(TrackedCmdLocationArray);
|
||||
}
|
||||
|
||||
static TrackedCmdLocationArray* CreateTrackedCmdLocationArray(
|
||||
void* pMemory,
|
||||
Pal::Platform* pPlatform);
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_lastLocation = TrackedCmdLocationRef(this, BadIndex);
|
||||
m_clientId = InvalidClientId;
|
||||
m_locations.Clear();
|
||||
}
|
||||
|
||||
void Destroy();
|
||||
|
||||
uint64 GetClientId() const
|
||||
{
|
||||
return m_clientId;
|
||||
}
|
||||
|
||||
Result SetClientId(
|
||||
uint64 clientId);
|
||||
|
||||
Util::uint32 GetTotalSize() const
|
||||
{
|
||||
return m_locations.size();
|
||||
}
|
||||
|
||||
const TrackedCmdLocationVec& GetLocationsVec() const
|
||||
{
|
||||
return m_locations;
|
||||
}
|
||||
|
||||
TrackedCmdLocationVec& UseLocationsVec()
|
||||
{
|
||||
return m_locations;
|
||||
}
|
||||
|
||||
Pal::Result MakeNext(
|
||||
TrackedCmdLocationRef* pResult);
|
||||
|
||||
const TrackedCmdLocationRef GetLast() const
|
||||
{
|
||||
return m_lastLocation;
|
||||
}
|
||||
|
||||
bool IsLast(
|
||||
TrackedCmdLocationRef const& location) const
|
||||
{
|
||||
return location == m_lastLocation;
|
||||
}
|
||||
|
||||
private:
|
||||
TrackedCmdLocationVec m_locations;
|
||||
Pal::Platform* m_pPlatform;
|
||||
uint64 m_clientId;
|
||||
TrackedCmdLocationRef m_lastLocation;
|
||||
|
||||
TrackedCmdLocationArray(
|
||||
Pal::Platform* pPlatform);
|
||||
|
||||
~TrackedCmdLocationArray() = default;
|
||||
};
|
||||
|
||||
} // namespace CmdDisassembly
|
||||
} // namespace Pal
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palCmdTracking.h
|
||||
* @brief Defines a number of support classes used for construction and storage of struct TrackedCmdLocation
|
||||
* defined in trackedCmdLocation.h
|
||||
*
|
||||
* - struct TrackingEventInfo: A single from uint8 to name, used for logging
|
||||
* - class TrackedCmdSupportBase A set of TrackingEventInfo, maintained outside of Pal
|
||||
* - class TrackedCmdLocationArray The arrays for TrackedCmdLocation's used for reporting
|
||||
* correlation data through ICmdBufferReporting::CorrelationReportOnSubmit
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palVector.h"
|
||||
|
||||
#include "trackedCmdLocation.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
// forward decl
|
||||
class Platform;
|
||||
|
||||
namespace CmdDisassembly
|
||||
{
|
||||
|
||||
// forward definition
|
||||
class TrackedCmdLocationArray;
|
||||
|
||||
/**
|
||||
************************************************************************************************************************
|
||||
* @brief class TrackedCmdLocationRef
|
||||
* A copyable reference to a member in a TrackedCmdLocationArray, invariant to that array be
|
||||
* re-allocated.
|
||||
*
|
||||
* @detail Is simply a pointer to a TrackedCmdLocationArray, and an index in to that array
|
||||
*
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
class TrackedCmdLocationRef
|
||||
{
|
||||
public:
|
||||
TrackedCmdLocationRef()
|
||||
: m_pSourceArray(nullptr),
|
||||
m_index(0)
|
||||
{
|
||||
}
|
||||
|
||||
TrackedCmdLocationRef(
|
||||
TrackedCmdLocationArray* pSourceArray,
|
||||
Util::uint32 index)
|
||||
: m_pSourceArray(pSourceArray),
|
||||
m_index(index)
|
||||
{
|
||||
}
|
||||
|
||||
TrackedCmdLocationRef(
|
||||
TrackedCmdLocationRef&& other) = default;
|
||||
TrackedCmdLocationRef(
|
||||
TrackedCmdLocationRef const& other) = default;
|
||||
TrackedCmdLocationRef& operator=(
|
||||
TrackedCmdLocationRef&& other) = default;
|
||||
TrackedCmdLocationRef& operator=(
|
||||
TrackedCmdLocationRef const& other) = default;
|
||||
|
||||
bool operator==(
|
||||
TrackedCmdLocationRef const& other) const
|
||||
{ return (this->m_pSourceArray == other.m_pSourceArray) && (this->m_index == other.m_index); }
|
||||
bool operator!=(
|
||||
TrackedCmdLocationRef const& other) const
|
||||
{ return (this->m_pSourceArray != other.m_pSourceArray) || (this->m_index != other.m_index); }
|
||||
|
||||
TrackedCmdLocation* Use();
|
||||
const TrackedCmdLocation* Get() const;
|
||||
|
||||
Util::uint32 GetIndex() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
/// Helper functions
|
||||
///
|
||||
|
||||
/// Clears the TrackedCmdLocation referred to by this TrackedCmdLocationRef
|
||||
///
|
||||
/// @returns
|
||||
/// Result::ErrorInvalidPointer if (IsValid() == false)
|
||||
/// Result::Success if successful
|
||||
Result Clear();
|
||||
|
||||
/// @returns
|
||||
/// TrackedCmdLocationMode::Invalid if (IsValid() == false)
|
||||
/// Get()->m_mode otherwise
|
||||
TrackedCmdLocationMode GetMode() const;
|
||||
|
||||
/// Sets the TrackedCmdLocation referred to by this TrackedCmdLocationRef
|
||||
/// to mode TrackedCmdLocationMode::Before
|
||||
///
|
||||
/// @param [in] eventId Refers to an uint8 event that has a begin and/or an end associated with it
|
||||
/// Most likely, a value registered to a TrackedCmdSupportBase
|
||||
/// @param [in] beforePtr The end pointer for the cmdList being tracked before the event referred to by eventId
|
||||
/// Only 48-bits of beforePtr are used
|
||||
///
|
||||
/// @returns
|
||||
/// Result::ErrorInvalidPointer if (IsValid() == false)
|
||||
/// Result::Success if successful
|
||||
Result SetAsBefore(
|
||||
uint8 eventId,
|
||||
uint64 beforePtr);
|
||||
|
||||
/// Sets the TrackedCmdLocation referred to by this TrackedCmdLocationRef
|
||||
/// to mode TrackedCmdLocationMode::After
|
||||
///
|
||||
/// @param [in] eventId Refers to an uint8 event that has a begin and/or an end associated with it
|
||||
/// Most likely, a value registered to a TrackedCmdSupportBase
|
||||
/// @param [in] afterPtr The end pointer for the cmdList being tracked after the event referred to by eventId
|
||||
/// Only 48-bits of afterPtr are used
|
||||
///
|
||||
/// @returns
|
||||
/// Result::ErrorInvalidPointer if (IsValid() == false)
|
||||
/// Result::Success if successful
|
||||
Result SetAsAfter(
|
||||
uint8 eventId,
|
||||
uint64 afterPtr);
|
||||
|
||||
/// Sets the TrackedCmdLocation referred to by this TrackedCmdLocationRef
|
||||
/// to mode TrackedCmdLocationMode::Delta, with no begin or end (ie, no data can be written to
|
||||
/// the cmdList being tracked "during" the event referred to be eventId
|
||||
///
|
||||
/// @param [in] eventId Refers to an uint8 event that does not have a begin and/or an end associated with it
|
||||
/// Such as Pal::CmdDisassembly::TrackedCmdLocation::PostClientEvent
|
||||
/// @param [in] ptr The end pointer for the cmdList being tracked after the event referred to by eventId
|
||||
/// Only 48-bits of ptr are used
|
||||
///
|
||||
/// @returns
|
||||
/// Result::ErrorInvalidPointer if (IsValid() == false)
|
||||
/// Result::Success if successful
|
||||
Result SetAsEmptyDelta(
|
||||
uint8 eventId,
|
||||
uint64 ptr);
|
||||
|
||||
/// Sets the TrackedCmdLocation referred to by this TrackedCmdLocationRef
|
||||
/// to mode TrackedCmdLocationMode::ClientId
|
||||
///
|
||||
/// @param [in] clientId A 61-bit bit value used by the client application to identify which cmdList is being
|
||||
/// tracked
|
||||
///
|
||||
/// @returns
|
||||
/// Result::ErrorInvalidPointer if (IsValid() == false)
|
||||
/// Result::Success if successful
|
||||
Result SetAsClientId(
|
||||
uint64 clientId);
|
||||
|
||||
/// Sets the TrackedCmdLocation referred to by this TrackedCmdLocationRef
|
||||
/// to mode TrackedCmdLocationMode::ClientEventId
|
||||
///
|
||||
/// @param [in] clientEventId A 61-bit bit value used by the client application to identify
|
||||
/// a client event relative to the current end position of the cmdList being tracked
|
||||
///
|
||||
/// @returns
|
||||
/// Result::ErrorInvalidPointer if (IsValid() == false)
|
||||
/// Result::Success if successful
|
||||
Result SetAsClientEvent(
|
||||
uint64 clientEventId);
|
||||
|
||||
/// @brief bool TrackedCmdLocation::TrySetAsDelta(uint64 afterPtr)
|
||||
/// Will attempt to set this TrackedCmdLocation to type TrackedCmdLocationMode::Delta
|
||||
///
|
||||
/// @detail If GetMode() == TrackedCmdLocationMode::Before and afterPtr - m_correlateInternal.m_ptr is small
|
||||
/// enough to be encoded in m_correlateInternal.m_deltaInDWords, the mode will be altered to
|
||||
/// TrackedCmdLocationMode::Delta, with afterPtr - m_correlateInternal.m_ptr encoded in
|
||||
/// m_correlateInternal.m_deltaInDWords.
|
||||
/// If this attempt fails, the calling function should instead create a TrackedCmdLocationMode::After
|
||||
/// TrackedCmdLocation
|
||||
///
|
||||
/// @param [in] afterPtr, the value a TrackedCmdLocationMode::After would have for m_correlateInternal.m_ptr
|
||||
/// @return Result::Success if it was possible to set this TrackedCmdLocation to type
|
||||
/// TrackedCmdLocationMode::Delta
|
||||
/// Result::Unsupported if the conditions described above are not met.
|
||||
Result TrySetAsDelta(
|
||||
uint64 afterPtr);
|
||||
|
||||
private:
|
||||
TrackedCmdLocationArray* m_pSourceArray;
|
||||
Util::uint32 m_index;
|
||||
|
||||
Result SetMode(
|
||||
TrackedCmdLocationMode mode);
|
||||
};
|
||||
|
||||
/// @brief struct TrackingEventInfo
|
||||
/// Essentially just a name, plus a boolean to indicate whether the name is valid / has been set
|
||||
struct TrackingEventInfo
|
||||
{
|
||||
Util::StringView<char> name;
|
||||
bool isValid;
|
||||
|
||||
TrackingEventInfo()
|
||||
: isValid(false)
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
************************************************************************************************************************
|
||||
* @brief class TrackedCmdSupportBase translates eventId's to strings for internal correlation events
|
||||
*
|
||||
* @detail For use in Pal::Queue when dumping to text files. Corresponds to
|
||||
* TrackedCmdLocation::m_correlateInternal.m_event for the cases where TrackedCmdLocation::m_mode
|
||||
* is not TrackedCmdLocationMode::ClientEvent
|
||||
*
|
||||
* The implementation for this is in whatever client of Pal that is creating the internal correlation events,
|
||||
*
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
class TrackedCmdSupportBase
|
||||
{
|
||||
public:
|
||||
virtual ~TrackedCmdSupportBase() = default;
|
||||
|
||||
void SetEventIdName(
|
||||
uint8 eventId,
|
||||
const char* name)
|
||||
{
|
||||
PAL_ASSERT(static_cast<uint32>(eventId) < NumUInt8Values);
|
||||
m_allEventsMap[eventId].name = name;
|
||||
m_allEventsMap[eventId].isValid = true;
|
||||
}
|
||||
|
||||
TrackingEventInfo const& GetEventInfo(
|
||||
uint8 eventId) const
|
||||
{
|
||||
PAL_ASSERT(static_cast<uint32>(eventId) < NumUInt8Values);
|
||||
return m_allEventsMap[eventId];
|
||||
}
|
||||
|
||||
protected:
|
||||
static constexpr uint32 NumUInt8Values = UINT8_MAX + 1;
|
||||
|
||||
TrackingEventInfo m_allEventsMap[NumUInt8Values];
|
||||
|
||||
TrackedCmdSupportBase() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
************************************************************************************************************************
|
||||
* @brief class TrackedCmdLocationArray is simple a TrackedCmdLocationVec together with a clientId
|
||||
* and some helpers. TrackedCmdLocationArray live on Pal::GfxCmdBuffer
|
||||
*
|
||||
* @detail Each Pal::GfxCmdBuffer has at most CmdDisassembly::MaxNumSubCmdBuffers TrackedCmdLocationArray's
|
||||
* corresponding to Pal::GfxCmdBuffer::NumCmdStreams();
|
||||
*
|
||||
* The clientId used for TrackedCmdLocationArray::m_clientId, corresponds to the client Id used in
|
||||
* TrackedCmdLocation::m_clientId.m_clientId
|
||||
*
|
||||
* For the moment, the underlying implementation used is
|
||||
* Util::Vector<TrackedCmdLocation, DefaultCapacity, Pal::Platform>, but could be changed to use a Chunk
|
||||
* scheme, especially as sizes of cmdLists can become very large.
|
||||
* The only requirement to a change, is for TrackedCmdLocationRef continues to function as an accessor
|
||||
*
|
||||
* Note that the functions in TrackedCmdLocationArray are not designed for thread-safety, as they are
|
||||
* issued from command-list-building functions that are, in their turn, not thread safe. Adding mutex
|
||||
* behavior here would potentially hide issues relating to thread-safety.
|
||||
*
|
||||
************************************************************************************************************************
|
||||
*/
|
||||
class TrackedCmdLocationArray
|
||||
{
|
||||
public:
|
||||
static constexpr uint32 DefaultCapacity = 1024;
|
||||
static constexpr uint32 BadIndex = UINT32_MAX;
|
||||
static constexpr uint64 InvalidClientId = UINT64_MAX;
|
||||
|
||||
typedef Util::Vector<TrackedCmdLocation, DefaultCapacity, Pal::Platform> TrackedCmdLocationVec;
|
||||
|
||||
static uint32 GetTrackedCmdLocationArraySizeInBytes()
|
||||
{
|
||||
return sizeof(TrackedCmdLocationArray);
|
||||
}
|
||||
|
||||
static TrackedCmdLocationArray* CreateTrackedCmdLocationArray(
|
||||
void* pMemory,
|
||||
Pal::Platform* pPlatform);
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_lastLocation = TrackedCmdLocationRef(this, BadIndex);
|
||||
m_clientId = InvalidClientId;
|
||||
m_locations.Clear();
|
||||
}
|
||||
|
||||
void Destroy();
|
||||
|
||||
uint64 GetClientId() const
|
||||
{
|
||||
return m_clientId;
|
||||
}
|
||||
|
||||
Result SetClientId(
|
||||
uint64 clientId);
|
||||
|
||||
Util::uint32 GetTotalSize() const
|
||||
{
|
||||
return m_locations.size();
|
||||
}
|
||||
|
||||
const TrackedCmdLocationVec& GetLocationsVec() const
|
||||
{
|
||||
return m_locations;
|
||||
}
|
||||
|
||||
TrackedCmdLocationVec& UseLocationsVec()
|
||||
{
|
||||
return m_locations;
|
||||
}
|
||||
|
||||
Pal::Result MakeNext(
|
||||
TrackedCmdLocationRef* pResult);
|
||||
|
||||
const TrackedCmdLocationRef GetLast() const
|
||||
{
|
||||
return m_lastLocation;
|
||||
}
|
||||
|
||||
bool IsLast(
|
||||
TrackedCmdLocationRef const& location) const
|
||||
{
|
||||
return location == m_lastLocation;
|
||||
}
|
||||
|
||||
private:
|
||||
TrackedCmdLocationVec m_locations;
|
||||
Pal::Platform* m_pPlatform;
|
||||
uint64 m_clientId;
|
||||
TrackedCmdLocationRef m_lastLocation;
|
||||
|
||||
TrackedCmdLocationArray(
|
||||
Pal::Platform* pPlatform);
|
||||
|
||||
~TrackedCmdLocationArray() = default;
|
||||
};
|
||||
|
||||
} // namespace CmdDisassembly
|
||||
} // namespace Pal
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palDestroyable.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IDestroyable interface.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IDestroyable
|
||||
* @brief Interface inherited by objects that must be explicitly destroyed by the client.
|
||||
*
|
||||
* This includes all objects except:
|
||||
*
|
||||
* + @ref IColorTargetView, @ref IDepthStencilView - These classes are treated as SRDs by the DX12 runtime. Therefore,
|
||||
* PAL guarantees that no action needs to be taken at Destroy() - the client should just free the memory backing these
|
||||
* classes.
|
||||
* + @ref IDevice - These objects are created during IPlatform::EnumerateDevices() and are automatically destroyed
|
||||
* along with the Platform object.
|
||||
* + @ref IPrivateScreen - These objects are created as during IPlatform::EnumerateDevices() based on
|
||||
* which screens are attached to each device. They are automatically destroyed along with the Platform object.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IDestroyable
|
||||
{
|
||||
public:
|
||||
/// Frees all resources associated with this object.
|
||||
///
|
||||
/// It is the client's responsibility to only call this method once there are no more existing references to this
|
||||
/// object. This method does not free the system memory associated with the object (as specified in pPlacementAddr
|
||||
/// during creation); the client is responsible for freeing that memory since they allocated it.
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
protected:
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IDestroyable() { }
|
||||
};
|
||||
|
||||
} // Pal
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palDestroyable.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IDestroyable interface.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IDestroyable
|
||||
* @brief Interface inherited by objects that must be explicitly destroyed by the client.
|
||||
*
|
||||
* This includes all objects except:
|
||||
*
|
||||
* + @ref IColorTargetView, @ref IDepthStencilView - These classes are treated as SRDs by the DX12 runtime. Therefore,
|
||||
* PAL guarantees that no action needs to be taken at Destroy() - the client should just free the memory backing these
|
||||
* classes.
|
||||
* + @ref IDevice - These objects are created during IPlatform::EnumerateDevices() and are automatically destroyed
|
||||
* along with the Platform object.
|
||||
* + @ref IPrivateScreen - These objects are created as during IPlatform::EnumerateDevices() based on
|
||||
* which screens are attached to each device. They are automatically destroyed along with the Platform object.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IDestroyable
|
||||
{
|
||||
public:
|
||||
/// Frees all resources associated with this object.
|
||||
///
|
||||
/// It is the client's responsibility to only call this method once there are no more existing references to this
|
||||
/// object. This method does not free the system memory associated with the object (as specified in pPlacementAddr
|
||||
/// during creation); the client is responsible for freeing that memory since they allocated it.
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
protected:
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IDestroyable() { }
|
||||
};
|
||||
|
||||
} // Pal
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,171 +1,171 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palFence.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IFence interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palDestroyable.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
/// Specifies properties for fence @ref IFence fence creation. Input structure to IDevice::CreateFence().
|
||||
struct FenceCreateInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 signaled : 1; ///< Specify whether the initial status of the fence is signaled or not.
|
||||
uint32 eventCanBeInherited : 1; ///< The event handle can be inherited by child process.
|
||||
uint32 shareable : 1; ///< This fence may be opened for use by a different device.
|
||||
uint32 reserved : 29; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags; ///< Fence creation flags.
|
||||
#if defined(_WIN32)
|
||||
const wchar_t* pName; /// The name of the event object, Windows uses this name to uniquely identify fence objects
|
||||
/// across processes.
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Specifies properties for fence opening. Input structure to IDevice::OpenFence().
|
||||
struct FenceOpenInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 isReference : 1; ///< If set, then the opened fence will reference the same sync object
|
||||
///< in the kernel. Otherwise, the object is copied to the new Fence.
|
||||
uint32 reserved : 31; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags;
|
||||
|
||||
OsExternalHandle externalFence; ///< External shared fence handle.
|
||||
#if defined(_WIN32)
|
||||
const wchar_t* pName; /// The name of the event object,Windows uses this name to uniquely identify
|
||||
/// fence objects across processes.
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Specifies properties for fence exporting. Input structure to IFence::ExportExternalHandle().
|
||||
struct FenceExportInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 isReference : 1; ///< If set, then the fence exporting a handle that reference the same sync
|
||||
///< object in the kernel. Otherwise, the object is copied to the new Fence.
|
||||
uint32 implicitReset : 1; ///< If set, a fence reset will be done for the sync fd exported.
|
||||
uint32 reserved : 30; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags;
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IFence
|
||||
* @brief Represents a command buffer fence the client can use for coarse-level synchronization between the GPU and
|
||||
* CPU.
|
||||
*
|
||||
* Fences can be specified when calling IQueue::Submit() and will be signaled when certain prior queue operations have
|
||||
* completed. The status of the fence can be queried by the client to determine when the GPU work of interest has
|
||||
* completed.
|
||||
*
|
||||
* Fences are guaranteed to wait for:
|
||||
* + Prior command buffer submissions.
|
||||
* + Prior queue semaphore signals and waits.
|
||||
* + Prior direct presents.
|
||||
*
|
||||
* @see IDevice::CreateFence()
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IFence : public IDestroyable
|
||||
{
|
||||
public:
|
||||
/// Gets the status (completed or not) of the fence.
|
||||
///
|
||||
/// @returns Success if the fence has been reached, or NotReady if the fence hasn't been reached. Other return
|
||||
/// codes indicate an error:
|
||||
/// + ErrorFenceNeverSubmitted if the fence hasn't been submitted yet and the fence is not created with
|
||||
/// initialSignaled set to true.
|
||||
virtual Result GetStatus() const = 0;
|
||||
|
||||
/// Export the event handle or sync object handle of the fence for external usage.
|
||||
/// If @ref FenceExportInfo::isReference is not set, then this also performs an implicit reset operation on
|
||||
/// the Fence.
|
||||
///
|
||||
/// @param [in] exportInfo Information describing how the Fence handle should be exported.
|
||||
/// @returns the handle in the type OsExternalHandle
|
||||
virtual OsExternalHandle ExportExternalHandle(
|
||||
const FenceExportInfo& exportInfo) const = 0;
|
||||
|
||||
/// Returns the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @returns Pointer to client data.
|
||||
void* GetClientData() const
|
||||
{
|
||||
return m_pClientData;
|
||||
}
|
||||
|
||||
/// Sets the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @param [in] pClientData A pointer to arbitrary client data.
|
||||
void SetClientData(
|
||||
void* pClientData)
|
||||
{
|
||||
m_pClientData = pClientData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @internal Constructor. Prevent use of new operator on this interface. Client must create objects by explicitly
|
||||
/// called the proper create method.
|
||||
IFence() : m_pClientData(nullptr) {}
|
||||
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IFence() { }
|
||||
|
||||
private:
|
||||
/// @internal Client data pointer. This can have an arbitrary value and can be returned by calling GetClientData()
|
||||
/// and set via SetClientData().
|
||||
/// For non-top-layer objects, this will point to the layer above the current object.
|
||||
void* m_pClientData;
|
||||
};
|
||||
|
||||
} // Pal
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palFence.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IFence interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palDestroyable.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
/// Specifies properties for fence @ref IFence fence creation. Input structure to IDevice::CreateFence().
|
||||
struct FenceCreateInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 signaled : 1; ///< Specify whether the initial status of the fence is signaled or not.
|
||||
uint32 eventCanBeInherited : 1; ///< The event handle can be inherited by child process.
|
||||
uint32 shareable : 1; ///< This fence may be opened for use by a different device.
|
||||
uint32 reserved : 29; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags; ///< Fence creation flags.
|
||||
#if defined(_WIN32)
|
||||
const wchar_t* pName; /// The name of the event object, Windows uses this name to uniquely identify fence objects
|
||||
/// across processes.
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Specifies properties for fence opening. Input structure to IDevice::OpenFence().
|
||||
struct FenceOpenInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 isReference : 1; ///< If set, then the opened fence will reference the same sync object
|
||||
///< in the kernel. Otherwise, the object is copied to the new Fence.
|
||||
uint32 reserved : 31; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags;
|
||||
|
||||
OsExternalHandle externalFence; ///< External shared fence handle.
|
||||
#if defined(_WIN32)
|
||||
const wchar_t* pName; /// The name of the event object,Windows uses this name to uniquely identify
|
||||
/// fence objects across processes.
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Specifies properties for fence exporting. Input structure to IFence::ExportExternalHandle().
|
||||
struct FenceExportInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 isReference : 1; ///< If set, then the fence exporting a handle that reference the same sync
|
||||
///< object in the kernel. Otherwise, the object is copied to the new Fence.
|
||||
uint32 implicitReset : 1; ///< If set, a fence reset will be done for the sync fd exported.
|
||||
uint32 reserved : 30; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags;
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IFence
|
||||
* @brief Represents a command buffer fence the client can use for coarse-level synchronization between the GPU and
|
||||
* CPU.
|
||||
*
|
||||
* Fences can be specified when calling IQueue::Submit() and will be signaled when certain prior queue operations have
|
||||
* completed. The status of the fence can be queried by the client to determine when the GPU work of interest has
|
||||
* completed.
|
||||
*
|
||||
* Fences are guaranteed to wait for:
|
||||
* + Prior command buffer submissions.
|
||||
* + Prior queue semaphore signals and waits.
|
||||
* + Prior direct presents.
|
||||
*
|
||||
* @see IDevice::CreateFence()
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IFence : public IDestroyable
|
||||
{
|
||||
public:
|
||||
/// Gets the status (completed or not) of the fence.
|
||||
///
|
||||
/// @returns Success if the fence has been reached, or NotReady if the fence hasn't been reached. Other return
|
||||
/// codes indicate an error:
|
||||
/// + ErrorFenceNeverSubmitted if the fence hasn't been submitted yet and the fence is not created with
|
||||
/// initialSignaled set to true.
|
||||
virtual Result GetStatus() const = 0;
|
||||
|
||||
/// Export the event handle or sync object handle of the fence for external usage.
|
||||
/// If @ref FenceExportInfo::isReference is not set, then this also performs an implicit reset operation on
|
||||
/// the Fence.
|
||||
///
|
||||
/// @param [in] exportInfo Information describing how the Fence handle should be exported.
|
||||
/// @returns the handle in the type OsExternalHandle
|
||||
virtual OsExternalHandle ExportExternalHandle(
|
||||
const FenceExportInfo& exportInfo) const = 0;
|
||||
|
||||
/// Returns the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @returns Pointer to client data.
|
||||
void* GetClientData() const
|
||||
{
|
||||
return m_pClientData;
|
||||
}
|
||||
|
||||
/// Sets the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @param [in] pClientData A pointer to arbitrary client data.
|
||||
void SetClientData(
|
||||
void* pClientData)
|
||||
{
|
||||
m_pClientData = pClientData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @internal Constructor. Prevent use of new operator on this interface. Client must create objects by explicitly
|
||||
/// called the proper create method.
|
||||
IFence() : m_pClientData(nullptr) {}
|
||||
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IFence() { }
|
||||
|
||||
private:
|
||||
/// @internal Client data pointer. This can have an arbitrary value and can be returned by calling GetClientData()
|
||||
/// and set via SetClientData().
|
||||
/// For non-top-layer objects, this will point to the layer above the current object.
|
||||
void* m_pClientData;
|
||||
};
|
||||
|
||||
} // Pal
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,139 +1,139 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palGpuMemoryBindable.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IGpuMemoryBindable interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palDestroyable.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
class IGpuMemory;
|
||||
|
||||
/// Reports required properties of a GPU memory object bound to a specific object. The client must query these
|
||||
/// properties via IGpuMemoryBindable::GetGpuMemoryRequirements() and bind an @ref IGpuMemory object matching these
|
||||
/// requirements to the @ref IGpuMemoryBindable object using IGpuMemoryBindable::BindGpuMemory().
|
||||
struct GpuMemoryRequirements
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 cpuAccess : 1; ///< CPU access is required. If set, the client must not set cpuInvisible in
|
||||
/// GpuMemoryCreateFlags and must provide CPU visible heaps or CPU visible heap
|
||||
/// access mode. If not set, it's strongly recommended to set cpuInvisible.
|
||||
uint32 reserved : 31; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags; ///< Flags specifying required GPU memory properties.
|
||||
|
||||
gpusize size; ///< Amount of GPU memory required, in bytes.
|
||||
gpusize alignment; ///< Required GPU memory virtual address alignment, in bytes.
|
||||
uint32 heapCount; ///< Number of valid entries in heaps[].
|
||||
GpuHeap heaps[GpuHeapCount]; ///< List of allowed heaps for the GPU memory in order of predicted performance.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IGpuMemoryBindable
|
||||
* @brief Interface inherited by objects that may require GPU memory be bound to them.
|
||||
*
|
||||
* In the future, PAL may discover a need to allocate GPU memory for a class that currently doesn't require it. In that
|
||||
* situation, that class will be updated to inherit from IGpuMemoryBindable. This change would break backward
|
||||
* compatibility and would result in the major interface version being incremented.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IGpuMemoryBindable : public IDestroyable
|
||||
{
|
||||
public:
|
||||
/// Queries the GPU memory properties required by this object. The client should query properties with this method,
|
||||
/// create/sub-allocate a memory range matching the requirements, then bind the memory to the object via
|
||||
/// @ref BindGpuMemory().
|
||||
///
|
||||
/// @note Not all objects may actually need GPU memory, and in that case the memory properties will reflect a 0 size
|
||||
/// and alignment.
|
||||
///
|
||||
/// @param [out] pGpuMemReqs Required properties of GPU memory to be bound to this object. Includes properties like
|
||||
/// size, alignment, and allowed heaps.
|
||||
virtual void GetGpuMemoryRequirements(
|
||||
GpuMemoryRequirements* pGpuMemReqs) const = 0;
|
||||
|
||||
/// Binds GPU memory to this object according to the requirements queried via GetGpuMemoryRequirements().
|
||||
///
|
||||
/// Binding memory to objects other than images automatically initializes the object memory as necessary. Image
|
||||
/// objects used as color or depth-stencil targets have to be explicitly initialized in command buffers using a
|
||||
/// ICmdBuffer::CmdReleaseThenAcquire() command to transition them out of the LayoutUninitializedTarget usage.
|
||||
///
|
||||
/// Binding memory to an object automatically unbinds any previously bound memory. There is no need to bind null to
|
||||
/// an object to explicitly unbind a previously bound allocation before binding a new allocation.
|
||||
///
|
||||
/// This call is invalid on objects that have no memory requirements, even if binding null.
|
||||
///
|
||||
/// @param [in] pGpuMemory GPU memory to be bound. If null, the previous binding will be released.
|
||||
/// @param [in] offset Offset into the GPU memory where the object's memory range should begin. This allows
|
||||
/// sub-allocating many object's GPU memory from the same IGpuMemory object.
|
||||
///
|
||||
/// @returns Success if the specified GPU memory was successfully bound to the object. Otherwise, one of the
|
||||
/// following errors may be returned:
|
||||
/// + ErrorUnavailable if binding a non-image to a virtual allocation.
|
||||
/// + ErrorInvalidAlignment if the offset does not match the alignment requirements of the object.
|
||||
/// + ErrorInvalidMemorySize if the object's required memory size does not fit completely within the given
|
||||
/// memory object at the specified offset.
|
||||
virtual Result BindGpuMemory(
|
||||
IGpuMemory* pGpuMemory,
|
||||
gpusize offset) = 0;
|
||||
|
||||
/// Returns the GPU memory object and offset that this object is bound to or nullptr and 0 if not bound.
|
||||
///
|
||||
/// @param [out] ppGpuMemory Returns the GPU memory object to the address specified in this pointer.
|
||||
/// Returns nullptr if this object is not bound to any GPU memory.
|
||||
/// @param [out] pOffset Returns the GPU memory offset to the address specified in this pointer.
|
||||
/// Returns 0 if this object is not bound to any GPU memory.
|
||||
///
|
||||
/// @returns Success if the GPU memory and offset was successfully returned. Otherwise, one of the following errors
|
||||
/// may be returned:
|
||||
/// + ErrorGpuMemoryNotBound if this object is not bound to any GPU memory.
|
||||
/// + ErrorInvalidPointer if either ppGpuMemory or pOffset is nullptr.
|
||||
/// + ErrorUnavailable if binding is not supported in the derived class
|
||||
virtual Result GetGpuMemory(
|
||||
IGpuMemory** ppGpuMemory,
|
||||
gpusize* pOffset) const = 0;
|
||||
|
||||
protected:
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IGpuMemoryBindable() { }
|
||||
};
|
||||
|
||||
} // Pal
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palGpuMemoryBindable.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IGpuMemoryBindable interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palDestroyable.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
class IGpuMemory;
|
||||
|
||||
/// Reports required properties of a GPU memory object bound to a specific object. The client must query these
|
||||
/// properties via IGpuMemoryBindable::GetGpuMemoryRequirements() and bind an @ref IGpuMemory object matching these
|
||||
/// requirements to the @ref IGpuMemoryBindable object using IGpuMemoryBindable::BindGpuMemory().
|
||||
struct GpuMemoryRequirements
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 cpuAccess : 1; ///< CPU access is required. If set, the client must not set cpuInvisible in
|
||||
/// GpuMemoryCreateFlags and must provide CPU visible heaps or CPU visible heap
|
||||
/// access mode. If not set, it's strongly recommended to set cpuInvisible.
|
||||
uint32 reserved : 31; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags; ///< Flags specifying required GPU memory properties.
|
||||
|
||||
gpusize size; ///< Amount of GPU memory required, in bytes.
|
||||
gpusize alignment; ///< Required GPU memory virtual address alignment, in bytes.
|
||||
uint32 heapCount; ///< Number of valid entries in heaps[].
|
||||
GpuHeap heaps[GpuHeapCount]; ///< List of allowed heaps for the GPU memory in order of predicted performance.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IGpuMemoryBindable
|
||||
* @brief Interface inherited by objects that may require GPU memory be bound to them.
|
||||
*
|
||||
* In the future, PAL may discover a need to allocate GPU memory for a class that currently doesn't require it. In that
|
||||
* situation, that class will be updated to inherit from IGpuMemoryBindable. This change would break backward
|
||||
* compatibility and would result in the major interface version being incremented.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IGpuMemoryBindable : public IDestroyable
|
||||
{
|
||||
public:
|
||||
/// Queries the GPU memory properties required by this object. The client should query properties with this method,
|
||||
/// create/sub-allocate a memory range matching the requirements, then bind the memory to the object via
|
||||
/// @ref BindGpuMemory().
|
||||
///
|
||||
/// @note Not all objects may actually need GPU memory, and in that case the memory properties will reflect a 0 size
|
||||
/// and alignment.
|
||||
///
|
||||
/// @param [out] pGpuMemReqs Required properties of GPU memory to be bound to this object. Includes properties like
|
||||
/// size, alignment, and allowed heaps.
|
||||
virtual void GetGpuMemoryRequirements(
|
||||
GpuMemoryRequirements* pGpuMemReqs) const = 0;
|
||||
|
||||
/// Binds GPU memory to this object according to the requirements queried via GetGpuMemoryRequirements().
|
||||
///
|
||||
/// Binding memory to objects other than images automatically initializes the object memory as necessary. Image
|
||||
/// objects used as color or depth-stencil targets have to be explicitly initialized in command buffers using a
|
||||
/// ICmdBuffer::CmdReleaseThenAcquire() command to transition them out of the LayoutUninitializedTarget usage.
|
||||
///
|
||||
/// Binding memory to an object automatically unbinds any previously bound memory. There is no need to bind null to
|
||||
/// an object to explicitly unbind a previously bound allocation before binding a new allocation.
|
||||
///
|
||||
/// This call is invalid on objects that have no memory requirements, even if binding null.
|
||||
///
|
||||
/// @param [in] pGpuMemory GPU memory to be bound. If null, the previous binding will be released.
|
||||
/// @param [in] offset Offset into the GPU memory where the object's memory range should begin. This allows
|
||||
/// sub-allocating many object's GPU memory from the same IGpuMemory object.
|
||||
///
|
||||
/// @returns Success if the specified GPU memory was successfully bound to the object. Otherwise, one of the
|
||||
/// following errors may be returned:
|
||||
/// + ErrorUnavailable if binding a non-image to a virtual allocation.
|
||||
/// + ErrorInvalidAlignment if the offset does not match the alignment requirements of the object.
|
||||
/// + ErrorInvalidMemorySize if the object's required memory size does not fit completely within the given
|
||||
/// memory object at the specified offset.
|
||||
virtual Result BindGpuMemory(
|
||||
IGpuMemory* pGpuMemory,
|
||||
gpusize offset) = 0;
|
||||
|
||||
/// Returns the GPU memory object and offset that this object is bound to or nullptr and 0 if not bound.
|
||||
///
|
||||
/// @param [out] ppGpuMemory Returns the GPU memory object to the address specified in this pointer.
|
||||
/// Returns nullptr if this object is not bound to any GPU memory.
|
||||
/// @param [out] pOffset Returns the GPU memory offset to the address specified in this pointer.
|
||||
/// Returns 0 if this object is not bound to any GPU memory.
|
||||
///
|
||||
/// @returns Success if the GPU memory and offset was successfully returned. Otherwise, one of the following errors
|
||||
/// may be returned:
|
||||
/// + ErrorGpuMemoryNotBound if this object is not bound to any GPU memory.
|
||||
/// + ErrorInvalidPointer if either ppGpuMemory or pOffset is nullptr.
|
||||
/// + ErrorUnavailable if binding is not supported in the derived class
|
||||
virtual Result GetGpuMemory(
|
||||
IGpuMemory** ppGpuMemory,
|
||||
gpusize* pOffset) const = 0;
|
||||
|
||||
protected:
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IGpuMemoryBindable() { }
|
||||
};
|
||||
|
||||
} // Pal
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,187 +1,187 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palMsaaState.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IMsaaState interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palDestroyable.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
/// Specifies conservative rasterization mode
|
||||
enum class ConservativeRasterizationMode : uint8
|
||||
{
|
||||
Overestimate = 0x0, ///< Fragments will be generated if the primitive area covers any portion of the pixel.
|
||||
Underestimate = 0x1, ///< Fragments will be generated if all of the pixel is covered by the primitive.
|
||||
Count
|
||||
};
|
||||
|
||||
/// Maximum supported number of MSAA color samples.
|
||||
constexpr uint32 MaxMsaaColorSamples = 16;
|
||||
|
||||
/// Maximum supported number of MSAA depth samples.
|
||||
constexpr uint32 MaxMsaaDepthSamples = 8;
|
||||
|
||||
/// Maximum supported number of MSAA fragments.
|
||||
constexpr uint32 MaxMsaaFragments = 8;
|
||||
|
||||
/// Sampling pattern grid size. This is a quad of pixels, i.e. 2x2 grid of pixels.
|
||||
constexpr Extent2d MaxGridSize = { 2, 2 };
|
||||
|
||||
/// The positions are rounded to 1/Pow2(SubPixelBits)
|
||||
constexpr uint32 SubPixelBits = 4;
|
||||
|
||||
/// Each pixel is subdivided into Pow2(SubPixelBits) x Pow2(SubPixelBits) grid of possible sample locations.
|
||||
constexpr Extent2d SubPixelGridSize = { 16, 16 };
|
||||
|
||||
/// Represents a 2D coordinate with each component in [-8/16, 7/16]
|
||||
struct SampleLocation
|
||||
{
|
||||
int8 x; ///< X offset.
|
||||
int8 y; ///< Y offset.
|
||||
|
||||
/// Conversion operator that does sign-extension.
|
||||
operator Offset2d() const { return { x, y }; }
|
||||
};
|
||||
|
||||
/// Specifies a custom multisample pattern for a pixel quad.
|
||||
struct MsaaQuadSamplePattern
|
||||
{
|
||||
SampleLocation topLeft[MaxMsaaRasterizerSamples]; ///< Sample locations for TL pixel of quad.
|
||||
SampleLocation topRight[MaxMsaaRasterizerSamples]; ///< Sample locations for TR pixel of quad.
|
||||
SampleLocation bottomLeft[MaxMsaaRasterizerSamples]; ///< Sample locations for BL pixel of quad.
|
||||
SampleLocation bottomRight[MaxMsaaRasterizerSamples]; ///< Sample locations for BR pixel of quad.
|
||||
};
|
||||
|
||||
/// Specifies properties for creation of an @ref IMsaaState object. Input structure to IDevice::CreateMsaaState().
|
||||
struct MsaaStateCreateInfo
|
||||
{
|
||||
uint8 coverageSamples; ///< Number of rasterizer samples. Must be greater than or equal to all sample
|
||||
/// rates in the pipeline. Valid values are 1, 2, 4, 8, and 16.
|
||||
uint8 exposedSamples; ///< Number of samples exposed in the pixel shader coverage mask. Must be less
|
||||
/// than or equal to coverageSamples. Valid values are 1, 2, 4, and 8.
|
||||
uint8 pixelShaderSamples; ///< Controls the pixel shader execution rate. Must be less than or equal to
|
||||
/// coverageSamples. Valid values are 1, 2, 4, and 8. Note that value with
|
||||
/// greater than 1 doesn't mean sample rate shading is enabled. Sample rate
|
||||
/// shading is enabled by either @ref forceSampleRateShading or pixel shader.
|
||||
uint8 depthStencilSamples; ///< Number of samples in the bound depth target. Must be less than or equal to
|
||||
/// coverageSamples. Valid values are 1, 2, 4, and 8.
|
||||
uint8 shaderExportMaskSamples; ///< Number of samples to use in the shader export mask. Should match the number
|
||||
/// of color target fragments clamped to
|
||||
/// @ref DeviceProperties imageProperties.maxMsaaFragments.
|
||||
uint8 sampleClusters; ///< Number of sample clusters to control over-rasterization (all samples in a
|
||||
/// cluster are rasterized if any are hit). Must be less than or equal to
|
||||
/// coverageSamples. Valid values are 1, 2, 4, and 8.
|
||||
uint8 alphaToCoverageSamples; ///< How many samples of quality to generate with alpha-to-coverage. Must be
|
||||
/// less than or equal to coverageSamples. Valid values are 1, 2, 4, 8, and 16.
|
||||
uint8 occlusionQuerySamples; ///< Controls the number of samples to use for occlusion queries.
|
||||
/// This value must never exceed the MSAA rate.
|
||||
uint16 sampleMask; ///< Bitmask of which color target and depth/stencil samples should be updated.
|
||||
/// The lowest bit corresponds to sample 0.
|
||||
|
||||
/// Selects overestimate or underestimate conservative rasterization mode. Used only if
|
||||
/// @ref MsaaStateCreateInfo::flags::enableConservativeRasterization is set to true.
|
||||
ConservativeRasterizationMode conservativeRasterizationMode;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 enableConservativeRasterization : 1; ///< Set to true to enable conservative rasterization
|
||||
uint8 enable1xMsaaSampleLocations : 1; ///< Set to true to enable 1xMSAA quad sample pattern
|
||||
uint8 disableAlphaToCoverageDither : 1; ///< Disables coverage dithering.
|
||||
uint8 enableLineStipple : 1; ///< Set to true to enable line stippling
|
||||
uint8 forceSampleRateShading : 1; ///< Sample rate shading can be enabled by either the pixel
|
||||
/// shader, or forced here with forceSampleRateShading = 1.
|
||||
/// Value 0 means sample rate shading is decided by pixel shader
|
||||
/// and value 1 means sample rate shading is forced enabled.
|
||||
/// This bit is for openGL glMinSampleShading, where sample rate
|
||||
/// shading can be enabled by glEnable(GL_SAMPLE_SHADING)
|
||||
/// instead of by the pixel shader.
|
||||
uint8 reserved : 3; ///< Reserved for future use
|
||||
};
|
||||
uint8 u8All;
|
||||
} flags;
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IMsaaState
|
||||
* @brief Dynamic state object controlling fixed function MSAA state.
|
||||
*
|
||||
* Configures sample counts of various portions of the pipeline, specifies sample positions, etc. The full range of
|
||||
* EQAA hardware features are exposed.
|
||||
*
|
||||
* @see IDevice::CreateMsaaState
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IMsaaState : public IDestroyable
|
||||
{
|
||||
public:
|
||||
|
||||
/// Returns the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @returns Pointer to client data.
|
||||
void* GetClientData() const
|
||||
{
|
||||
return m_pClientData;
|
||||
}
|
||||
|
||||
/// Sets the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @param [in] pClientData A pointer to arbitrary client data.
|
||||
void SetClientData(
|
||||
void* pClientData)
|
||||
{
|
||||
m_pClientData = pClientData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @internal Constructor. Prevent use of new operator on this interface. Client must create objects by explicitly
|
||||
/// called the proper create method.
|
||||
IMsaaState() : m_pClientData(nullptr) {}
|
||||
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IMsaaState() { }
|
||||
|
||||
private:
|
||||
/// @internal Client data pointer. This can have an arbitrary value and can be returned by calling GetClientData()
|
||||
/// and set via SetClientData().
|
||||
/// For non-top-layer objects, this will point to the layer above the current object.
|
||||
void* m_pClientData;
|
||||
};
|
||||
|
||||
} // Pal
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palMsaaState.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IMsaaState interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palDestroyable.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
/// Specifies conservative rasterization mode
|
||||
enum class ConservativeRasterizationMode : uint8
|
||||
{
|
||||
Overestimate = 0x0, ///< Fragments will be generated if the primitive area covers any portion of the pixel.
|
||||
Underestimate = 0x1, ///< Fragments will be generated if all of the pixel is covered by the primitive.
|
||||
Count
|
||||
};
|
||||
|
||||
/// Maximum supported number of MSAA color samples.
|
||||
constexpr uint32 MaxMsaaColorSamples = 16;
|
||||
|
||||
/// Maximum supported number of MSAA depth samples.
|
||||
constexpr uint32 MaxMsaaDepthSamples = 8;
|
||||
|
||||
/// Maximum supported number of MSAA fragments.
|
||||
constexpr uint32 MaxMsaaFragments = 8;
|
||||
|
||||
/// Sampling pattern grid size. This is a quad of pixels, i.e. 2x2 grid of pixels.
|
||||
constexpr Extent2d MaxGridSize = { 2, 2 };
|
||||
|
||||
/// The positions are rounded to 1/Pow2(SubPixelBits)
|
||||
constexpr uint32 SubPixelBits = 4;
|
||||
|
||||
/// Each pixel is subdivided into Pow2(SubPixelBits) x Pow2(SubPixelBits) grid of possible sample locations.
|
||||
constexpr Extent2d SubPixelGridSize = { 16, 16 };
|
||||
|
||||
/// Represents a 2D coordinate with each component in [-8/16, 7/16]
|
||||
struct SampleLocation
|
||||
{
|
||||
int8 x; ///< X offset.
|
||||
int8 y; ///< Y offset.
|
||||
|
||||
/// Conversion operator that does sign-extension.
|
||||
operator Offset2d() const { return { x, y }; }
|
||||
};
|
||||
|
||||
/// Specifies a custom multisample pattern for a pixel quad.
|
||||
struct MsaaQuadSamplePattern
|
||||
{
|
||||
SampleLocation topLeft[MaxMsaaRasterizerSamples]; ///< Sample locations for TL pixel of quad.
|
||||
SampleLocation topRight[MaxMsaaRasterizerSamples]; ///< Sample locations for TR pixel of quad.
|
||||
SampleLocation bottomLeft[MaxMsaaRasterizerSamples]; ///< Sample locations for BL pixel of quad.
|
||||
SampleLocation bottomRight[MaxMsaaRasterizerSamples]; ///< Sample locations for BR pixel of quad.
|
||||
};
|
||||
|
||||
/// Specifies properties for creation of an @ref IMsaaState object. Input structure to IDevice::CreateMsaaState().
|
||||
struct MsaaStateCreateInfo
|
||||
{
|
||||
uint8 coverageSamples; ///< Number of rasterizer samples. Must be greater than or equal to all sample
|
||||
/// rates in the pipeline. Valid values are 1, 2, 4, 8, and 16.
|
||||
uint8 exposedSamples; ///< Number of samples exposed in the pixel shader coverage mask. Must be less
|
||||
/// than or equal to coverageSamples. Valid values are 1, 2, 4, and 8.
|
||||
uint8 pixelShaderSamples; ///< Controls the pixel shader execution rate. Must be less than or equal to
|
||||
/// coverageSamples. Valid values are 1, 2, 4, and 8. Note that value with
|
||||
/// greater than 1 doesn't mean sample rate shading is enabled. Sample rate
|
||||
/// shading is enabled by either @ref forceSampleRateShading or pixel shader.
|
||||
uint8 depthStencilSamples; ///< Number of samples in the bound depth target. Must be less than or equal to
|
||||
/// coverageSamples. Valid values are 1, 2, 4, and 8.
|
||||
uint8 shaderExportMaskSamples; ///< Number of samples to use in the shader export mask. Should match the number
|
||||
/// of color target fragments clamped to
|
||||
/// @ref DeviceProperties imageProperties.maxMsaaFragments.
|
||||
uint8 sampleClusters; ///< Number of sample clusters to control over-rasterization (all samples in a
|
||||
/// cluster are rasterized if any are hit). Must be less than or equal to
|
||||
/// coverageSamples. Valid values are 1, 2, 4, and 8.
|
||||
uint8 alphaToCoverageSamples; ///< How many samples of quality to generate with alpha-to-coverage. Must be
|
||||
/// less than or equal to coverageSamples. Valid values are 1, 2, 4, 8, and 16.
|
||||
uint8 occlusionQuerySamples; ///< Controls the number of samples to use for occlusion queries.
|
||||
/// This value must never exceed the MSAA rate.
|
||||
uint16 sampleMask; ///< Bitmask of which color target and depth/stencil samples should be updated.
|
||||
/// The lowest bit corresponds to sample 0.
|
||||
|
||||
/// Selects overestimate or underestimate conservative rasterization mode. Used only if
|
||||
/// @ref MsaaStateCreateInfo::flags::enableConservativeRasterization is set to true.
|
||||
ConservativeRasterizationMode conservativeRasterizationMode;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 enableConservativeRasterization : 1; ///< Set to true to enable conservative rasterization
|
||||
uint8 enable1xMsaaSampleLocations : 1; ///< Set to true to enable 1xMSAA quad sample pattern
|
||||
uint8 disableAlphaToCoverageDither : 1; ///< Disables coverage dithering.
|
||||
uint8 enableLineStipple : 1; ///< Set to true to enable line stippling
|
||||
uint8 forceSampleRateShading : 1; ///< Sample rate shading can be enabled by either the pixel
|
||||
/// shader, or forced here with forceSampleRateShading = 1.
|
||||
/// Value 0 means sample rate shading is decided by pixel shader
|
||||
/// and value 1 means sample rate shading is forced enabled.
|
||||
/// This bit is for openGL glMinSampleShading, where sample rate
|
||||
/// shading can be enabled by glEnable(GL_SAMPLE_SHADING)
|
||||
/// instead of by the pixel shader.
|
||||
uint8 reserved : 3; ///< Reserved for future use
|
||||
};
|
||||
uint8 u8All;
|
||||
} flags;
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IMsaaState
|
||||
* @brief Dynamic state object controlling fixed function MSAA state.
|
||||
*
|
||||
* Configures sample counts of various portions of the pipeline, specifies sample positions, etc. The full range of
|
||||
* EQAA hardware features are exposed.
|
||||
*
|
||||
* @see IDevice::CreateMsaaState
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IMsaaState : public IDestroyable
|
||||
{
|
||||
public:
|
||||
|
||||
/// Returns the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @returns Pointer to client data.
|
||||
void* GetClientData() const
|
||||
{
|
||||
return m_pClientData;
|
||||
}
|
||||
|
||||
/// Sets the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @param [in] pClientData A pointer to arbitrary client data.
|
||||
void SetClientData(
|
||||
void* pClientData)
|
||||
{
|
||||
m_pClientData = pClientData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @internal Constructor. Prevent use of new operator on this interface. Client must create objects by explicitly
|
||||
/// called the proper create method.
|
||||
IMsaaState() : m_pClientData(nullptr) {}
|
||||
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IMsaaState() { }
|
||||
|
||||
private:
|
||||
/// @internal Client data pointer. This can have an arbitrary value and can be returned by calling GetClientData()
|
||||
/// and set via SetClientData().
|
||||
/// For non-top-layer objects, this will point to the layer above the current object.
|
||||
void* m_pClientData;
|
||||
};
|
||||
|
||||
} // Pal
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,234 +1,234 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palQueryPool.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IQueryPool interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palGpuMemoryBindable.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
/// Specifies a category of GPU query pool.
|
||||
enum class QueryPoolType : uint32
|
||||
{
|
||||
Occlusion = 0x0, ///< Occlusion query pool. Supports queries based on the Z test.
|
||||
PipelineStats = 0x1, ///< Pipeline stats query pool. Supports queries based on statistics from the GPU's execution
|
||||
/// such as a count of prims generated, shader invocations, etc.
|
||||
StreamoutStats = 0x2, ///< Streamout query pool. Supports queries based on statistics from the GPU's execution
|
||||
/// such as number of primitives written to SO buffer and storage needed.
|
||||
Count,
|
||||
};
|
||||
|
||||
/// Specifies what data a query slot must produce. Some query pool types support multiple query types.
|
||||
enum class QueryType : uint32
|
||||
{
|
||||
Occlusion = 0x0, ///< The total passes recorded by the Z test.
|
||||
BinaryOcclusion = 0x1, ///< One if there were one or more Z test passes, zero otherwise.
|
||||
PipelineStats = 0x2, ///< The total statistics selected by the given pipeline stats query pool.
|
||||
StreamoutStats = 0x3, ///< SO statistics tracked by CP/VGT including primitives written and storage needed.
|
||||
StreamoutStats1 = 0x4, ///< SO1 statistics tracked by CP/VGT including primitives written and storage needed.
|
||||
StreamoutStats2 = 0x5, ///< SO2 statistics tracked by CP/VGT including primitives written and storage needed.
|
||||
StreamoutStats3 = 0x6, ///< SO3 statistics tracked by CP/VGT including primitives written and storage needed.
|
||||
Count,
|
||||
};
|
||||
|
||||
/// Specifies which pipeline stats should be tracked by a pipeline stats query pool.
|
||||
enum QueryPipelineStatsFlags : uint32
|
||||
{
|
||||
QueryPipelineStatsIaVertices = 0x1, ///< Input vertices.
|
||||
QueryPipelineStatsIaPrimitives = 0x2, ///< Input primitives.
|
||||
QueryPipelineStatsVsInvocations = 0x4, ///< Vertex shader invocations.
|
||||
QueryPipelineStatsGsInvocations = 0x8, ///< Geometry shader invocations.
|
||||
QueryPipelineStatsGsPrimitives = 0x10, ///< Geometry shader primitives.
|
||||
QueryPipelineStatsCInvocations = 0x20, ///< Clipper invocations.
|
||||
QueryPipelineStatsCPrimitives = 0x40, ///< Clipper primitives.
|
||||
QueryPipelineStatsPsInvocations = 0x80, ///< Pixel shader invocations.
|
||||
QueryPipelineStatsHsInvocations = 0x100, ///< Hull shader invocations.
|
||||
QueryPipelineStatsDsInvocations = 0x200, ///< Domain shader invocations.
|
||||
QueryPipelineStatsCsInvocations = 0x400, ///< Compute shader invocations.
|
||||
QueryPipelineStatsTsInvocations = 0x800, ///< Task shader invocations.
|
||||
QueryPipelineStatsMsInvocations = 0x1000, ///< Mesh shader invocations.
|
||||
QueryPipelineStatsMsPrimitives = 0x2000, ///< Mesh shader primitives.
|
||||
QueryPipelineStatsAll = 0x3FFF ///< All of the above stats.
|
||||
};
|
||||
|
||||
/// Specifies properties for @ref IQueryPool creation. Input structure to IDevice::CreateQueryPool().
|
||||
struct QueryPoolCreateInfo
|
||||
{
|
||||
QueryPoolType queryPoolType; ///< Type of query pool to create (i.e., occlusion vs. pipeline stats).
|
||||
uint32 numSlots; ///< Number of slots in the query pool.
|
||||
uint32 enabledStats; ///< An ORed mask of stats flags specific to the query pool type.
|
||||
/// @see QueryPipelineStatsFlags for PipelineStats query pools.
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/// If true, this query pool can have results retrieved using the CPU (using @ref IQueryPool::GetResults)
|
||||
/// and can be reset using the CPU (using @ref IQueryPool::Reset). Otherwise, the client must use command
|
||||
/// buffers to perform these operations (using @ref ICmdBuffer::CmdResetQueryPool and
|
||||
/// @ref ICmdBuffer::CmdResolveQuery).
|
||||
uint32 enableCpuAccess : 1;
|
||||
uint32 reserved : 31; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed together as a uint32.
|
||||
} flags; ///< Flags controlling QueryPool behavior.
|
||||
};
|
||||
|
||||
/// Controls operations that compute query results.
|
||||
enum QueryResultFlags : uint32
|
||||
{
|
||||
QueryResultDefault = 0x0, ///< Default to 32-bit results with no waiting.
|
||||
QueryResult64Bit = 0x1, ///< Store all results as 64-bit values.
|
||||
QueryResultWait = 0x2, ///< Wait for the queries to finish when computing the results.
|
||||
QueryResultAvailability = 0x4, ///< If the results of a query are available at computation time a one will be
|
||||
/// written as a separate value after the result value, if the results were not
|
||||
/// available a zero will be written.
|
||||
QueryResultPartial = 0x8, ///< If the final result of a query would be unavailable, then return a
|
||||
/// result for that query between 0 and what the final result would be.
|
||||
QueryResultAccumulate = 0x10, ///< Results are added to the values present in the destination, if availability
|
||||
/// data is enabled it will be ANDed with the present availability data.
|
||||
QueryResultPreferShaderPath = 0x20, ///< Prefer a shader resolve path over a command processor path.
|
||||
QueryResultOnlyPrimNeeded = 0x40, ///< Select only primitives storage needed in Streamout query results
|
||||
QueryResultAll = 0x7F ///< Clients should NOT use it, for internal static_assert purpose only.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IQueryPool
|
||||
* @brief Represents a set of queries that can be used to retrieve detailed info about the GPU's execution of a
|
||||
* particular range of a command buffer.
|
||||
*
|
||||
* Currently, only occlusion queries and pipeline statistic queries are supported. All queries in a pool are the same
|
||||
* type.
|
||||
*
|
||||
* @see IDevice::CreateQueryPool()
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IQueryPool : public IGpuMemoryBindable
|
||||
{
|
||||
public:
|
||||
/// Retrieves query results from a query pool.
|
||||
///
|
||||
/// Multiple consecutive query results can be retrieved with one call.
|
||||
///
|
||||
/// @param [in] flags Flags that control the result data layout and how the results are retrieved.
|
||||
/// @param [in] queryType Specifies what data the query slots must produce.
|
||||
/// @param [in] startQuery First query pool slot to retrieve data for.
|
||||
/// @param [in] queryCount Number of query pool slots to retrieve data for.
|
||||
/// @param [in] pMappedGpuAddr Specify the query buffer mapped address. If the parameter equals nullptr,
|
||||
// this method will use Map\UnMap to access the data.
|
||||
/// @param [in,out] pDataSize Input value specifies the available size in pData in bytes; output value reports the
|
||||
/// number of bytes required to hold all result data.
|
||||
/// @param [out] pData Location where the query results should be written. Can be null in order to query the
|
||||
/// required size. The data returned depends on the query pool type and flags. All data
|
||||
/// entries are either uint32 or uint64 integers. One or more type-specific entries will
|
||||
/// be optionally followed by one entry for availability. The type-specific data is:<br>
|
||||
/// + QueryOcclusion: One entry to store the zPass count.
|
||||
/// + QueryPipelineStats: One entry per statistic enabled in the create info. The stats
|
||||
/// will be written in the appropriate order for each PAL client.
|
||||
/// @param [in] stride Stride in bytes between subsequent query result data or zero to request tightly
|
||||
/// packed result data.
|
||||
///
|
||||
/// @returns Success if query results were successfully returned in pData, or NotReady if any of the requested query
|
||||
/// slots does not yet have results available. Otherwise, one of the following error codes may be
|
||||
/// returned:
|
||||
/// + ErrorInvalidValue if the range defined by startQuery and queryCount is not valid for this query pool.
|
||||
/// + ErrorGpuMemoryNotBound if the query pool requires GPU memory but none is bound.
|
||||
/// + ErrorInvalidMemorySize if pData is non-null and the value stored in pDataSize is too small.
|
||||
virtual Result GetResults(
|
||||
QueryResultFlags flags,
|
||||
QueryType queryType,
|
||||
uint32 startQuery,
|
||||
uint32 queryCount,
|
||||
const void* pMappedGpuAddr,
|
||||
size_t* pDataSize,
|
||||
void* pData,
|
||||
size_t stride) = 0;
|
||||
|
||||
/// Use CPU to reset the query pool slots.
|
||||
///
|
||||
/// Supported for occlusion and video decode statistics query pools.
|
||||
///
|
||||
/// @param [in] startQuery First query pool slot to reset.
|
||||
/// @param [in] queryCount Number of query pool slots to reset.
|
||||
/// @param [in] pMappedCpuAddr Specify the query buffer mapped address. If the parameter equals nullptr,
|
||||
// this method will use Map/UnMap to access the data.
|
||||
///
|
||||
/// @returns Success if the reset was successfully performed.
|
||||
virtual Result Reset(
|
||||
uint32 startQuery,
|
||||
uint32 queryCount,
|
||||
void* pMappedCpuAddr) = 0;
|
||||
|
||||
/// Returns the distance, in bytes, between successive query slots in the bound GPU memory.
|
||||
/// This method is only supported for @ref QueryPoolType::VideoDecodeStats
|
||||
///
|
||||
/// @returns the distance, in bytes, between successive query slots in the bound GPU memory.
|
||||
virtual gpusize GetQuerySlotStride() const = 0;
|
||||
|
||||
/// Returns the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @returns Pointer to client data.
|
||||
void* GetClientData() const
|
||||
{
|
||||
return m_pClientData;
|
||||
}
|
||||
|
||||
/// Sets the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @param [in] pClientData A pointer to arbitrary client data.
|
||||
void SetClientData(
|
||||
void* pClientData)
|
||||
{
|
||||
m_pClientData = pClientData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @internal Constructor. Prevent use of new operator on this interface. Client must create objects by explicitly
|
||||
/// called the proper create method.
|
||||
IQueryPool() : m_pClientData(nullptr) {}
|
||||
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IQueryPool() { }
|
||||
|
||||
private:
|
||||
/// @internal Client data pointer. This can have an arbitrary value and can be returned by calling GetClientData()
|
||||
/// and set via SetClientData().
|
||||
/// For non-top-layer objects, this will point to the layer above the current object.
|
||||
void* m_pClientData;
|
||||
};
|
||||
|
||||
} // Pal
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palQueryPool.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IQueryPool interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palGpuMemoryBindable.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
/// Specifies a category of GPU query pool.
|
||||
enum class QueryPoolType : uint32
|
||||
{
|
||||
Occlusion = 0x0, ///< Occlusion query pool. Supports queries based on the Z test.
|
||||
PipelineStats = 0x1, ///< Pipeline stats query pool. Supports queries based on statistics from the GPU's execution
|
||||
/// such as a count of prims generated, shader invocations, etc.
|
||||
StreamoutStats = 0x2, ///< Streamout query pool. Supports queries based on statistics from the GPU's execution
|
||||
/// such as number of primitives written to SO buffer and storage needed.
|
||||
Count,
|
||||
};
|
||||
|
||||
/// Specifies what data a query slot must produce. Some query pool types support multiple query types.
|
||||
enum class QueryType : uint32
|
||||
{
|
||||
Occlusion = 0x0, ///< The total passes recorded by the Z test.
|
||||
BinaryOcclusion = 0x1, ///< One if there were one or more Z test passes, zero otherwise.
|
||||
PipelineStats = 0x2, ///< The total statistics selected by the given pipeline stats query pool.
|
||||
StreamoutStats = 0x3, ///< SO statistics tracked by CP/VGT including primitives written and storage needed.
|
||||
StreamoutStats1 = 0x4, ///< SO1 statistics tracked by CP/VGT including primitives written and storage needed.
|
||||
StreamoutStats2 = 0x5, ///< SO2 statistics tracked by CP/VGT including primitives written and storage needed.
|
||||
StreamoutStats3 = 0x6, ///< SO3 statistics tracked by CP/VGT including primitives written and storage needed.
|
||||
Count,
|
||||
};
|
||||
|
||||
/// Specifies which pipeline stats should be tracked by a pipeline stats query pool.
|
||||
enum QueryPipelineStatsFlags : uint32
|
||||
{
|
||||
QueryPipelineStatsIaVertices = 0x1, ///< Input vertices.
|
||||
QueryPipelineStatsIaPrimitives = 0x2, ///< Input primitives.
|
||||
QueryPipelineStatsVsInvocations = 0x4, ///< Vertex shader invocations.
|
||||
QueryPipelineStatsGsInvocations = 0x8, ///< Geometry shader invocations.
|
||||
QueryPipelineStatsGsPrimitives = 0x10, ///< Geometry shader primitives.
|
||||
QueryPipelineStatsCInvocations = 0x20, ///< Clipper invocations.
|
||||
QueryPipelineStatsCPrimitives = 0x40, ///< Clipper primitives.
|
||||
QueryPipelineStatsPsInvocations = 0x80, ///< Pixel shader invocations.
|
||||
QueryPipelineStatsHsInvocations = 0x100, ///< Hull shader invocations.
|
||||
QueryPipelineStatsDsInvocations = 0x200, ///< Domain shader invocations.
|
||||
QueryPipelineStatsCsInvocations = 0x400, ///< Compute shader invocations.
|
||||
QueryPipelineStatsTsInvocations = 0x800, ///< Task shader invocations.
|
||||
QueryPipelineStatsMsInvocations = 0x1000, ///< Mesh shader invocations.
|
||||
QueryPipelineStatsMsPrimitives = 0x2000, ///< Mesh shader primitives.
|
||||
QueryPipelineStatsAll = 0x3FFF ///< All of the above stats.
|
||||
};
|
||||
|
||||
/// Specifies properties for @ref IQueryPool creation. Input structure to IDevice::CreateQueryPool().
|
||||
struct QueryPoolCreateInfo
|
||||
{
|
||||
QueryPoolType queryPoolType; ///< Type of query pool to create (i.e., occlusion vs. pipeline stats).
|
||||
uint32 numSlots; ///< Number of slots in the query pool.
|
||||
uint32 enabledStats; ///< An ORed mask of stats flags specific to the query pool type.
|
||||
/// @see QueryPipelineStatsFlags for PipelineStats query pools.
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/// If true, this query pool can have results retrieved using the CPU (using @ref IQueryPool::GetResults)
|
||||
/// and can be reset using the CPU (using @ref IQueryPool::Reset). Otherwise, the client must use command
|
||||
/// buffers to perform these operations (using @ref ICmdBuffer::CmdResetQueryPool and
|
||||
/// @ref ICmdBuffer::CmdResolveQuery).
|
||||
uint32 enableCpuAccess : 1;
|
||||
uint32 reserved : 31; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed together as a uint32.
|
||||
} flags; ///< Flags controlling QueryPool behavior.
|
||||
};
|
||||
|
||||
/// Controls operations that compute query results.
|
||||
enum QueryResultFlags : uint32
|
||||
{
|
||||
QueryResultDefault = 0x0, ///< Default to 32-bit results with no waiting.
|
||||
QueryResult64Bit = 0x1, ///< Store all results as 64-bit values.
|
||||
QueryResultWait = 0x2, ///< Wait for the queries to finish when computing the results.
|
||||
QueryResultAvailability = 0x4, ///< If the results of a query are available at computation time a one will be
|
||||
/// written as a separate value after the result value, if the results were not
|
||||
/// available a zero will be written.
|
||||
QueryResultPartial = 0x8, ///< If the final result of a query would be unavailable, then return a
|
||||
/// result for that query between 0 and what the final result would be.
|
||||
QueryResultAccumulate = 0x10, ///< Results are added to the values present in the destination, if availability
|
||||
/// data is enabled it will be ANDed with the present availability data.
|
||||
QueryResultPreferShaderPath = 0x20, ///< Prefer a shader resolve path over a command processor path.
|
||||
QueryResultOnlyPrimNeeded = 0x40, ///< Select only primitives storage needed in Streamout query results
|
||||
QueryResultAll = 0x7F ///< Clients should NOT use it, for internal static_assert purpose only.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IQueryPool
|
||||
* @brief Represents a set of queries that can be used to retrieve detailed info about the GPU's execution of a
|
||||
* particular range of a command buffer.
|
||||
*
|
||||
* Currently, only occlusion queries and pipeline statistic queries are supported. All queries in a pool are the same
|
||||
* type.
|
||||
*
|
||||
* @see IDevice::CreateQueryPool()
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IQueryPool : public IGpuMemoryBindable
|
||||
{
|
||||
public:
|
||||
/// Retrieves query results from a query pool.
|
||||
///
|
||||
/// Multiple consecutive query results can be retrieved with one call.
|
||||
///
|
||||
/// @param [in] flags Flags that control the result data layout and how the results are retrieved.
|
||||
/// @param [in] queryType Specifies what data the query slots must produce.
|
||||
/// @param [in] startQuery First query pool slot to retrieve data for.
|
||||
/// @param [in] queryCount Number of query pool slots to retrieve data for.
|
||||
/// @param [in] pMappedGpuAddr Specify the query buffer mapped address. If the parameter equals nullptr,
|
||||
// this method will use Map\UnMap to access the data.
|
||||
/// @param [in,out] pDataSize Input value specifies the available size in pData in bytes; output value reports the
|
||||
/// number of bytes required to hold all result data.
|
||||
/// @param [out] pData Location where the query results should be written. Can be null in order to query the
|
||||
/// required size. The data returned depends on the query pool type and flags. All data
|
||||
/// entries are either uint32 or uint64 integers. One or more type-specific entries will
|
||||
/// be optionally followed by one entry for availability. The type-specific data is:<br>
|
||||
/// + QueryOcclusion: One entry to store the zPass count.
|
||||
/// + QueryPipelineStats: One entry per statistic enabled in the create info. The stats
|
||||
/// will be written in the appropriate order for each PAL client.
|
||||
/// @param [in] stride Stride in bytes between subsequent query result data or zero to request tightly
|
||||
/// packed result data.
|
||||
///
|
||||
/// @returns Success if query results were successfully returned in pData, or NotReady if any of the requested query
|
||||
/// slots does not yet have results available. Otherwise, one of the following error codes may be
|
||||
/// returned:
|
||||
/// + ErrorInvalidValue if the range defined by startQuery and queryCount is not valid for this query pool.
|
||||
/// + ErrorGpuMemoryNotBound if the query pool requires GPU memory but none is bound.
|
||||
/// + ErrorInvalidMemorySize if pData is non-null and the value stored in pDataSize is too small.
|
||||
virtual Result GetResults(
|
||||
QueryResultFlags flags,
|
||||
QueryType queryType,
|
||||
uint32 startQuery,
|
||||
uint32 queryCount,
|
||||
const void* pMappedGpuAddr,
|
||||
size_t* pDataSize,
|
||||
void* pData,
|
||||
size_t stride) = 0;
|
||||
|
||||
/// Use CPU to reset the query pool slots.
|
||||
///
|
||||
/// Supported for occlusion and video decode statistics query pools.
|
||||
///
|
||||
/// @param [in] startQuery First query pool slot to reset.
|
||||
/// @param [in] queryCount Number of query pool slots to reset.
|
||||
/// @param [in] pMappedCpuAddr Specify the query buffer mapped address. If the parameter equals nullptr,
|
||||
// this method will use Map/UnMap to access the data.
|
||||
///
|
||||
/// @returns Success if the reset was successfully performed.
|
||||
virtual Result Reset(
|
||||
uint32 startQuery,
|
||||
uint32 queryCount,
|
||||
void* pMappedCpuAddr) = 0;
|
||||
|
||||
/// Returns the distance, in bytes, between successive query slots in the bound GPU memory.
|
||||
/// This method is only supported for @ref QueryPoolType::VideoDecodeStats
|
||||
///
|
||||
/// @returns the distance, in bytes, between successive query slots in the bound GPU memory.
|
||||
virtual gpusize GetQuerySlotStride() const = 0;
|
||||
|
||||
/// Returns the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @returns Pointer to client data.
|
||||
void* GetClientData() const
|
||||
{
|
||||
return m_pClientData;
|
||||
}
|
||||
|
||||
/// Sets the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @param [in] pClientData A pointer to arbitrary client data.
|
||||
void SetClientData(
|
||||
void* pClientData)
|
||||
{
|
||||
m_pClientData = pClientData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @internal Constructor. Prevent use of new operator on this interface. Client must create objects by explicitly
|
||||
/// called the proper create method.
|
||||
IQueryPool() : m_pClientData(nullptr) {}
|
||||
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IQueryPool() { }
|
||||
|
||||
private:
|
||||
/// @internal Client data pointer. This can have an arbitrary value and can be returned by calling GetClientData()
|
||||
/// and set via SetClientData().
|
||||
/// For non-top-layer objects, this will point to the layer above the current object.
|
||||
void* m_pClientData;
|
||||
};
|
||||
|
||||
} // Pal
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,275 +1,275 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palQueueSemaphore.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IQueueSemaphore interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palDestroyable.h"
|
||||
#include <chrono>
|
||||
|
||||
#if defined(_WIN32)
|
||||
struct _SECURITY_ATTRIBUTES;
|
||||
#endif
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
class IQueueSemaphore;
|
||||
|
||||
/// Specifies properties for @ref IQueueSemaphore creation. Input structure to IDevice::CreateQueueSemaphore().
|
||||
struct QueueSemaphoreCreateInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/// This queue semaphore may be opened for use by a different device.
|
||||
/// For DX12 native fence, the flag needs to be consistent with D3DDDI_SYNCHRONIZATIONOBJECT_FLAGS.Shared
|
||||
/// given by DX runtime.
|
||||
uint32 shareable : 1;
|
||||
/// This queue semaphore can only be shared through Nt handle.
|
||||
/// For DX12 native fence, the flag needs to be consistent with
|
||||
/// D3DDDI_SYNCHRONIZATIONOBJECT_FLAGS.NtSecuritySharing given by DX runtime.
|
||||
uint32 sharedViaNtHandle : 1;
|
||||
uint32 externalOpened : 1; ///< Semaphore was created by other APIs
|
||||
/// This queue semaphore is a timeline semaphore. Timeline semaphores have a 64-bit unsigned integer payload
|
||||
/// which gets monotonically increased with each Signal operation. A wait on a timeline semaphore blocks the
|
||||
/// waiter until the specified payload value has been signaled.
|
||||
/// For DX12 native fence, runtime determines initialCount. Therefore, timeline flag has to be set.
|
||||
uint32 timeline : 1;
|
||||
/// Do not signal the queue semaphore to max if the device is lost.
|
||||
/// For DX12 native fence, the flag needs to be consistent with
|
||||
/// D3DDDI_SYNCHRONIZATIONOBJECT_FLAGS.NoSignalMaxValueOnTdr given by DX runtime.
|
||||
uint32 noSignalOnDeviceLost : 1;
|
||||
/// For native fence only. If it's 0x0, the native fence type is D3DDDI_NATIVEFENCE_TYPE_DEFAULT.
|
||||
/// If it's 0x1, native fence type is D3DDDI_NATIVEFENCE_TYPE_INTRA_GPU.
|
||||
/// For DX12, the value is determined by runtime. DXCP needs to set it by reading D3DDDI_NATIVEFENCEINFO.
|
||||
uint32 gpuOnly : 1;
|
||||
/// This queue semaphore will be a monitored fence if this flag set, even if OS supports native fence.
|
||||
uint32 forceUseMonitoredFence : 1;
|
||||
uint32 reserved : 25; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags; ///< Queue semaphore creation flags.
|
||||
|
||||
uint32 maxCount; ///< The maximum signal count; once reached, further signals are dropped. Must be
|
||||
/// non-zero and no more than maxSemaphoreCount in @ref DeviceProperties. For
|
||||
/// example, a value of one would request a binary semaphore.
|
||||
/// NOTE: maxCount does not apply to timeline semaphores.
|
||||
|
||||
uint64 initialCount; ///< Initial value for timeline semaphores. (or)
|
||||
/// Initial count value for counting semaphores.
|
||||
/// Must not be larger than maxCount for counting semaphores.
|
||||
/// For DX12 native fence, DXCP needs to pass InitialFenceValue from
|
||||
/// D3DDDI_NATIVEFENCEINFO.
|
||||
|
||||
};
|
||||
|
||||
/// Specifies parameters for opening a queue semaphore for use on another device. Input structure to
|
||||
/// IDevice::OpenSharedQueueSemaphore().
|
||||
struct QueueSemaphoreOpenInfo
|
||||
{
|
||||
/// Shared queue semaphore object from another device to be opened.
|
||||
IQueueSemaphore* pSharedQueueSemaphore;
|
||||
};
|
||||
|
||||
/// Specifies parameters for opening a queue semaphore created by other APIs such as D3D.
|
||||
struct ExternalQueueSemaphoreOpenInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 crossProcess : 1; ///< This semaphore is created in another process.
|
||||
uint32 sharedViaNtHandle : 1; ///< The shared semaphore handle is NT handle.
|
||||
uint32 isReference : 1; ///< If set, then the opened semaphore will reference the same sync
|
||||
///< object in the kernel. Otherwise, the object is copied to the
|
||||
///< new Semaphore.
|
||||
/// This queue semaphore is a timeline semaphore. Timeline semaphores have a 64-bit unsigned integer payload
|
||||
/// which gets monotonically increased with each Signal operation. A wait on a timeline semaphore blocks the
|
||||
/// waiter until the specified payload value has been signaled.
|
||||
uint32 timeline : 1;
|
||||
uint32 reserved : 28; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags; ///< External queue semaphore open flags.
|
||||
|
||||
OsExternalHandle externalSemaphore; ///< External shared semaphore handle.
|
||||
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION < 882
|
||||
#if defined(__unix__) && PAL_KMT_BUILD
|
||||
uint64 syncFdSignalValue; ///< Signal timeline value when importing the state of a sync file
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Specifies parameters for exporting a queue semaphore. Input structure to IQueueSemaphore::ExportExternalHandle().
|
||||
struct QueueSemaphoreExportInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 isReference : 1; ///< If set, then the semaphore exporting a handle that reference the
|
||||
///< same sync object in the kernel. Otherwise, the object is copied
|
||||
///< to the new Semaphore.
|
||||
uint32 reserved : 31; ///< Resevered for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags; ///< External queue semaphore export flags.
|
||||
|
||||
#if PAL_KMT_BUILD
|
||||
const _SECURITY_ATTRIBUTES* pSecurityAttributes; ///< It specifies the security descriptor and the inheritable
|
||||
/// attribute.
|
||||
const wchar_t* pNtObjectName; ///< A name to NT handle, if the object is exported as a NT
|
||||
/// handle with a name, and then the handle can be acquired
|
||||
/// via this name.
|
||||
uint32 accessFlags; ///< Desried access rights of GPU memory.
|
||||
#if defined(__unix__)
|
||||
uint64 syncFdWaitValue; ///< Wait timeline value when exporting the state of a sync file
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IQueueSemaphore
|
||||
* @brief Semaphore object used to synchronize GPU work performed by multiple, parallel queues.
|
||||
*
|
||||
* These semaphores are used by calling IQueue::SignalQueueSemaphore() and IQueue::WaitQueueSemaphore().
|
||||
*
|
||||
* @see IDevice::CreateQueueSemaphore()
|
||||
* @see IDevice::OpenSharedQueueSemaphore()
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IQueueSemaphore : public IDestroyable
|
||||
{
|
||||
public:
|
||||
/// An IQueue::WaitQueueSemaphore operation may need to be sent down to the OS after the corresponding
|
||||
/// IQueue::SignalQueueSemaphore operation due to GPU scheduler limitations. This method checks if any queues have
|
||||
/// batched-up commands waiting for a SignalQueueSemaphore operation to appear.
|
||||
///
|
||||
/// @returns True if one or more queues have some number of commands batched-up waiting for other queues to signal
|
||||
/// this semaphore. False otherwise.
|
||||
virtual bool HasStalledQueues() = 0;
|
||||
|
||||
/// Query timeline Semaphore payload
|
||||
///
|
||||
/// @param [out] pValue returned payload from querying
|
||||
///
|
||||
/// @returns Success if the timeline semaphore is queried successful. Otherwise, one of the following errors may
|
||||
/// be returned:
|
||||
/// + ErrorInvalidValue if an unexpected conversion error occurs.
|
||||
/// + ErrorInvalidObjectType if semaphore is non-timeline type.
|
||||
virtual Result QuerySemaphoreValue(
|
||||
uint64* pValue) = 0;
|
||||
|
||||
/// Wait on timeline Semaphore points, to be clarified, this is a CPU wait.
|
||||
///
|
||||
/// @param [in] value Indicate which point to be waited.
|
||||
/// @param [in] timeout the max waiting time, timeout is the timeout period in units of nanoseconds.
|
||||
///
|
||||
/// @returns Success if the timeline semaphore point is waited successful. Otherwise, one of the following errors
|
||||
/// may be returned:
|
||||
/// + ErrorInvalidValue if an unexpected conversion error occurs.
|
||||
/// + ErrorInvalidObjectType if semaphore is non-timeline type.
|
||||
virtual Result WaitSemaphoreValue(
|
||||
uint64 value,
|
||||
std::chrono::nanoseconds timeout) = 0;
|
||||
|
||||
/// Signal on timeline Semaphore points, to be clarified, this is a CPU signal.
|
||||
///
|
||||
/// @param [in] value Indicate which point to be signaled.
|
||||
///
|
||||
/// @returns Success if the timeline semaphore point is signaled successful. Otherwise, one of the following errors
|
||||
/// may be returned:
|
||||
/// + ErrorInvalidValue if an unexpected conversion error occurs.
|
||||
/// + ErrorInvalidObjectType if semaphore is non-timeline type.
|
||||
virtual Result SignalSemaphoreValue(
|
||||
uint64 value) = 0;
|
||||
|
||||
#if PAL_KMT_BUILD || PAL_AMDGPU_BUILD
|
||||
/// Returns an OS-specific handle which can be used to refer to this semaphore object across processes. This will
|
||||
/// return a null or invalid handle if the object was not created with the external create flag set.
|
||||
///
|
||||
/// @param [in] exportInfo Information describing how the Semamphore handle should be exported.
|
||||
/// @note This function is only available for Linux builds.
|
||||
///
|
||||
/// @returns An OS-specific handle which can be used to access the semaphore object across processes.
|
||||
virtual OsExternalHandle ExportExternalHandle(
|
||||
const QueueSemaphoreExportInfo& exportInfo) const = 0;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
/// Returns an OS-specific handle which can be used by another device to access the semaphore object.
|
||||
///
|
||||
/// @returns An OS-specific handle which can be used by another device to access the semaphore object.
|
||||
virtual OsExternalHandle ExportKmtHandle() const = 0;
|
||||
#endif
|
||||
|
||||
/// Returns the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @returns Pointer to client data.
|
||||
void* GetClientData() const
|
||||
{
|
||||
return m_pClientData;
|
||||
}
|
||||
|
||||
/// Sets the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @param [in] pClientData A pointer to arbitrary client data.
|
||||
void SetClientData(
|
||||
void* pClientData)
|
||||
{
|
||||
m_pClientData = pClientData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @internal Constructor. Prevent use of new operator on this interface. Client must create objects by explicitly
|
||||
/// called the proper create method.
|
||||
IQueueSemaphore() : m_pClientData(nullptr) {}
|
||||
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IQueueSemaphore() { }
|
||||
|
||||
private:
|
||||
/// @internal Client data pointer. This can have an arbitrary value and can be returned by calling GetClientData()
|
||||
/// and set via SetClientData().
|
||||
/// For non-top-layer objects, this will point to the layer above the current object.
|
||||
void* m_pClientData;
|
||||
};
|
||||
|
||||
} // Pal
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palQueueSemaphore.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IQueueSemaphore interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palDestroyable.h"
|
||||
#include <chrono>
|
||||
|
||||
#if defined(_WIN32)
|
||||
struct _SECURITY_ATTRIBUTES;
|
||||
#endif
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
class IQueueSemaphore;
|
||||
|
||||
/// Specifies properties for @ref IQueueSemaphore creation. Input structure to IDevice::CreateQueueSemaphore().
|
||||
struct QueueSemaphoreCreateInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/// This queue semaphore may be opened for use by a different device.
|
||||
/// For DX12 native fence, the flag needs to be consistent with D3DDDI_SYNCHRONIZATIONOBJECT_FLAGS.Shared
|
||||
/// given by DX runtime.
|
||||
uint32 shareable : 1;
|
||||
/// This queue semaphore can only be shared through Nt handle.
|
||||
/// For DX12 native fence, the flag needs to be consistent with
|
||||
/// D3DDDI_SYNCHRONIZATIONOBJECT_FLAGS.NtSecuritySharing given by DX runtime.
|
||||
uint32 sharedViaNtHandle : 1;
|
||||
uint32 externalOpened : 1; ///< Semaphore was created by other APIs
|
||||
/// This queue semaphore is a timeline semaphore. Timeline semaphores have a 64-bit unsigned integer payload
|
||||
/// which gets monotonically increased with each Signal operation. A wait on a timeline semaphore blocks the
|
||||
/// waiter until the specified payload value has been signaled.
|
||||
/// For DX12 native fence, runtime determines initialCount. Therefore, timeline flag has to be set.
|
||||
uint32 timeline : 1;
|
||||
/// Do not signal the queue semaphore to max if the device is lost.
|
||||
/// For DX12 native fence, the flag needs to be consistent with
|
||||
/// D3DDDI_SYNCHRONIZATIONOBJECT_FLAGS.NoSignalMaxValueOnTdr given by DX runtime.
|
||||
uint32 noSignalOnDeviceLost : 1;
|
||||
/// For native fence only. If it's 0x0, the native fence type is D3DDDI_NATIVEFENCE_TYPE_DEFAULT.
|
||||
/// If it's 0x1, native fence type is D3DDDI_NATIVEFENCE_TYPE_INTRA_GPU.
|
||||
/// For DX12, the value is determined by runtime. DXCP needs to set it by reading D3DDDI_NATIVEFENCEINFO.
|
||||
uint32 gpuOnly : 1;
|
||||
/// This queue semaphore will be a monitored fence if this flag set, even if OS supports native fence.
|
||||
uint32 forceUseMonitoredFence : 1;
|
||||
uint32 reserved : 25; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags; ///< Queue semaphore creation flags.
|
||||
|
||||
uint32 maxCount; ///< The maximum signal count; once reached, further signals are dropped. Must be
|
||||
/// non-zero and no more than maxSemaphoreCount in @ref DeviceProperties. For
|
||||
/// example, a value of one would request a binary semaphore.
|
||||
/// NOTE: maxCount does not apply to timeline semaphores.
|
||||
|
||||
uint64 initialCount; ///< Initial value for timeline semaphores. (or)
|
||||
/// Initial count value for counting semaphores.
|
||||
/// Must not be larger than maxCount for counting semaphores.
|
||||
/// For DX12 native fence, DXCP needs to pass InitialFenceValue from
|
||||
/// D3DDDI_NATIVEFENCEINFO.
|
||||
|
||||
};
|
||||
|
||||
/// Specifies parameters for opening a queue semaphore for use on another device. Input structure to
|
||||
/// IDevice::OpenSharedQueueSemaphore().
|
||||
struct QueueSemaphoreOpenInfo
|
||||
{
|
||||
/// Shared queue semaphore object from another device to be opened.
|
||||
IQueueSemaphore* pSharedQueueSemaphore;
|
||||
};
|
||||
|
||||
/// Specifies parameters for opening a queue semaphore created by other APIs such as D3D.
|
||||
struct ExternalQueueSemaphoreOpenInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 crossProcess : 1; ///< This semaphore is created in another process.
|
||||
uint32 sharedViaNtHandle : 1; ///< The shared semaphore handle is NT handle.
|
||||
uint32 isReference : 1; ///< If set, then the opened semaphore will reference the same sync
|
||||
///< object in the kernel. Otherwise, the object is copied to the
|
||||
///< new Semaphore.
|
||||
/// This queue semaphore is a timeline semaphore. Timeline semaphores have a 64-bit unsigned integer payload
|
||||
/// which gets monotonically increased with each Signal operation. A wait on a timeline semaphore blocks the
|
||||
/// waiter until the specified payload value has been signaled.
|
||||
uint32 timeline : 1;
|
||||
uint32 reserved : 28; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags; ///< External queue semaphore open flags.
|
||||
|
||||
OsExternalHandle externalSemaphore; ///< External shared semaphore handle.
|
||||
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION < 882
|
||||
#if defined(__unix__) && PAL_KMT_BUILD
|
||||
uint64 syncFdSignalValue; ///< Signal timeline value when importing the state of a sync file
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Specifies parameters for exporting a queue semaphore. Input structure to IQueueSemaphore::ExportExternalHandle().
|
||||
struct QueueSemaphoreExportInfo
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 isReference : 1; ///< If set, then the semaphore exporting a handle that reference the
|
||||
///< same sync object in the kernel. Otherwise, the object is copied
|
||||
///< to the new Semaphore.
|
||||
uint32 reserved : 31; ///< Resevered for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
} flags; ///< External queue semaphore export flags.
|
||||
|
||||
#if PAL_KMT_BUILD
|
||||
const _SECURITY_ATTRIBUTES* pSecurityAttributes; ///< It specifies the security descriptor and the inheritable
|
||||
/// attribute.
|
||||
const wchar_t* pNtObjectName; ///< A name to NT handle, if the object is exported as a NT
|
||||
/// handle with a name, and then the handle can be acquired
|
||||
/// via this name.
|
||||
uint32 accessFlags; ///< Desried access rights of GPU memory.
|
||||
#if defined(__unix__)
|
||||
uint64 syncFdWaitValue; ///< Wait timeline value when exporting the state of a sync file
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IQueueSemaphore
|
||||
* @brief Semaphore object used to synchronize GPU work performed by multiple, parallel queues.
|
||||
*
|
||||
* These semaphores are used by calling IQueue::SignalQueueSemaphore() and IQueue::WaitQueueSemaphore().
|
||||
*
|
||||
* @see IDevice::CreateQueueSemaphore()
|
||||
* @see IDevice::OpenSharedQueueSemaphore()
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IQueueSemaphore : public IDestroyable
|
||||
{
|
||||
public:
|
||||
/// An IQueue::WaitQueueSemaphore operation may need to be sent down to the OS after the corresponding
|
||||
/// IQueue::SignalQueueSemaphore operation due to GPU scheduler limitations. This method checks if any queues have
|
||||
/// batched-up commands waiting for a SignalQueueSemaphore operation to appear.
|
||||
///
|
||||
/// @returns True if one or more queues have some number of commands batched-up waiting for other queues to signal
|
||||
/// this semaphore. False otherwise.
|
||||
virtual bool HasStalledQueues() = 0;
|
||||
|
||||
/// Query timeline Semaphore payload
|
||||
///
|
||||
/// @param [out] pValue returned payload from querying
|
||||
///
|
||||
/// @returns Success if the timeline semaphore is queried successful. Otherwise, one of the following errors may
|
||||
/// be returned:
|
||||
/// + ErrorInvalidValue if an unexpected conversion error occurs.
|
||||
/// + ErrorInvalidObjectType if semaphore is non-timeline type.
|
||||
virtual Result QuerySemaphoreValue(
|
||||
uint64* pValue) = 0;
|
||||
|
||||
/// Wait on timeline Semaphore points, to be clarified, this is a CPU wait.
|
||||
///
|
||||
/// @param [in] value Indicate which point to be waited.
|
||||
/// @param [in] timeout the max waiting time, timeout is the timeout period in units of nanoseconds.
|
||||
///
|
||||
/// @returns Success if the timeline semaphore point is waited successful. Otherwise, one of the following errors
|
||||
/// may be returned:
|
||||
/// + ErrorInvalidValue if an unexpected conversion error occurs.
|
||||
/// + ErrorInvalidObjectType if semaphore is non-timeline type.
|
||||
virtual Result WaitSemaphoreValue(
|
||||
uint64 value,
|
||||
std::chrono::nanoseconds timeout) = 0;
|
||||
|
||||
/// Signal on timeline Semaphore points, to be clarified, this is a CPU signal.
|
||||
///
|
||||
/// @param [in] value Indicate which point to be signaled.
|
||||
///
|
||||
/// @returns Success if the timeline semaphore point is signaled successful. Otherwise, one of the following errors
|
||||
/// may be returned:
|
||||
/// + ErrorInvalidValue if an unexpected conversion error occurs.
|
||||
/// + ErrorInvalidObjectType if semaphore is non-timeline type.
|
||||
virtual Result SignalSemaphoreValue(
|
||||
uint64 value) = 0;
|
||||
|
||||
#if PAL_KMT_BUILD || PAL_AMDGPU_BUILD
|
||||
/// Returns an OS-specific handle which can be used to refer to this semaphore object across processes. This will
|
||||
/// return a null or invalid handle if the object was not created with the external create flag set.
|
||||
///
|
||||
/// @param [in] exportInfo Information describing how the Semamphore handle should be exported.
|
||||
/// @note This function is only available for Linux builds.
|
||||
///
|
||||
/// @returns An OS-specific handle which can be used to access the semaphore object across processes.
|
||||
virtual OsExternalHandle ExportExternalHandle(
|
||||
const QueueSemaphoreExportInfo& exportInfo) const = 0;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
/// Returns an OS-specific handle which can be used by another device to access the semaphore object.
|
||||
///
|
||||
/// @returns An OS-specific handle which can be used by another device to access the semaphore object.
|
||||
virtual OsExternalHandle ExportKmtHandle() const = 0;
|
||||
#endif
|
||||
|
||||
/// Returns the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @returns Pointer to client data.
|
||||
void* GetClientData() const
|
||||
{
|
||||
return m_pClientData;
|
||||
}
|
||||
|
||||
/// Sets the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @param [in] pClientData A pointer to arbitrary client data.
|
||||
void SetClientData(
|
||||
void* pClientData)
|
||||
{
|
||||
m_pClientData = pClientData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @internal Constructor. Prevent use of new operator on this interface. Client must create objects by explicitly
|
||||
/// called the proper create method.
|
||||
IQueueSemaphore() : m_pClientData(nullptr) {}
|
||||
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IQueueSemaphore() { }
|
||||
|
||||
private:
|
||||
/// @internal Client data pointer. This can have an arbitrary value and can be returned by calling GetClientData()
|
||||
/// and set via SetClientData().
|
||||
/// For non-top-layer objects, this will point to the layer above the current object.
|
||||
void* m_pClientData;
|
||||
};
|
||||
|
||||
} // Pal
|
||||
|
||||
@@ -1,251 +1,253 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palShaderLibrary.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IShaderLibrary interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palDestroyable.h"
|
||||
#include "palStringView.h"
|
||||
#include "palSpan.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
struct GpuMemSubAllocInfo;
|
||||
|
||||
/// Common flags controlling creation of shader libraries.
|
||||
union LibraryCreateFlags
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 clientInternal : 1; ///< Internal library not created by the application.
|
||||
uint32 isGraphics : 1; ///< Whether it is a graphics library
|
||||
uint32 reserved : 30; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
};
|
||||
|
||||
/// Specifies properties about an indirect function belonging to a @ref IShaderLibrary object. Part of the input
|
||||
/// structure to IDevice::CreateShaderLibrary().
|
||||
struct ShaderLibraryFunctionInfo
|
||||
{
|
||||
Util::StringView<char> symbolName; ///< ELF Symbol name for the associated function.
|
||||
gpusize gpuVirtAddr; ///< [out] GPU virtual address of the function. This is computed by PAL during
|
||||
/// library creation.
|
||||
};
|
||||
|
||||
/// Specifies a shader sub type / ShaderKind.
|
||||
enum class ShaderSubType : uint32
|
||||
{
|
||||
Unknown = 0,
|
||||
Traversal,
|
||||
RayGeneration,
|
||||
Intersection,
|
||||
AnyHit,
|
||||
ClosestHit,
|
||||
Miss,
|
||||
Callable,
|
||||
LaunchKernel, ///< Raytracing launch kernel
|
||||
Count
|
||||
};
|
||||
|
||||
/// Specifies properties for creation of a compute @ref IShaderLibrary object. Input structure to
|
||||
/// IDevice::CreateShaderLibrary().
|
||||
struct ShaderLibraryCreateInfo
|
||||
{
|
||||
LibraryCreateFlags flags; ///< Library creation flags
|
||||
|
||||
const void* pCodeObject; ///< Pointer to code-object ELF binary implementing the Pipeline ABI interface.
|
||||
/// The code-object ELF contains pre-compiled shaders, register values, and
|
||||
/// additional metadata.
|
||||
size_t codeObjectSize; ///< Size of code object in bytes.
|
||||
};
|
||||
|
||||
/// Reports properties of a compiled library.
|
||||
struct LibraryInfo
|
||||
{
|
||||
PipelineHash internalLibraryHash; ///< 128-bit identifier extracted from this library's ELF binary, composed of
|
||||
/// the state the compiler decided was appropriate to identify the compiled
|
||||
/// library. The lower 64 bits are "stable"; the upper 64 bits are "unique".
|
||||
};
|
||||
|
||||
/// Reports shader stats. Multiple bits set in the shader stage mask indicates that multiple shaders have been combined
|
||||
/// due to HW support. The same information will be repeated for both the constituent shaders in this case.
|
||||
struct ShaderLibStats
|
||||
{
|
||||
ShaderHash shaderHash; ///< Shader hash.
|
||||
CommonShaderStats common; ///< The shader compilation parameters for this shader.
|
||||
/// Maximum number of VGPRs the compiler was allowed to use for this shader. This limit will be the minimum
|
||||
/// of any architectural restriction and any client-requested limit intended to increase the number of waves in
|
||||
/// flight.
|
||||
uint32 numAvailableVgprs;
|
||||
/// Maximum number of SGPRs the compiler was allowed to use for this shader. This limit will be the minimum
|
||||
/// of any architectural restriction and any client-requested limit intended to increase the number of waves in
|
||||
/// flight.
|
||||
uint32 numAvailableSgprs;
|
||||
size_t isaSizeInBytes; ///< Size of the shader ISA disassembly for this shader.
|
||||
PipelineHash palInternalLibraryHash; ///< Internal hash of the shader compilation data used by PAL.
|
||||
uint32 stackFrameSizeInBytes; ///< Shader function stack frame size
|
||||
ShaderSubType shaderSubType; ///< ShaderSubType / Shader Kind
|
||||
CompilerStackSizes cpsStackSizes; ///< Stack used in Continuation
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IShaderLibrary
|
||||
* @brief Object containing one or more shader functions stored in GPU memory. These shader functions are callable
|
||||
* from the shaders contained within IPipeline objects.
|
||||
*
|
||||
* Before a pipeline which calls into this library is bound to a command buffer (using @ref ICmdBuffer::BindPipeline),
|
||||
* the client must call @ref IPipeline::LinkWithLibraries() and specify this library in the list of linked libraries.
|
||||
* Failure to comply with this requirement is an error and will result in undefined behavior.
|
||||
*
|
||||
* @see IDevice::CreateShaderLibrary()
|
||||
* @see IPipeline::LinkWithLibraries()
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IShaderLibrary : public IDestroyable
|
||||
{
|
||||
public:
|
||||
/// Returns properties of this library and its corresponding shader functions.
|
||||
///
|
||||
/// @returns Property structure describing this library.
|
||||
virtual const LibraryInfo& GetInfo() const = 0;
|
||||
|
||||
/// Returns a list of GPU memory allocations used by this library.
|
||||
///
|
||||
/// @param [in,out] pNumEntries Input value specifies the available size in pAllocInfoList; output value
|
||||
/// reports the number of GPU memory allocations.
|
||||
/// @param [out] pAllocInfoList If pAllocInfoList=nullptr, then pNumEntries is ignored on input. On output it
|
||||
/// will reflect the number of allocations that make up this pipeline. If
|
||||
/// pAllocInfoList!=nullptr, then on input pNumEntries is assumed to be the number
|
||||
/// of entries in the pAllocInfoList array. On output, pNumEntries reflects the
|
||||
/// number of entries in pAllocInfoList that are valid.
|
||||
/// @returns Success if the allocation info was successfully written to the buffer.
|
||||
/// + ErrorInvalidValue if the caller provides a buffer size that is different from the size needed.
|
||||
/// + ErrorInvalidPointer if pNumEntries is nullptr.
|
||||
virtual Result QueryAllocationInfo(
|
||||
size_t* pNumEntries,
|
||||
GpuMemSubAllocInfo* const pAllocInfoList) const = 0;
|
||||
|
||||
/// Gives the client access to the resource ID used for internal Pal events.
|
||||
/// EX: Resource Create, Resource Bind, Resource Destroy.
|
||||
///
|
||||
/// @returns The Resource ID.
|
||||
virtual const void* GetResourceId() const = 0;
|
||||
|
||||
/// Obtains the binary code object for this library.
|
||||
///
|
||||
/// @param [in, out] pSize Represents the size of the shader ISA code.
|
||||
///
|
||||
/// @param [out] pBuffer If non-null, the library ELF is written in the buffer. If null, the size required
|
||||
/// for the library ELF is given out in the location pSize.
|
||||
///
|
||||
/// @returns Success if the library binary was fetched successfully.
|
||||
/// +ErrorUnavailable if the library binary was not fetched successfully.
|
||||
virtual Result GetCodeObject(
|
||||
uint32* pSize,
|
||||
void* pBuffer) const = 0;
|
||||
|
||||
/// Returns the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @returns Pointer to client data.
|
||||
void* GetClientData() const { return m_pClientData; }
|
||||
|
||||
/// Sets the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @param [in] pClientData A pointer to arbitrary client data.
|
||||
void SetClientData(
|
||||
void* pClientData)
|
||||
{
|
||||
m_pClientData = pClientData;
|
||||
}
|
||||
|
||||
/// Obtains the compiled shader ISA code for the shader function specified.
|
||||
///
|
||||
/// @param [in] pShaderExportName The shader exported name
|
||||
///
|
||||
/// @param [in, out] pSize Represents the size of the shader ISA code.
|
||||
///
|
||||
/// @param [out] pBuffer If non-null, the shader ISA code is written in the buffer. If null, the size required
|
||||
/// for the shader ISA is given out in the location pSize.
|
||||
///
|
||||
/// @returns Success if the shader ISA code was fetched successfully.
|
||||
/// +ErrorUnavailable if the shader ISA code was not fetched successfully.
|
||||
|
||||
virtual Result GetShaderFunctionCode(
|
||||
Util::StringView<char> shaderExportName,
|
||||
size_t* pSize,
|
||||
void* pBuffer) const = 0;
|
||||
|
||||
/// Obtains the shader pre and post compilation stats/params for the specified shader.
|
||||
///
|
||||
/// @param [in] pShaderExportName The shader exported name
|
||||
///
|
||||
/// @param [out] pShaderStats Pointer to the ShaderStats structure which will be filled with the shader stats for
|
||||
/// the shader stage mentioned in shaderType. This cannot be nullptr.
|
||||
/// @param [in] getDisassemblySize If set to true performs disassembly on the shader binary code and reports the
|
||||
/// size of the disassembly string in ShaderStats::isaSizeInBytes. Else reports 0.
|
||||
/// @returns Success if the stats were successfully obtained for this shader, including the shader disassembly size.
|
||||
/// +ErrorUnavailable if a wrong shader stage for this pipeline was specified, or if some internal error
|
||||
/// occured.
|
||||
virtual Result GetShaderFunctionStats(
|
||||
Util::StringView<char> shaderExportName,
|
||||
ShaderLibStats* pShaderStats) const = 0;
|
||||
|
||||
/// Returns the function list owned by this shader library
|
||||
///
|
||||
/// @returns A list of ShaderLibraryFunctionInfo.
|
||||
virtual const Util::Span<const ShaderLibraryFunctionInfo> GetShaderLibFunctionInfos() const = 0;
|
||||
|
||||
protected:
|
||||
/// @internal Constructor. Prevent use of new operator on this interface. Client must create objects by explicitly
|
||||
/// called the proper create method.
|
||||
IShaderLibrary() : m_pClientData(nullptr) { }
|
||||
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IShaderLibrary() { }
|
||||
|
||||
private:
|
||||
/// @internal Client data pointer. This can have an arbitrary value and can be returned by calling GetClientData()
|
||||
/// and set via SetClientData().
|
||||
/// For non-top-layer objects, this will point to the layer above the current object.
|
||||
void* m_pClientData;
|
||||
|
||||
IShaderLibrary(const IShaderLibrary&) = delete;
|
||||
IShaderLibrary& operator=(const IShaderLibrary&) = delete;
|
||||
};
|
||||
|
||||
} // Pal
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palShaderLibrary.h
|
||||
* @brief Defines the Platform Abstraction Library (PAL) IShaderLibrary interface and related types.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
#include "palDestroyable.h"
|
||||
#include "palStringView.h"
|
||||
#include "palSpan.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
|
||||
struct GpuMemSubAllocInfo;
|
||||
|
||||
/// Common flags controlling creation of shader libraries.
|
||||
union LibraryCreateFlags
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 clientInternal : 1; ///< Internal library not created by the application.
|
||||
uint32 isGraphics : 1; ///< Whether it is a graphics library
|
||||
uint32 reserved : 30; ///< Reserved for future use.
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
};
|
||||
|
||||
/// Specifies properties about an indirect function belonging to a @ref IShaderLibrary object. Part of the input
|
||||
/// structure to IDevice::CreateShaderLibrary().
|
||||
struct ShaderLibraryFunctionInfo
|
||||
{
|
||||
Util::StringView<char> symbolName; ///< ELF Symbol name for the associated function.
|
||||
gpusize gpuVirtAddr; ///< [out] GPU virtual address of the function. This is computed by PAL during
|
||||
/// library creation.
|
||||
};
|
||||
|
||||
/// Specifies a shader sub type / ShaderKind.
|
||||
enum class ShaderSubType : uint32
|
||||
{
|
||||
Unknown = 0,
|
||||
Traversal,
|
||||
RayGeneration,
|
||||
Intersection,
|
||||
AnyHit,
|
||||
ClosestHit,
|
||||
Miss,
|
||||
Callable,
|
||||
LaunchKernel, ///< Raytracing launch kernel
|
||||
Count
|
||||
};
|
||||
|
||||
/// Specifies properties for creation of a compute @ref IShaderLibrary object. Input structure to
|
||||
/// IDevice::CreateShaderLibrary().
|
||||
struct ShaderLibraryCreateInfo
|
||||
{
|
||||
LibraryCreateFlags flags; ///< Library creation flags
|
||||
|
||||
const void* pCodeObject; ///< Pointer to code-object ELF binary implementing the Pipeline ABI interface.
|
||||
/// The code-object ELF contains pre-compiled shaders, register values, and
|
||||
/// additional metadata.
|
||||
size_t codeObjectSize; ///< Size of code object in bytes.
|
||||
};
|
||||
|
||||
/// Reports properties of a compiled library.
|
||||
struct LibraryInfo
|
||||
{
|
||||
PipelineHash internalLibraryHash; ///< 128-bit identifier extracted from this library's ELF binary, composed of
|
||||
/// the state the compiler decided was appropriate to identify the compiled
|
||||
/// library. The lower 64 bits are "stable"; the upper 64 bits are "unique".
|
||||
Util::StringView<char> colorExports; ///< For a Graphics Partial Pipeline pixel shader, an opaque
|
||||
/// string to pass to the compiler to build the color export shader.
|
||||
};
|
||||
|
||||
/// Reports shader stats. Multiple bits set in the shader stage mask indicates that multiple shaders have been combined
|
||||
/// due to HW support. The same information will be repeated for both the constituent shaders in this case.
|
||||
struct ShaderLibStats
|
||||
{
|
||||
ShaderHash shaderHash; ///< Shader hash.
|
||||
CommonShaderStats common; ///< The shader compilation parameters for this shader.
|
||||
/// Maximum number of VGPRs the compiler was allowed to use for this shader. This limit will be the minimum
|
||||
/// of any architectural restriction and any client-requested limit intended to increase the number of waves in
|
||||
/// flight.
|
||||
uint32 numAvailableVgprs;
|
||||
/// Maximum number of SGPRs the compiler was allowed to use for this shader. This limit will be the minimum
|
||||
/// of any architectural restriction and any client-requested limit intended to increase the number of waves in
|
||||
/// flight.
|
||||
uint32 numAvailableSgprs;
|
||||
size_t isaSizeInBytes; ///< Size of the shader ISA disassembly for this shader.
|
||||
PipelineHash palInternalLibraryHash; ///< Internal hash of the shader compilation data used by PAL.
|
||||
uint32 stackFrameSizeInBytes; ///< Shader function stack frame size
|
||||
ShaderSubType shaderSubType; ///< ShaderSubType / Shader Kind
|
||||
CompilerStackSizes cpsStackSizes; ///< Stack used in Continuation
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @interface IShaderLibrary
|
||||
* @brief Object containing one or more shader functions stored in GPU memory. These shader functions are callable
|
||||
* from the shaders contained within IPipeline objects.
|
||||
*
|
||||
* Before a pipeline which calls into this library is bound to a command buffer (using @ref ICmdBuffer::BindPipeline),
|
||||
* the client must call @ref IPipeline::LinkWithLibraries() and specify this library in the list of linked libraries.
|
||||
* Failure to comply with this requirement is an error and will result in undefined behavior.
|
||||
*
|
||||
* @see IDevice::CreateShaderLibrary()
|
||||
* @see IPipeline::LinkWithLibraries()
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class IShaderLibrary : public IDestroyable
|
||||
{
|
||||
public:
|
||||
/// Returns properties of this library and its corresponding shader functions.
|
||||
///
|
||||
/// @returns Property structure describing this library.
|
||||
virtual const LibraryInfo& GetInfo() const = 0;
|
||||
|
||||
/// Returns a list of GPU memory allocations used by this library.
|
||||
///
|
||||
/// @param [in,out] pNumEntries Input value specifies the available size in pAllocInfoList; output value
|
||||
/// reports the number of GPU memory allocations.
|
||||
/// @param [out] pAllocInfoList If pAllocInfoList=nullptr, then pNumEntries is ignored on input. On output it
|
||||
/// will reflect the number of allocations that make up this pipeline. If
|
||||
/// pAllocInfoList!=nullptr, then on input pNumEntries is assumed to be the number
|
||||
/// of entries in the pAllocInfoList array. On output, pNumEntries reflects the
|
||||
/// number of entries in pAllocInfoList that are valid.
|
||||
/// @returns Success if the allocation info was successfully written to the buffer.
|
||||
/// + ErrorInvalidValue if the caller provides a buffer size that is different from the size needed.
|
||||
/// + ErrorInvalidPointer if pNumEntries is nullptr.
|
||||
virtual Result QueryAllocationInfo(
|
||||
size_t* pNumEntries,
|
||||
GpuMemSubAllocInfo* const pAllocInfoList) const = 0;
|
||||
|
||||
/// Gives the client access to the resource ID used for internal Pal events.
|
||||
/// EX: Resource Create, Resource Bind, Resource Destroy.
|
||||
///
|
||||
/// @returns The Resource ID.
|
||||
virtual const void* GetResourceId() const = 0;
|
||||
|
||||
/// Obtains the binary code object for this library.
|
||||
///
|
||||
/// @param [in, out] pSize Represents the size of the shader ISA code.
|
||||
///
|
||||
/// @param [out] pBuffer If non-null, the library ELF is written in the buffer. If null, the size required
|
||||
/// for the library ELF is given out in the location pSize.
|
||||
///
|
||||
/// @returns Success if the library binary was fetched successfully.
|
||||
/// +ErrorUnavailable if the library binary was not fetched successfully.
|
||||
virtual Result GetCodeObject(
|
||||
uint32* pSize,
|
||||
void* pBuffer) const = 0;
|
||||
|
||||
/// Returns the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @returns Pointer to client data.
|
||||
void* GetClientData() const { return m_pClientData; }
|
||||
|
||||
/// Sets the value of the associated arbitrary client data pointer.
|
||||
/// Can be used to associate arbitrary data with a particular PAL object.
|
||||
///
|
||||
/// @param [in] pClientData A pointer to arbitrary client data.
|
||||
void SetClientData(
|
||||
void* pClientData)
|
||||
{
|
||||
m_pClientData = pClientData;
|
||||
}
|
||||
|
||||
/// Obtains the compiled shader ISA code for the shader function specified.
|
||||
///
|
||||
/// @param [in] pShaderExportName The shader exported name
|
||||
///
|
||||
/// @param [in, out] pSize Represents the size of the shader ISA code.
|
||||
///
|
||||
/// @param [out] pBuffer If non-null, the shader ISA code is written in the buffer. If null, the size required
|
||||
/// for the shader ISA is given out in the location pSize.
|
||||
///
|
||||
/// @returns Success if the shader ISA code was fetched successfully.
|
||||
/// +ErrorUnavailable if the shader ISA code was not fetched successfully.
|
||||
|
||||
virtual Result GetShaderFunctionCode(
|
||||
Util::StringView<char> shaderExportName,
|
||||
size_t* pSize,
|
||||
void* pBuffer) const = 0;
|
||||
|
||||
/// Obtains the shader pre and post compilation stats/params for the specified shader.
|
||||
///
|
||||
/// @param [in] pShaderExportName The shader exported name
|
||||
///
|
||||
/// @param [out] pShaderStats Pointer to the ShaderStats structure which will be filled with the shader stats for
|
||||
/// the shader stage mentioned in shaderType. This cannot be nullptr.
|
||||
/// @param [in] getDisassemblySize If set to true performs disassembly on the shader binary code and reports the
|
||||
/// size of the disassembly string in ShaderStats::isaSizeInBytes. Else reports 0.
|
||||
/// @returns Success if the stats were successfully obtained for this shader, including the shader disassembly size.
|
||||
/// +ErrorUnavailable if a wrong shader stage for this pipeline was specified, or if some internal error
|
||||
/// occured.
|
||||
virtual Result GetShaderFunctionStats(
|
||||
Util::StringView<char> shaderExportName,
|
||||
ShaderLibStats* pShaderStats) const = 0;
|
||||
|
||||
/// Returns the function list owned by this shader library
|
||||
///
|
||||
/// @returns A list of ShaderLibraryFunctionInfo.
|
||||
virtual const Util::Span<const ShaderLibraryFunctionInfo> GetShaderLibFunctionInfos() const = 0;
|
||||
|
||||
protected:
|
||||
/// @internal Constructor. Prevent use of new operator on this interface. Client must create objects by explicitly
|
||||
/// called the proper create method.
|
||||
IShaderLibrary() : m_pClientData(nullptr) { }
|
||||
|
||||
/// @internal Destructor. Prevent use of delete operator on this interface. Client must destroy objects by
|
||||
/// explicitly calling IDestroyable::Destroy() and is responsible for freeing the system memory allocated for the
|
||||
/// object on their own.
|
||||
virtual ~IShaderLibrary() { }
|
||||
|
||||
private:
|
||||
/// @internal Client data pointer. This can have an arbitrary value and can be returned by calling GetClientData()
|
||||
/// and set via SetClientData().
|
||||
/// For non-top-layer objects, this will point to the layer above the current object.
|
||||
void* m_pClientData;
|
||||
|
||||
IShaderLibrary(const IShaderLibrary&) = delete;
|
||||
IShaderLibrary& operator=(const IShaderLibrary&) = delete;
|
||||
};
|
||||
|
||||
} // Pal
|
||||
|
||||
@@ -1,212 +1,214 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2023-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palGpaSession.h"
|
||||
#include "palGpuUtil.h"
|
||||
#include "palTraceSession.h"
|
||||
#include "palVector.h"
|
||||
#include "palHashSet.h"
|
||||
#include "palMutex.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
class IPlatform;
|
||||
class IDevice;
|
||||
class IShaderLibrary;
|
||||
} // namespace Pal
|
||||
|
||||
namespace GpuUtil
|
||||
{
|
||||
class GpaSession;
|
||||
} // namespace GpuUtil
|
||||
|
||||
namespace GpuUtil
|
||||
{
|
||||
|
||||
namespace TraceChunk
|
||||
{
|
||||
|
||||
/// "CodeObject" RDF chunk identifier & version
|
||||
constexpr char CodeObjectChunkId[TextIdentifierSize] = "CodeObject";
|
||||
constexpr Pal::uint32 CodeObjectChunkVersion = 2;
|
||||
|
||||
/// Header for the "CodeObject" RDF chunk
|
||||
struct CodeObjectHeader
|
||||
{
|
||||
Pal::uint32 pciId; /// The ID of the GPU the trace was run on
|
||||
Pal::ShaderHash codeObjectHash; /// Hash of the Code Object binary
|
||||
};
|
||||
|
||||
/// "COLoadEvent" RDF chunk identifier & version
|
||||
constexpr char CodeObjectLoadEventChunkId[TextIdentifierSize] = "COLoadEvent";
|
||||
constexpr Pal::uint32 CodeObjectLoadEventChunkVersion = 3;
|
||||
|
||||
struct CodeObjectLoadEventHeader
|
||||
{
|
||||
Pal::uint32 count; /// Number of load events in this chunk
|
||||
};
|
||||
|
||||
/// Describes whether a load event was into GPU memory or from.
|
||||
enum class CodeObjectLoadEventType : Pal::uint32
|
||||
{
|
||||
LoadToGpuMemory = 0, /// Code Object was loaded into GPU memory
|
||||
UnloadFromGpuMemory = 1 /// Code Object was unloaded from GPU memory
|
||||
};
|
||||
|
||||
/// Describes one or more GPU load/unload(s) of a Code Object. Payload for "COLoadEvent" RDF chunk.
|
||||
struct CodeObjectLoadEvent
|
||||
{
|
||||
Pal::uint32 pciId; /// The ID of the GPU the trace was run on
|
||||
CodeObjectLoadEventType eventType; /// Type of loader event
|
||||
Pal::uint64 baseAddress; /// Base address where the Code Object was loaded
|
||||
Pal::ShaderHash codeObjectHash; /// Hash of the (un)loaded Code Object binary
|
||||
Pal::uint64 timestamp; /// CPU timestamp of this event being triggered
|
||||
};
|
||||
|
||||
/// "PsoCorrelation" RDF chunk identifier & version
|
||||
constexpr char PsoCorrelationChunkId[TextIdentifierSize] = "PsoCorrelation";
|
||||
constexpr Pal::uint32 PsoCorrelationChunkVersion = 3;
|
||||
|
||||
struct PsoCorrelationHeader
|
||||
{
|
||||
Pal::uint32 count; /// Number of PSO correlations in this chunk
|
||||
};
|
||||
|
||||
/// Payload for the "PsoCorrelation" RDF chunks
|
||||
struct PsoCorrelation
|
||||
{
|
||||
Pal::uint32 pciId; /// The ID of the GPU the trace was run on
|
||||
Pal::uint64 apiPsoHash; /// Hash of the API-level Pipeline State Object
|
||||
Pal::PipelineHash internalPipelineHash; /// Hash of all inputs to the pipeline compiler
|
||||
char apiLevelObjectName[64]; /// Debug object name (null-terminated)
|
||||
};
|
||||
|
||||
/// "COCorrelation" RDF chunk identifier & version
|
||||
constexpr char CodeObjectCorrelationChunkId[TextIdentifierSize] = "COCorrelation";
|
||||
constexpr uint32_t CodeObjectCorrelationChunkVersion = 4;
|
||||
|
||||
struct CodeObjectCorrelationHeader
|
||||
{
|
||||
Pal::uint32 count; /// Number of Code Object Correlations in this chunk
|
||||
};
|
||||
|
||||
/// Payload for the "CodeObjectCorrelation" RDF chunks
|
||||
struct CodeObjectCorrelation
|
||||
{
|
||||
Pal::PipelineHash internalPipelineHash; /// Hash of all inputs to the pipeline compiler
|
||||
Pal::ShaderHash codeObjectHash; /// Hash of the Code Object binary in the CO Database
|
||||
Pal::uint32 containsMetadata : 1; /// 1 if the code object contains metadata, 0 otherwise
|
||||
Pal::uint32 reserved : 31; /// Bitflags reserved for future use
|
||||
};
|
||||
|
||||
} // namespace TraceChunk
|
||||
|
||||
/// CodeObject Trace Source name & version
|
||||
constexpr char CodeObjectTraceSourceName[] = "codeobject";
|
||||
constexpr Pal::uint32 CodeObjectTraceSourceVersion = 3;
|
||||
|
||||
// =====================================================================================================================
|
||||
class CodeObjectTraceSource : public ITraceSource
|
||||
{
|
||||
public:
|
||||
CodeObjectTraceSource(Pal::IPlatform* pPlatform);
|
||||
~CodeObjectTraceSource();
|
||||
|
||||
// ==== TraceSource Native Functions ========================================================================== //
|
||||
Pal::Result RegisterPipeline(const Pal::IPipeline* pPipeline, const RegisterPipelineInfo& clientInfo);
|
||||
Pal::Result UnregisterPipeline(const Pal::IPipeline* pPipeline);
|
||||
|
||||
Pal::Result RegisterLibrary(const Pal::IShaderLibrary* pLibrary, const RegisterLibraryInfo& clientInfo);
|
||||
Pal::Result UnregisterLibrary(const Pal::IShaderLibrary* pLibrary);
|
||||
|
||||
Pal::Result RegisterElfBinary(const ElfBinaryInfo& elfBinaryInfo);
|
||||
Pal::Result UnregisterElfBinary(const ElfBinaryInfo& elfBinaryInfo);
|
||||
|
||||
// ==== Base Class Overrides =================================================================================== //
|
||||
virtual void OnConfigUpdated(DevDriver::StructuredValue* pJsonConfig) override { }
|
||||
|
||||
virtual Pal::uint64 QueryGpuWorkMask() const override { return 0; }
|
||||
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 908
|
||||
virtual void OnTraceAccepted(Pal::uint32 gpuIndex, Pal::ICmdBuffer* pCmdBuf) override { }
|
||||
#else
|
||||
virtual void OnTraceAccepted() override { }
|
||||
#endif
|
||||
virtual void OnTraceBegin(Pal::uint32 gpuIndex, Pal::ICmdBuffer* pCmdBuf) override { }
|
||||
virtual void OnTraceEnd(Pal::uint32 gpuIndex, Pal::ICmdBuffer* pCmdBuf) override { }
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 939
|
||||
virtual void OnPostambleEnd(
|
||||
Pal::uint32 gpuIndex,
|
||||
Pal::ICmdBuffer* pCmdBuf) override { }
|
||||
#endif
|
||||
virtual void OnTraceFinished() override;
|
||||
|
||||
virtual const char* GetName() const override { return CodeObjectTraceSourceName; }
|
||||
virtual Pal::uint32 GetVersion() const override { return CodeObjectTraceSourceVersion; }
|
||||
|
||||
private:
|
||||
Pal::Result RegisterSinglePipeline(const Pal::IPipeline* pPipeline, const RegisterPipelineInfo& clientInfo);
|
||||
Pal::Result UnregisterSinglePipeline(const Pal::IPipeline* pPipeline);
|
||||
|
||||
Pal::Result AddCodeObjectLoadEvent(
|
||||
const Pal::IShaderLibrary* pLibrary,
|
||||
TraceChunk::CodeObjectLoadEventType eventType);
|
||||
Pal::Result AddCodeObjectLoadEvent(
|
||||
const Pal::IPipeline* pLibrary,
|
||||
TraceChunk::CodeObjectLoadEventType eventType);
|
||||
Pal::Result AddCodeObjectLoadEvent(
|
||||
const ElfBinaryInfo& elfBinaryInfo,
|
||||
TraceChunk::CodeObjectLoadEventType eventType);
|
||||
|
||||
Pal::Result WriteCodeObjectChunks();
|
||||
Pal::Result WriteLoaderEventsChunk();
|
||||
Pal::Result WritePsoCorrelationChunk();
|
||||
Pal::Result WriteCoCorrelationChunk();
|
||||
|
||||
struct CodeObjectDatabaseRecord
|
||||
{
|
||||
Pal::uint32 recordSize;
|
||||
Pal::ShaderHash codeObjectHash;
|
||||
};
|
||||
|
||||
Pal::IPlatform* const m_pPlatform;
|
||||
|
||||
Util::RWLock m_registerPipelineLock;
|
||||
Util::Vector<CodeObjectDatabaseRecord*, 1, Pal::IPlatform> m_codeObjectRecords;
|
||||
Util::Vector<TraceChunk::CodeObjectLoadEvent, 1, Pal::IPlatform> m_loadEventRecords;
|
||||
Util::Vector<TraceChunk::PsoCorrelation, 1, Pal::IPlatform> m_psoCorrelationRecords;
|
||||
Util::Vector<TraceChunk::CodeObjectCorrelation, 1, Pal::IPlatform> m_coCorrelationRecords;
|
||||
|
||||
// API hashes -> internal pipeline hash (-> child code object hashes)
|
||||
Util::HashSet<Pal::uint64, Pal::IPlatform, Util::JenkinsHashFunc> m_registeredApiHashes;
|
||||
Util::HashSet<Pal::uint64, Pal::IPlatform, Util::JenkinsHashFunc> m_registeredPipelines;
|
||||
Util::HashSet<Pal::uint64, Pal::IPlatform, Util::JenkinsHashFunc> m_registeredCoHashes;
|
||||
|
||||
};
|
||||
|
||||
} // namespace GpuUtil
|
||||
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2023-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palGpaSession.h"
|
||||
#include "palGpuUtil.h"
|
||||
#include "palTraceSession.h"
|
||||
#include "palVector.h"
|
||||
#include "palHashSet.h"
|
||||
#include "palMutex.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
class IPlatform;
|
||||
class IDevice;
|
||||
class IShaderLibrary;
|
||||
} // namespace Pal
|
||||
|
||||
namespace GpuUtil
|
||||
{
|
||||
class GpaSession;
|
||||
} // namespace GpuUtil
|
||||
|
||||
namespace GpuUtil
|
||||
{
|
||||
|
||||
namespace TraceChunk
|
||||
{
|
||||
|
||||
/// "CodeObject" RDF chunk identifier & version
|
||||
constexpr char CodeObjectChunkId[TextIdentifierSize] = "CodeObject";
|
||||
constexpr Pal::uint32 CodeObjectChunkVersion = 2;
|
||||
|
||||
/// Header for the "CodeObject" RDF chunk
|
||||
struct CodeObjectHeader
|
||||
{
|
||||
Pal::uint32 pciId; /// The ID of the GPU the trace was run on
|
||||
Pal::ShaderHash codeObjectHash; /// Hash of the Code Object binary
|
||||
};
|
||||
|
||||
/// "COLoadEvent" RDF chunk identifier & version
|
||||
constexpr char CodeObjectLoadEventChunkId[TextIdentifierSize] = "COLoadEvent";
|
||||
constexpr Pal::uint32 CodeObjectLoadEventChunkVersion = 3;
|
||||
|
||||
struct CodeObjectLoadEventHeader
|
||||
{
|
||||
Pal::uint32 count; /// Number of load events in this chunk
|
||||
};
|
||||
|
||||
/// Describes whether a load event was into GPU memory or from.
|
||||
enum class CodeObjectLoadEventType : Pal::uint32
|
||||
{
|
||||
LoadToGpuMemory = 0, /// Code Object was loaded into GPU memory
|
||||
UnloadFromGpuMemory = 1 /// Code Object was unloaded from GPU memory
|
||||
};
|
||||
|
||||
/// Describes one or more GPU load/unload(s) of a Code Object. Payload for "COLoadEvent" RDF chunk.
|
||||
struct CodeObjectLoadEvent
|
||||
{
|
||||
Pal::uint32 pciId; /// The ID of the GPU the trace was run on
|
||||
CodeObjectLoadEventType eventType; /// Type of loader event
|
||||
Pal::uint64 baseAddress; /// Base address where the Code Object was loaded
|
||||
Pal::ShaderHash codeObjectHash; /// Hash of the (un)loaded Code Object binary
|
||||
Pal::uint64 timestamp; /// CPU timestamp of this event being triggered
|
||||
};
|
||||
|
||||
/// "PsoCorrelation" RDF chunk identifier & version
|
||||
constexpr char PsoCorrelationChunkId[TextIdentifierSize] = "PsoCorrelation";
|
||||
constexpr Pal::uint32 PsoCorrelationChunkVersion = 3;
|
||||
|
||||
struct PsoCorrelationHeader
|
||||
{
|
||||
Pal::uint32 count; /// Number of PSO correlations in this chunk
|
||||
};
|
||||
|
||||
/// Payload for the "PsoCorrelation" RDF chunks
|
||||
struct PsoCorrelation
|
||||
{
|
||||
Pal::uint32 pciId; /// The ID of the GPU the trace was run on
|
||||
Pal::uint64 apiPsoHash; /// Hash of the API-level Pipeline State Object
|
||||
Pal::PipelineHash internalPipelineHash; /// Hash of all inputs to the pipeline compiler
|
||||
char apiLevelObjectName[64]; /// Debug object name (null-terminated)
|
||||
};
|
||||
|
||||
/// "COCorrelation" RDF chunk identifier & version
|
||||
constexpr char CodeObjectCorrelationChunkId[TextIdentifierSize] = "COCorrelation";
|
||||
constexpr uint32_t CodeObjectCorrelationChunkVersion = 4;
|
||||
|
||||
struct CodeObjectCorrelationHeader
|
||||
{
|
||||
Pal::uint32 count; /// Number of Code Object Correlations in this chunk
|
||||
};
|
||||
|
||||
/// Payload for the "CodeObjectCorrelation" RDF chunks
|
||||
struct CodeObjectCorrelation
|
||||
{
|
||||
Pal::PipelineHash internalPipelineHash; /// Hash of all inputs to the pipeline compiler
|
||||
Pal::ShaderHash codeObjectHash; /// Hash of the Code Object binary in the CO Database
|
||||
Pal::uint32 containsMetadata : 1; /// 1 if the code object contains metadata, 0 otherwise
|
||||
Pal::uint32 reserved : 31; /// Bitflags reserved for future use
|
||||
};
|
||||
|
||||
} // namespace TraceChunk
|
||||
|
||||
/// CodeObject Trace Source name & version
|
||||
constexpr char CodeObjectTraceSourceName[] = "codeobject";
|
||||
constexpr Pal::uint32 CodeObjectTraceSourceVersion = 3;
|
||||
|
||||
// =====================================================================================================================
|
||||
class CodeObjectTraceSource : public ITraceSource
|
||||
{
|
||||
public:
|
||||
CodeObjectTraceSource(Pal::IPlatform* pPlatform);
|
||||
~CodeObjectTraceSource();
|
||||
|
||||
// ==== TraceSource Native Functions ========================================================================== //
|
||||
Pal::Result RegisterPipeline(const Pal::IPipeline* pPipeline, const RegisterPipelineInfo& clientInfo);
|
||||
Pal::Result UnregisterPipeline(const Pal::IPipeline* pPipeline);
|
||||
|
||||
Pal::Result RegisterLibrary(const Pal::IShaderLibrary* pLibrary, const RegisterLibraryInfo& clientInfo);
|
||||
Pal::Result UnregisterLibrary(const Pal::IShaderLibrary* pLibrary);
|
||||
|
||||
Pal::Result RegisterElfBinary(const ElfBinaryInfo& elfBinaryInfo);
|
||||
Pal::Result UnregisterElfBinary(const ElfBinaryInfo& elfBinaryInfo);
|
||||
|
||||
// ==== Base Class Overrides =================================================================================== //
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION < COMPRESSION_ARG_VERSION
|
||||
virtual void OnConfigUpdated(DevDriver::StructuredValue* pJsonConfig) override { }
|
||||
#endif
|
||||
|
||||
virtual Pal::uint64 QueryGpuWorkMask() const override { return 0; }
|
||||
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 908
|
||||
virtual void OnTraceAccepted(Pal::uint32 gpuIndex, Pal::ICmdBuffer* pCmdBuf) override { }
|
||||
#else
|
||||
virtual void OnTraceAccepted() override { }
|
||||
#endif
|
||||
virtual void OnTraceBegin(Pal::uint32 gpuIndex, Pal::ICmdBuffer* pCmdBuf) override { }
|
||||
virtual void OnTraceEnd(Pal::uint32 gpuIndex, Pal::ICmdBuffer* pCmdBuf) override { }
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 939
|
||||
virtual void OnPostambleEnd(
|
||||
Pal::uint32 gpuIndex,
|
||||
Pal::ICmdBuffer* pCmdBuf) override { }
|
||||
#endif
|
||||
virtual void OnTraceFinished() override;
|
||||
|
||||
virtual const char* GetName() const override { return CodeObjectTraceSourceName; }
|
||||
virtual Pal::uint32 GetVersion() const override { return CodeObjectTraceSourceVersion; }
|
||||
|
||||
private:
|
||||
Pal::Result RegisterSinglePipeline(const Pal::IPipeline* pPipeline, const RegisterPipelineInfo& clientInfo);
|
||||
Pal::Result UnregisterSinglePipeline(const Pal::IPipeline* pPipeline);
|
||||
|
||||
Pal::Result AddCodeObjectLoadEvent(
|
||||
const Pal::IShaderLibrary* pLibrary,
|
||||
TraceChunk::CodeObjectLoadEventType eventType);
|
||||
Pal::Result AddCodeObjectLoadEvent(
|
||||
const Pal::IPipeline* pLibrary,
|
||||
TraceChunk::CodeObjectLoadEventType eventType);
|
||||
Pal::Result AddCodeObjectLoadEvent(
|
||||
const ElfBinaryInfo& elfBinaryInfo,
|
||||
TraceChunk::CodeObjectLoadEventType eventType);
|
||||
|
||||
Pal::Result WriteCodeObjectChunks();
|
||||
Pal::Result WriteLoaderEventsChunk();
|
||||
Pal::Result WritePsoCorrelationChunk();
|
||||
Pal::Result WriteCoCorrelationChunk();
|
||||
|
||||
struct CodeObjectDatabaseRecord
|
||||
{
|
||||
Pal::uint32 recordSize;
|
||||
Pal::ShaderHash codeObjectHash;
|
||||
};
|
||||
|
||||
Pal::IPlatform* const m_pPlatform;
|
||||
|
||||
Util::RWLock m_registerPipelineLock;
|
||||
Util::Vector<CodeObjectDatabaseRecord*, 1, Pal::IPlatform> m_codeObjectRecords;
|
||||
Util::Vector<TraceChunk::CodeObjectLoadEvent, 1, Pal::IPlatform> m_loadEventRecords;
|
||||
Util::Vector<TraceChunk::PsoCorrelation, 1, Pal::IPlatform> m_psoCorrelationRecords;
|
||||
Util::Vector<TraceChunk::CodeObjectCorrelation, 1, Pal::IPlatform> m_coCorrelationRecords;
|
||||
|
||||
// API hashes -> internal pipeline hash (-> child code object hashes)
|
||||
Util::HashSet<Pal::uint64, Pal::IPlatform, Util::JenkinsHashFunc> m_registeredApiHashes;
|
||||
Util::HashSet<Pal::uint64, Pal::IPlatform, Util::JenkinsHashFunc> m_registeredPipelines;
|
||||
Util::HashSet<Pal::uint64, Pal::IPlatform, Util::JenkinsHashFunc> m_registeredCoHashes;
|
||||
|
||||
};
|
||||
|
||||
} // namespace GpuUtil
|
||||
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,141 +1,141 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palGpuUtil.h
|
||||
* @brief Common include for the PAL GPU utility collection. Defines common types, macros, enums, etc.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
// Forward declarations.
|
||||
namespace Pal
|
||||
{
|
||||
struct DeviceProperties;
|
||||
class IImage;
|
||||
class IGpuMemory;
|
||||
struct ImageCopyRegion;
|
||||
struct TypedBufferCopyRegion;
|
||||
struct MemoryImageCopyRegion;
|
||||
}
|
||||
|
||||
/// Library-wide namespace encapsulating all PAL GPU utility entities.
|
||||
namespace GpuUtil
|
||||
{
|
||||
|
||||
/// Validate image copy region.
|
||||
///
|
||||
/// @param [in] properties The device properties.
|
||||
/// @param [in] engineType Engine to validate.
|
||||
/// @param [in] src Src image.
|
||||
/// @param [in] dst Des image.
|
||||
/// @param [in] region Copy region.
|
||||
///
|
||||
/// @returns true if the image copy is supported by the specific engine, otherwise false.
|
||||
extern bool ValidateImageCopyRegion(
|
||||
const Pal::DeviceProperties& properties,
|
||||
Pal::EngineType engineType,
|
||||
const Pal::IImage& src,
|
||||
const Pal::IImage& dst,
|
||||
const Pal::ImageCopyRegion& region);
|
||||
|
||||
/// Validate typed buffer copy region.
|
||||
///
|
||||
/// @param [in] properties The device properties.
|
||||
/// @param [in] engineType Engine to validate.
|
||||
/// @param [in] region Copy region.
|
||||
///
|
||||
/// @returns true if the typed buffer copy is supported by the specific engine, otherwise false.
|
||||
extern bool ValidateTypedBufferCopyRegion(
|
||||
const Pal::DeviceProperties& properties,
|
||||
Pal::EngineType engineType,
|
||||
const Pal::TypedBufferCopyRegion& region);
|
||||
|
||||
/// Validate image-memory copy region.
|
||||
///
|
||||
/// @param [in] properties The device properties.
|
||||
/// @param [in] engineType Engine to validate.
|
||||
/// @param [in] image The IImage object.
|
||||
/// @param [in] region Copy region.
|
||||
///
|
||||
/// @returns true if the image-memory copy is supported by the specific engine, otherwise false.
|
||||
extern bool ValidateMemoryImageRegion(
|
||||
const Pal::DeviceProperties& properties,
|
||||
Pal::EngineType engineType,
|
||||
const Pal::IImage& image,
|
||||
const Pal::IGpuMemory& memory,
|
||||
const Pal::MemoryImageCopyRegion& region);
|
||||
|
||||
/// Generate a 64-bit uniqueId for a GPU memory allocation
|
||||
///
|
||||
/// @param [in] isInterprocess Indicates this uniqueId is for an externally shareable GPU memory allocation
|
||||
///
|
||||
/// @returns 64-bit uniqueId
|
||||
extern Pal::uint64 GenerateGpuMemoryUniqueId(
|
||||
bool isInterprocess);
|
||||
|
||||
} // GpuUtil
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @page GpuUtilOverview GPU Utility Collection
|
||||
*
|
||||
* In addition to the generic, OS-abstracted software utilities, PAL provides GPU-specific utilities in the @ref GpuUtil
|
||||
* namespace. The PAL GPU Utility Collection relies on both PAL core and PAL Utility. They are also available for use by
|
||||
* its clients.
|
||||
*
|
||||
* All available PAL GPU utilities are defined in the @ref GpuUtil namespace, and are briefly summarized below. See the
|
||||
* Reference topics for more detailed information on specific classes, enums, etc.
|
||||
*
|
||||
* ### TextWriter
|
||||
* The TextWriter GPU utility class provides a method for clients to write text directly to an image. This can be used
|
||||
* for debugging purposes. PAL's internal DbgOverlay uses the TextWriter class to write information about the current
|
||||
* FPS and total allocated GPU video memory usage.
|
||||
*
|
||||
* The TextWriter class is broken up into palTextWriter.h and palTextWriterImpl.h. The intention is that palTextWriter.h
|
||||
* will be included from other header files that need a full TextWriter definition, while palTextWriterImpl.h will be
|
||||
* included by .cpp files that actually interact with the TextWriter. This should keep build times down versus putting
|
||||
* all implementations directly in palTextWriter.h.
|
||||
*
|
||||
* Also included in the TextWriter is the TextWriterFont namespace, which defines the shader IL for drawing the text via
|
||||
* a compute shader. It also defines the Font data, which is a packed binary that represents which pixels of a 10x16
|
||||
* rectangle to render. The font is monospaced.
|
||||
*
|
||||
* ### Helper Functions
|
||||
* ValidateImageCopyRegion - Validate the image copy region, returns true if the image copy is supported by the specific
|
||||
* engine, otherwise false.
|
||||
*
|
||||
* ValidateTypedBufferCopyRegion - Validate the typed buffer copy region, returns true if the typed buffer copy is
|
||||
* supported by the specific engine, otherwise false.
|
||||
*
|
||||
* ValidateMemoryImageRegion - Validate the image-memory copy region, returns true if the image-memory copy is supported
|
||||
* by the specific engine, otherwise false.
|
||||
*
|
||||
* Next: @ref Overview
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palGpuUtil.h
|
||||
* @brief Common include for the PAL GPU utility collection. Defines common types, macros, enums, etc.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
// Forward declarations.
|
||||
namespace Pal
|
||||
{
|
||||
struct DeviceProperties;
|
||||
class IImage;
|
||||
class IGpuMemory;
|
||||
struct ImageCopyRegion;
|
||||
struct TypedBufferCopyRegion;
|
||||
struct MemoryImageCopyRegion;
|
||||
}
|
||||
|
||||
/// Library-wide namespace encapsulating all PAL GPU utility entities.
|
||||
namespace GpuUtil
|
||||
{
|
||||
|
||||
/// Validate image copy region.
|
||||
///
|
||||
/// @param [in] properties The device properties.
|
||||
/// @param [in] engineType Engine to validate.
|
||||
/// @param [in] src Src image.
|
||||
/// @param [in] dst Des image.
|
||||
/// @param [in] region Copy region.
|
||||
///
|
||||
/// @returns true if the image copy is supported by the specific engine, otherwise false.
|
||||
extern bool ValidateImageCopyRegion(
|
||||
const Pal::DeviceProperties& properties,
|
||||
Pal::EngineType engineType,
|
||||
const Pal::IImage& src,
|
||||
const Pal::IImage& dst,
|
||||
const Pal::ImageCopyRegion& region);
|
||||
|
||||
/// Validate typed buffer copy region.
|
||||
///
|
||||
/// @param [in] properties The device properties.
|
||||
/// @param [in] engineType Engine to validate.
|
||||
/// @param [in] region Copy region.
|
||||
///
|
||||
/// @returns true if the typed buffer copy is supported by the specific engine, otherwise false.
|
||||
extern bool ValidateTypedBufferCopyRegion(
|
||||
const Pal::DeviceProperties& properties,
|
||||
Pal::EngineType engineType,
|
||||
const Pal::TypedBufferCopyRegion& region);
|
||||
|
||||
/// Validate image-memory copy region.
|
||||
///
|
||||
/// @param [in] properties The device properties.
|
||||
/// @param [in] engineType Engine to validate.
|
||||
/// @param [in] image The IImage object.
|
||||
/// @param [in] region Copy region.
|
||||
///
|
||||
/// @returns true if the image-memory copy is supported by the specific engine, otherwise false.
|
||||
extern bool ValidateMemoryImageRegion(
|
||||
const Pal::DeviceProperties& properties,
|
||||
Pal::EngineType engineType,
|
||||
const Pal::IImage& image,
|
||||
const Pal::IGpuMemory& memory,
|
||||
const Pal::MemoryImageCopyRegion& region);
|
||||
|
||||
/// Generate a 64-bit uniqueId for a GPU memory allocation
|
||||
///
|
||||
/// @param [in] isInterprocess Indicates this uniqueId is for an externally shareable GPU memory allocation
|
||||
///
|
||||
/// @returns 64-bit uniqueId
|
||||
extern Pal::uint64 GenerateGpuMemoryUniqueId(
|
||||
bool isInterprocess);
|
||||
|
||||
} // GpuUtil
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @page GpuUtilOverview GPU Utility Collection
|
||||
*
|
||||
* In addition to the generic, OS-abstracted software utilities, PAL provides GPU-specific utilities in the @ref GpuUtil
|
||||
* namespace. The PAL GPU Utility Collection relies on both PAL core and PAL Utility. They are also available for use by
|
||||
* its clients.
|
||||
*
|
||||
* All available PAL GPU utilities are defined in the @ref GpuUtil namespace, and are briefly summarized below. See the
|
||||
* Reference topics for more detailed information on specific classes, enums, etc.
|
||||
*
|
||||
* ### TextWriter
|
||||
* The TextWriter GPU utility class provides a method for clients to write text directly to an image. This can be used
|
||||
* for debugging purposes. PAL's internal DbgOverlay uses the TextWriter class to write information about the current
|
||||
* FPS and total allocated GPU video memory usage.
|
||||
*
|
||||
* The TextWriter class is broken up into palTextWriter.h and palTextWriterImpl.h. The intention is that palTextWriter.h
|
||||
* will be included from other header files that need a full TextWriter definition, while palTextWriterImpl.h will be
|
||||
* included by .cpp files that actually interact with the TextWriter. This should keep build times down versus putting
|
||||
* all implementations directly in palTextWriter.h.
|
||||
*
|
||||
* Also included in the TextWriter is the TextWriterFont namespace, which defines the shader IL for drawing the text via
|
||||
* a compute shader. It also defines the Font data, which is a packed binary that represents which pixels of a 10x16
|
||||
* rectangle to render. The font is monospaced.
|
||||
*
|
||||
* ### Helper Functions
|
||||
* ValidateImageCopyRegion - Validate the image copy region, returns true if the image copy is supported by the specific
|
||||
* engine, otherwise false.
|
||||
*
|
||||
* ValidateTypedBufferCopyRegion - Validate the typed buffer copy region, returns true if the typed buffer copy is
|
||||
* supported by the specific engine, otherwise false.
|
||||
*
|
||||
* ValidateMemoryImageRegion - Validate the image-memory copy region, returns true if the image-memory copy is supported
|
||||
* by the specific engine, otherwise false.
|
||||
*
|
||||
* Next: @ref Overview
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
@@ -1,236 +1,238 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2024-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palGpuUtil.h"
|
||||
#include "palTraceSession.h"
|
||||
#include "palGpaSession.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
struct SqttQueueEventRecord;
|
||||
struct SqttQueueInfoRecord;
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
class Platform;
|
||||
}
|
||||
|
||||
namespace GpuUtil
|
||||
{
|
||||
namespace TraceChunk
|
||||
{
|
||||
|
||||
/// "QueueInfo" RDF chunk identifier & version
|
||||
constexpr char QueueInfoChunkId[TextIdentifierSize] = "QueueInfo";
|
||||
constexpr Pal::uint32 QueueInfoChunkVersion = 1;
|
||||
|
||||
/// Enum describing logical queue types
|
||||
enum class QueueType : Pal::uint8
|
||||
{
|
||||
Unknown = 0,
|
||||
Universal = 1,
|
||||
Compute = 2,
|
||||
Dma = 3,
|
||||
Encode = 4,
|
||||
Decode = 5,
|
||||
Security = 6,
|
||||
VideoProcessor = 7
|
||||
};
|
||||
|
||||
/// Enum describing hardware engine types
|
||||
enum class HwEngineType : Pal::uint8
|
||||
{
|
||||
Unknown = 0,
|
||||
Universal = 1,
|
||||
Compute = 2,
|
||||
ExclusiveCompute = 3,
|
||||
Dma = 4,
|
||||
Decode = 5,
|
||||
Encode = 6,
|
||||
HighPriorityUniversal = 7,
|
||||
HighPriorityGraphics = 8,
|
||||
Security = 9,
|
||||
Vpe = 10
|
||||
};
|
||||
|
||||
/// Structure describing a queue's properties
|
||||
struct QueueInfo
|
||||
{
|
||||
Pal::uint32 pciId; ///< The ID of the GPU queried
|
||||
Pal::uint64 queueId; ///< API-specific queue ID
|
||||
Pal::uint64 queueContext; ///< OS-level queue context value from Windows KMD to correlate with ETW data.
|
||||
/// Only applicable to D3D on Windows; 0 otherwise.
|
||||
QueueType queueType; ///< The logical queue type
|
||||
HwEngineType engineType; ///< The hardware engine that the queue is mapped to
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
|
||||
/// "QueueEvent" RDF chunk identifier & version
|
||||
constexpr char QueueEventChunkId[TextIdentifierSize] = "QueueEvent";
|
||||
constexpr Pal::uint32 QueueEventChunkVersion = 1;
|
||||
|
||||
/// The type of queue-level timings event
|
||||
enum class QueueEventType : Pal::uint32
|
||||
{
|
||||
CmdBufSubmit = 0,
|
||||
SignalSemaphore = 1,
|
||||
WaitSemaphore = 2,
|
||||
Present = 3
|
||||
};
|
||||
|
||||
/// Structure describing a queue-level timings event
|
||||
struct QueueEvent
|
||||
{
|
||||
Pal::uint32 pciId; ///< The ID of the GPU queried
|
||||
Pal::uint64 queueId; ///< The API-specific queue ID which triggered the event
|
||||
QueueEventType eventType; ///< The type of the queue-timing event
|
||||
Pal::uint32 sqttCmdBufId; ///< [`CmdBufSubmit` only; 0 otherwise]
|
||||
/// SQTT command buffer ID matching CmdBufStart user data marker
|
||||
Pal::uint64 frameIndex; ///< [`CmdBufSubmit` & `Present` only; 0 otherwise]
|
||||
/// Global frame index incremented for each "Present" call
|
||||
Pal::uint32 submitSubIndex; ///< [`CmdBufSubmit` only; 0 otherwise]
|
||||
/// Sub-index of event within submission.
|
||||
/// When there is only one CmdBuffer per submission, `submitSubIndex` is 0.
|
||||
/// When there are multiple command buffers per submission, `submitSubIndex`
|
||||
/// is incremented by one for each command buffer within the submission.
|
||||
Pal::uint64 apiEventId; ///< [`CmdBufSubmit`] API-specific command buffer ID signaled
|
||||
/// [`SignalSemaphore`] API-specific semaphore ID signaled
|
||||
/// [`WaitSemaphore`] API-specific semaphore ID waited on
|
||||
/// [`Present`] N/A (set to 0)
|
||||
Pal::uint64 cpuTimestamp; ///< CPU start timestamp of when this event is triggered in clock cycle units
|
||||
Pal::uint64 gpuTimestamp1; ///< [`CmdBufSubmit`] GPU timestamp when the HW execution of command buffer began
|
||||
/// [`SignalSemaphore`] GPU timestamp when the HW signaled the queue semaphore
|
||||
/// [`WaitSemaphore`] GPU timestamp when HW finished waiting on the semaphore
|
||||
/// [`Present`] GPU timestamp when HW processed the Present call
|
||||
///
|
||||
/// All timestamps are expressed in clock cycle units.
|
||||
Pal::uint64 gpuTimestamp2; ///< [`CmdBufSubmit` only; 0 otherwise]
|
||||
/// GPU timestamp when the HW execution of command buffer finished
|
||||
};
|
||||
|
||||
} // namespace TraceChunk
|
||||
|
||||
// QueueTimings Trace Source name & version
|
||||
constexpr char QueueTimingsTraceSourceName[] = "queuetimings";
|
||||
constexpr Pal::uint32 QueueTimingsTraceSourceVersion = 2;
|
||||
|
||||
// =====================================================================================================================
|
||||
// This trace source captures queue timings data through GPA session & produces "QueueInfo" and "QueueEvent" RDF chunks
|
||||
class QueueTimingsTraceSource : public ITraceSource
|
||||
{
|
||||
public:
|
||||
explicit QueueTimingsTraceSource(Pal::IPlatform* pPlatform);
|
||||
virtual ~QueueTimingsTraceSource();
|
||||
|
||||
// ==== TraceSource Native Functions ========================================================================== //
|
||||
Pal::Result Init(Pal::IDevice* pDevice);
|
||||
|
||||
Pal::Result RegisterTimedQueue(Pal::IQueue* pQueue,
|
||||
Pal::uint64 queueId,
|
||||
Pal::uint64 queueContext);
|
||||
|
||||
Pal::Result UnregisterTimedQueue(Pal::IQueue* pQueue);
|
||||
|
||||
Pal::Result TimedSubmit(Pal::IQueue* pQueue,
|
||||
const Pal::MultiSubmitInfo& submitInfo,
|
||||
const TimedSubmitInfo& timedSubmitInfo);
|
||||
|
||||
Pal::Result TimedSignalQueueSemaphore(Pal::IQueue* pQueue,
|
||||
Pal::IQueueSemaphore* pQueueSemaphore,
|
||||
const TimedQueueSemaphoreInfo& timedSignalInfo,
|
||||
Pal::uint64 value = 0);
|
||||
|
||||
Pal::Result TimedWaitQueueSemaphore(Pal::IQueue* pQueue,
|
||||
Pal::IQueueSemaphore* pQueueSemaphore,
|
||||
const TimedQueueSemaphoreInfo& timedWaitInfo,
|
||||
Pal::uint64 value = 0);
|
||||
|
||||
Pal::Result TimedQueuePresent(Pal::IQueue* pQueue,
|
||||
const TimedQueuePresentInfo& timedPresentInfo);
|
||||
|
||||
Pal::Result ExternalTimedWaitQueueSemaphore(Pal::uint64 queueContext,
|
||||
Pal::uint64 cpuSubmissionTimestamp,
|
||||
Pal::uint64 cpuCompletionTimestamp,
|
||||
const TimedQueueSemaphoreInfo& timedWaitInfo);
|
||||
|
||||
Pal::Result ExternalTimedSignalQueueSemaphore(Pal::uint64 queueContext,
|
||||
Pal::uint64 cpuSubmissionTimestamp,
|
||||
Pal::uint64 cpuCompletionTimestamp,
|
||||
const TimedQueueSemaphoreInfo& timedSignalInfo);
|
||||
|
||||
bool IsTimingInProgress() const;
|
||||
|
||||
// ==== Base Class Overrides =================================================================================== //
|
||||
virtual void OnConfigUpdated(DevDriver::StructuredValue* pJsonConfig) override { };
|
||||
|
||||
virtual Pal::uint64 QueryGpuWorkMask() const override { return 0; }
|
||||
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 908
|
||||
virtual void OnTraceAccepted(Pal::uint32 gpuIndex, Pal::ICmdBuffer* pCmdBuf) override;
|
||||
#else
|
||||
virtual void OnTraceAccepted() override;
|
||||
#endif
|
||||
virtual void OnTraceBegin(Pal::uint32 gpuIndex, Pal::ICmdBuffer* pCmdBuf) override { };
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 939
|
||||
virtual void OnPostambleEnd(
|
||||
Pal::uint32 gpuIndex,
|
||||
Pal::ICmdBuffer* pCmdBuf) override;
|
||||
virtual void OnTraceEnd(
|
||||
Pal::uint32 gpuIndex,
|
||||
Pal::ICmdBuffer* pCmdBuf) override {};
|
||||
#else
|
||||
virtual void OnTraceEnd(
|
||||
Pal::uint32 gpuIndex,
|
||||
Pal::ICmdBuffer* pCmdBuf) override;
|
||||
#endif
|
||||
virtual void OnTraceFinished() override;
|
||||
|
||||
virtual const char* GetName() const override { return QueueTimingsTraceSourceName; }
|
||||
virtual Pal::uint32 GetVersion() const override { return QueueTimingsTraceSourceVersion; }
|
||||
|
||||
private:
|
||||
void WriteQueueInfoChunks(
|
||||
const SqttQueueInfoRecord* pQueueInfoRecords,
|
||||
size_t numQueueInfoRecords);
|
||||
|
||||
void WriteQueueEventChunks(
|
||||
const SqttQueueInfoRecord* pQueueInfoRecords,
|
||||
size_t numQueueInfoRecords,
|
||||
const SqttQueueEventRecord* pQueueEventRecords,
|
||||
size_t numQueueEventRecords);
|
||||
|
||||
void ReportInternalError(const char* pErrorMsg, Pal::Result result);
|
||||
|
||||
Pal::IPlatform* const m_pPlatform; // IPlatform owning the parent TraceSession
|
||||
GpaSession* m_pGpaSession; // Handle to GpaSession object for tracking queue timings
|
||||
bool m_traceIsHealthy; // Internal flag for tracking resource and state health
|
||||
std::atomic<bool> m_timingInProgress; // Flag for tracking if queue timings operations are ongoing
|
||||
|
||||
};
|
||||
|
||||
} // namespace GpuUtil
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2024-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palGpuUtil.h"
|
||||
#include "palTraceSession.h"
|
||||
#include "palGpaSession.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
struct SqttQueueEventRecord;
|
||||
struct SqttQueueInfoRecord;
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
class Platform;
|
||||
}
|
||||
|
||||
namespace GpuUtil
|
||||
{
|
||||
namespace TraceChunk
|
||||
{
|
||||
|
||||
/// "QueueInfo" RDF chunk identifier & version
|
||||
constexpr char QueueInfoChunkId[TextIdentifierSize] = "QueueInfo";
|
||||
constexpr Pal::uint32 QueueInfoChunkVersion = 1;
|
||||
|
||||
/// Enum describing logical queue types
|
||||
enum class QueueType : Pal::uint8
|
||||
{
|
||||
Unknown = 0,
|
||||
Universal = 1,
|
||||
Compute = 2,
|
||||
Dma = 3,
|
||||
Encode = 4,
|
||||
Decode = 5,
|
||||
Security = 6,
|
||||
VideoProcessor = 7
|
||||
};
|
||||
|
||||
/// Enum describing hardware engine types
|
||||
enum class HwEngineType : Pal::uint8
|
||||
{
|
||||
Unknown = 0,
|
||||
Universal = 1,
|
||||
Compute = 2,
|
||||
ExclusiveCompute = 3,
|
||||
Dma = 4,
|
||||
Decode = 5,
|
||||
Encode = 6,
|
||||
HighPriorityUniversal = 7,
|
||||
HighPriorityGraphics = 8,
|
||||
Security = 9,
|
||||
Vpe = 10
|
||||
};
|
||||
|
||||
/// Structure describing a queue's properties
|
||||
struct QueueInfo
|
||||
{
|
||||
Pal::uint32 pciId; ///< The ID of the GPU queried
|
||||
Pal::uint64 queueId; ///< API-specific queue ID
|
||||
Pal::uint64 queueContext; ///< OS-level queue context value from Windows KMD to correlate with ETW data.
|
||||
/// Only applicable to D3D on Windows; 0 otherwise.
|
||||
QueueType queueType; ///< The logical queue type
|
||||
HwEngineType engineType; ///< The hardware engine that the queue is mapped to
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
|
||||
/// "QueueEvent" RDF chunk identifier & version
|
||||
constexpr char QueueEventChunkId[TextIdentifierSize] = "QueueEvent";
|
||||
constexpr Pal::uint32 QueueEventChunkVersion = 1;
|
||||
|
||||
/// The type of queue-level timings event
|
||||
enum class QueueEventType : Pal::uint32
|
||||
{
|
||||
CmdBufSubmit = 0,
|
||||
SignalSemaphore = 1,
|
||||
WaitSemaphore = 2,
|
||||
Present = 3
|
||||
};
|
||||
|
||||
/// Structure describing a queue-level timings event
|
||||
struct QueueEvent
|
||||
{
|
||||
Pal::uint32 pciId; ///< The ID of the GPU queried
|
||||
Pal::uint64 queueId; ///< The API-specific queue ID which triggered the event
|
||||
QueueEventType eventType; ///< The type of the queue-timing event
|
||||
Pal::uint32 sqttCmdBufId; ///< [`CmdBufSubmit` only; 0 otherwise]
|
||||
/// SQTT command buffer ID matching CmdBufStart user data marker
|
||||
Pal::uint64 frameIndex; ///< [`CmdBufSubmit` & `Present` only; 0 otherwise]
|
||||
/// Global frame index incremented for each "Present" call
|
||||
Pal::uint32 submitSubIndex; ///< [`CmdBufSubmit` only; 0 otherwise]
|
||||
/// Sub-index of event within submission.
|
||||
/// When there is only one CmdBuffer per submission, `submitSubIndex` is 0.
|
||||
/// When there are multiple command buffers per submission, `submitSubIndex`
|
||||
/// is incremented by one for each command buffer within the submission.
|
||||
Pal::uint64 apiEventId; ///< [`CmdBufSubmit`] API-specific command buffer ID signaled
|
||||
/// [`SignalSemaphore`] API-specific semaphore ID signaled
|
||||
/// [`WaitSemaphore`] API-specific semaphore ID waited on
|
||||
/// [`Present`] N/A (set to 0)
|
||||
Pal::uint64 cpuTimestamp; ///< CPU start timestamp of when this event is triggered in clock cycle units
|
||||
Pal::uint64 gpuTimestamp1; ///< [`CmdBufSubmit`] GPU timestamp when the HW execution of command buffer began
|
||||
/// [`SignalSemaphore`] GPU timestamp when the HW signaled the queue semaphore
|
||||
/// [`WaitSemaphore`] GPU timestamp when HW finished waiting on the semaphore
|
||||
/// [`Present`] GPU timestamp when HW processed the Present call
|
||||
///
|
||||
/// All timestamps are expressed in clock cycle units.
|
||||
Pal::uint64 gpuTimestamp2; ///< [`CmdBufSubmit` only; 0 otherwise]
|
||||
/// GPU timestamp when the HW execution of command buffer finished
|
||||
};
|
||||
|
||||
} // namespace TraceChunk
|
||||
|
||||
// QueueTimings Trace Source name & version
|
||||
constexpr char QueueTimingsTraceSourceName[] = "queuetimings";
|
||||
constexpr Pal::uint32 QueueTimingsTraceSourceVersion = 2;
|
||||
|
||||
// =====================================================================================================================
|
||||
// This trace source captures queue timings data through GPA session & produces "QueueInfo" and "QueueEvent" RDF chunks
|
||||
class QueueTimingsTraceSource : public ITraceSource
|
||||
{
|
||||
public:
|
||||
explicit QueueTimingsTraceSource(Pal::IPlatform* pPlatform);
|
||||
virtual ~QueueTimingsTraceSource();
|
||||
|
||||
// ==== TraceSource Native Functions ========================================================================== //
|
||||
Pal::Result Init(Pal::IDevice* pDevice);
|
||||
|
||||
Pal::Result RegisterTimedQueue(Pal::IQueue* pQueue,
|
||||
Pal::uint64 queueId,
|
||||
Pal::uint64 queueContext);
|
||||
|
||||
Pal::Result UnregisterTimedQueue(Pal::IQueue* pQueue);
|
||||
|
||||
Pal::Result TimedSubmit(Pal::IQueue* pQueue,
|
||||
const Pal::MultiSubmitInfo& submitInfo,
|
||||
const TimedSubmitInfo& timedSubmitInfo);
|
||||
|
||||
Pal::Result TimedSignalQueueSemaphore(Pal::IQueue* pQueue,
|
||||
Pal::IQueueSemaphore* pQueueSemaphore,
|
||||
const TimedQueueSemaphoreInfo& timedSignalInfo,
|
||||
Pal::uint64 value = 0);
|
||||
|
||||
Pal::Result TimedWaitQueueSemaphore(Pal::IQueue* pQueue,
|
||||
Pal::IQueueSemaphore* pQueueSemaphore,
|
||||
const TimedQueueSemaphoreInfo& timedWaitInfo,
|
||||
Pal::uint64 value = 0);
|
||||
|
||||
Pal::Result TimedQueuePresent(Pal::IQueue* pQueue,
|
||||
const TimedQueuePresentInfo& timedPresentInfo);
|
||||
|
||||
Pal::Result ExternalTimedWaitQueueSemaphore(Pal::uint64 queueContext,
|
||||
Pal::uint64 cpuSubmissionTimestamp,
|
||||
Pal::uint64 cpuCompletionTimestamp,
|
||||
const TimedQueueSemaphoreInfo& timedWaitInfo);
|
||||
|
||||
Pal::Result ExternalTimedSignalQueueSemaphore(Pal::uint64 queueContext,
|
||||
Pal::uint64 cpuSubmissionTimestamp,
|
||||
Pal::uint64 cpuCompletionTimestamp,
|
||||
const TimedQueueSemaphoreInfo& timedSignalInfo);
|
||||
|
||||
bool IsTimingInProgress() const;
|
||||
|
||||
// ==== Base Class Overrides =================================================================================== //
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION < COMPRESSION_ARG_VERSION
|
||||
virtual void OnConfigUpdated(DevDriver::StructuredValue* pJsonConfig) override { }
|
||||
#endif
|
||||
|
||||
virtual Pal::uint64 QueryGpuWorkMask() const override { return 0; }
|
||||
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 908
|
||||
virtual void OnTraceAccepted(Pal::uint32 gpuIndex, Pal::ICmdBuffer* pCmdBuf) override;
|
||||
#else
|
||||
virtual void OnTraceAccepted() override;
|
||||
#endif
|
||||
virtual void OnTraceBegin(Pal::uint32 gpuIndex, Pal::ICmdBuffer* pCmdBuf) override { };
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 939
|
||||
virtual void OnPostambleEnd(
|
||||
Pal::uint32 gpuIndex,
|
||||
Pal::ICmdBuffer* pCmdBuf) override;
|
||||
virtual void OnTraceEnd(
|
||||
Pal::uint32 gpuIndex,
|
||||
Pal::ICmdBuffer* pCmdBuf) override {};
|
||||
#else
|
||||
virtual void OnTraceEnd(
|
||||
Pal::uint32 gpuIndex,
|
||||
Pal::ICmdBuffer* pCmdBuf) override;
|
||||
#endif
|
||||
virtual void OnTraceFinished() override;
|
||||
|
||||
virtual const char* GetName() const override { return QueueTimingsTraceSourceName; }
|
||||
virtual Pal::uint32 GetVersion() const override { return QueueTimingsTraceSourceVersion; }
|
||||
|
||||
private:
|
||||
void WriteQueueInfoChunks(
|
||||
const SqttQueueInfoRecord* pQueueInfoRecords,
|
||||
size_t numQueueInfoRecords);
|
||||
|
||||
void WriteQueueEventChunks(
|
||||
const SqttQueueInfoRecord* pQueueInfoRecords,
|
||||
size_t numQueueInfoRecords,
|
||||
const SqttQueueEventRecord* pQueueEventRecords,
|
||||
size_t numQueueEventRecords);
|
||||
|
||||
void ReportInternalError(const char* pErrorMsg, Pal::Result result);
|
||||
|
||||
Pal::IPlatform* const m_pPlatform; // IPlatform owning the parent TraceSession
|
||||
GpaSession* m_pGpaSession; // Handle to GpaSession object for tracking queue timings
|
||||
bool m_traceIsHealthy; // Internal flag for tracking resource and state health
|
||||
std::atomic<bool> m_timingInProgress; // Flag for tracking if queue timings operations are ongoing
|
||||
|
||||
};
|
||||
|
||||
} // namespace GpuUtil
|
||||
|
||||
@@ -1,150 +1,155 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2024-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palTraceSession.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
class IPlatform;
|
||||
class IQueue;
|
||||
class ICmdBuffer;
|
||||
class Device;
|
||||
}
|
||||
|
||||
namespace GpuUtil
|
||||
{
|
||||
|
||||
/// Supported render operations used to advance the trace
|
||||
enum RenderOp : Pal::uint8
|
||||
{
|
||||
RenderOpDraw = (1u << 0),
|
||||
RenderOpDispatch = (1u << 1)
|
||||
};
|
||||
|
||||
/// Structure used to batch submit render operations on queue submission
|
||||
/// This struct should have a `*Count` field for each @ref RenderOp enumeration above
|
||||
struct RenderOpCounts
|
||||
{
|
||||
Pal::uint32 drawCount;
|
||||
Pal::uint32 dispatchCount;
|
||||
};
|
||||
|
||||
constexpr Pal::uint32 RenderOpTraceControllerVersion = 4;
|
||||
constexpr char RenderOpTraceControllerName[] = "renderop";
|
||||
|
||||
// =====================================================================================================================
|
||||
class RenderOpTraceController : public ITraceController
|
||||
{
|
||||
public:
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION < 896
|
||||
using RenderOp = GpuUtil::RenderOp;
|
||||
#endif
|
||||
RenderOpTraceController(Pal::IPlatform* pPlatform, Pal::IDevice* pDevice);
|
||||
virtual ~RenderOpTraceController();
|
||||
|
||||
virtual const char* GetName() const override { return RenderOpTraceControllerName; }
|
||||
virtual Pal::uint32 GetVersion() const override { return RenderOpTraceControllerVersion; }
|
||||
|
||||
virtual void OnConfigUpdated(DevDriver::StructuredValue* pJsonConfig) override;
|
||||
virtual Pal::Result OnTraceRequested() override;
|
||||
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 908
|
||||
virtual Pal::Result OnPreparationGpuWork(Pal::uint32 gpuIndex, Pal::ICmdBuffer** ppCmdBuf) override;
|
||||
#endif
|
||||
virtual Pal::Result OnBeginGpuWork(Pal::uint32 gpuIndex, Pal::ICmdBuffer** ppCmdBuffer) override;
|
||||
virtual Pal::Result OnEndGpuWork(Pal::uint32 gpuIndex, Pal::ICmdBuffer** ppCmdBuffer) override;
|
||||
virtual Pal::Result OnEndPostambleGpuWork(
|
||||
Pal::uint32 gpuIndex,
|
||||
Pal::ICmdBuffer** ppCmdBuffer) override;
|
||||
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION < 896
|
||||
void RecordRenderOp(Pal::IQueue* pQueue, RenderOp renderOp);
|
||||
#endif
|
||||
|
||||
void FinishTrace();
|
||||
|
||||
// Cancel the trace currently in progress.
|
||||
virtual Pal::Result OnTraceCanceled() override;
|
||||
|
||||
/// This function must be called by client drivers implementing the RenderOp controller.
|
||||
/// On every queue submission, this function is called with the cumulative counts of render operations
|
||||
/// recorded into that queue's command buffers.
|
||||
/// Based on the controller's internal mask, set by the user during trace configuration,
|
||||
/// the trace controller may advance its state.
|
||||
void RecordRenderOps(Pal::IQueue* pQueue, const RenderOpCounts& renderOpCounts);
|
||||
|
||||
private:
|
||||
/// Controls whether the trace proceeds on absolute render op counts or relative
|
||||
enum class CaptureMode : Pal::uint8
|
||||
{
|
||||
Relative = 0, ///< Relative to when the trace request is received
|
||||
Absolute ///< Absolute render op index
|
||||
};
|
||||
|
||||
Pal::Result AcceptTrace();
|
||||
Pal::Result BeginTrace();
|
||||
|
||||
Pal::Result SubmitBeginTraceGpuWork() const;
|
||||
Pal::Result SubmitEndTraceGpuWork();
|
||||
Pal::Result SubmitEndPostambleGpuWork();
|
||||
|
||||
Pal::Result WaitForTraceEndGpuWorkCompletion() const;
|
||||
Pal::Result CreateFence(Pal::IFence** ppFence) const;
|
||||
Pal::Result CreateCommandBuffer(bool traceEnd, Pal::ICmdBuffer** ppCmdBuf) const;
|
||||
Pal::Result CreateCmdAllocator();
|
||||
|
||||
void OnRenderOpUpdated(Pal::uint64 countRecorded);
|
||||
void FreeResources();
|
||||
void AbortTrace();
|
||||
|
||||
Pal::IPlatform* const m_pPlatform; // Platform associated with this TraceController
|
||||
Pal::IDevice* m_pDevice; // Device associated with this TraceController
|
||||
Pal::ICmdAllocator* m_pCmdAllocator; // Command allocator for the TraceController
|
||||
|
||||
TraceSession* m_pTraceSession; // TraceSession owning this TraceController
|
||||
Pal::uint64 m_supportedGpuMask; // Bit mask of GPU indices that are capable of participating in the trace
|
||||
Pal::uint8 m_renderOpMask; // Bitmask of RenderOp modes, indicating which are accepted
|
||||
CaptureMode m_captureMode; // Modality for determining the starting renderop index of the trace
|
||||
Pal::uint64 m_renderOpCount; // The "global" count, incremented on every render op
|
||||
Pal::uint64 m_prepStartRenderOp; // Relative or absolute render op number indicating trace begin
|
||||
Pal::uint64 m_numPrepRenderOps; // Number of "warm-up" frames before the start frame
|
||||
Pal::uint64 m_captureRenderOpCount; // Number of frames to wait before ending the trace
|
||||
Pal::uint64 m_renderOpTraceAccepted; // The frame number when the trace was accepted
|
||||
|
||||
Util::Mutex m_renderOpLock; // Lock over UpdateFrame/OnFrameUpdated
|
||||
Pal::IQueue* m_pQueue; // The queue being used to submit Begin/End GPU trace command buffers
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 908
|
||||
Pal::ICmdBuffer* m_pCmdBufTracePrepare; // Command buffer for recording during the prep phase
|
||||
#endif
|
||||
Pal::ICmdBuffer* m_pCmdBufTraceBegin; // Command buffer to submit Trace Begin
|
||||
Pal::ICmdBuffer* m_pCmdBufTraceEnd; // Command buffer to submit Trace End
|
||||
Pal::ICmdBuffer* m_pCmdBufPostambleEnd; // Command buffer to submit Postamble End
|
||||
Pal::IFence* m_pFenceTraceEnd; // Fence to wait for Trace End command buffer completion
|
||||
Pal::IFence* m_pFencePostambleEnd; // Fence to wait for Postamble End command buffer completion
|
||||
};
|
||||
|
||||
} // namespace GpuUtil
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2024-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palTraceSession.h"
|
||||
|
||||
namespace Pal
|
||||
{
|
||||
class IPlatform;
|
||||
class IQueue;
|
||||
class ICmdBuffer;
|
||||
class Device;
|
||||
}
|
||||
|
||||
namespace GpuUtil
|
||||
{
|
||||
|
||||
/// Supported render operations used to advance the trace
|
||||
enum RenderOp : Pal::uint8
|
||||
{
|
||||
RenderOpDraw = (1u << 0),
|
||||
RenderOpDispatch = (1u << 1)
|
||||
};
|
||||
|
||||
/// Structure used to batch submit render operations on queue submission
|
||||
/// This struct should have a `*Count` field for each @ref RenderOp enumeration above
|
||||
struct RenderOpCounts
|
||||
{
|
||||
Pal::uint32 drawCount;
|
||||
Pal::uint32 dispatchCount;
|
||||
};
|
||||
|
||||
constexpr Pal::uint32 RenderOpTraceControllerVersion = 4;
|
||||
constexpr char RenderOpTraceControllerName[] = "renderop";
|
||||
|
||||
// =====================================================================================================================
|
||||
class RenderOpTraceController : public ITraceController
|
||||
{
|
||||
public:
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION < 896
|
||||
using RenderOp = GpuUtil::RenderOp;
|
||||
#endif
|
||||
RenderOpTraceController(Pal::IPlatform* pPlatform, Pal::IDevice* pDevice);
|
||||
virtual ~RenderOpTraceController();
|
||||
|
||||
virtual const char* GetName() const override { return RenderOpTraceControllerName; }
|
||||
virtual Pal::uint32 GetVersion() const override { return RenderOpTraceControllerVersion; }
|
||||
|
||||
virtual void OnConfigUpdated(DevDriver::StructuredValue* pJsonConfig) override;
|
||||
virtual Pal::Result OnTraceRequested() override;
|
||||
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 908
|
||||
virtual Pal::Result OnPreparationGpuWork(Pal::uint32 gpuIndex, Pal::ICmdBuffer** ppCmdBuf) override;
|
||||
#endif
|
||||
virtual Pal::Result OnBeginGpuWork(Pal::uint32 gpuIndex, Pal::ICmdBuffer** ppCmdBuffer) override;
|
||||
virtual Pal::Result OnEndGpuWork(Pal::uint32 gpuIndex, Pal::ICmdBuffer** ppCmdBuffer) override;
|
||||
virtual Pal::Result OnEndPostambleGpuWork(
|
||||
Pal::uint32 gpuIndex,
|
||||
Pal::ICmdBuffer** ppCmdBuffer) override;
|
||||
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION < 896
|
||||
void RecordRenderOp(Pal::IQueue* pQueue, RenderOp renderOp);
|
||||
#endif
|
||||
|
||||
void FinishTrace();
|
||||
|
||||
// Cancel the trace currently in progress.
|
||||
virtual Pal::Result OnTraceCanceled() override;
|
||||
|
||||
/// This function must be called by client drivers implementing the RenderOp controller.
|
||||
/// On every queue submission, this function is called with the cumulative counts of render operations
|
||||
/// recorded into that queue's command buffers.
|
||||
/// Based on the controller's internal mask, set by the user during trace configuration,
|
||||
/// the trace controller may advance its state.
|
||||
void RecordRenderOps(Pal::IQueue* pQueue, const RenderOpCounts& renderOpCounts);
|
||||
|
||||
// Force a controller update
|
||||
virtual void OnUpdated() override { OnRenderOpUpdated(0); }
|
||||
|
||||
virtual Pal::IQueue* GetTraceQueue() const override { return m_pQueue; }
|
||||
|
||||
private:
|
||||
/// Controls whether the trace proceeds on absolute render op counts or relative
|
||||
enum class CaptureMode : Pal::uint8
|
||||
{
|
||||
Relative = 0, ///< Relative to when the trace request is received
|
||||
Absolute ///< Absolute render op index
|
||||
};
|
||||
|
||||
Pal::Result AcceptTrace();
|
||||
Pal::Result BeginTrace();
|
||||
|
||||
Pal::Result SubmitBeginTraceGpuWork() const;
|
||||
Pal::Result SubmitEndTraceGpuWork();
|
||||
Pal::Result SubmitEndPostambleGpuWork();
|
||||
|
||||
Pal::Result WaitForTraceEndGpuWorkCompletion() const;
|
||||
Pal::Result CreateFence(Pal::IFence** ppFence) const;
|
||||
Pal::Result CreateCommandBuffer(bool traceEnd, Pal::ICmdBuffer** ppCmdBuf) const;
|
||||
Pal::Result CreateCmdAllocator();
|
||||
|
||||
void OnRenderOpUpdated(Pal::uint64 countRecorded);
|
||||
void FreeResources();
|
||||
void AbortTrace();
|
||||
|
||||
Pal::IPlatform* const m_pPlatform; // Platform associated with this TraceController
|
||||
Pal::IDevice* m_pDevice; // Device associated with this TraceController
|
||||
Pal::ICmdAllocator* m_pCmdAllocator; // Command allocator for the TraceController
|
||||
|
||||
TraceSession* m_pTraceSession; // TraceSession owning this TraceController
|
||||
Pal::uint64 m_supportedGpuMask; // Bit mask of GPU indices that are capable of participating in the trace
|
||||
Pal::uint8 m_renderOpMask; // Bitmask of RenderOp modes, indicating which are accepted
|
||||
CaptureMode m_captureMode; // Modality for determining the starting renderop index of the trace
|
||||
Pal::uint64 m_renderOpCount; // The "global" count, incremented on every render op
|
||||
Pal::uint64 m_prepStartRenderOp; // Relative or absolute render op number indicating trace begin
|
||||
Pal::uint64 m_numPrepRenderOps; // Number of "warm-up" frames before the start frame
|
||||
Pal::uint64 m_captureRenderOpCount; // Number of frames to wait before ending the trace
|
||||
Pal::uint64 m_renderOpTraceAccepted; // The frame number when the trace was accepted
|
||||
|
||||
Util::Mutex m_renderOpLock; // Lock over UpdateFrame/OnFrameUpdated
|
||||
Pal::IQueue* m_pQueue; // The queue being used to submit Begin/End GPU trace command buffers
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 908
|
||||
Pal::ICmdBuffer* m_pCmdBufTracePrepare; // Command buffer for recording during the prep phase
|
||||
#endif
|
||||
Pal::ICmdBuffer* m_pCmdBufTraceBegin; // Command buffer to submit Trace Begin
|
||||
Pal::ICmdBuffer* m_pCmdBufTraceEnd; // Command buffer to submit Trace End
|
||||
Pal::ICmdBuffer* m_pCmdBufPostambleEnd; // Command buffer to submit Postamble End
|
||||
Pal::IFence* m_pFenceTraceEnd; // Fence to wait for Trace End command buffer completion
|
||||
Pal::IFence* m_pFencePostambleEnd; // Fence to wait for Postamble End command buffer completion
|
||||
};
|
||||
|
||||
} // namespace GpuUtil
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,368 +1,368 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2017-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palAssert.h
|
||||
* @brief PAL utility collection assert macros.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palDbgPrint.h"
|
||||
#include "palUtil.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <intrin.h>
|
||||
/// OS-independent macro to force a break into the debugger.
|
||||
#define PAL_DEBUG_BREAK() [[unlikely]] __debugbreak()
|
||||
#else
|
||||
#include <signal.h>
|
||||
/// OS-independent macro to force a break into the debugger.
|
||||
#define PAL_DEBUG_BREAK() [[unlikely]] raise(SIGTRAP);
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
/// Macro to direct static code analysis to assume the specified expression will always be true.
|
||||
/// Purpose is to suppress warnings from MSVC's /analysis setting.
|
||||
/// Only pertains to static code analysis. Does not impact compile optimization. Not the same as C++23's [[assume]].
|
||||
# define PAL_ANALYSIS_ASSUME(_expr) __analysis_assume(_expr)
|
||||
#else
|
||||
/// This macro is only useful on MSVC builds. It has no meaning for other builds.
|
||||
# define PAL_ANALYSIS_ASSUME(_expr) ((void)0)
|
||||
#endif
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// A helper function to check the size-in-bits of a 'reserved' member in a bitfield.
|
||||
/// This is intended for use with static_asserts to ensure things don't go out-of-sync.
|
||||
///
|
||||
/// @param [in] expectedTotalBitWidth Number of bits expected in the whole type
|
||||
/// @param [in] expectedReservedBits Number of bits in the 'reserved' field
|
||||
///
|
||||
/// @return true if the bit lengths of the type T match the values in the args.
|
||||
/// true if the compiler lacks support to do this at compile time.
|
||||
///
|
||||
/// @note This may not work properly with old compilers, but this is meant for linting anyhow.
|
||||
template <typename T>
|
||||
constexpr bool CheckReservedBits(
|
||||
uint32 expectedTotalBitWidth,
|
||||
uint32 expectedReservedBits)
|
||||
{
|
||||
bool match = false;
|
||||
|
||||
// Fail if the whole size is different
|
||||
if (sizeof(T) * 8 == expectedTotalBitWidth)
|
||||
{
|
||||
// Get the width of the reserved field by detecting when it stops filling bits
|
||||
T sample = {};
|
||||
uint64 mask = 0;
|
||||
uint32 reservedBits = 0;
|
||||
do
|
||||
{
|
||||
sample = {};
|
||||
mask = (mask << 1) | 1;
|
||||
reservedBits++;
|
||||
sample.reserved = mask;
|
||||
} while ((sample.reserved == mask) && (reservedBits < sizeof(T) * 8));
|
||||
// when the loop terminates, it's one past the size of the field.
|
||||
match = (reservedBits - 1) == expectedReservedBits;
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
/// A helper function to check that a series of static numeric values are sequential.
|
||||
/// This is intended for use with static_asserts to ensure things don't go out-of-sync.
|
||||
///
|
||||
/// @param [in] args Array of numeric values to check
|
||||
/// @param [in] interval Expected interval between each (default 1, 4 is also common for field offsets)
|
||||
///
|
||||
/// @return true if all the values are sequential
|
||||
/// true if the compiler lacks support to do this at compile time.
|
||||
///
|
||||
/// @note This may not work properly with old compilers, but this is meant for linting anyhow.
|
||||
template <typename T, size_t N>
|
||||
constexpr bool CheckSequential(
|
||||
const T (&args)[N],
|
||||
T interval = 1)
|
||||
{
|
||||
bool isSequential = true;
|
||||
for (int i = 0; i < (N - 1); i++)
|
||||
{
|
||||
if ((args[i] + interval) != args[i + 1])
|
||||
{
|
||||
isSequential = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isSequential;
|
||||
}
|
||||
|
||||
#if (PAL_ENABLE_PRINTS_ASSERTS || PAL_ENABLE_LOGGING)
|
||||
|
||||
/// Specifies how severe an triggered assert (or alert) is.
|
||||
///
|
||||
/// Both asserts and alerts can print out a debug string and break into the debugger. Asserts are to be used to verify
|
||||
/// the known, assumed state of the program at any time. Alerts are to be used to notify the developer of a _possible_,
|
||||
/// but unexpected condition such as memory allocation failure, an OS call failure, or an application behavior that is
|
||||
/// known to be slow.
|
||||
enum AssertCategory : uint32
|
||||
{
|
||||
AssertCatAssert = 0,
|
||||
AssertCatAlert,
|
||||
AssertCatCount
|
||||
};
|
||||
|
||||
/// Enables/disables the specified assert category.
|
||||
///
|
||||
/// Probably controlled by a setting and set during initialization.
|
||||
///
|
||||
/// @param [in] category Assert category to enable/disable (asserts or alerts).
|
||||
/// @param [in] enable True to enable the specified assert category, false to disable it.
|
||||
extern void EnableAssertMode(
|
||||
AssertCategory category,
|
||||
bool enable);
|
||||
|
||||
/// Returns true if the specified assert category is enabled and false otherwise.
|
||||
///
|
||||
/// @param [in] category Assert category to check
|
||||
extern bool IsAssertCategoryEnabled(
|
||||
AssertCategory category);
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace Util
|
||||
|
||||
#if (PAL_ENABLE_PRINTS_ASSERTS || PAL_ENABLE_LOGGING)
|
||||
/// Prints an error message with the specified reason via the debug print system. A debug break will also be triggered
|
||||
/// if they're currently enabled for asserts.
|
||||
///
|
||||
/// @note This version of assert inlines an 'int 3' every time it is used so that each occurrence can be zapped
|
||||
/// independently. This macro cannot be used in assignment operations.
|
||||
#define PAL_TRIGGER_ASSERT(_pFormat, ...) [[unlikely]] \
|
||||
do { \
|
||||
PAL_DPERROR(_pFormat, ##__VA_ARGS__); \
|
||||
if (::Util::IsAssertCategoryEnabled(::Util::AssertCatAssert)) \
|
||||
{ \
|
||||
PAL_DEBUG_BREAK(); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
/// If the expression evaluates to false, then it calls the PAL_TRIGGER_ASSERT macro with an error message with the
|
||||
/// specified reason.
|
||||
///
|
||||
/// @note This assert should not be used in constant evaluated contexts (e.g., constexpr functions).
|
||||
//
|
||||
// This previously said:
|
||||
// if (_expr_eval == false) [[unlikely]]
|
||||
// {
|
||||
// PAL_TRIGGER_ASSERT(...);
|
||||
// }
|
||||
// However there is a bug in the initial gcc implementation of [[unlikely]] that means you cannot
|
||||
// attach it to a compound statement. So:
|
||||
// 1. we ignore PAL coding standards and don't use a compound statement;
|
||||
// 2. we don't use [[unlikely]] as the expansion of PAL_TRIGGER_ASSERT already has one.
|
||||
#define PAL_ASSERT_MSG(_expr, _pReasonFmt, ...) \
|
||||
do { \
|
||||
const bool _expr_eval = static_cast<bool>(_expr); \
|
||||
if (_expr_eval == false) \
|
||||
PAL_TRIGGER_ASSERT("Assertion failed: %s | Reason: " _pReasonFmt, #_expr, ##__VA_ARGS__); \
|
||||
PAL_ANALYSIS_ASSUME(_expr_eval); \
|
||||
} while (false)
|
||||
|
||||
#if !defined(__clang__) && !defined(_MSC_VER) && (__GNUC__ < 6)
|
||||
|
||||
// Function to circumvent gcc 5.x inability to use lambdas in unevaluated constant expression contexts.
|
||||
constexpr void PalTriggerAssertImpl(
|
||||
const char* pFormat,
|
||||
const char* pExpr,
|
||||
const char* pFile,
|
||||
int line,
|
||||
const char* pFunc)
|
||||
{
|
||||
// pExpr is always not nullptr, as it's supposed to be a preprocessor string, but it does convince gcc
|
||||
// to compile PalTriggerAssertImpl() as potentially constexpr
|
||||
pExpr != nullptr ?
|
||||
[&]
|
||||
{
|
||||
Util::DbgPrintf(
|
||||
Util::DbgPrintCatErrorMsg,
|
||||
Util::DbgPrintStyleDefault,
|
||||
pFormat,
|
||||
pExpr,
|
||||
pFile,
|
||||
line,
|
||||
pFunc);
|
||||
if (Util::IsAssertCategoryEnabled(Util::AssertCatAssert))
|
||||
{
|
||||
PAL_DEBUG_BREAK();
|
||||
}
|
||||
return 0;
|
||||
}()
|
||||
: 0;
|
||||
}
|
||||
|
||||
// gcc 5.4 implementation of PAL_CONSTEXPR_ASSERT_MSG that ignores the additional reason for the assertion
|
||||
//
|
||||
// This previously said:
|
||||
// if (_expr_eval == false) [[unlikely]]
|
||||
// {
|
||||
// PalTriggerAssertImpl(...);
|
||||
// }
|
||||
// However there is a bug in the initial gcc implementation of [[unlikely]] that means you cannot
|
||||
// attach it to a compound statement. So we ignore PAL coding standards and don't use a compound statement.
|
||||
#define PAL_CONSTEXPR_ASSERT_MSG(_expr, _pReasonFmt, ...) \
|
||||
do { \
|
||||
const bool _expr_eval = static_cast<bool>(_expr); \
|
||||
if (_expr_eval == false) [[unlikely]] \
|
||||
PalTriggerAssertImpl("Assertion failed: %s (%s:%d:%s)", #_expr, __FILE__, __LINE__, __func__); \
|
||||
PAL_ANALYSIS_ASSUME(_expr_eval); \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
/// If the expression evaluates to false, then it calls the PAL_TRIGGER_ASSERT macro with an error message with the
|
||||
/// specified reason.
|
||||
///
|
||||
/// @note This assert should be used in constant evaluated contexts (e.g., constexpr functions).
|
||||
/// @note This assert uses an immediately-invoked function expression in the form of an internal lambda to signal a
|
||||
/// failed assert. Since PAL_TRIGGER_ASSERT is not constexpr, an _expr that evaluates to false will fail to
|
||||
/// compile the function operator of the lambda.
|
||||
//
|
||||
// This previously said:
|
||||
// if (_expr_eval == false) [[unlikely]]
|
||||
// {
|
||||
// [&] { PAL_TRIGGER_ASSERT(...); }();
|
||||
// }
|
||||
// However there is a bug in the initial gcc implementation of [[unlikely]] that means you cannot
|
||||
// attach it to a compound statement. So we ignore PAL coding standards and don't use a compound statement.
|
||||
#define PAL_CONSTEXPR_ASSERT_MSG(_expr, _pReasonFmt, ...) \
|
||||
do { \
|
||||
const bool _expr_eval = static_cast<bool>(_expr); \
|
||||
if (_expr_eval == false) [[unlikely]] \
|
||||
[&] { PAL_TRIGGER_ASSERT("Assertion failed: %s | Reason: " _pReasonFmt, #_expr, ##__VA_ARGS__); }(); \
|
||||
PAL_ANALYSIS_ASSUME(_expr_eval); \
|
||||
} while (false)
|
||||
|
||||
#endif
|
||||
|
||||
/// Calls the PAL_ASSERT_MSG macro with a generic reason string
|
||||
#define PAL_ASSERT(_expr) PAL_ASSERT_MSG(_expr, "%s", "Unknown")
|
||||
|
||||
/// Calls the PAL_CONSTEXPR_ASSERT_MSG macro with a generic reason string
|
||||
#define PAL_CONSTEXPR_ASSERT(_expr) PAL_CONSTEXPR_ASSERT_MSG(_expr, "%s", "Unknown")
|
||||
|
||||
#if DEBUG
|
||||
/// Debug build only PAL assert, the typical usage is when make an assertion on a debug-only variables.
|
||||
/// The only difference than PAL assert is it's empty in release mode.
|
||||
#define PAL_DEBUG_BUILD_ONLY_ASSERT(_expr) \
|
||||
do { \
|
||||
PAL_ASSERT(_expr); \
|
||||
} while (false)
|
||||
#else
|
||||
#define PAL_DEBUG_BUILD_ONLY_ASSERT(_expr) ((void)0)
|
||||
#endif
|
||||
|
||||
/// If the expression evaluates to true, then a warning message with the specified reason will be printed via the
|
||||
/// debug print system. A debug break will also be triggered if they're currently enabled for alerts.
|
||||
///
|
||||
/// @note This is the opposite polarity of asserts. The assert macro _asserts_ that the specified condition is true.
|
||||
/// While the alert macro _alerts_ the developer if the specified condition is true.
|
||||
///
|
||||
/// This macro should be used in places where an assert is inappropriate because an error condition is _possible_, but
|
||||
/// not typically expected. For example, asserting that an OS call succeeded should be avoided since there cannot be an
|
||||
/// assumption that it will succeed. Nonetheless, a developer may want to be alerted immediately and dropped into the
|
||||
/// debugger when such a failure occurs.
|
||||
#define PAL_TRIGGER_ALERT(_pFormat, ...) [[unlikely]] \
|
||||
do { \
|
||||
PAL_DPWARN(_pFormat, ##__VA_ARGS__); \
|
||||
if (::Util::IsAssertCategoryEnabled(::Util::AssertCatAlert)) \
|
||||
{ \
|
||||
PAL_DEBUG_BREAK(); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
//
|
||||
// This previously said:
|
||||
// if (_expr) [[unlikely]]
|
||||
// {
|
||||
// PAL_TRIGGER_ASSERT(...);
|
||||
// }
|
||||
// However there is a bug in the initial gcc implementation of [[unlikely]] that means you cannot
|
||||
// attach it to a compound statement. So:
|
||||
// 1. we ignore PAL coding standards and don't use a compound statement;
|
||||
// 2. we don't use [[unlikely]] as the expansion of PAL_TRIGGER_ASSERT already has one.
|
||||
#define PAL_ALERT_MSG(_expr, _pReasonFmt, ...) \
|
||||
do { \
|
||||
if (_expr) \
|
||||
PAL_TRIGGER_ALERT("Alert triggered: %s | Reason: " _pReasonFmt, #_expr, ##__VA_ARGS__); \
|
||||
} while (false)
|
||||
|
||||
/// Calls the PAL_ALERT_MSG macro with a generic reason string
|
||||
#define PAL_ALERT(_expr) PAL_ALERT_MSG(_expr, "%s", "Unknown")
|
||||
|
||||
/// Convenience macro that asserts if something has never been tested.
|
||||
#define PAL_NOT_TESTED_MSG(_pReasonFmt, ...) PAL_TRIGGER_ASSERT("Code Not Tested! | Reason: " _pReasonFmt, ##__VA_ARGS__)
|
||||
#define PAL_NOT_TESTED() PAL_NOT_TESTED_MSG("%s", "Unknown")
|
||||
|
||||
/// Convenience macro that asserts if something has not been implemented.
|
||||
#define PAL_NOT_IMPLEMENTED_MSG(_pReasonFmt, ...) PAL_TRIGGER_ASSERT("Not Implemented! | Reason: " _pReasonFmt, ##__VA_ARGS__)
|
||||
#define PAL_NOT_IMPLEMENTED() PAL_NOT_IMPLEMENTED_MSG("%s", "Unknown")
|
||||
|
||||
/// Convenience macro that asserts if an area of code that shouldn't be executed is reached.
|
||||
#define PAL_NEVER_CALLED_MSG(_pReasonFmt, ...) PAL_TRIGGER_ASSERT("Code should never be called! | Reason: " _pReasonFmt, ##__VA_ARGS__)
|
||||
#define PAL_NEVER_CALLED() PAL_NEVER_CALLED_MSG("%s", "Unknown")
|
||||
|
||||
/// Convenience macro that always asserts. Expect this to be used instead of PAL_ASSERT(false).
|
||||
#define PAL_ASSERT_ALWAYS_MSG(_pReasonFmt, ...) PAL_TRIGGER_ASSERT("Unconditional Assert | Reason: " _pReasonFmt, ##__VA_ARGS__)
|
||||
#define PAL_ASSERT_ALWAYS() PAL_ASSERT_ALWAYS_MSG("%s", "Unknown")
|
||||
|
||||
/// Convenience macro that always alerts. Expect this to be used instead of PAL_ALERT(true).
|
||||
#define PAL_ALERT_ALWAYS_MSG(_pReasonFmt, ...) PAL_TRIGGER_ALERT("Unconditional Alert | Reason: " _pReasonFmt, ##__VA_ARGS__)
|
||||
#define PAL_ALERT_ALWAYS() PAL_ALERT_ALWAYS_MSG("%s", "Unknown")
|
||||
|
||||
#else
|
||||
|
||||
#define PAL_ASSERT(_expr) PAL_ANALYSIS_ASSUME(_expr)
|
||||
#define PAL_CONSTEXPR_ASSERT(_expr) PAL_ANALYSIS_ASSUME(_expr)
|
||||
#define PAL_ASSERT_MSG(_expr, ...) PAL_ANALYSIS_ASSUME(_expr)
|
||||
#define PAL_CONSTEXPR_ASSERT_MSG(_expr, ...) PAL_ANALYSIS_ASSUME(_expr)
|
||||
#define PAL_DEBUG_BUILD_ONLY_ASSERT(_expr) ((void)0)
|
||||
#define PAL_ALERT(_expr) ((void)0)
|
||||
#define PAL_ALERT_MSG(_expr, ...) ((void)0)
|
||||
#define PAL_NOT_TESTED() [[unlikely]] ((void)0)
|
||||
#define PAL_NOT_TESTED_MSG(...) [[unlikely]] ((void)0)
|
||||
#define PAL_NOT_IMPLEMENTED() [[unlikely]] ((void)0)
|
||||
#define PAL_NOT_IMPLEMENTED_MSG(...) [[unlikely]] ((void)0)
|
||||
#define PAL_NEVER_CALLED() [[unlikely]] ((void)0)
|
||||
#define PAL_NEVER_CALLED_MSG(...) [[unlikely]] ((void)0)
|
||||
#define PAL_ASSERT_ALWAYS() [[unlikely]] ((void)0)
|
||||
#define PAL_ASSERT_ALWAYS_MSG(...) [[unlikely]] ((void)0)
|
||||
#define PAL_ALERT_ALWAYS() [[unlikely]] ((void)0)
|
||||
#define PAL_ALERT_ALWAYS_MSG(...) [[unlikely]] ((void)0)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2017-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palAssert.h
|
||||
* @brief PAL utility collection assert macros.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palDbgPrint.h"
|
||||
#include "palUtil.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <intrin.h>
|
||||
/// OS-independent macro to force a break into the debugger.
|
||||
#define PAL_DEBUG_BREAK() [[unlikely]] __debugbreak()
|
||||
#else
|
||||
#include <signal.h>
|
||||
/// OS-independent macro to force a break into the debugger.
|
||||
#define PAL_DEBUG_BREAK() [[unlikely]] raise(SIGTRAP);
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
/// Macro to direct static code analysis to assume the specified expression will always be true.
|
||||
/// Purpose is to suppress warnings from MSVC's /analysis setting.
|
||||
/// Only pertains to static code analysis. Does not impact compile optimization. Not the same as C++23's [[assume]].
|
||||
# define PAL_ANALYSIS_ASSUME(_expr) __analysis_assume(_expr)
|
||||
#else
|
||||
/// This macro is only useful on MSVC builds. It has no meaning for other builds.
|
||||
# define PAL_ANALYSIS_ASSUME(_expr) ((void)0)
|
||||
#endif
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// A helper function to check the size-in-bits of a 'reserved' member in a bitfield.
|
||||
/// This is intended for use with static_asserts to ensure things don't go out-of-sync.
|
||||
///
|
||||
/// @param [in] expectedTotalBitWidth Number of bits expected in the whole type
|
||||
/// @param [in] expectedReservedBits Number of bits in the 'reserved' field
|
||||
///
|
||||
/// @return true if the bit lengths of the type T match the values in the args.
|
||||
/// true if the compiler lacks support to do this at compile time.
|
||||
///
|
||||
/// @note This may not work properly with old compilers, but this is meant for linting anyhow.
|
||||
template <typename T>
|
||||
constexpr bool CheckReservedBits(
|
||||
uint32 expectedTotalBitWidth,
|
||||
uint32 expectedReservedBits)
|
||||
{
|
||||
bool match = false;
|
||||
|
||||
// Fail if the whole size is different
|
||||
if (sizeof(T) * 8 == expectedTotalBitWidth)
|
||||
{
|
||||
// Get the width of the reserved field by detecting when it stops filling bits
|
||||
T sample = {};
|
||||
uint64 mask = 0;
|
||||
uint32 reservedBits = 0;
|
||||
do
|
||||
{
|
||||
sample = {};
|
||||
mask = (mask << 1) | 1;
|
||||
reservedBits++;
|
||||
sample.reserved = mask;
|
||||
} while ((sample.reserved == mask) && (reservedBits < sizeof(T) * 8));
|
||||
// when the loop terminates, it's one past the size of the field.
|
||||
match = (reservedBits - 1) == expectedReservedBits;
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
/// A helper function to check that a series of static numeric values are sequential.
|
||||
/// This is intended for use with static_asserts to ensure things don't go out-of-sync.
|
||||
///
|
||||
/// @param [in] args Array of numeric values to check
|
||||
/// @param [in] interval Expected interval between each (default 1, 4 is also common for field offsets)
|
||||
///
|
||||
/// @return true if all the values are sequential
|
||||
/// true if the compiler lacks support to do this at compile time.
|
||||
///
|
||||
/// @note This may not work properly with old compilers, but this is meant for linting anyhow.
|
||||
template <typename T, size_t N>
|
||||
constexpr bool CheckSequential(
|
||||
const T (&args)[N],
|
||||
T interval = 1)
|
||||
{
|
||||
bool isSequential = true;
|
||||
for (int i = 0; i < (N - 1); i++)
|
||||
{
|
||||
if ((args[i] + interval) != args[i + 1])
|
||||
{
|
||||
isSequential = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isSequential;
|
||||
}
|
||||
|
||||
#if (PAL_ENABLE_PRINTS_ASSERTS || PAL_ENABLE_LOGGING)
|
||||
|
||||
/// Specifies how severe an triggered assert (or alert) is.
|
||||
///
|
||||
/// Both asserts and alerts can print out a debug string and break into the debugger. Asserts are to be used to verify
|
||||
/// the known, assumed state of the program at any time. Alerts are to be used to notify the developer of a _possible_,
|
||||
/// but unexpected condition such as memory allocation failure, an OS call failure, or an application behavior that is
|
||||
/// known to be slow.
|
||||
enum AssertCategory : uint32
|
||||
{
|
||||
AssertCatAssert = 0,
|
||||
AssertCatAlert,
|
||||
AssertCatCount
|
||||
};
|
||||
|
||||
/// Enables/disables the specified assert category.
|
||||
///
|
||||
/// Probably controlled by a setting and set during initialization.
|
||||
///
|
||||
/// @param [in] category Assert category to enable/disable (asserts or alerts).
|
||||
/// @param [in] enable True to enable the specified assert category, false to disable it.
|
||||
extern void EnableAssertMode(
|
||||
AssertCategory category,
|
||||
bool enable);
|
||||
|
||||
/// Returns true if the specified assert category is enabled and false otherwise.
|
||||
///
|
||||
/// @param [in] category Assert category to check
|
||||
extern bool IsAssertCategoryEnabled(
|
||||
AssertCategory category);
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace Util
|
||||
|
||||
#if (PAL_ENABLE_PRINTS_ASSERTS || PAL_ENABLE_LOGGING)
|
||||
/// Prints an error message with the specified reason via the debug print system. A debug break will also be triggered
|
||||
/// if they're currently enabled for asserts.
|
||||
///
|
||||
/// @note This version of assert inlines an 'int 3' every time it is used so that each occurrence can be zapped
|
||||
/// independently. This macro cannot be used in assignment operations.
|
||||
#define PAL_TRIGGER_ASSERT(_pFormat, ...) [[unlikely]] \
|
||||
do { \
|
||||
PAL_DPERROR(_pFormat, ##__VA_ARGS__); \
|
||||
if (::Util::IsAssertCategoryEnabled(::Util::AssertCatAssert)) \
|
||||
{ \
|
||||
PAL_DEBUG_BREAK(); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
/// If the expression evaluates to false, then it calls the PAL_TRIGGER_ASSERT macro with an error message with the
|
||||
/// specified reason.
|
||||
///
|
||||
/// @note This assert should not be used in constant evaluated contexts (e.g., constexpr functions).
|
||||
//
|
||||
// This previously said:
|
||||
// if (_expr_eval == false) [[unlikely]]
|
||||
// {
|
||||
// PAL_TRIGGER_ASSERT(...);
|
||||
// }
|
||||
// However there is a bug in the initial gcc implementation of [[unlikely]] that means you cannot
|
||||
// attach it to a compound statement. So:
|
||||
// 1. we ignore PAL coding standards and don't use a compound statement;
|
||||
// 2. we don't use [[unlikely]] as the expansion of PAL_TRIGGER_ASSERT already has one.
|
||||
#define PAL_ASSERT_MSG(_expr, _pReasonFmt, ...) \
|
||||
do { \
|
||||
const bool _expr_eval = static_cast<bool>(_expr); \
|
||||
if (_expr_eval == false) \
|
||||
PAL_TRIGGER_ASSERT("Assertion failed: %s | Reason: " _pReasonFmt, #_expr, ##__VA_ARGS__); \
|
||||
PAL_ANALYSIS_ASSUME(_expr_eval); \
|
||||
} while (false)
|
||||
|
||||
#if !defined(__clang__) && !defined(_MSC_VER) && (__GNUC__ < 6)
|
||||
|
||||
// Function to circumvent gcc 5.x inability to use lambdas in unevaluated constant expression contexts.
|
||||
constexpr void PalTriggerAssertImpl(
|
||||
const char* pFormat,
|
||||
const char* pExpr,
|
||||
const char* pFile,
|
||||
int line,
|
||||
const char* pFunc)
|
||||
{
|
||||
// pExpr is always not nullptr, as it's supposed to be a preprocessor string, but it does convince gcc
|
||||
// to compile PalTriggerAssertImpl() as potentially constexpr
|
||||
pExpr != nullptr ?
|
||||
[&]
|
||||
{
|
||||
Util::DbgPrintf(
|
||||
Util::DbgPrintCatErrorMsg,
|
||||
Util::DbgPrintStyleDefault,
|
||||
pFormat,
|
||||
pExpr,
|
||||
pFile,
|
||||
line,
|
||||
pFunc);
|
||||
if (Util::IsAssertCategoryEnabled(Util::AssertCatAssert))
|
||||
{
|
||||
PAL_DEBUG_BREAK();
|
||||
}
|
||||
return 0;
|
||||
}()
|
||||
: 0;
|
||||
}
|
||||
|
||||
// gcc 5.4 implementation of PAL_CONSTEXPR_ASSERT_MSG that ignores the additional reason for the assertion
|
||||
//
|
||||
// This previously said:
|
||||
// if (_expr_eval == false) [[unlikely]]
|
||||
// {
|
||||
// PalTriggerAssertImpl(...);
|
||||
// }
|
||||
// However there is a bug in the initial gcc implementation of [[unlikely]] that means you cannot
|
||||
// attach it to a compound statement. So we ignore PAL coding standards and don't use a compound statement.
|
||||
#define PAL_CONSTEXPR_ASSERT_MSG(_expr, _pReasonFmt, ...) \
|
||||
do { \
|
||||
const bool _expr_eval = static_cast<bool>(_expr); \
|
||||
if (_expr_eval == false) [[unlikely]] \
|
||||
PalTriggerAssertImpl("Assertion failed: %s (%s:%d:%s)", #_expr, __FILE__, __LINE__, __func__); \
|
||||
PAL_ANALYSIS_ASSUME(_expr_eval); \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
/// If the expression evaluates to false, then it calls the PAL_TRIGGER_ASSERT macro with an error message with the
|
||||
/// specified reason.
|
||||
///
|
||||
/// @note This assert should be used in constant evaluated contexts (e.g., constexpr functions).
|
||||
/// @note This assert uses an immediately-invoked function expression in the form of an internal lambda to signal a
|
||||
/// failed assert. Since PAL_TRIGGER_ASSERT is not constexpr, an _expr that evaluates to false will fail to
|
||||
/// compile the function operator of the lambda.
|
||||
//
|
||||
// This previously said:
|
||||
// if (_expr_eval == false) [[unlikely]]
|
||||
// {
|
||||
// [&] { PAL_TRIGGER_ASSERT(...); }();
|
||||
// }
|
||||
// However there is a bug in the initial gcc implementation of [[unlikely]] that means you cannot
|
||||
// attach it to a compound statement. So we ignore PAL coding standards and don't use a compound statement.
|
||||
#define PAL_CONSTEXPR_ASSERT_MSG(_expr, _pReasonFmt, ...) \
|
||||
do { \
|
||||
const bool _expr_eval = static_cast<bool>(_expr); \
|
||||
if (_expr_eval == false) [[unlikely]] \
|
||||
[&] { PAL_TRIGGER_ASSERT("Assertion failed: %s | Reason: " _pReasonFmt, #_expr, ##__VA_ARGS__); }(); \
|
||||
PAL_ANALYSIS_ASSUME(_expr_eval); \
|
||||
} while (false)
|
||||
|
||||
#endif
|
||||
|
||||
/// Calls the PAL_ASSERT_MSG macro with a generic reason string
|
||||
#define PAL_ASSERT(_expr) PAL_ASSERT_MSG(_expr, "%s", "Unknown")
|
||||
|
||||
/// Calls the PAL_CONSTEXPR_ASSERT_MSG macro with a generic reason string
|
||||
#define PAL_CONSTEXPR_ASSERT(_expr) PAL_CONSTEXPR_ASSERT_MSG(_expr, "%s", "Unknown")
|
||||
|
||||
#if DEBUG
|
||||
/// Debug build only PAL assert, the typical usage is when make an assertion on a debug-only variables.
|
||||
/// The only difference than PAL assert is it's empty in release mode.
|
||||
#define PAL_DEBUG_BUILD_ONLY_ASSERT(_expr) \
|
||||
do { \
|
||||
PAL_ASSERT(_expr); \
|
||||
} while (false)
|
||||
#else
|
||||
#define PAL_DEBUG_BUILD_ONLY_ASSERT(_expr) ((void)0)
|
||||
#endif
|
||||
|
||||
/// If the expression evaluates to true, then a warning message with the specified reason will be printed via the
|
||||
/// debug print system. A debug break will also be triggered if they're currently enabled for alerts.
|
||||
///
|
||||
/// @note This is the opposite polarity of asserts. The assert macro _asserts_ that the specified condition is true.
|
||||
/// While the alert macro _alerts_ the developer if the specified condition is true.
|
||||
///
|
||||
/// This macro should be used in places where an assert is inappropriate because an error condition is _possible_, but
|
||||
/// not typically expected. For example, asserting that an OS call succeeded should be avoided since there cannot be an
|
||||
/// assumption that it will succeed. Nonetheless, a developer may want to be alerted immediately and dropped into the
|
||||
/// debugger when such a failure occurs.
|
||||
#define PAL_TRIGGER_ALERT(_pFormat, ...) [[unlikely]] \
|
||||
do { \
|
||||
PAL_DPWARN(_pFormat, ##__VA_ARGS__); \
|
||||
if (::Util::IsAssertCategoryEnabled(::Util::AssertCatAlert)) \
|
||||
{ \
|
||||
PAL_DEBUG_BREAK(); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
//
|
||||
// This previously said:
|
||||
// if (_expr) [[unlikely]]
|
||||
// {
|
||||
// PAL_TRIGGER_ASSERT(...);
|
||||
// }
|
||||
// However there is a bug in the initial gcc implementation of [[unlikely]] that means you cannot
|
||||
// attach it to a compound statement. So:
|
||||
// 1. we ignore PAL coding standards and don't use a compound statement;
|
||||
// 2. we don't use [[unlikely]] as the expansion of PAL_TRIGGER_ASSERT already has one.
|
||||
#define PAL_ALERT_MSG(_expr, _pReasonFmt, ...) \
|
||||
do { \
|
||||
if (_expr) \
|
||||
PAL_TRIGGER_ALERT("Alert triggered: %s | Reason: " _pReasonFmt, #_expr, ##__VA_ARGS__); \
|
||||
} while (false)
|
||||
|
||||
/// Calls the PAL_ALERT_MSG macro with a generic reason string
|
||||
#define PAL_ALERT(_expr) PAL_ALERT_MSG(_expr, "%s", "Unknown")
|
||||
|
||||
/// Convenience macro that asserts if something has never been tested.
|
||||
#define PAL_NOT_TESTED_MSG(_pReasonFmt, ...) PAL_TRIGGER_ASSERT("Code Not Tested! | Reason: " _pReasonFmt, ##__VA_ARGS__)
|
||||
#define PAL_NOT_TESTED() PAL_NOT_TESTED_MSG("%s", "Unknown")
|
||||
|
||||
/// Convenience macro that asserts if something has not been implemented.
|
||||
#define PAL_NOT_IMPLEMENTED_MSG(_pReasonFmt, ...) PAL_TRIGGER_ASSERT("Not Implemented! | Reason: " _pReasonFmt, ##__VA_ARGS__)
|
||||
#define PAL_NOT_IMPLEMENTED() PAL_NOT_IMPLEMENTED_MSG("%s", "Unknown")
|
||||
|
||||
/// Convenience macro that asserts if an area of code that shouldn't be executed is reached.
|
||||
#define PAL_NEVER_CALLED_MSG(_pReasonFmt, ...) PAL_TRIGGER_ASSERT("Code should never be called! | Reason: " _pReasonFmt, ##__VA_ARGS__)
|
||||
#define PAL_NEVER_CALLED() PAL_NEVER_CALLED_MSG("%s", "Unknown")
|
||||
|
||||
/// Convenience macro that always asserts. Expect this to be used instead of PAL_ASSERT(false).
|
||||
#define PAL_ASSERT_ALWAYS_MSG(_pReasonFmt, ...) PAL_TRIGGER_ASSERT("Unconditional Assert | Reason: " _pReasonFmt, ##__VA_ARGS__)
|
||||
#define PAL_ASSERT_ALWAYS() PAL_ASSERT_ALWAYS_MSG("%s", "Unknown")
|
||||
|
||||
/// Convenience macro that always alerts. Expect this to be used instead of PAL_ALERT(true).
|
||||
#define PAL_ALERT_ALWAYS_MSG(_pReasonFmt, ...) PAL_TRIGGER_ALERT("Unconditional Alert | Reason: " _pReasonFmt, ##__VA_ARGS__)
|
||||
#define PAL_ALERT_ALWAYS() PAL_ALERT_ALWAYS_MSG("%s", "Unknown")
|
||||
|
||||
#else
|
||||
|
||||
#define PAL_ASSERT(_expr) PAL_ANALYSIS_ASSUME(_expr)
|
||||
#define PAL_CONSTEXPR_ASSERT(_expr) PAL_ANALYSIS_ASSUME(_expr)
|
||||
#define PAL_ASSERT_MSG(_expr, ...) PAL_ANALYSIS_ASSUME(_expr)
|
||||
#define PAL_CONSTEXPR_ASSERT_MSG(_expr, ...) PAL_ANALYSIS_ASSUME(_expr)
|
||||
#define PAL_DEBUG_BUILD_ONLY_ASSERT(_expr) ((void)0)
|
||||
#define PAL_ALERT(_expr) ((void)0)
|
||||
#define PAL_ALERT_MSG(_expr, ...) ((void)0)
|
||||
#define PAL_NOT_TESTED() [[unlikely]] ((void)0)
|
||||
#define PAL_NOT_TESTED_MSG(...) [[unlikely]] ((void)0)
|
||||
#define PAL_NOT_IMPLEMENTED() [[unlikely]] ((void)0)
|
||||
#define PAL_NOT_IMPLEMENTED_MSG(...) [[unlikely]] ((void)0)
|
||||
#define PAL_NEVER_CALLED() [[unlikely]] ((void)0)
|
||||
#define PAL_NEVER_CALLED_MSG(...) [[unlikely]] ((void)0)
|
||||
#define PAL_ASSERT_ALWAYS() [[unlikely]] ((void)0)
|
||||
#define PAL_ASSERT_ALWAYS_MSG(...) [[unlikely]] ((void)0)
|
||||
#define PAL_ALERT_ALWAYS() [[unlikely]] ((void)0)
|
||||
#define PAL_ALERT_ALWAYS_MSG(...) [[unlikely]] ((void)0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,212 +1,212 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palAutoBuffer.h
|
||||
* @brief PAL utility collection AutoBuffer class definition.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palSpan.h"
|
||||
#include "palSysMemory.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Safe version of C99's variable-length arrays.
|
||||
*
|
||||
* The general idea is that this class encapsulates a variable-length array where we expect the size required to not
|
||||
* exceed the 'defaultCapacity' template parameter most of the time. In those "normal" cases, this buffer will
|
||||
* reference a static array of size 'defaultCapacity', but if the constructor's parameter exceeds defaultCapacity, then
|
||||
* a dynamic array will be allocated from the heap to satisfy the space requirements. The destructor will clean-up any
|
||||
* dynamic allocation made by the constructor.
|
||||
*
|
||||
* This class violates several PAL coding conventions, but for good reason:
|
||||
*
|
||||
* - We have overloaded the [] (array-element-accessor) operator to make using this class just like using a regular
|
||||
* array, which it semantically represents.
|
||||
* - In order to return array elements by-reference instead of by-value, we need to use C++ references in the
|
||||
* overloaded operators because this is required by C++.
|
||||
*
|
||||
* This class __does not__ clear the contents of the static or dynamic arrays, for performance reasons. If a client
|
||||
* needs the buffer to be cleared, it must do the memset itself. (However, if 'Item' is a class type rather than
|
||||
* plain-old-data, the default c'tor will be invoked.)
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename Item, size_t defaultCapacity, typename Allocator>
|
||||
class AutoBuffer
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
///
|
||||
/// The object is initialized to use the static array of items if the required capacity is less than or equal to the
|
||||
/// default capacity. Otherwise, a larger array is allocated on the heap.
|
||||
///
|
||||
/// @param [in] requiredCapacity Number of items actually required (unknown until runtime).
|
||||
/// @param [in] pAllocator The allocator that will allocate memory if required.
|
||||
AutoBuffer(
|
||||
size_t requiredCapacity,
|
||||
Allocator*const pAllocator)
|
||||
:
|
||||
m_capacity(requiredCapacity),
|
||||
m_pBuffer(reinterpret_cast<Item*>(m_localBuffer)),
|
||||
m_pAllocator(pAllocator)
|
||||
{
|
||||
if (requiredCapacity > defaultCapacity)
|
||||
{
|
||||
// Create dynamically allocated array, by allocating memory and constructing its objects.
|
||||
// On failure, to avoid subtle bugs from misuse, AutoBuffer will be in a zombie state with zero capacity.
|
||||
m_pBuffer = PAL_NEW_ARRAY(Item, requiredCapacity, pAllocator, AllocInternalTemp);
|
||||
if (m_pBuffer == nullptr)
|
||||
{
|
||||
m_capacity = 0;
|
||||
}
|
||||
}
|
||||
else if (!std::is_trivial<Item>::value)
|
||||
{
|
||||
// Explicitly construct all objects of non-trivial type in the local buffer.
|
||||
for (uint32 idx = 0; idx < m_capacity; ++idx)
|
||||
{
|
||||
PAL_PLACEMENT_NEW(m_pBuffer + idx) Item();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
///
|
||||
/// Cleans up the dynamically allocated buffer if we allocated one.
|
||||
~AutoBuffer()
|
||||
{
|
||||
if (m_pBuffer != reinterpret_cast<Item*>(m_localBuffer))
|
||||
{
|
||||
// Destory dynamically allocated array, by destroying its objects and freeing memory.
|
||||
PAL_SAFE_DELETE_ARRAY(m_pBuffer, m_pAllocator);
|
||||
}
|
||||
else if (!std::is_trivial<Item>::value)
|
||||
{
|
||||
// Explicitly destroy all objects of non-trivial type from the local buffer.
|
||||
for (uint32 idx = 0; idx < m_capacity; ++idx)
|
||||
{
|
||||
m_pBuffer[idx].~Item();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Getter for the capacity of the buffer.
|
||||
///
|
||||
/// Clients can use this function to determine if the constuctor's allocation succeeded.
|
||||
///
|
||||
/// @returns Size of the array in bytes. Should match the requiredCapacity parameter passed to the constructor
|
||||
/// unless a dynamic memory allocation failed.
|
||||
constexpr size_t Capacity() const noexcept { return m_capacity; }
|
||||
|
||||
/// Getter for the size of this buffer, in bytes.
|
||||
constexpr size_t SizeBytes() const noexcept { return (sizeof(Item) * m_capacity); }
|
||||
|
||||
/// Accessor for the nth element of this buffer.
|
||||
const Item& operator[](size_t n) const
|
||||
{
|
||||
PAL_ASSERT(n < m_capacity);
|
||||
return m_pBuffer[n];
|
||||
}
|
||||
|
||||
/// Non-const accessor for the nth element of this buffer.
|
||||
Item& operator[](size_t n)
|
||||
{
|
||||
PAL_ASSERT(n < m_capacity);
|
||||
return m_pBuffer[n];
|
||||
}
|
||||
|
||||
///@{
|
||||
/// Implicitly gets the current contents of the buffer as a Span.
|
||||
///
|
||||
/// @returns The contents of the buffer as a Span; same as Span<T>(Data(), Size()).
|
||||
operator Span<Item>() { return Span<Item>(Data(), Capacity()); }
|
||||
operator Span<const Item>() const { return Span<const Item>(Data(), Capacity()); }
|
||||
///@}
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage.
|
||||
/// The returned pointer defines always valid range [Data(), Data() + Capacity()).
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage for read & write access.
|
||||
/// The returned pointer contains address of the first element.
|
||||
constexpr Item* Data() noexcept { return m_pBuffer; }
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage.
|
||||
/// The returned pointer defines always valid range [Data(), Data() + Capacity()),
|
||||
/// even if the container is empty (Data() is not dereferenceable in that case).
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage for read only access.
|
||||
/// The returned pointer contains address of the first element.
|
||||
constexpr const Item* Data() const noexcept { return m_pBuffer; }
|
||||
|
||||
///@{
|
||||
/// @internal Satisfies concept `range_expression`, using Item* as `iterator` and 64-bit size and difference types
|
||||
///
|
||||
/// @note - These are a convenience intended to be used by c++ language features such as range-based-for-loops.
|
||||
using value_type = Item;
|
||||
using reference = Item&;
|
||||
using const_reference = const Item&;
|
||||
using iterator = Item*;
|
||||
using const_iterator = const Item*;
|
||||
using difference_type = ptrdiff_t;
|
||||
using size_type = size_t;
|
||||
|
||||
constexpr iterator begin() noexcept { return Data(); }
|
||||
constexpr iterator end() noexcept { return Data() + Capacity(); }
|
||||
constexpr const_iterator begin() const noexcept { return Data(); }
|
||||
constexpr const_iterator end() const noexcept { return Data() + Capacity(); }
|
||||
constexpr const_iterator cbegin() const noexcept { return Data(); }
|
||||
constexpr const_iterator cend() const noexcept { return Data() + Capacity(); }
|
||||
[[nodiscard]] constexpr bool empty() const noexcept { return Capacity() == 0; }
|
||||
constexpr size_type size() const noexcept { return Capacity(); }
|
||||
///@}
|
||||
|
||||
private:
|
||||
// This is a POD-type that exactly fits one Item value.
|
||||
using ValueStorage = typename std::aligned_storage<sizeof(Item), alignof(Item)>::type;
|
||||
|
||||
// Capacity of this buffer (in Items).
|
||||
size_t m_capacity;
|
||||
|
||||
// Buffer pointer this object uses to access the buffer's elements: if the required capacity exceeds the default
|
||||
// capacity, this points to a dynamic array of Items. Otherwise, this points to m_localBuffer.
|
||||
Item* m_pBuffer;
|
||||
|
||||
// Static array providing storage for Items which we expect most objects of this type to end up using.
|
||||
ValueStorage m_localBuffer[defaultCapacity];
|
||||
|
||||
// Allocator for this AutoBuffer.
|
||||
Allocator*const m_pAllocator;
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(AutoBuffer);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(AutoBuffer);
|
||||
};
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palAutoBuffer.h
|
||||
* @brief PAL utility collection AutoBuffer class definition.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palSpan.h"
|
||||
#include "palSysMemory.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Safe version of C99's variable-length arrays.
|
||||
*
|
||||
* The general idea is that this class encapsulates a variable-length array where we expect the size required to not
|
||||
* exceed the 'defaultCapacity' template parameter most of the time. In those "normal" cases, this buffer will
|
||||
* reference a static array of size 'defaultCapacity', but if the constructor's parameter exceeds defaultCapacity, then
|
||||
* a dynamic array will be allocated from the heap to satisfy the space requirements. The destructor will clean-up any
|
||||
* dynamic allocation made by the constructor.
|
||||
*
|
||||
* This class violates several PAL coding conventions, but for good reason:
|
||||
*
|
||||
* - We have overloaded the [] (array-element-accessor) operator to make using this class just like using a regular
|
||||
* array, which it semantically represents.
|
||||
* - In order to return array elements by-reference instead of by-value, we need to use C++ references in the
|
||||
* overloaded operators because this is required by C++.
|
||||
*
|
||||
* This class __does not__ clear the contents of the static or dynamic arrays, for performance reasons. If a client
|
||||
* needs the buffer to be cleared, it must do the memset itself. (However, if 'Item' is a class type rather than
|
||||
* plain-old-data, the default c'tor will be invoked.)
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename Item, size_t defaultCapacity, typename Allocator>
|
||||
class AutoBuffer
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
///
|
||||
/// The object is initialized to use the static array of items if the required capacity is less than or equal to the
|
||||
/// default capacity. Otherwise, a larger array is allocated on the heap.
|
||||
///
|
||||
/// @param [in] requiredCapacity Number of items actually required (unknown until runtime).
|
||||
/// @param [in] pAllocator The allocator that will allocate memory if required.
|
||||
AutoBuffer(
|
||||
size_t requiredCapacity,
|
||||
Allocator*const pAllocator)
|
||||
:
|
||||
m_capacity(requiredCapacity),
|
||||
m_pBuffer(reinterpret_cast<Item*>(m_localBuffer)),
|
||||
m_pAllocator(pAllocator)
|
||||
{
|
||||
if (requiredCapacity > defaultCapacity)
|
||||
{
|
||||
// Create dynamically allocated array, by allocating memory and constructing its objects.
|
||||
// On failure, to avoid subtle bugs from misuse, AutoBuffer will be in a zombie state with zero capacity.
|
||||
m_pBuffer = PAL_NEW_ARRAY(Item, requiredCapacity, pAllocator, AllocInternalTemp);
|
||||
if (m_pBuffer == nullptr)
|
||||
{
|
||||
m_capacity = 0;
|
||||
}
|
||||
}
|
||||
else if (!std::is_trivial<Item>::value)
|
||||
{
|
||||
// Explicitly construct all objects of non-trivial type in the local buffer.
|
||||
for (uint32 idx = 0; idx < m_capacity; ++idx)
|
||||
{
|
||||
PAL_PLACEMENT_NEW(m_pBuffer + idx) Item();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
///
|
||||
/// Cleans up the dynamically allocated buffer if we allocated one.
|
||||
~AutoBuffer()
|
||||
{
|
||||
if (m_pBuffer != reinterpret_cast<Item*>(m_localBuffer))
|
||||
{
|
||||
// Destory dynamically allocated array, by destroying its objects and freeing memory.
|
||||
PAL_SAFE_DELETE_ARRAY(m_pBuffer, m_pAllocator);
|
||||
}
|
||||
else if (!std::is_trivial<Item>::value)
|
||||
{
|
||||
// Explicitly destroy all objects of non-trivial type from the local buffer.
|
||||
for (uint32 idx = 0; idx < m_capacity; ++idx)
|
||||
{
|
||||
m_pBuffer[idx].~Item();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Getter for the capacity of the buffer.
|
||||
///
|
||||
/// Clients can use this function to determine if the constuctor's allocation succeeded.
|
||||
///
|
||||
/// @returns Size of the array in bytes. Should match the requiredCapacity parameter passed to the constructor
|
||||
/// unless a dynamic memory allocation failed.
|
||||
constexpr size_t Capacity() const noexcept { return m_capacity; }
|
||||
|
||||
/// Getter for the size of this buffer, in bytes.
|
||||
constexpr size_t SizeBytes() const noexcept { return (sizeof(Item) * m_capacity); }
|
||||
|
||||
/// Accessor for the nth element of this buffer.
|
||||
const Item& operator[](size_t n) const
|
||||
{
|
||||
PAL_ASSERT(n < m_capacity);
|
||||
return m_pBuffer[n];
|
||||
}
|
||||
|
||||
/// Non-const accessor for the nth element of this buffer.
|
||||
Item& operator[](size_t n)
|
||||
{
|
||||
PAL_ASSERT(n < m_capacity);
|
||||
return m_pBuffer[n];
|
||||
}
|
||||
|
||||
///@{
|
||||
/// Implicitly gets the current contents of the buffer as a Span.
|
||||
///
|
||||
/// @returns The contents of the buffer as a Span; same as Span<T>(Data(), Size()).
|
||||
operator Span<Item>() { return Span<Item>(Data(), Capacity()); }
|
||||
operator Span<const Item>() const { return Span<const Item>(Data(), Capacity()); }
|
||||
///@}
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage.
|
||||
/// The returned pointer defines always valid range [Data(), Data() + Capacity()).
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage for read & write access.
|
||||
/// The returned pointer contains address of the first element.
|
||||
constexpr Item* Data() noexcept { return m_pBuffer; }
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage.
|
||||
/// The returned pointer defines always valid range [Data(), Data() + Capacity()),
|
||||
/// even if the container is empty (Data() is not dereferenceable in that case).
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage for read only access.
|
||||
/// The returned pointer contains address of the first element.
|
||||
constexpr const Item* Data() const noexcept { return m_pBuffer; }
|
||||
|
||||
///@{
|
||||
/// @internal Satisfies concept `range_expression`, using Item* as `iterator` and 64-bit size and difference types
|
||||
///
|
||||
/// @note - These are a convenience intended to be used by c++ language features such as range-based-for-loops.
|
||||
using value_type = Item;
|
||||
using reference = Item&;
|
||||
using const_reference = const Item&;
|
||||
using iterator = Item*;
|
||||
using const_iterator = const Item*;
|
||||
using difference_type = ptrdiff_t;
|
||||
using size_type = size_t;
|
||||
|
||||
constexpr iterator begin() noexcept { return Data(); }
|
||||
constexpr iterator end() noexcept { return Data() + Capacity(); }
|
||||
constexpr const_iterator begin() const noexcept { return Data(); }
|
||||
constexpr const_iterator end() const noexcept { return Data() + Capacity(); }
|
||||
constexpr const_iterator cbegin() const noexcept { return Data(); }
|
||||
constexpr const_iterator cend() const noexcept { return Data() + Capacity(); }
|
||||
[[nodiscard]] constexpr bool empty() const noexcept { return Capacity() == 0; }
|
||||
constexpr size_type size() const noexcept { return Capacity(); }
|
||||
///@}
|
||||
|
||||
private:
|
||||
// This is a POD-type that exactly fits one Item value.
|
||||
using ValueStorage = typename std::aligned_storage<sizeof(Item), alignof(Item)>::type;
|
||||
|
||||
// Capacity of this buffer (in Items).
|
||||
size_t m_capacity;
|
||||
|
||||
// Buffer pointer this object uses to access the buffer's elements: if the required capacity exceeds the default
|
||||
// capacity, this points to a dynamic array of Items. Otherwise, this points to m_localBuffer.
|
||||
Item* m_pBuffer;
|
||||
|
||||
// Static array providing storage for Items which we expect most objects of this type to end up using.
|
||||
ValueStorage m_localBuffer[defaultCapacity];
|
||||
|
||||
// Allocator for this AutoBuffer.
|
||||
Allocator*const m_pAllocator;
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(AutoBuffer);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(AutoBuffer);
|
||||
};
|
||||
|
||||
} // Util
|
||||
|
||||
@@ -1,202 +1,202 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palBuddyAllocator.h
|
||||
* @brief PAL utility BuddyAllocator class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palUtil.h"
|
||||
#include "palHashSet.h"
|
||||
#include "palHashMap.h"
|
||||
#include "palMutex.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Buddy Allocator
|
||||
*
|
||||
* Responsible for managing small GPU memory requests by allocating a large base allocation and dividing it into
|
||||
* appropriately sized suballocation blocks.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template <typename Allocator>
|
||||
class BuddyAllocator
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param [in] pAllocator The allocator that will allocate memory if required.
|
||||
/// @param [in] baseAllocSize The size of the base allocation this buddy allocator suballocates.
|
||||
/// @param [in] minAllocSize The size of the smallest block this buddy allocator can allocate.
|
||||
BuddyAllocator(
|
||||
Allocator* pAllocator,
|
||||
gpusize baseAllocSize,
|
||||
gpusize minAllocSize);
|
||||
~BuddyAllocator();
|
||||
|
||||
/// Initializes the buddy allocator.
|
||||
///
|
||||
/// @returns Success if the buddy allocator has been successfully initialized.
|
||||
Result Init();
|
||||
|
||||
/// Suballocates a block from the base allocation that this buddy allocator manages. Expects @ref ClaimGpuMemory to
|
||||
/// be called directly before it. If a memory manager with multiple buddyAllocators is used, use pattern should
|
||||
/// be: Iterate through buddyAllocators calling ClaimGpuMemory, if one returns @ref Success break out of the loop,
|
||||
/// then call Allocate on that buddyAllocator. If none return @ref Success, then a new buddyAllocator needs to be
|
||||
/// created. The purpose of splitting up buddyAllocator selection and Allocation is to reduce lock contention in
|
||||
/// multithreaded memory managers.
|
||||
///
|
||||
/// @param [in] size The size of the requested suballocation.
|
||||
/// @param [in] alignment The alignment requirements of the requested suballocation.
|
||||
/// @param [out] pOffset The offset the suballocated block starts within the base allocation.
|
||||
///
|
||||
/// @returns Success if the allocation succeeded, @ref ErrorOutOfMemory if there isn't enough system memory to
|
||||
/// fulfill the request, or @ref ErrorOutOfGpuMemory if there isn't a large enough block free in the
|
||||
/// base allocation to fulfill the request.
|
||||
///
|
||||
/// @warning Unless @ref ClaimGpuMemory is called before every single call, the results of @ref Allocate will
|
||||
/// be invalid. If @ref ClaimGpuMemory returns @ref Success, then @ref ErrorOutOfGpuMemory will never be
|
||||
/// returned.
|
||||
Result Allocate(
|
||||
gpusize size,
|
||||
gpusize alignment,
|
||||
gpusize* pOffset);
|
||||
|
||||
/// Frees a previously allocated suballocation.
|
||||
///
|
||||
/// @param [in] offset The offset the suballocated block starts within the base allocation.
|
||||
/// @param [in] size Optional parameter specifying the size of the original allocation.
|
||||
/// @param [in] alignment Optional parameter specifying the alignment of the original allocation.
|
||||
void Free(
|
||||
gpusize offset,
|
||||
gpusize size = 0,
|
||||
gpusize alignment = 0);
|
||||
|
||||
/// Tells whether the base allocation is completely free. If the returned value is true then the caller is safe
|
||||
/// to deallocate the base allocation.
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return (m_numSuballocations == 0);
|
||||
}
|
||||
|
||||
/// Returns the size of the largest allocation that can be suballocated with this buddy allocator.
|
||||
gpusize MaximumAllocationSize() const;
|
||||
|
||||
/// Claims (doesn't allocate) some memory, used to quickly determine if a pool of memory has availible memory.
|
||||
/// Doesn't affect internal state unless Result::Success is returned
|
||||
///
|
||||
/// @param [in] size The size of the requested suballocation.
|
||||
/// @param [in] alignment The alignment requirements of the requested suballocation.
|
||||
///
|
||||
/// @returns Success if there is enough memory in this buddyAllocator to allocate the requested size of memory,
|
||||
/// @ref ErrorOutOfGpuMemory if there is not enough memory
|
||||
///
|
||||
/// @warning Unless this is called to test availible memory before every call to Allocate, then the results will not
|
||||
/// be valid.
|
||||
Result ClaimGpuMemory(
|
||||
gpusize size,
|
||||
gpusize alignment);
|
||||
|
||||
/// Checks if @ref ClaimGpuMemory can actually claim memory, can be used to find the best fit pool. This function
|
||||
/// does NOT acquire a lock on the structures ClaimGpuMemory uses, and does NOT claim or allocate the memory.
|
||||
///
|
||||
/// @param [in] size The size of the requested suballocation.
|
||||
/// @param [in] alignment The alignment requirements of the requested suballocation.
|
||||
/// @param [out] pKval The highest kval that will need to be split will be stored here.
|
||||
///
|
||||
/// @returns Success if there is enough memory in this buddyAllocator to allocate the requested size of memory,
|
||||
/// @ref ErrorOutOfGpuMemory if there is not enough memory
|
||||
///
|
||||
Result CheckIfOpenMemory(
|
||||
gpusize size,
|
||||
gpusize alignment,
|
||||
uint32* pKval);
|
||||
|
||||
private:
|
||||
typedef Util::HashSet<gpusize, Allocator, JenkinsHashFunc> FreeSet;
|
||||
typedef Util::HashMap<gpusize, uint32, Allocator, JenkinsHashFunc> UsedMap;
|
||||
|
||||
Result GetNextFreeBlock(
|
||||
uint32 kval,
|
||||
gpusize* pOffset);
|
||||
|
||||
Result FreeBlock(gpusize offset);
|
||||
|
||||
static constexpr gpusize KvalToSize(uint32 kVal) { return (1ull << kVal); }
|
||||
|
||||
static uint32 SizeToKval(gpusize size) { return Log2(size); }
|
||||
|
||||
Allocator* const m_pAllocator;
|
||||
|
||||
const uint32 m_baseAllocKval;
|
||||
const uint32 m_minKval;
|
||||
|
||||
// Array of hashSets of blocks that are free at each level
|
||||
FreeSet* m_pFreeBlockSets;
|
||||
|
||||
// Hashmap of blocks that are used, key=offset, value=level (kval)
|
||||
UsedMap* m_pUsedBlockMap;
|
||||
// List of the free memory at each level
|
||||
uint32* m_pNumFreeList;
|
||||
// The highest Kval that has at least 1 free block (used in ClaimGpuMemory)
|
||||
uint32 m_highestFreeKval;
|
||||
|
||||
uint32 m_numSuballocations;
|
||||
|
||||
// mutex on altering the numFreeList
|
||||
Util::Mutex m_numFreeMutex;
|
||||
// mutex on the used block map
|
||||
Util::Mutex m_usedBlockMapMutex;
|
||||
// array of mutexes, one for each freeBlockSet
|
||||
Util::Mutex* m_pFreeSetMutexes;
|
||||
// mutex on the freeing. Serialize freeing blocks and don't allow allocating blocks while one is freeing. Based on
|
||||
// testing, applications typically don't try to free and allocate memory at the same time, and almost all of the
|
||||
// memory freeing is done at the end of the application.
|
||||
Util::RWLock m_freeLock;
|
||||
|
||||
// Set to true if ClaimGpuMemory is ever called on this buddyAllocator. This signals to free to not merge blocks
|
||||
// if m_pNumFreeList[kval - m_minKval] = 0
|
||||
bool m_usedClaim;
|
||||
|
||||
// HashSet and HashMap utility functions
|
||||
Result InsertToFreeSet(gpusize offset, uint32 kval);
|
||||
bool GetKvalUsed(gpusize offset, uint32* pKval);
|
||||
Result SetKvalUsed(gpusize offset, uint32 kval);
|
||||
Result PopFromFreeSet(gpusize* pOffset, uint32 kval);
|
||||
bool IsOffsetFree(gpusize offset, uint32 kval);
|
||||
Result RemoveOffsetFromFreeSet(gpusize offset, uint32 kval);
|
||||
Result RemoveOffsetFromUsedMap(gpusize offset);
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(BuddyAllocator);
|
||||
PAL_DISALLOW_DEFAULT_CTOR(BuddyAllocator);
|
||||
};
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palBuddyAllocator.h
|
||||
* @brief PAL utility BuddyAllocator class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palUtil.h"
|
||||
#include "palHashSet.h"
|
||||
#include "palHashMap.h"
|
||||
#include "palMutex.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Buddy Allocator
|
||||
*
|
||||
* Responsible for managing small GPU memory requests by allocating a large base allocation and dividing it into
|
||||
* appropriately sized suballocation blocks.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template <typename Allocator>
|
||||
class BuddyAllocator
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param [in] pAllocator The allocator that will allocate memory if required.
|
||||
/// @param [in] baseAllocSize The size of the base allocation this buddy allocator suballocates.
|
||||
/// @param [in] minAllocSize The size of the smallest block this buddy allocator can allocate.
|
||||
BuddyAllocator(
|
||||
Allocator* pAllocator,
|
||||
gpusize baseAllocSize,
|
||||
gpusize minAllocSize);
|
||||
~BuddyAllocator();
|
||||
|
||||
/// Initializes the buddy allocator.
|
||||
///
|
||||
/// @returns Success if the buddy allocator has been successfully initialized.
|
||||
Result Init();
|
||||
|
||||
/// Suballocates a block from the base allocation that this buddy allocator manages. Expects @ref ClaimGpuMemory to
|
||||
/// be called directly before it. If a memory manager with multiple buddyAllocators is used, use pattern should
|
||||
/// be: Iterate through buddyAllocators calling ClaimGpuMemory, if one returns @ref Success break out of the loop,
|
||||
/// then call Allocate on that buddyAllocator. If none return @ref Success, then a new buddyAllocator needs to be
|
||||
/// created. The purpose of splitting up buddyAllocator selection and Allocation is to reduce lock contention in
|
||||
/// multithreaded memory managers.
|
||||
///
|
||||
/// @param [in] size The size of the requested suballocation.
|
||||
/// @param [in] alignment The alignment requirements of the requested suballocation.
|
||||
/// @param [out] pOffset The offset the suballocated block starts within the base allocation.
|
||||
///
|
||||
/// @returns Success if the allocation succeeded, @ref ErrorOutOfMemory if there isn't enough system memory to
|
||||
/// fulfill the request, or @ref ErrorOutOfGpuMemory if there isn't a large enough block free in the
|
||||
/// base allocation to fulfill the request.
|
||||
///
|
||||
/// @warning Unless @ref ClaimGpuMemory is called before every single call, the results of @ref Allocate will
|
||||
/// be invalid. If @ref ClaimGpuMemory returns @ref Success, then @ref ErrorOutOfGpuMemory will never be
|
||||
/// returned.
|
||||
Result Allocate(
|
||||
gpusize size,
|
||||
gpusize alignment,
|
||||
gpusize* pOffset);
|
||||
|
||||
/// Frees a previously allocated suballocation.
|
||||
///
|
||||
/// @param [in] offset The offset the suballocated block starts within the base allocation.
|
||||
/// @param [in] size Optional parameter specifying the size of the original allocation.
|
||||
/// @param [in] alignment Optional parameter specifying the alignment of the original allocation.
|
||||
void Free(
|
||||
gpusize offset,
|
||||
gpusize size = 0,
|
||||
gpusize alignment = 0);
|
||||
|
||||
/// Tells whether the base allocation is completely free. If the returned value is true then the caller is safe
|
||||
/// to deallocate the base allocation.
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return (m_numSuballocations == 0);
|
||||
}
|
||||
|
||||
/// Returns the size of the largest allocation that can be suballocated with this buddy allocator.
|
||||
gpusize MaximumAllocationSize() const;
|
||||
|
||||
/// Claims (doesn't allocate) some memory, used to quickly determine if a pool of memory has availible memory.
|
||||
/// Doesn't affect internal state unless Result::Success is returned
|
||||
///
|
||||
/// @param [in] size The size of the requested suballocation.
|
||||
/// @param [in] alignment The alignment requirements of the requested suballocation.
|
||||
///
|
||||
/// @returns Success if there is enough memory in this buddyAllocator to allocate the requested size of memory,
|
||||
/// @ref ErrorOutOfGpuMemory if there is not enough memory
|
||||
///
|
||||
/// @warning Unless this is called to test availible memory before every call to Allocate, then the results will not
|
||||
/// be valid.
|
||||
Result ClaimGpuMemory(
|
||||
gpusize size,
|
||||
gpusize alignment);
|
||||
|
||||
/// Checks if @ref ClaimGpuMemory can actually claim memory, can be used to find the best fit pool. This function
|
||||
/// does NOT acquire a lock on the structures ClaimGpuMemory uses, and does NOT claim or allocate the memory.
|
||||
///
|
||||
/// @param [in] size The size of the requested suballocation.
|
||||
/// @param [in] alignment The alignment requirements of the requested suballocation.
|
||||
/// @param [out] pKval The highest kval that will need to be split will be stored here.
|
||||
///
|
||||
/// @returns Success if there is enough memory in this buddyAllocator to allocate the requested size of memory,
|
||||
/// @ref ErrorOutOfGpuMemory if there is not enough memory
|
||||
///
|
||||
Result CheckIfOpenMemory(
|
||||
gpusize size,
|
||||
gpusize alignment,
|
||||
uint32* pKval);
|
||||
|
||||
private:
|
||||
typedef Util::HashSet<gpusize, Allocator, JenkinsHashFunc> FreeSet;
|
||||
typedef Util::HashMap<gpusize, uint32, Allocator, JenkinsHashFunc> UsedMap;
|
||||
|
||||
Result GetNextFreeBlock(
|
||||
uint32 kval,
|
||||
gpusize* pOffset);
|
||||
|
||||
Result FreeBlock(gpusize offset);
|
||||
|
||||
static constexpr gpusize KvalToSize(uint32 kVal) { return (1ull << kVal); }
|
||||
|
||||
static uint32 SizeToKval(gpusize size) { return Log2(size); }
|
||||
|
||||
Allocator* const m_pAllocator;
|
||||
|
||||
const uint32 m_baseAllocKval;
|
||||
const uint32 m_minKval;
|
||||
|
||||
// Array of hashSets of blocks that are free at each level
|
||||
FreeSet* m_pFreeBlockSets;
|
||||
|
||||
// Hashmap of blocks that are used, key=offset, value=level (kval)
|
||||
UsedMap* m_pUsedBlockMap;
|
||||
// List of the free memory at each level
|
||||
uint32* m_pNumFreeList;
|
||||
// The highest Kval that has at least 1 free block (used in ClaimGpuMemory)
|
||||
uint32 m_highestFreeKval;
|
||||
|
||||
uint32 m_numSuballocations;
|
||||
|
||||
// mutex on altering the numFreeList
|
||||
Util::Mutex m_numFreeMutex;
|
||||
// mutex on the used block map
|
||||
Util::Mutex m_usedBlockMapMutex;
|
||||
// array of mutexes, one for each freeBlockSet
|
||||
Util::Mutex* m_pFreeSetMutexes;
|
||||
// mutex on the freeing. Serialize freeing blocks and don't allow allocating blocks while one is freeing. Based on
|
||||
// testing, applications typically don't try to free and allocate memory at the same time, and almost all of the
|
||||
// memory freeing is done at the end of the application.
|
||||
Util::RWLock m_freeLock;
|
||||
|
||||
// Set to true if ClaimGpuMemory is ever called on this buddyAllocator. This signals to free to not merge blocks
|
||||
// if m_pNumFreeList[kval - m_minKval] = 0
|
||||
bool m_usedClaim;
|
||||
|
||||
// HashSet and HashMap utility functions
|
||||
Result InsertToFreeSet(gpusize offset, uint32 kval);
|
||||
bool GetKvalUsed(gpusize offset, uint32* pKval);
|
||||
Result SetKvalUsed(gpusize offset, uint32 kval);
|
||||
Result PopFromFreeSet(gpusize* pOffset, uint32 kval);
|
||||
bool IsOffsetFree(gpusize offset, uint32 kval);
|
||||
Result RemoveOffsetFromFreeSet(gpusize offset, uint32 kval);
|
||||
Result RemoveOffsetFromUsedMap(gpusize offset);
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(BuddyAllocator);
|
||||
PAL_DISALLOW_DEFAULT_CTOR(BuddyAllocator);
|
||||
};
|
||||
|
||||
} // Util
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,364 +1,364 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2017-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palDbgPrint.h
|
||||
* @brief Defines PAL utility collection debug print functionality.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palUtil.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#if PAL_ENABLE_LOGGING
|
||||
#include "palDbgLogHelper.h"
|
||||
#endif
|
||||
|
||||
namespace Util
|
||||
{
|
||||
#if (PAL_ENABLE_PRINTS_ASSERTS || PAL_ENABLE_LOGGING)
|
||||
// Forward declarations.
|
||||
class File;
|
||||
enum FileAccessMode : uint32;
|
||||
|
||||
/// Specifies the category of a debug print.
|
||||
///
|
||||
/// Driver developer can enable/disable each category separately through settings.
|
||||
enum DbgPrintCategory : uint32
|
||||
{
|
||||
DbgPrintCatInfoMsg = 0, ///< Generic informational messages.
|
||||
DbgPrintCatWarnMsg, ///< Warning messages.
|
||||
DbgPrintCatErrorMsg, ///< Error messages.
|
||||
DbgPrintCatScMsg, ///< Generic shader compiler messages.
|
||||
DbgPrintCatEventPrintMsg, ///< System event messages.
|
||||
DbgPrintCatEventPrintCallbackMsg, ///< System event messages via callback.
|
||||
DbgPrintCatMsgFile, ///< All Messages via file.
|
||||
DbgPrintCatCount
|
||||
};
|
||||
|
||||
/// Specifies the debug print mode: disabled, print to debugger, or print to file.
|
||||
enum class DbgPrintMode : uint32
|
||||
{
|
||||
Disable, ///< Debug print is ignored.
|
||||
Print, ///< Debug print is routed to the debug window or stdout.
|
||||
File, ///< Debug print is routed to a file.
|
||||
PrintCallback, ///< Debug print is routed to the print callback only
|
||||
};
|
||||
|
||||
/// Flags specifying style controls for a debug print.
|
||||
enum DbgPrintStyle : uint32
|
||||
{
|
||||
DbgPrintStyleDefault = 0x0, ///< Normal mode: has a prefix and a CR-LF.
|
||||
DbgPrintStyleNoPrefix = 0x1, ///< Skip the prefix.
|
||||
DbgPrintStyleNoCrLf = 0x2, ///< Skip the CR-LF.
|
||||
DbgPrintStyleNoPrefixNoCrLf = 0x3, ///< Skip both the prefix and the CR-LF.
|
||||
};
|
||||
|
||||
/// Definition for debug print callback.
|
||||
///
|
||||
/// @param [in] pUserData User data that is installed with the callback for use by the installer.
|
||||
/// @param [in] category Debug print category that the message belongs to.
|
||||
/// @param [in] pText Text data to be printed by the callback.
|
||||
typedef void (PAL_STDCALL *DbgPrintCallbackFunc)(
|
||||
void* pUserdata,
|
||||
DbgPrintCategory category,
|
||||
const char* pText);
|
||||
|
||||
/// Debug print callback struct that bundles the callback function and its userdata pointer.
|
||||
struct DbgPrintCallback
|
||||
{
|
||||
DbgPrintCallbackFunc pCallbackFunc;
|
||||
void* pUserdata;
|
||||
};
|
||||
|
||||
/// Generic debug printf function to be used when the caller wishes to specify the output category and style. Clients
|
||||
/// should use the PAL_DPF macro instead of calling this function directly.
|
||||
///
|
||||
/// @param [in] category Message category (e.g., CS dumps, SC output, etc.).
|
||||
/// @param [in] style Text output style (i.e., has prefix and/or CR-LF).
|
||||
/// @param [in] pFormat Printf-style format string.
|
||||
extern void DbgPrintf(
|
||||
DbgPrintCategory category,
|
||||
DbgPrintStyle style,
|
||||
const char* pFormat,
|
||||
...);
|
||||
|
||||
/// Generic printf function to be used when the caller wishes to specify the output category and style, and has
|
||||
/// pre-started the variable arg list (va_list argument instead of ...).
|
||||
///
|
||||
/// @param [in] category Message category (e.g., CS dumps, SC output, etc.).
|
||||
/// @param [in] style Text output style (i.e., has prefix and/or CR-LF).
|
||||
/// @param [in] pFormat Printf-style format string.
|
||||
/// @param [in] argList Variable argument list.
|
||||
extern void DbgVPrintf(
|
||||
DbgPrintCategory category,
|
||||
DbgPrintStyle style,
|
||||
const char* pFormat,
|
||||
va_list argList);
|
||||
|
||||
#endif
|
||||
|
||||
#if PAL_ENABLE_PRINTS_ASSERTS
|
||||
/// Sets the debug print mode (output to debugger, write to file, or disabled) for the specified category of messages.
|
||||
///
|
||||
/// Probably controlled by a setting and set during initialization.
|
||||
///
|
||||
/// @param [in] category Message category to control (e.g., CS dumps, SC output, etc.).
|
||||
/// @param [in] mode New mode to be used for this message category (print to file, etc.).
|
||||
extern void SetDbgPrintMode(
|
||||
DbgPrintCategory category,
|
||||
DbgPrintMode mode);
|
||||
|
||||
/// Opens a file that resides in the selected log directory.
|
||||
///
|
||||
/// This function exists in all build configurations.
|
||||
///
|
||||
/// @param [in,out] pFile File object to represent the opened file.
|
||||
/// @param [in] pFilename Filename to open.
|
||||
/// @param [in] flags ORed mask of FileAccessMode values specifying how this file will be accessed.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
extern Result OpenLogFile(
|
||||
File* pFile,
|
||||
const char* pFilename,
|
||||
uint32 flags);
|
||||
|
||||
/// Sets the global debug print callback.
|
||||
///
|
||||
/// @param [in] callback Debug print callback struct that contains the callback function and a userdata pointer
|
||||
extern void SetDbgPrintCallback(
|
||||
const DbgPrintCallback& callback);
|
||||
|
||||
#endif
|
||||
|
||||
// Forward declarations.
|
||||
template<typename CharT> class StringView;
|
||||
|
||||
/// Logs a text string via client callback when provided.
|
||||
///
|
||||
/// @param [in] pClientData Pointer to client-defined data. The pClientData value specified in the pLogCbInfo
|
||||
/// parameter to CreatePlatform() will be passed back to the client on every log callback.
|
||||
/// @param [in] level Log priority level associated with the message.
|
||||
/// @param [in] categoryMask Log category mask that represents what category fields the message relates to.
|
||||
/// @param [in] pFormat Format string for the log message.
|
||||
/// @param [in] args Variable arguments that correspond to the format string.
|
||||
typedef void (PAL_STDCALL *LogCallbackFunc)(
|
||||
void* pClientData,
|
||||
uint32 level,
|
||||
uint64 categoryMask,
|
||||
const char* pFormat,
|
||||
va_list args);
|
||||
|
||||
/// Specifies client-provided logging callbacks. Used as a parameter to Pal::CreatePlatform().
|
||||
///
|
||||
/// @ingroup LibInit
|
||||
struct LogCallbackInfo
|
||||
{
|
||||
void* pClientData; ///< Opaque pointer to data of client's choosing. This pointer will be passed back to
|
||||
/// every @ref LogCallbackFunc call made by PAL.
|
||||
LogCallbackFunc pfnLogCb; ///< Debug print logging callback. @see LogCallbackFunc.
|
||||
};
|
||||
|
||||
/// Compiler-specific wrapper of the standard snprintf implementation.
|
||||
///
|
||||
/// @param [out] pOutput Output string.
|
||||
/// @param [in] bufSize Available space in pOutput.
|
||||
/// @param [in] pFormat Printf-style format string.
|
||||
///
|
||||
/// @returns The resultant length of the formatted string.
|
||||
extern int32 Snprintf(
|
||||
char* pOutput,
|
||||
size_t bufSize,
|
||||
const char* pFormat,
|
||||
...);
|
||||
|
||||
/// Compiler-specific wrapper of the standard vsnprintf implementation.
|
||||
///
|
||||
/// @param [out] pOutput Output string. If buffer is a nullptr it returns the length of the string that would be
|
||||
/// printed had a buffer with enough space been provided.
|
||||
/// @param [in] bufSize Available space in pOutput.
|
||||
/// @param [in] pFormat Printf-style format string.
|
||||
/// @param [in] argList variable argument list.
|
||||
///
|
||||
/// @returns The resultant length of the formatted string.
|
||||
extern int32 Vsnprintf(
|
||||
char* pOutput,
|
||||
size_t bufSize,
|
||||
const char* pFormat,
|
||||
va_list argList);
|
||||
|
||||
/// Compiler-specific wrapper of the standard snprintf implementation.
|
||||
///
|
||||
/// @param [out] pOutput Output string.
|
||||
/// @param [in] bufSize Available space in pOutput.
|
||||
/// @param [in] pFormat Printf-style format string.
|
||||
///
|
||||
/// @returns The resultant length of the formatted string.
|
||||
extern int32 Snprintf(
|
||||
wchar_t* pOutput,
|
||||
size_t bufSize,
|
||||
const wchar_t* pFormat,
|
||||
...);
|
||||
|
||||
/// Compiler-specific wrapper of the standard vsnprintf implementation.
|
||||
///
|
||||
/// @param [out] pOutput Output string. If buffer is a nullptr it returns the length of the string that would be
|
||||
/// printed had a buffer with enough space been provided.
|
||||
/// @param [in] bufSize Available space in pOutput.
|
||||
/// @param [in] pFormat Printf-style format string.
|
||||
/// @param [in] argList variable argument list.
|
||||
///
|
||||
/// @returns The resultant length of the formatted string.
|
||||
extern int32 Vsnprintf(
|
||||
wchar_t* pOutput,
|
||||
size_t bufSize,
|
||||
const wchar_t* pFormat,
|
||||
va_list argList);
|
||||
|
||||
/// Copy an arbitrary string into the provided buffer, encoding as necessary to avoid characters that are illegal
|
||||
/// in filenames (assuming the more restrictive Windows rules, even on non-Windows OSs).
|
||||
///
|
||||
/// Any byte that would be illegal is encoded as % then two hex digits, like in a URL.
|
||||
///
|
||||
/// @param [out] pOutput Output string.
|
||||
/// @param bufSize Available space in pOutput.
|
||||
/// @param [in] input Input string
|
||||
/// @param allowSpace Allow (do not % encode) space
|
||||
/// @param allowDirSeparator Allow (do not % encode) / and \ characters
|
||||
///
|
||||
/// @returns Works like C++ standard snprintf:
|
||||
/// - If the provided buffer is big enough, it returns the number of bytes written, excluding the
|
||||
/// terminating \0.
|
||||
/// - If the provided buffer is not big enough, then the result string is truncated to fit, and the
|
||||
/// function returns the number of bytes that would have been written if the buffer had been long
|
||||
/// enough, excluding the terminating \0.
|
||||
/// - Passing 0 buffer length is allowed as a special case of that, and nullptr pOutput is then allowed.
|
||||
extern size_t EncodeAsFilename(
|
||||
char* pOutput,
|
||||
size_t bufSize,
|
||||
const StringView<char>& input,
|
||||
bool allowSpace,
|
||||
bool allowDirSeparator);
|
||||
|
||||
/// Generate a log filename.
|
||||
///
|
||||
/// @param [inout] pFilenameBuffer Buffer to hold the filename.
|
||||
/// @param maxSize Max size of the pFilenameBuffer.
|
||||
/// @param nextPost The next write position.
|
||||
/// @param [in] pExt The filename extension.
|
||||
/// @param logDuplicate Log duplicate objects.
|
||||
extern void GenLogFilename(
|
||||
char* pFilenameBuffer,
|
||||
size_t maxSize,
|
||||
size_t nextPos,
|
||||
const char* const pExt,
|
||||
bool logDuplicate);
|
||||
|
||||
} // Util
|
||||
|
||||
/// PAL_ENABLE_LOGGING enables the new logging code. At this time, both, the current and new logging
|
||||
/// code will be active for development purpose if both macros are enabled.
|
||||
#if (PAL_ENABLE_PRINTS_ASSERTS && PAL_ENABLE_LOGGING)
|
||||
/// Debug printf macro.
|
||||
#define PAL_DPF ::Util::DbgPrintf
|
||||
/// Debug info printf macro.
|
||||
#define PAL_DPINFO(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgPrintf(::Util::DbgPrintCatInfoMsg, ::Util::DbgPrintStyleDefault, _pFormat " (%s:%d:%s)", \
|
||||
##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
::Util::DbgLog(::Util::SeverityLevel::Info, ::Util::OriginationType::DebugPrint, \
|
||||
"AMD-PAL", _pFormat " (%s:%d:%s)", ##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
/// Debug warning printf macro.
|
||||
#define PAL_DPWARN(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgPrintf(::Util::DbgPrintCatWarnMsg, ::Util::DbgPrintStyleDefault, _pFormat " (%s:%d:%s)", \
|
||||
##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
::Util::DbgLog(::Util::SeverityLevel::Warning, ::Util::OriginationType::DebugPrint, \
|
||||
"AMD-PAL", _pFormat " (%s:%d:%s)", ##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
/// Debug error printf macro.
|
||||
#define PAL_DPERROR(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgPrintf(::Util::DbgPrintCatErrorMsg, ::Util::DbgPrintStyleDefault, _pFormat " (%s:%d:%s)", \
|
||||
##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
::Util::DbgLog(::Util::SeverityLevel::Error, ::Util::OriginationType::DebugPrint, \
|
||||
"AMD-PAL", _pFormat " (%s:%d:%s)", ##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
#elif PAL_ENABLE_PRINTS_ASSERTS
|
||||
/// Debug printf macro.
|
||||
#define PAL_DPF ::Util::DbgPrintf
|
||||
/// Debug info printf macro.
|
||||
#define PAL_DPINFO(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgPrintf(::Util::DbgPrintCatInfoMsg, ::Util::DbgPrintStyleDefault, _pFormat " (%s:%d:%s)", \
|
||||
##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
/// Debug warning printf macro.
|
||||
#define PAL_DPWARN(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgPrintf(::Util::DbgPrintCatWarnMsg, ::Util::DbgPrintStyleDefault, _pFormat " (%s:%d:%s)", \
|
||||
##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
/// Debug error printf macro.
|
||||
#define PAL_DPERROR(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgPrintf(::Util::DbgPrintCatErrorMsg, ::Util::DbgPrintStyleDefault, _pFormat " (%s:%d:%s)", \
|
||||
##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
#elif PAL_ENABLE_LOGGING
|
||||
/// Debug printf macro.
|
||||
#define PAL_DPF ::Util::DbgPrintf
|
||||
/// Debug info printf macro.
|
||||
#define PAL_DPINFO(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgLog(::Util::SeverityLevel::Info, ::Util::OriginationType::DebugPrint, \
|
||||
"AMD-PAL", _pFormat " (%s:%d:%s)", ##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
/// Debug warning printf macro.
|
||||
#define PAL_DPWARN(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgLog(::Util::SeverityLevel::Warning, ::Util::OriginationType::DebugPrint, \
|
||||
"AMD-PAL", _pFormat " (%s:%d:%s)", ##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
/// Debug error printf macro.
|
||||
#define PAL_DPERROR(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgLog(::Util::SeverityLevel::Error, ::Util::OriginationType::DebugPrint, \
|
||||
"AMD-PAL", _pFormat " (%s:%d:%s)", ##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
#else
|
||||
/// Debug printf macro.
|
||||
#define PAL_DPF(...) ((void)0)
|
||||
/// Debug info printf macro.
|
||||
#define PAL_DPINFO(...) ((void)0)
|
||||
/// Debug warning printf macro.
|
||||
#define PAL_DPWARN(...) ((void)0)
|
||||
/// Debug error printf macro.
|
||||
#define PAL_DPERROR(...) ((void)0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2017-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palDbgPrint.h
|
||||
* @brief Defines PAL utility collection debug print functionality.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palUtil.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#if PAL_ENABLE_LOGGING
|
||||
#include "palDbgLogHelper.h"
|
||||
#endif
|
||||
|
||||
namespace Util
|
||||
{
|
||||
#if (PAL_ENABLE_PRINTS_ASSERTS || PAL_ENABLE_LOGGING)
|
||||
// Forward declarations.
|
||||
class File;
|
||||
enum FileAccessMode : uint32;
|
||||
|
||||
/// Specifies the category of a debug print.
|
||||
///
|
||||
/// Driver developer can enable/disable each category separately through settings.
|
||||
enum DbgPrintCategory : uint32
|
||||
{
|
||||
DbgPrintCatInfoMsg = 0, ///< Generic informational messages.
|
||||
DbgPrintCatWarnMsg, ///< Warning messages.
|
||||
DbgPrintCatErrorMsg, ///< Error messages.
|
||||
DbgPrintCatScMsg, ///< Generic shader compiler messages.
|
||||
DbgPrintCatEventPrintMsg, ///< System event messages.
|
||||
DbgPrintCatEventPrintCallbackMsg, ///< System event messages via callback.
|
||||
DbgPrintCatMsgFile, ///< All Messages via file.
|
||||
DbgPrintCatCount
|
||||
};
|
||||
|
||||
/// Specifies the debug print mode: disabled, print to debugger, or print to file.
|
||||
enum class DbgPrintMode : uint32
|
||||
{
|
||||
Disable, ///< Debug print is ignored.
|
||||
Print, ///< Debug print is routed to the debug window or stdout.
|
||||
File, ///< Debug print is routed to a file.
|
||||
PrintCallback, ///< Debug print is routed to the print callback only
|
||||
};
|
||||
|
||||
/// Flags specifying style controls for a debug print.
|
||||
enum DbgPrintStyle : uint32
|
||||
{
|
||||
DbgPrintStyleDefault = 0x0, ///< Normal mode: has a prefix and a CR-LF.
|
||||
DbgPrintStyleNoPrefix = 0x1, ///< Skip the prefix.
|
||||
DbgPrintStyleNoCrLf = 0x2, ///< Skip the CR-LF.
|
||||
DbgPrintStyleNoPrefixNoCrLf = 0x3, ///< Skip both the prefix and the CR-LF.
|
||||
};
|
||||
|
||||
/// Definition for debug print callback.
|
||||
///
|
||||
/// @param [in] pUserData User data that is installed with the callback for use by the installer.
|
||||
/// @param [in] category Debug print category that the message belongs to.
|
||||
/// @param [in] pText Text data to be printed by the callback.
|
||||
typedef void (PAL_STDCALL *DbgPrintCallbackFunc)(
|
||||
void* pUserdata,
|
||||
DbgPrintCategory category,
|
||||
const char* pText);
|
||||
|
||||
/// Debug print callback struct that bundles the callback function and its userdata pointer.
|
||||
struct DbgPrintCallback
|
||||
{
|
||||
DbgPrintCallbackFunc pCallbackFunc;
|
||||
void* pUserdata;
|
||||
};
|
||||
|
||||
/// Generic debug printf function to be used when the caller wishes to specify the output category and style. Clients
|
||||
/// should use the PAL_DPF macro instead of calling this function directly.
|
||||
///
|
||||
/// @param [in] category Message category (e.g., CS dumps, SC output, etc.).
|
||||
/// @param [in] style Text output style (i.e., has prefix and/or CR-LF).
|
||||
/// @param [in] pFormat Printf-style format string.
|
||||
extern void DbgPrintf(
|
||||
DbgPrintCategory category,
|
||||
DbgPrintStyle style,
|
||||
const char* pFormat,
|
||||
...);
|
||||
|
||||
/// Generic printf function to be used when the caller wishes to specify the output category and style, and has
|
||||
/// pre-started the variable arg list (va_list argument instead of ...).
|
||||
///
|
||||
/// @param [in] category Message category (e.g., CS dumps, SC output, etc.).
|
||||
/// @param [in] style Text output style (i.e., has prefix and/or CR-LF).
|
||||
/// @param [in] pFormat Printf-style format string.
|
||||
/// @param [in] argList Variable argument list.
|
||||
extern void DbgVPrintf(
|
||||
DbgPrintCategory category,
|
||||
DbgPrintStyle style,
|
||||
const char* pFormat,
|
||||
va_list argList);
|
||||
|
||||
#endif
|
||||
|
||||
#if PAL_ENABLE_PRINTS_ASSERTS
|
||||
/// Sets the debug print mode (output to debugger, write to file, or disabled) for the specified category of messages.
|
||||
///
|
||||
/// Probably controlled by a setting and set during initialization.
|
||||
///
|
||||
/// @param [in] category Message category to control (e.g., CS dumps, SC output, etc.).
|
||||
/// @param [in] mode New mode to be used for this message category (print to file, etc.).
|
||||
extern void SetDbgPrintMode(
|
||||
DbgPrintCategory category,
|
||||
DbgPrintMode mode);
|
||||
|
||||
/// Opens a file that resides in the selected log directory.
|
||||
///
|
||||
/// This function exists in all build configurations.
|
||||
///
|
||||
/// @param [in,out] pFile File object to represent the opened file.
|
||||
/// @param [in] pFilename Filename to open.
|
||||
/// @param [in] flags ORed mask of FileAccessMode values specifying how this file will be accessed.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
extern Result OpenLogFile(
|
||||
File* pFile,
|
||||
const char* pFilename,
|
||||
uint32 flags);
|
||||
|
||||
/// Sets the global debug print callback.
|
||||
///
|
||||
/// @param [in] callback Debug print callback struct that contains the callback function and a userdata pointer
|
||||
extern void SetDbgPrintCallback(
|
||||
const DbgPrintCallback& callback);
|
||||
|
||||
#endif
|
||||
|
||||
// Forward declarations.
|
||||
template<typename CharT> class StringView;
|
||||
|
||||
/// Logs a text string via client callback when provided.
|
||||
///
|
||||
/// @param [in] pClientData Pointer to client-defined data. The pClientData value specified in the pLogCbInfo
|
||||
/// parameter to CreatePlatform() will be passed back to the client on every log callback.
|
||||
/// @param [in] level Log priority level associated with the message.
|
||||
/// @param [in] categoryMask Log category mask that represents what category fields the message relates to.
|
||||
/// @param [in] pFormat Format string for the log message.
|
||||
/// @param [in] args Variable arguments that correspond to the format string.
|
||||
typedef void (PAL_STDCALL *LogCallbackFunc)(
|
||||
void* pClientData,
|
||||
uint32 level,
|
||||
uint64 categoryMask,
|
||||
const char* pFormat,
|
||||
va_list args);
|
||||
|
||||
/// Specifies client-provided logging callbacks. Used as a parameter to Pal::CreatePlatform().
|
||||
///
|
||||
/// @ingroup LibInit
|
||||
struct LogCallbackInfo
|
||||
{
|
||||
void* pClientData; ///< Opaque pointer to data of client's choosing. This pointer will be passed back to
|
||||
/// every @ref LogCallbackFunc call made by PAL.
|
||||
LogCallbackFunc pfnLogCb; ///< Debug print logging callback. @see LogCallbackFunc.
|
||||
};
|
||||
|
||||
/// Compiler-specific wrapper of the standard snprintf implementation.
|
||||
///
|
||||
/// @param [out] pOutput Output string.
|
||||
/// @param [in] bufSize Available space in pOutput.
|
||||
/// @param [in] pFormat Printf-style format string.
|
||||
///
|
||||
/// @returns The resultant length of the formatted string.
|
||||
extern int32 Snprintf(
|
||||
char* pOutput,
|
||||
size_t bufSize,
|
||||
const char* pFormat,
|
||||
...);
|
||||
|
||||
/// Compiler-specific wrapper of the standard vsnprintf implementation.
|
||||
///
|
||||
/// @param [out] pOutput Output string. If buffer is a nullptr it returns the length of the string that would be
|
||||
/// printed had a buffer with enough space been provided.
|
||||
/// @param [in] bufSize Available space in pOutput.
|
||||
/// @param [in] pFormat Printf-style format string.
|
||||
/// @param [in] argList variable argument list.
|
||||
///
|
||||
/// @returns The resultant length of the formatted string.
|
||||
extern int32 Vsnprintf(
|
||||
char* pOutput,
|
||||
size_t bufSize,
|
||||
const char* pFormat,
|
||||
va_list argList);
|
||||
|
||||
/// Compiler-specific wrapper of the standard snprintf implementation.
|
||||
///
|
||||
/// @param [out] pOutput Output string.
|
||||
/// @param [in] bufSize Available space in pOutput.
|
||||
/// @param [in] pFormat Printf-style format string.
|
||||
///
|
||||
/// @returns The resultant length of the formatted string.
|
||||
extern int32 Snprintf(
|
||||
wchar_t* pOutput,
|
||||
size_t bufSize,
|
||||
const wchar_t* pFormat,
|
||||
...);
|
||||
|
||||
/// Compiler-specific wrapper of the standard vsnprintf implementation.
|
||||
///
|
||||
/// @param [out] pOutput Output string. If buffer is a nullptr it returns the length of the string that would be
|
||||
/// printed had a buffer with enough space been provided.
|
||||
/// @param [in] bufSize Available space in pOutput.
|
||||
/// @param [in] pFormat Printf-style format string.
|
||||
/// @param [in] argList variable argument list.
|
||||
///
|
||||
/// @returns The resultant length of the formatted string.
|
||||
extern int32 Vsnprintf(
|
||||
wchar_t* pOutput,
|
||||
size_t bufSize,
|
||||
const wchar_t* pFormat,
|
||||
va_list argList);
|
||||
|
||||
/// Copy an arbitrary string into the provided buffer, encoding as necessary to avoid characters that are illegal
|
||||
/// in filenames (assuming the more restrictive Windows rules, even on non-Windows OSs).
|
||||
///
|
||||
/// Any byte that would be illegal is encoded as % then two hex digits, like in a URL.
|
||||
///
|
||||
/// @param [out] pOutput Output string.
|
||||
/// @param bufSize Available space in pOutput.
|
||||
/// @param [in] input Input string
|
||||
/// @param allowSpace Allow (do not % encode) space
|
||||
/// @param allowDirSeparator Allow (do not % encode) / and \ characters
|
||||
///
|
||||
/// @returns Works like C++ standard snprintf:
|
||||
/// - If the provided buffer is big enough, it returns the number of bytes written, excluding the
|
||||
/// terminating \0.
|
||||
/// - If the provided buffer is not big enough, then the result string is truncated to fit, and the
|
||||
/// function returns the number of bytes that would have been written if the buffer had been long
|
||||
/// enough, excluding the terminating \0.
|
||||
/// - Passing 0 buffer length is allowed as a special case of that, and nullptr pOutput is then allowed.
|
||||
extern size_t EncodeAsFilename(
|
||||
char* pOutput,
|
||||
size_t bufSize,
|
||||
const StringView<char>& input,
|
||||
bool allowSpace,
|
||||
bool allowDirSeparator);
|
||||
|
||||
/// Generate a log filename.
|
||||
///
|
||||
/// @param [inout] pFilenameBuffer Buffer to hold the filename.
|
||||
/// @param maxSize Max size of the pFilenameBuffer.
|
||||
/// @param nextPost The next write position.
|
||||
/// @param [in] pExt The filename extension.
|
||||
/// @param logDuplicate Log duplicate objects.
|
||||
extern void GenLogFilename(
|
||||
char* pFilenameBuffer,
|
||||
size_t maxSize,
|
||||
size_t nextPos,
|
||||
const char* const pExt,
|
||||
bool logDuplicate);
|
||||
|
||||
} // Util
|
||||
|
||||
/// PAL_ENABLE_LOGGING enables the new logging code. At this time, both, the current and new logging
|
||||
/// code will be active for development purpose if both macros are enabled.
|
||||
#if (PAL_ENABLE_PRINTS_ASSERTS && PAL_ENABLE_LOGGING)
|
||||
/// Debug printf macro.
|
||||
#define PAL_DPF ::Util::DbgPrintf
|
||||
/// Debug info printf macro.
|
||||
#define PAL_DPINFO(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgPrintf(::Util::DbgPrintCatInfoMsg, ::Util::DbgPrintStyleDefault, _pFormat " (%s:%d:%s)", \
|
||||
##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
::Util::DbgLog(::Util::SeverityLevel::Info, ::Util::OriginationType::DebugPrint, \
|
||||
"AMD-PAL", _pFormat " (%s:%d:%s)", ##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
/// Debug warning printf macro.
|
||||
#define PAL_DPWARN(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgPrintf(::Util::DbgPrintCatWarnMsg, ::Util::DbgPrintStyleDefault, _pFormat " (%s:%d:%s)", \
|
||||
##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
::Util::DbgLog(::Util::SeverityLevel::Warning, ::Util::OriginationType::DebugPrint, \
|
||||
"AMD-PAL", _pFormat " (%s:%d:%s)", ##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
/// Debug error printf macro.
|
||||
#define PAL_DPERROR(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgPrintf(::Util::DbgPrintCatErrorMsg, ::Util::DbgPrintStyleDefault, _pFormat " (%s:%d:%s)", \
|
||||
##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
::Util::DbgLog(::Util::SeverityLevel::Error, ::Util::OriginationType::DebugPrint, \
|
||||
"AMD-PAL", _pFormat " (%s:%d:%s)", ##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
#elif PAL_ENABLE_PRINTS_ASSERTS
|
||||
/// Debug printf macro.
|
||||
#define PAL_DPF ::Util::DbgPrintf
|
||||
/// Debug info printf macro.
|
||||
#define PAL_DPINFO(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgPrintf(::Util::DbgPrintCatInfoMsg, ::Util::DbgPrintStyleDefault, _pFormat " (%s:%d:%s)", \
|
||||
##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
/// Debug warning printf macro.
|
||||
#define PAL_DPWARN(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgPrintf(::Util::DbgPrintCatWarnMsg, ::Util::DbgPrintStyleDefault, _pFormat " (%s:%d:%s)", \
|
||||
##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
/// Debug error printf macro.
|
||||
#define PAL_DPERROR(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgPrintf(::Util::DbgPrintCatErrorMsg, ::Util::DbgPrintStyleDefault, _pFormat " (%s:%d:%s)", \
|
||||
##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
#elif PAL_ENABLE_LOGGING
|
||||
/// Debug printf macro.
|
||||
#define PAL_DPF ::Util::DbgPrintf
|
||||
/// Debug info printf macro.
|
||||
#define PAL_DPINFO(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgLog(::Util::SeverityLevel::Info, ::Util::OriginationType::DebugPrint, \
|
||||
"AMD-PAL", _pFormat " (%s:%d:%s)", ##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
/// Debug warning printf macro.
|
||||
#define PAL_DPWARN(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgLog(::Util::SeverityLevel::Warning, ::Util::OriginationType::DebugPrint, \
|
||||
"AMD-PAL", _pFormat " (%s:%d:%s)", ##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
/// Debug error printf macro.
|
||||
#define PAL_DPERROR(_pFormat, ...) \
|
||||
{ \
|
||||
::Util::DbgLog(::Util::SeverityLevel::Error, ::Util::OriginationType::DebugPrint, \
|
||||
"AMD-PAL", _pFormat " (%s:%d:%s)", ##__VA_ARGS__, __FILE__, __LINE__, __func__); \
|
||||
}
|
||||
#else
|
||||
/// Debug printf macro.
|
||||
#define PAL_DPF(...) ((void)0)
|
||||
/// Debug info printf macro.
|
||||
#define PAL_DPINFO(...) ((void)0)
|
||||
/// Debug warning printf macro.
|
||||
#define PAL_DPWARN(...) ((void)0)
|
||||
/// Debug error printf macro.
|
||||
#define PAL_DPERROR(...) ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,319 +1,319 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palDeque.h
|
||||
* @brief PAL utility collection Deque and DequeIterator class declarations.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palAssert.h"
|
||||
#include "palSysMemory.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
template<typename T, typename Allocator> class Deque;
|
||||
|
||||
/// @internal Private structure used by Deque and its iterators to store chunks of data elements.
|
||||
struct DequeBlockHeader
|
||||
{
|
||||
DequeBlockHeader* pPrev; ///< Pointer to the previous block.
|
||||
DequeBlockHeader* pNext; ///< Pointer to the next block.
|
||||
void* pStart; ///< Pointer to the first element in this block.
|
||||
void* pEnd; ///< Pointer to the last element in this block.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Iterator for traversal of elements in a Deque collection.
|
||||
*
|
||||
* Allows traversal of all elements in a Deque going either forwards or backwards. If you traverse off either end of
|
||||
* the deque, then you must create a new iterator by calling either the Deque's Begin() or End() method.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T, typename Allocator>
|
||||
class DequeIterator
|
||||
{
|
||||
public:
|
||||
/// Trivial destructor.
|
||||
~DequeIterator() { }
|
||||
|
||||
/// Returns a pointer to the current element. Will return null if we've gone past the end.
|
||||
T* Get() const { return m_pCurrent; }
|
||||
|
||||
/// Advances the iterator to the next position (move forward).
|
||||
void Next();
|
||||
|
||||
/// Advances the iterator to the previous position (move backward).
|
||||
void Prev();
|
||||
|
||||
/// Check if the element the iterator references is valid.
|
||||
bool IsValid() const { return m_pCurrent != nullptr; }
|
||||
|
||||
private:
|
||||
DequeIterator(const Deque<T, Allocator>* pDeque, DequeBlockHeader* pHeader, T* pCurrent);
|
||||
|
||||
const Deque<T, Allocator>*const m_pDeque; // The Deque we're iterating over.
|
||||
const DequeBlockHeader* m_pCurrentHeader; // The block we're iterating over.
|
||||
T* m_pCurrent; // Pointer to the current element. Null if we've gone past the
|
||||
// end.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(DequeIterator);
|
||||
|
||||
// Although this is a transgression of coding standards, it means that Deque does not need to have a public
|
||||
// interface specifically to implement this class. The added encapsulation this provides is worthwhile.
|
||||
friend class Deque<T, Allocator>;
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Simple templated deque container - a double-ended queue.
|
||||
*
|
||||
* This is meant for storing elements of an arbitrary (but uniform) type. Operations which this class supports are:
|
||||
*
|
||||
* - Insertion from the front and back.
|
||||
* - Deletion from the front and back.
|
||||
* - Forwards and reverse iteration
|
||||
*
|
||||
* @warning This class is not thread-safe for push, pop, or iteration!
|
||||
*
|
||||
* @note This class is only designed to work with native types and POD-style structures. If it is needed to have a Deque
|
||||
* of complex objects with nontrivial destructors, copy constructors or assign operators, then a specialized
|
||||
* implementation of CleanupElement() will need to be explicitly defined.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T, typename Allocator>
|
||||
class Deque
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param [in] pAllocator The allocator that will allocate memory if required.
|
||||
Deque(Allocator*const pAllocator, size_t numElementsPerBlock = 256);
|
||||
~Deque();
|
||||
|
||||
/// Returns the number of elements in the deque.
|
||||
size_t NumElements() const { return m_numElements; }
|
||||
|
||||
/// Returns an iterator pointing to the first element in the deque.
|
||||
///
|
||||
/// @returns An iterator pointing at the front end of the deque.
|
||||
DequeIterator<T, Allocator> Begin() const { return DequeIterator<T, Allocator>(this, m_pFrontHeader, m_pFront); }
|
||||
|
||||
/// Returns an iterator pointing to the last element in the deque.
|
||||
///
|
||||
/// This is somewhat different from std::deque.End() which returns a pointer to the theoretical object _past_ the
|
||||
/// end of the deque.
|
||||
///
|
||||
/// @returns An iterator pointing at the back end of the deque.
|
||||
DequeIterator<T, Allocator> End() const { return DequeIterator<T, Allocator>(this, m_pBackHeader, m_pBack); }
|
||||
|
||||
///@{
|
||||
/// Returns the element at the location specified.
|
||||
///
|
||||
/// @warning Calling this function with an out-of-bounds index will cause an access violation!
|
||||
///
|
||||
/// @param [in] index Integer location of the element needed.
|
||||
///
|
||||
/// @returns The element at location specified by index by reference
|
||||
T& At(uint32 index);
|
||||
|
||||
const T& At(uint32 index) const;
|
||||
|
||||
T& operator[](uint32 index);
|
||||
const T& operator[](uint32 index) const;
|
||||
///@}
|
||||
|
||||
/// Returns the object at the front of the deque.
|
||||
///
|
||||
/// @warning This will cause an access violation if called on an empty deque!
|
||||
///
|
||||
/// @returns Reference to the item stored at the front end of the deque.
|
||||
T& Front() const
|
||||
{
|
||||
PAL_ASSERT(m_numElements != 0);
|
||||
return *m_pFront;
|
||||
}
|
||||
|
||||
/// Returns the object at the tail of the deque.
|
||||
///
|
||||
/// @warning This will cause an access violation if called on an empty deque!
|
||||
///
|
||||
/// @returns Reference to the item stored at the back end of the deque.
|
||||
T& Back() const
|
||||
{
|
||||
PAL_ASSERT(m_numElements != 0);
|
||||
return *m_pBack;
|
||||
}
|
||||
|
||||
/// Pushes a copy of the specified item onto the front of the deque.
|
||||
///
|
||||
/// @param [in] data Item to be added to the front of the deque.
|
||||
///
|
||||
/// @returns @ref Success if the item was successfully added to the deque or @ref ErrorOutOfMemory if the operation
|
||||
/// failed because of an internal failure to allocate system memory.
|
||||
Result PushFront(const T& data);
|
||||
|
||||
/// Emplaces a newly constructed item onto the front of the deque.
|
||||
///
|
||||
/// @param [in] args arguments used to construct the new item.
|
||||
///
|
||||
/// @returns @ref Success if the item was successfully added to the deque or @ref ErrorOutOfMemory if the operation
|
||||
/// failed because of an internal failure to allocate system memory.
|
||||
template<typename... Args>
|
||||
Result EmplaceFront(Args&&... args);
|
||||
|
||||
/// Pushes a copy of the specified item onto the back of the deque.
|
||||
///
|
||||
/// @param [in] data Item to be added to the back of the deque.
|
||||
///
|
||||
/// @returns @ref Success if the item was successfully added to the deque or @ref ErrorOutOfMemory if the operation
|
||||
/// failed because of an internal failure to allocate system memory.
|
||||
Result PushBack(const T& data);
|
||||
|
||||
/// Emplaces a newly constructed item onto the back of the deque.
|
||||
///
|
||||
/// @param [in] args arguments used to construct the new item.
|
||||
///
|
||||
/// @returns @ref Success if the item was successfully added to the deque or @ref ErrorOutOfMemory if the operation
|
||||
/// failed because of an internal failure to allocate system memory.
|
||||
template<typename... Args>
|
||||
Result EmplaceBack(Args&&... args);
|
||||
|
||||
/// Pops the first item off the front of the deque, returning the popped value.
|
||||
///
|
||||
/// @param [out] pOut Item popped off the front of the deque.
|
||||
///
|
||||
/// @returns @ref Success if the item was successfully popped from the deque or @ref ErrorUnavailable if the deque
|
||||
/// is empty.
|
||||
Result PopFront(T* pOut);
|
||||
|
||||
/// Pops the first item off the back of the deque, returning the popped value.
|
||||
///
|
||||
/// @param [out] pOut Item popped off the back of the deque.
|
||||
///
|
||||
/// @returns @ref Success if the item was successfully popped from the deque or @ref ErrorUnavailable if the deque
|
||||
/// is empty.
|
||||
Result PopBack(T* pOut);
|
||||
|
||||
private:
|
||||
Result AllocateFront(T**);
|
||||
Result AllocateBack(T**);
|
||||
DequeBlockHeader* AllocateNewBlock();
|
||||
void FreeUnusedBlock(DequeBlockHeader* pHeader);
|
||||
|
||||
// A helper function to avoid duplication in const and non-const versions of At().
|
||||
T& InternalAt(uint32 index) const;
|
||||
|
||||
size_t m_numElements; // Number of elements
|
||||
const size_t m_numElementsPerBlock; // Block granularity when we need to alloc a new one
|
||||
|
||||
DequeBlockHeader* m_pFrontHeader; // First block of data elements, null for empty deques.
|
||||
DequeBlockHeader* m_pBackHeader; // Last block of data elements, null for empty deques/
|
||||
|
||||
T* m_pFront; // First data element, null for empty deques.
|
||||
T* m_pBack; // Last data element, null for empty deques.
|
||||
|
||||
DequeBlockHeader* m_pLazyFreeHeader; // Cached pointer to the most-recently freed block.
|
||||
|
||||
Allocator*const m_pAllocator; // Pointer to the allocator for this deque.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(Deque);
|
||||
|
||||
// Although this is a transgression of coding standards, it prevents DequeIterator requiring a public constructor;
|
||||
// constructing a 'bare' DequeIterator (i.e. without calling Deque::GetIterator) can never be a legal operation, so
|
||||
// this means that these two classes are much safer to use.
|
||||
friend class DequeIterator<T, Allocator>;
|
||||
};
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename T, typename Allocator>
|
||||
Deque<T, Allocator>::Deque(
|
||||
Allocator*const pAllocator,
|
||||
size_t numElementsPerBlock)
|
||||
:
|
||||
m_numElements(0),
|
||||
m_numElementsPerBlock(numElementsPerBlock),
|
||||
m_pFrontHeader(nullptr),
|
||||
m_pBackHeader(nullptr),
|
||||
m_pFront(nullptr),
|
||||
m_pBack(nullptr),
|
||||
m_pLazyFreeHeader(nullptr),
|
||||
m_pAllocator(pAllocator)
|
||||
{
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Frees all of the blocks this object allocated over its lifetime.
|
||||
template<typename T, typename Allocator>
|
||||
Deque<T, Allocator>::~Deque()
|
||||
{
|
||||
if (!std::is_trivial<T>::value)
|
||||
{
|
||||
while (m_pFrontHeader != nullptr)
|
||||
{
|
||||
// Explicitly destroy the removed value since it's non-trivial and advance.
|
||||
// We must destroy all of them in the current block before freeing it.
|
||||
m_pFront->~T();
|
||||
++m_pFront;
|
||||
--m_numElements;
|
||||
|
||||
if ((m_pFront == m_pFrontHeader->pEnd) || (m_numElements == 0))
|
||||
{
|
||||
// Okay, the front block is now empty. Free it and advance to the next block.
|
||||
DequeBlockHeader* pBlockToFree = m_pFrontHeader;
|
||||
m_pFrontHeader = m_pFrontHeader->pNext;
|
||||
PAL_SAFE_FREE(pBlockToFree, m_pAllocator);
|
||||
|
||||
if (m_pFrontHeader != nullptr)
|
||||
{
|
||||
// Fixup to the new block.
|
||||
m_pFront = static_cast<T*>(m_pFrontHeader->pStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Elements are trivial so skip iterating through elements and free each block.
|
||||
while (m_pFrontHeader != nullptr)
|
||||
{
|
||||
DequeBlockHeader* pBlockToFree = m_pFrontHeader;
|
||||
m_pFrontHeader = m_pFrontHeader->pNext;
|
||||
PAL_SAFE_FREE(pBlockToFree, m_pAllocator);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pLazyFreeHeader != nullptr)
|
||||
{
|
||||
PAL_SAFE_FREE(m_pLazyFreeHeader, m_pAllocator);
|
||||
}
|
||||
}
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palDeque.h
|
||||
* @brief PAL utility collection Deque and DequeIterator class declarations.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palAssert.h"
|
||||
#include "palSysMemory.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
template<typename T, typename Allocator> class Deque;
|
||||
|
||||
/// @internal Private structure used by Deque and its iterators to store chunks of data elements.
|
||||
struct DequeBlockHeader
|
||||
{
|
||||
DequeBlockHeader* pPrev; ///< Pointer to the previous block.
|
||||
DequeBlockHeader* pNext; ///< Pointer to the next block.
|
||||
void* pStart; ///< Pointer to the first element in this block.
|
||||
void* pEnd; ///< Pointer to the last element in this block.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Iterator for traversal of elements in a Deque collection.
|
||||
*
|
||||
* Allows traversal of all elements in a Deque going either forwards or backwards. If you traverse off either end of
|
||||
* the deque, then you must create a new iterator by calling either the Deque's Begin() or End() method.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T, typename Allocator>
|
||||
class DequeIterator
|
||||
{
|
||||
public:
|
||||
/// Trivial destructor.
|
||||
~DequeIterator() { }
|
||||
|
||||
/// Returns a pointer to the current element. Will return null if we've gone past the end.
|
||||
T* Get() const { return m_pCurrent; }
|
||||
|
||||
/// Advances the iterator to the next position (move forward).
|
||||
void Next();
|
||||
|
||||
/// Advances the iterator to the previous position (move backward).
|
||||
void Prev();
|
||||
|
||||
/// Check if the element the iterator references is valid.
|
||||
bool IsValid() const { return m_pCurrent != nullptr; }
|
||||
|
||||
private:
|
||||
DequeIterator(const Deque<T, Allocator>* pDeque, DequeBlockHeader* pHeader, T* pCurrent);
|
||||
|
||||
const Deque<T, Allocator>*const m_pDeque; // The Deque we're iterating over.
|
||||
const DequeBlockHeader* m_pCurrentHeader; // The block we're iterating over.
|
||||
T* m_pCurrent; // Pointer to the current element. Null if we've gone past the
|
||||
// end.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(DequeIterator);
|
||||
|
||||
// Although this is a transgression of coding standards, it means that Deque does not need to have a public
|
||||
// interface specifically to implement this class. The added encapsulation this provides is worthwhile.
|
||||
friend class Deque<T, Allocator>;
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Simple templated deque container - a double-ended queue.
|
||||
*
|
||||
* This is meant for storing elements of an arbitrary (but uniform) type. Operations which this class supports are:
|
||||
*
|
||||
* - Insertion from the front and back.
|
||||
* - Deletion from the front and back.
|
||||
* - Forwards and reverse iteration
|
||||
*
|
||||
* @warning This class is not thread-safe for push, pop, or iteration!
|
||||
*
|
||||
* @note This class is only designed to work with native types and POD-style structures. If it is needed to have a Deque
|
||||
* of complex objects with nontrivial destructors, copy constructors or assign operators, then a specialized
|
||||
* implementation of CleanupElement() will need to be explicitly defined.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T, typename Allocator>
|
||||
class Deque
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param [in] pAllocator The allocator that will allocate memory if required.
|
||||
Deque(Allocator*const pAllocator, size_t numElementsPerBlock = 256);
|
||||
~Deque();
|
||||
|
||||
/// Returns the number of elements in the deque.
|
||||
size_t NumElements() const { return m_numElements; }
|
||||
|
||||
/// Returns an iterator pointing to the first element in the deque.
|
||||
///
|
||||
/// @returns An iterator pointing at the front end of the deque.
|
||||
DequeIterator<T, Allocator> Begin() const { return DequeIterator<T, Allocator>(this, m_pFrontHeader, m_pFront); }
|
||||
|
||||
/// Returns an iterator pointing to the last element in the deque.
|
||||
///
|
||||
/// This is somewhat different from std::deque.End() which returns a pointer to the theoretical object _past_ the
|
||||
/// end of the deque.
|
||||
///
|
||||
/// @returns An iterator pointing at the back end of the deque.
|
||||
DequeIterator<T, Allocator> End() const { return DequeIterator<T, Allocator>(this, m_pBackHeader, m_pBack); }
|
||||
|
||||
///@{
|
||||
/// Returns the element at the location specified.
|
||||
///
|
||||
/// @warning Calling this function with an out-of-bounds index will cause an access violation!
|
||||
///
|
||||
/// @param [in] index Integer location of the element needed.
|
||||
///
|
||||
/// @returns The element at location specified by index by reference
|
||||
T& At(uint32 index);
|
||||
|
||||
const T& At(uint32 index) const;
|
||||
|
||||
T& operator[](uint32 index);
|
||||
const T& operator[](uint32 index) const;
|
||||
///@}
|
||||
|
||||
/// Returns the object at the front of the deque.
|
||||
///
|
||||
/// @warning This will cause an access violation if called on an empty deque!
|
||||
///
|
||||
/// @returns Reference to the item stored at the front end of the deque.
|
||||
T& Front() const
|
||||
{
|
||||
PAL_ASSERT(m_numElements != 0);
|
||||
return *m_pFront;
|
||||
}
|
||||
|
||||
/// Returns the object at the tail of the deque.
|
||||
///
|
||||
/// @warning This will cause an access violation if called on an empty deque!
|
||||
///
|
||||
/// @returns Reference to the item stored at the back end of the deque.
|
||||
T& Back() const
|
||||
{
|
||||
PAL_ASSERT(m_numElements != 0);
|
||||
return *m_pBack;
|
||||
}
|
||||
|
||||
/// Pushes a copy of the specified item onto the front of the deque.
|
||||
///
|
||||
/// @param [in] data Item to be added to the front of the deque.
|
||||
///
|
||||
/// @returns @ref Success if the item was successfully added to the deque or @ref ErrorOutOfMemory if the operation
|
||||
/// failed because of an internal failure to allocate system memory.
|
||||
Result PushFront(const T& data);
|
||||
|
||||
/// Emplaces a newly constructed item onto the front of the deque.
|
||||
///
|
||||
/// @param [in] args arguments used to construct the new item.
|
||||
///
|
||||
/// @returns @ref Success if the item was successfully added to the deque or @ref ErrorOutOfMemory if the operation
|
||||
/// failed because of an internal failure to allocate system memory.
|
||||
template<typename... Args>
|
||||
Result EmplaceFront(Args&&... args);
|
||||
|
||||
/// Pushes a copy of the specified item onto the back of the deque.
|
||||
///
|
||||
/// @param [in] data Item to be added to the back of the deque.
|
||||
///
|
||||
/// @returns @ref Success if the item was successfully added to the deque or @ref ErrorOutOfMemory if the operation
|
||||
/// failed because of an internal failure to allocate system memory.
|
||||
Result PushBack(const T& data);
|
||||
|
||||
/// Emplaces a newly constructed item onto the back of the deque.
|
||||
///
|
||||
/// @param [in] args arguments used to construct the new item.
|
||||
///
|
||||
/// @returns @ref Success if the item was successfully added to the deque or @ref ErrorOutOfMemory if the operation
|
||||
/// failed because of an internal failure to allocate system memory.
|
||||
template<typename... Args>
|
||||
Result EmplaceBack(Args&&... args);
|
||||
|
||||
/// Pops the first item off the front of the deque, returning the popped value.
|
||||
///
|
||||
/// @param [out] pOut Item popped off the front of the deque.
|
||||
///
|
||||
/// @returns @ref Success if the item was successfully popped from the deque or @ref ErrorUnavailable if the deque
|
||||
/// is empty.
|
||||
Result PopFront(T* pOut);
|
||||
|
||||
/// Pops the first item off the back of the deque, returning the popped value.
|
||||
///
|
||||
/// @param [out] pOut Item popped off the back of the deque.
|
||||
///
|
||||
/// @returns @ref Success if the item was successfully popped from the deque or @ref ErrorUnavailable if the deque
|
||||
/// is empty.
|
||||
Result PopBack(T* pOut);
|
||||
|
||||
private:
|
||||
Result AllocateFront(T**);
|
||||
Result AllocateBack(T**);
|
||||
DequeBlockHeader* AllocateNewBlock();
|
||||
void FreeUnusedBlock(DequeBlockHeader* pHeader);
|
||||
|
||||
// A helper function to avoid duplication in const and non-const versions of At().
|
||||
T& InternalAt(uint32 index) const;
|
||||
|
||||
size_t m_numElements; // Number of elements
|
||||
const size_t m_numElementsPerBlock; // Block granularity when we need to alloc a new one
|
||||
|
||||
DequeBlockHeader* m_pFrontHeader; // First block of data elements, null for empty deques.
|
||||
DequeBlockHeader* m_pBackHeader; // Last block of data elements, null for empty deques/
|
||||
|
||||
T* m_pFront; // First data element, null for empty deques.
|
||||
T* m_pBack; // Last data element, null for empty deques.
|
||||
|
||||
DequeBlockHeader* m_pLazyFreeHeader; // Cached pointer to the most-recently freed block.
|
||||
|
||||
Allocator*const m_pAllocator; // Pointer to the allocator for this deque.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(Deque);
|
||||
|
||||
// Although this is a transgression of coding standards, it prevents DequeIterator requiring a public constructor;
|
||||
// constructing a 'bare' DequeIterator (i.e. without calling Deque::GetIterator) can never be a legal operation, so
|
||||
// this means that these two classes are much safer to use.
|
||||
friend class DequeIterator<T, Allocator>;
|
||||
};
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename T, typename Allocator>
|
||||
Deque<T, Allocator>::Deque(
|
||||
Allocator*const pAllocator,
|
||||
size_t numElementsPerBlock)
|
||||
:
|
||||
m_numElements(0),
|
||||
m_numElementsPerBlock(numElementsPerBlock),
|
||||
m_pFrontHeader(nullptr),
|
||||
m_pBackHeader(nullptr),
|
||||
m_pFront(nullptr),
|
||||
m_pBack(nullptr),
|
||||
m_pLazyFreeHeader(nullptr),
|
||||
m_pAllocator(pAllocator)
|
||||
{
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Frees all of the blocks this object allocated over its lifetime.
|
||||
template<typename T, typename Allocator>
|
||||
Deque<T, Allocator>::~Deque()
|
||||
{
|
||||
if (!std::is_trivial<T>::value)
|
||||
{
|
||||
while (m_pFrontHeader != nullptr)
|
||||
{
|
||||
// Explicitly destroy the removed value since it's non-trivial and advance.
|
||||
// We must destroy all of them in the current block before freeing it.
|
||||
m_pFront->~T();
|
||||
++m_pFront;
|
||||
--m_numElements;
|
||||
|
||||
if ((m_pFront == m_pFrontHeader->pEnd) || (m_numElements == 0))
|
||||
{
|
||||
// Okay, the front block is now empty. Free it and advance to the next block.
|
||||
DequeBlockHeader* pBlockToFree = m_pFrontHeader;
|
||||
m_pFrontHeader = m_pFrontHeader->pNext;
|
||||
PAL_SAFE_FREE(pBlockToFree, m_pAllocator);
|
||||
|
||||
if (m_pFrontHeader != nullptr)
|
||||
{
|
||||
// Fixup to the new block.
|
||||
m_pFront = static_cast<T*>(m_pFrontHeader->pStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Elements are trivial so skip iterating through elements and free each block.
|
||||
while (m_pFrontHeader != nullptr)
|
||||
{
|
||||
DequeBlockHeader* pBlockToFree = m_pFrontHeader;
|
||||
m_pFrontHeader = m_pFrontHeader->pNext;
|
||||
PAL_SAFE_FREE(pBlockToFree, m_pAllocator);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pLazyFreeHeader != nullptr)
|
||||
{
|
||||
PAL_SAFE_FREE(m_pLazyFreeHeader, m_pAllocator);
|
||||
}
|
||||
}
|
||||
|
||||
} // Util
|
||||
|
||||
@@ -1,141 +1,141 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palEvent.h
|
||||
* @brief PAL utility collection Event class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palTime.h"
|
||||
#include "palUtil.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// Specifies the flags for event.
|
||||
struct EventCreateFlags
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 manualReset : 1; ///< If true, the event is created as manual reset.
|
||||
uint32 initiallySignaled : 1; ///< If true, the event is created in signaled state.
|
||||
#if defined(_WIN32)
|
||||
uint32 canBeInherited : 1; ///< If true, the event can be inherited by child process, it's
|
||||
/// Windows-specific.
|
||||
uint32 reserved : 29; ///< Reserved for future use.
|
||||
#else
|
||||
uint32 semaphore : 1; ///< If true, provide semaphore-like semantics for reads from the file
|
||||
/// descriptor.
|
||||
uint32 nonBlocking : 1; ///< If true, set the O_NONBLOCK file status flag on the new file descriptor.
|
||||
uint32 closeOnExecute : 1; ///< If true, set the close-on-exec flag for the new file descriptor.
|
||||
uint32 reserved : 27; ///< Reserved for future use.
|
||||
#endif
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Synchronization primitive that can either be in the _set_ or _reset_ state.
|
||||
*
|
||||
* Threads can call WaitForEvents() to block waiting for an Event object to be _set_. This is useful for fine-grain
|
||||
* synchronization between threads.
|
||||
*
|
||||
* Event objects start out in the _reset_ state.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
Event();
|
||||
~Event();
|
||||
/// Initializes the event object. Clients must call this before using the Event object.
|
||||
///
|
||||
/// @param flags Event creation flags.
|
||||
/// @param pName Specified the event's name, it's Windows-specific, Windows uses this name to
|
||||
/// uniquely identify fence objects across processes.
|
||||
/// @returns Success if the event was successfully initialized, otherwise an appropriate error code.
|
||||
Result Init(
|
||||
const EventCreateFlags& flags
|
||||
#if defined(_WIN32)
|
||||
,
|
||||
const wchar_t* pName = nullptr
|
||||
#endif
|
||||
);
|
||||
/// Changes the event state to _set_
|
||||
///
|
||||
/// @returns Success unless the Event has not been initialized yet (@ref ErrorUnavailable) or an unexpected internal
|
||||
/// error occured when calling the OS (ErrorUnknown).
|
||||
Result Set() const;
|
||||
|
||||
/// Changes the event state to _reset_.
|
||||
///
|
||||
/// @returns Success unless the Event has not been initialized yet (ErrorUnavailable) or an unexpected
|
||||
/// internal error occured when calling the OS (ErrorUnknown).
|
||||
Result Reset() const;
|
||||
|
||||
/// Waits for the event to enter the _set_ state before returning control to the caller. The event will change to
|
||||
/// the _reset_ state if manualReset was false on initialization.
|
||||
///
|
||||
/// @param [in] timeout Max time to wait, in seconds. If zero, this call will poll the event without blocking.
|
||||
///
|
||||
/// @returns Success if the wait completed successfully or Timeout if the wait did not complete but the operation
|
||||
/// timed out. Otherwise, one of the following errors may be returned:
|
||||
/// + ErrorInvalidValue will be returned if the timeout is negative.
|
||||
/// + ErrorUnknown may be returned if an unexpected internal occurs when calling the OS.
|
||||
Result Wait(fseconds timeout) const;
|
||||
|
||||
#if defined(_WIN32)
|
||||
/// On Windows, a handle to an OS event primitive is a HANDLE, which is just a void*.
|
||||
typedef void* EventHandle;
|
||||
#else
|
||||
/// On Linux, a handle to an OS event primitive is a file descriptor, which is just an int.
|
||||
typedef int32 EventHandle;
|
||||
#endif
|
||||
|
||||
/// Returns a handle to the actual OS event primitive associated with this object.
|
||||
EventHandle GetHandle() const { return m_hEvent; }
|
||||
|
||||
/// Open event handle.
|
||||
Result Open(EventHandle handle, bool isReference);
|
||||
|
||||
/// Constant EventHandle value which represents an invalid event object.
|
||||
static const EventHandle InvalidEvent;
|
||||
|
||||
private:
|
||||
EventHandle m_hEvent; // OS-specific event handle.
|
||||
bool m_isReference; // If true, the event is a global sharing object handle (not a duplicate) which is
|
||||
// imported from external, so it can't be closed in the currect destructor, and can only
|
||||
// be closed by the creater.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(Event);
|
||||
};
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palEvent.h
|
||||
* @brief PAL utility collection Event class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palTime.h"
|
||||
#include "palUtil.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// Specifies the flags for event.
|
||||
struct EventCreateFlags
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 manualReset : 1; ///< If true, the event is created as manual reset.
|
||||
uint32 initiallySignaled : 1; ///< If true, the event is created in signaled state.
|
||||
#if defined(_WIN32)
|
||||
uint32 canBeInherited : 1; ///< If true, the event can be inherited by child process, it's
|
||||
/// Windows-specific.
|
||||
uint32 reserved : 29; ///< Reserved for future use.
|
||||
#else
|
||||
uint32 semaphore : 1; ///< If true, provide semaphore-like semantics for reads from the file
|
||||
/// descriptor.
|
||||
uint32 nonBlocking : 1; ///< If true, set the O_NONBLOCK file status flag on the new file descriptor.
|
||||
uint32 closeOnExecute : 1; ///< If true, set the close-on-exec flag for the new file descriptor.
|
||||
uint32 reserved : 27; ///< Reserved for future use.
|
||||
#endif
|
||||
};
|
||||
uint32 u32All; ///< Flags packed as 32-bit uint.
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Synchronization primitive that can either be in the _set_ or _reset_ state.
|
||||
*
|
||||
* Threads can call WaitForEvents() to block waiting for an Event object to be _set_. This is useful for fine-grain
|
||||
* synchronization between threads.
|
||||
*
|
||||
* Event objects start out in the _reset_ state.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
Event();
|
||||
~Event();
|
||||
/// Initializes the event object. Clients must call this before using the Event object.
|
||||
///
|
||||
/// @param flags Event creation flags.
|
||||
/// @param pName Specified the event's name, it's Windows-specific, Windows uses this name to
|
||||
/// uniquely identify fence objects across processes.
|
||||
/// @returns Success if the event was successfully initialized, otherwise an appropriate error code.
|
||||
Result Init(
|
||||
const EventCreateFlags& flags
|
||||
#if defined(_WIN32)
|
||||
,
|
||||
const wchar_t* pName = nullptr
|
||||
#endif
|
||||
);
|
||||
/// Changes the event state to _set_
|
||||
///
|
||||
/// @returns Success unless the Event has not been initialized yet (@ref ErrorUnavailable) or an unexpected internal
|
||||
/// error occured when calling the OS (ErrorUnknown).
|
||||
Result Set() const;
|
||||
|
||||
/// Changes the event state to _reset_.
|
||||
///
|
||||
/// @returns Success unless the Event has not been initialized yet (ErrorUnavailable) or an unexpected
|
||||
/// internal error occured when calling the OS (ErrorUnknown).
|
||||
Result Reset() const;
|
||||
|
||||
/// Waits for the event to enter the _set_ state before returning control to the caller. The event will change to
|
||||
/// the _reset_ state if manualReset was false on initialization.
|
||||
///
|
||||
/// @param [in] timeout Max time to wait, in seconds. If zero, this call will poll the event without blocking.
|
||||
///
|
||||
/// @returns Success if the wait completed successfully or Timeout if the wait did not complete but the operation
|
||||
/// timed out. Otherwise, one of the following errors may be returned:
|
||||
/// + ErrorInvalidValue will be returned if the timeout is negative.
|
||||
/// + ErrorUnknown may be returned if an unexpected internal occurs when calling the OS.
|
||||
Result Wait(fseconds timeout) const;
|
||||
|
||||
#if defined(_WIN32)
|
||||
/// On Windows, a handle to an OS event primitive is a HANDLE, which is just a void*.
|
||||
typedef void* EventHandle;
|
||||
#else
|
||||
/// On Linux, a handle to an OS event primitive is a file descriptor, which is just an int.
|
||||
typedef int32 EventHandle;
|
||||
#endif
|
||||
|
||||
/// Returns a handle to the actual OS event primitive associated with this object.
|
||||
EventHandle GetHandle() const { return m_hEvent; }
|
||||
|
||||
/// Open event handle.
|
||||
Result Open(EventHandle handle, bool isReference);
|
||||
|
||||
/// Constant EventHandle value which represents an invalid event object.
|
||||
static const EventHandle InvalidEvent;
|
||||
|
||||
private:
|
||||
EventHandle m_hEvent; // OS-specific event handle.
|
||||
bool m_isReference; // If true, the event is a global sharing object handle (not a duplicate) which is
|
||||
// imported from external, so it can't be closed in the currect destructor, and can only
|
||||
// be closed by the creater.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(Event);
|
||||
};
|
||||
} // Util
|
||||
|
||||
@@ -1,300 +1,300 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palFile.h
|
||||
* @brief PAL utility collection File class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// pal
|
||||
#include "palUtil.h"
|
||||
#include "palInlineFuncs.h"
|
||||
|
||||
// stl
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
|
||||
#if defined(_WIN32)
|
||||
/// Macro for wide string literal concatenation.
|
||||
#define PAL_PATH_SEPW L"\\"
|
||||
/// Macro for narrow string literal concatenation.
|
||||
#define PAL_PATH_SEP "\\"
|
||||
#else
|
||||
/// Macro for wide string literal concatenation.
|
||||
#define PAL_PATH_SEPW L"/"
|
||||
/// Macro for narrow string literal concatenation.
|
||||
#define PAL_PATH_SEP "/"
|
||||
#endif
|
||||
|
||||
namespace Util
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
/// Wide-character of the platform's prefered path separator.
|
||||
static constexpr wchar_t PathSepW = L'\\';
|
||||
/// Narrow-character of the platform's prefered path separator.
|
||||
static constexpr char PathSep = '\\';
|
||||
#else
|
||||
/// Wide-character of the platform's prefered path separator.
|
||||
static constexpr wchar_t PathSepW = L'/';
|
||||
/// Narrow-character of the platform's prefered path separator.
|
||||
static constexpr char PathSep = '/';
|
||||
#endif
|
||||
|
||||
static constexpr uint32 MaxPathStrLen = 512;
|
||||
static constexpr uint32 MaxFileNameStrLen = 256;
|
||||
|
||||
/// Enumerates access modes that may be required on an opened file.
|
||||
/// Can be bitwise ORed together to specify multiple simultaneous modes.
|
||||
enum FileAccessMode : uint32
|
||||
{
|
||||
FileAccessRead = 0x1, ///< Read access.
|
||||
FileAccessWrite = 0x2, ///< Write access.
|
||||
FileAccessAppend = 0x4, ///< Append access.
|
||||
FileAccessBinary = 0x8, ///< Binary access.
|
||||
FileAccessNoDiscard = 0x10, ///< Don't discard existing file.
|
||||
FileAccessShared = 0x20, ///< Require shared file access (simultaneous reading/writing by more than one process)
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Exposes simple file I/O functionality by encapsulating standard C runtime file I/O functions like fopen,
|
||||
* fwrite, etc.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class File
|
||||
{
|
||||
public:
|
||||
// Platform-agnostic 64-bit stat structure.
|
||||
struct Stat
|
||||
{
|
||||
uint64 size; // Size of the file in bytes.
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION < 922
|
||||
uint64 ctime; // Time of creation of the file (not valid on FAT).
|
||||
uint64 atime; // Time of last access to the file (not valid on FAT).
|
||||
uint64 mtime; // Time of last modification to the file.
|
||||
#else
|
||||
std::chrono::system_clock::time_point ctime; // Time of creation of the file (not valid on FAT).
|
||||
std::chrono::system_clock::time_point atime; // Time of last access to the file (not valid on FAT).
|
||||
std::chrono::system_clock::time_point mtime; // Time of last modification to the file.
|
||||
#endif
|
||||
uint32 nlink; // Number of hard links (always 1 on FAT on Windows).
|
||||
uint32 mode; // Bitmask for the file-mode information.
|
||||
uint32 dev; // Drive number of the disk containing the file.
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 isDir : 1;
|
||||
uint32 isRegular : 1;
|
||||
uint32 reserved : 30;
|
||||
};
|
||||
uint32 u32All;
|
||||
} flags;
|
||||
|
||||
// Common stat members omitted from this structure:
|
||||
// uid, gid, and ino because it's not used on Windows
|
||||
// rdev because it's a duplicate of dev
|
||||
};
|
||||
|
||||
// Where in the file to start seeking from.
|
||||
enum class SeekPosition : int32
|
||||
{
|
||||
// start of the file
|
||||
Start = SEEK_SET,
|
||||
// current file pointer position
|
||||
Current = SEEK_CUR,
|
||||
// end of the file
|
||||
End = SEEK_END
|
||||
};
|
||||
|
||||
File() : m_pFileHandle(nullptr), m_ownsHandle(false) {}
|
||||
|
||||
/// Closes the file if it is still open.
|
||||
~File() { Close(); }
|
||||
|
||||
/// Opens a file stream for read, write or append access.
|
||||
///
|
||||
/// @param [in] pFilename Name of file to open.
|
||||
/// @param [in] accessFlags Bitmask of FileAccessMode values indicating the usage of the file.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result Open(const char* pFilename, uint32 accessFlags);
|
||||
|
||||
/// Borrows an externally opened C runtime file handle for use by a File object.
|
||||
///
|
||||
/// The caller is still responsible for closing this handle after the File object is destroyed.
|
||||
///
|
||||
/// @param [in] pFile Externally opened C runtime file handle to borrow.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result FromNative(std::FILE* pFile);
|
||||
|
||||
/// Closes the file handle.
|
||||
void Close();
|
||||
|
||||
/// Writes a stream of bytes to the file.
|
||||
///
|
||||
/// @param [in] pBuffer Byte stream to be written to the file.
|
||||
/// @param [in] bufferSize Number of bytes to write.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result Write(const void* pBuffer, size_t bufferSize);
|
||||
|
||||
/// Reads a stream of bytes from the file.
|
||||
///
|
||||
/// @param [out] pBuffer Buffer to be written with data read from file.
|
||||
/// @param [in] bufferSize Size of the output buffer.
|
||||
/// @param [out] pBytesRead Number of bytes actually read (can be null).
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result Read(void* pBuffer, size_t bufferSize, size_t* pBytesRead);
|
||||
|
||||
/// Reads a single line of bytes from the file.
|
||||
///
|
||||
/// @param [out] pBuffer Buffer to be written with data read from file.
|
||||
/// @param [in] bufferSize Size of the output buffer.
|
||||
/// @param [out] pBytesRead Number of bytes actually read (can be null).
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result ReadLine(void* pBuffer, size_t bufferSize, size_t* pBytesRead);
|
||||
|
||||
/// Prints a formatted string to the file.
|
||||
///
|
||||
/// @param [in] pFormatStr Printf-style format string.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result Printf(const char* pFormatStr, ...) const;
|
||||
|
||||
/// Prints a formatted string to the file.
|
||||
///
|
||||
/// @param [in] pFormatStr Printf-style format string.
|
||||
/// @param [in] argList Variable argument list.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result VPrintf(const char* pFormatStr, va_list argList);
|
||||
|
||||
/// Flushes pending I/O to the file.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result Flush() const;
|
||||
|
||||
/// Sets the file position to the beginning of the file.
|
||||
void Rewind();
|
||||
|
||||
/// Sets the position indicator to a new position.
|
||||
///
|
||||
/// @param offset Number of bytes to offset
|
||||
/// @param pos File position to seek from
|
||||
void Seek(int64 offset, SeekPosition pos);
|
||||
|
||||
/// Sets the position indicator to a new position relative to the beginning of the file.
|
||||
///
|
||||
/// @param offset Number of bytes to offset
|
||||
void Seek(size_t offset) { Seek(offset, SeekPosition::Start); }
|
||||
|
||||
/// Sets the position indicator to a new position relative to the end of the file
|
||||
///
|
||||
/// @param offset Number of bytes to offset
|
||||
void Rseek(size_t offset) { Seek(-static_cast<int64>(offset), SeekPosition::End); }
|
||||
|
||||
/// Sets the file position to the end of the file.
|
||||
void FastForward() { Rseek(0); }
|
||||
|
||||
/// Returns true if the file is presently open.
|
||||
bool IsOpen() const { return (m_pFileHandle != nullptr); }
|
||||
|
||||
/// Gets the size of the file contents in bytes
|
||||
///
|
||||
/// @param [in] pFilename Name of the file to check.
|
||||
///
|
||||
/// @returns Size of the file in bytes, or std::numeric_limits<size_t>::max() on failure.
|
||||
static size_t GetFileSize(const char* pFilename);
|
||||
|
||||
/// Checks if a file with the specified name exists.
|
||||
///
|
||||
/// @param [in] pFilename Name of the file to check.
|
||||
///
|
||||
/// @returns True if the specified file exists.
|
||||
static bool Exists(const char* pFilename);
|
||||
|
||||
/// Platform-agnostic 64-bit stat() function.
|
||||
///
|
||||
/// @param [in] pFilename Name of the file to check.
|
||||
/// @param [out] pStatus The status of that file, if it exists.
|
||||
///
|
||||
/// @returns Success if the structure was retrieved, error otherwise.
|
||||
static Result GetStat(const char* pFilename, Stat* pStatus);
|
||||
|
||||
/// Removes/erases a file, if it exists.
|
||||
///
|
||||
/// @param [in] pFilename Name of file to remove.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
static Result Remove(const char* pFilename);
|
||||
|
||||
/// Reads a file into memory.
|
||||
///
|
||||
/// @param [in] pFilename Name of the file to read.
|
||||
/// @param [in] pData Buffer where the file contents are written to.
|
||||
/// @param [in] dataSize Size of the buffer in bytes.
|
||||
/// @param [out] pBytesRead Number of bytes successfully read into the input buffer (can be null).
|
||||
/// @param [in] binary True for binary mode, false for text. Defaults to binary.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
///
|
||||
/// @note The input buffer must be large enough to hold the file's contents. If the buffer is larger than the file,
|
||||
/// then the region of the buffer beyond the file size is _not_ modified by this function. It is the caller's
|
||||
/// responsibility to _not_ read uninitialized portions of the supplied buffer after this call returns.
|
||||
///
|
||||
/// @note In binary mode, the number of bytes read is equal to the file size in bytes upon a successful return.
|
||||
/// In text mode, newline conversion is performed on Windows, in which case the number of bytes read may not equal
|
||||
/// the file size in bytes.
|
||||
///
|
||||
/// @note In text mode, should the caller treat the resulting data as a C string, it is the caller's responsibility
|
||||
/// to null-terminate the buffer.
|
||||
static Result ReadFile(
|
||||
const char* pFilename,
|
||||
void* pData,
|
||||
size_t dataSize,
|
||||
size_t* pBytesRead = nullptr,
|
||||
bool binary = true);
|
||||
|
||||
/// Gets the handle associated with this file.
|
||||
///
|
||||
/// @returns A pointer to the file handle
|
||||
const std::FILE* GetHandle() const { return m_pFileHandle; }
|
||||
|
||||
private:
|
||||
std::FILE* m_pFileHandle;
|
||||
bool m_ownsHandle; // This object owns the file handle and will close it on destruction.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(File);
|
||||
};
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palFile.h
|
||||
* @brief PAL utility collection File class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// pal
|
||||
#include "palUtil.h"
|
||||
#include "palInlineFuncs.h"
|
||||
|
||||
// stl
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
|
||||
#if defined(_WIN32)
|
||||
/// Macro for wide string literal concatenation.
|
||||
#define PAL_PATH_SEPW L"\\"
|
||||
/// Macro for narrow string literal concatenation.
|
||||
#define PAL_PATH_SEP "\\"
|
||||
#else
|
||||
/// Macro for wide string literal concatenation.
|
||||
#define PAL_PATH_SEPW L"/"
|
||||
/// Macro for narrow string literal concatenation.
|
||||
#define PAL_PATH_SEP "/"
|
||||
#endif
|
||||
|
||||
namespace Util
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
/// Wide-character of the platform's prefered path separator.
|
||||
static constexpr wchar_t PathSepW = L'\\';
|
||||
/// Narrow-character of the platform's prefered path separator.
|
||||
static constexpr char PathSep = '\\';
|
||||
#else
|
||||
/// Wide-character of the platform's prefered path separator.
|
||||
static constexpr wchar_t PathSepW = L'/';
|
||||
/// Narrow-character of the platform's prefered path separator.
|
||||
static constexpr char PathSep = '/';
|
||||
#endif
|
||||
|
||||
static constexpr uint32 MaxPathStrLen = 512;
|
||||
static constexpr uint32 MaxFileNameStrLen = 256;
|
||||
|
||||
/// Enumerates access modes that may be required on an opened file.
|
||||
/// Can be bitwise ORed together to specify multiple simultaneous modes.
|
||||
enum FileAccessMode : uint32
|
||||
{
|
||||
FileAccessRead = 0x1, ///< Read access.
|
||||
FileAccessWrite = 0x2, ///< Write access.
|
||||
FileAccessAppend = 0x4, ///< Append access.
|
||||
FileAccessBinary = 0x8, ///< Binary access.
|
||||
FileAccessNoDiscard = 0x10, ///< Don't discard existing file.
|
||||
FileAccessShared = 0x20, ///< Require shared file access (simultaneous reading/writing by more than one process)
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Exposes simple file I/O functionality by encapsulating standard C runtime file I/O functions like fopen,
|
||||
* fwrite, etc.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class File
|
||||
{
|
||||
public:
|
||||
// Platform-agnostic 64-bit stat structure.
|
||||
struct Stat
|
||||
{
|
||||
uint64 size; // Size of the file in bytes.
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION < 922
|
||||
uint64 ctime; // Time of creation of the file (not valid on FAT).
|
||||
uint64 atime; // Time of last access to the file (not valid on FAT).
|
||||
uint64 mtime; // Time of last modification to the file.
|
||||
#else
|
||||
std::chrono::system_clock::time_point ctime; // Time of creation of the file (not valid on FAT).
|
||||
std::chrono::system_clock::time_point atime; // Time of last access to the file (not valid on FAT).
|
||||
std::chrono::system_clock::time_point mtime; // Time of last modification to the file.
|
||||
#endif
|
||||
uint32 nlink; // Number of hard links (always 1 on FAT on Windows).
|
||||
uint32 mode; // Bitmask for the file-mode information.
|
||||
uint32 dev; // Drive number of the disk containing the file.
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 isDir : 1;
|
||||
uint32 isRegular : 1;
|
||||
uint32 reserved : 30;
|
||||
};
|
||||
uint32 u32All;
|
||||
} flags;
|
||||
|
||||
// Common stat members omitted from this structure:
|
||||
// uid, gid, and ino because it's not used on Windows
|
||||
// rdev because it's a duplicate of dev
|
||||
};
|
||||
|
||||
// Where in the file to start seeking from.
|
||||
enum class SeekPosition : int32
|
||||
{
|
||||
// start of the file
|
||||
Start = SEEK_SET,
|
||||
// current file pointer position
|
||||
Current = SEEK_CUR,
|
||||
// end of the file
|
||||
End = SEEK_END
|
||||
};
|
||||
|
||||
File() : m_pFileHandle(nullptr), m_ownsHandle(false) {}
|
||||
|
||||
/// Closes the file if it is still open.
|
||||
~File() { Close(); }
|
||||
|
||||
/// Opens a file stream for read, write or append access.
|
||||
///
|
||||
/// @param [in] pFilename Name of file to open.
|
||||
/// @param [in] accessFlags Bitmask of FileAccessMode values indicating the usage of the file.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result Open(const char* pFilename, uint32 accessFlags);
|
||||
|
||||
/// Borrows an externally opened C runtime file handle for use by a File object.
|
||||
///
|
||||
/// The caller is still responsible for closing this handle after the File object is destroyed.
|
||||
///
|
||||
/// @param [in] pFile Externally opened C runtime file handle to borrow.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result FromNative(std::FILE* pFile);
|
||||
|
||||
/// Closes the file handle.
|
||||
void Close();
|
||||
|
||||
/// Writes a stream of bytes to the file.
|
||||
///
|
||||
/// @param [in] pBuffer Byte stream to be written to the file.
|
||||
/// @param [in] bufferSize Number of bytes to write.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result Write(const void* pBuffer, size_t bufferSize);
|
||||
|
||||
/// Reads a stream of bytes from the file.
|
||||
///
|
||||
/// @param [out] pBuffer Buffer to be written with data read from file.
|
||||
/// @param [in] bufferSize Size of the output buffer.
|
||||
/// @param [out] pBytesRead Number of bytes actually read (can be null).
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result Read(void* pBuffer, size_t bufferSize, size_t* pBytesRead);
|
||||
|
||||
/// Reads a single line of bytes from the file.
|
||||
///
|
||||
/// @param [out] pBuffer Buffer to be written with data read from file.
|
||||
/// @param [in] bufferSize Size of the output buffer.
|
||||
/// @param [out] pBytesRead Number of bytes actually read (can be null).
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result ReadLine(void* pBuffer, size_t bufferSize, size_t* pBytesRead);
|
||||
|
||||
/// Prints a formatted string to the file.
|
||||
///
|
||||
/// @param [in] pFormatStr Printf-style format string.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result Printf(const char* pFormatStr, ...) const;
|
||||
|
||||
/// Prints a formatted string to the file.
|
||||
///
|
||||
/// @param [in] pFormatStr Printf-style format string.
|
||||
/// @param [in] argList Variable argument list.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result VPrintf(const char* pFormatStr, va_list argList);
|
||||
|
||||
/// Flushes pending I/O to the file.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
Result Flush() const;
|
||||
|
||||
/// Sets the file position to the beginning of the file.
|
||||
void Rewind();
|
||||
|
||||
/// Sets the position indicator to a new position.
|
||||
///
|
||||
/// @param offset Number of bytes to offset
|
||||
/// @param pos File position to seek from
|
||||
void Seek(int64 offset, SeekPosition pos);
|
||||
|
||||
/// Sets the position indicator to a new position relative to the beginning of the file.
|
||||
///
|
||||
/// @param offset Number of bytes to offset
|
||||
void Seek(size_t offset) { Seek(offset, SeekPosition::Start); }
|
||||
|
||||
/// Sets the position indicator to a new position relative to the end of the file
|
||||
///
|
||||
/// @param offset Number of bytes to offset
|
||||
void Rseek(size_t offset) { Seek(-static_cast<int64>(offset), SeekPosition::End); }
|
||||
|
||||
/// Sets the file position to the end of the file.
|
||||
void FastForward() { Rseek(0); }
|
||||
|
||||
/// Returns true if the file is presently open.
|
||||
bool IsOpen() const { return (m_pFileHandle != nullptr); }
|
||||
|
||||
/// Gets the size of the file contents in bytes
|
||||
///
|
||||
/// @param [in] pFilename Name of the file to check.
|
||||
///
|
||||
/// @returns Size of the file in bytes, or std::numeric_limits<size_t>::max() on failure.
|
||||
static size_t GetFileSize(const char* pFilename);
|
||||
|
||||
/// Checks if a file with the specified name exists.
|
||||
///
|
||||
/// @param [in] pFilename Name of the file to check.
|
||||
///
|
||||
/// @returns True if the specified file exists.
|
||||
static bool Exists(const char* pFilename);
|
||||
|
||||
/// Platform-agnostic 64-bit stat() function.
|
||||
///
|
||||
/// @param [in] pFilename Name of the file to check.
|
||||
/// @param [out] pStatus The status of that file, if it exists.
|
||||
///
|
||||
/// @returns Success if the structure was retrieved, error otherwise.
|
||||
static Result GetStat(const char* pFilename, Stat* pStatus);
|
||||
|
||||
/// Removes/erases a file, if it exists.
|
||||
///
|
||||
/// @param [in] pFilename Name of file to remove.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
static Result Remove(const char* pFilename);
|
||||
|
||||
/// Reads a file into memory.
|
||||
///
|
||||
/// @param [in] pFilename Name of the file to read.
|
||||
/// @param [in] pData Buffer where the file contents are written to.
|
||||
/// @param [in] dataSize Size of the buffer in bytes.
|
||||
/// @param [out] pBytesRead Number of bytes successfully read into the input buffer (can be null).
|
||||
/// @param [in] binary True for binary mode, false for text. Defaults to binary.
|
||||
///
|
||||
/// @returns Success if successful, otherwise an appropriate error.
|
||||
///
|
||||
/// @note The input buffer must be large enough to hold the file's contents. If the buffer is larger than the file,
|
||||
/// then the region of the buffer beyond the file size is _not_ modified by this function. It is the caller's
|
||||
/// responsibility to _not_ read uninitialized portions of the supplied buffer after this call returns.
|
||||
///
|
||||
/// @note In binary mode, the number of bytes read is equal to the file size in bytes upon a successful return.
|
||||
/// In text mode, newline conversion is performed on Windows, in which case the number of bytes read may not equal
|
||||
/// the file size in bytes.
|
||||
///
|
||||
/// @note In text mode, should the caller treat the resulting data as a C string, it is the caller's responsibility
|
||||
/// to null-terminate the buffer.
|
||||
static Result ReadFile(
|
||||
const char* pFilename,
|
||||
void* pData,
|
||||
size_t dataSize,
|
||||
size_t* pBytesRead = nullptr,
|
||||
bool binary = true);
|
||||
|
||||
/// Gets the handle associated with this file.
|
||||
///
|
||||
/// @returns A pointer to the file handle
|
||||
const std::FILE* GetHandle() const { return m_pFileHandle; }
|
||||
|
||||
private:
|
||||
std::FILE* m_pFileHandle;
|
||||
bool m_ownsHandle; // This object owns the file handle and will close it on destruction.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(File);
|
||||
};
|
||||
|
||||
} // Util
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,143 +1,137 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palHashMap.h
|
||||
* @brief PAL utility collection HashMap class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palHashBase.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// Encapsulates one key/value pair in a hash map.
|
||||
template<typename Key, typename Value>
|
||||
struct HashMapEntry
|
||||
{
|
||||
Key key; ///< Hash map entry key.
|
||||
Value value; ///< Hash map entry value.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Templated hash map container.
|
||||
*
|
||||
* This container is meant for storing elements of an arbitrary (but uniform) key/value type. Supported operations:
|
||||
*
|
||||
* - Searching
|
||||
* - Insertion
|
||||
* - Deletion
|
||||
* - Iteration
|
||||
*
|
||||
* HashFunc is a functor for hashing keys. Built-in choices for HashFunc are:
|
||||
*
|
||||
* - DefaultHashFunc: Good choice when the key is a pointer.
|
||||
* - JenkinsHashFunc: Good choice when the key is arbitrary binary data.
|
||||
* - StringJenkinsHashFunc: Good choice when the key is a C-style string.
|
||||
*
|
||||
* EqualFunc is a functor for comparing keys. Built-in choices for EqualFunc are:
|
||||
*
|
||||
* - DefaultEqualFunc: Determines keys are equal by bitwise comparison.
|
||||
* - StringEqualFunc: Treats keys as a char* and compares them as C-style strings.
|
||||
*
|
||||
* @warning This class is not thread-safe for Insert, FindAllocate, Erase, or iteration!
|
||||
* @warning Init() must be called before using this container. Begin() and Reset() can be safely called before
|
||||
* initialization and Begin() will always return an iterator that points to null.
|
||||
*
|
||||
* For more details please refer to @ref HashBase.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename Key,
|
||||
typename Value,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc = DefaultHashFunc,
|
||||
template<typename> class EqualFunc = DefaultEqualFunc,
|
||||
typename AllocFunc = HashAllocator<Allocator>,
|
||||
size_t GroupSize = PAL_CACHE_LINE_BYTES * 2>
|
||||
class HashMap : public HashBase<Key, HashMapEntry<Key, Value>, Allocator, HashFunc<Key>, EqualFunc<Key>, AllocFunc, GroupSize>
|
||||
{
|
||||
public:
|
||||
/// Convenience typedef for a templated entry of this hash map.
|
||||
typedef HashMapEntry<Key, Value> Entry;
|
||||
|
||||
/// @internal Constructor
|
||||
///
|
||||
/// @param [in] numBuckets Number of buckets to allocate for this hash container. The initial hash container will
|
||||
/// take (buckets * GroupSize) bytes.
|
||||
/// @param [in] pAllocator Pointer to an allocator that will create system memory requested by this hash container.
|
||||
explicit HashMap(uint32 numBuckets, Allocator*const pAllocator): Base::HashBase(numBuckets, pAllocator) { }
|
||||
virtual ~HashMap() { }
|
||||
|
||||
/// Finds a given entry; if no entry was found, allocate it.
|
||||
///
|
||||
/// @param [in] key Key to search for.
|
||||
/// @param [out] pExisted True if an entry for the specified key existed before this call was made. False indicates
|
||||
/// that a new entry was allocated as a result of this call.
|
||||
/// @param [out] ppValue Readable/writeable value in the hash map corresponding to the specified key.
|
||||
///
|
||||
/// @returns @ref Success if the operation completed successfully, or @ref ErrorOutOfMemory if the operation failed
|
||||
/// because an internal memory allocation failed.
|
||||
Result FindAllocate(const Key& key, bool* pExisted, Value** ppValue);
|
||||
|
||||
/// Gets a pointer to the value that matches the specified key.
|
||||
///
|
||||
/// @param [in] key Key to search for.
|
||||
///
|
||||
/// @returns A pointer to the value that matches the specified key or null if an entry for the key does not exist.
|
||||
Value* FindKey(const Key& key) const;
|
||||
|
||||
/// Inserts a key/value pair entry if the key doesn't already exist in the hash map.
|
||||
///
|
||||
/// @warning No action will be taken if an entry matching this key already exists, even if the specified value
|
||||
/// differs from the current value stored in the entry matching the specified key.
|
||||
///
|
||||
/// @param [in] key Key of the new entry to insert.
|
||||
/// @param [in] value Value of the new entry to insert.
|
||||
///
|
||||
/// @returns @ref Success if the operation completed successfully, or @ref ErrorOutOfMemory if the operation failed
|
||||
/// because an internal memory allocation failed.
|
||||
Result Insert(const Key& key, const Value& value);
|
||||
|
||||
/// Removes an entry that matches the specified key.
|
||||
///
|
||||
/// @param [in] key Key of the entry to erase.
|
||||
///
|
||||
/// @returns True if the erase completed successfully, false if an entry for this key did not exist.
|
||||
bool Erase(const Key& key);
|
||||
|
||||
private:
|
||||
// Typedef for the specialized 'HashBase' object we're inheriting from so we can use properly qualified names when
|
||||
// accessing members of HashBase.
|
||||
typedef HashBase<Key, HashMapEntry<Key, Value>, Allocator, HashFunc<Key>, EqualFunc<Key>, AllocFunc, GroupSize> Base;
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(HashMap);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(HashMap);
|
||||
};
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palHashMap.h
|
||||
* @brief PAL utility collection HashMap class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palHashBase.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// Encapsulates one key/value pair in a hash map.
|
||||
template<typename Key, typename Value>
|
||||
struct HashMapEntry
|
||||
{
|
||||
Key key; ///< Hash map entry key.
|
||||
Value value; ///< Hash map entry value.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Templated hash map container.
|
||||
*
|
||||
* This container is meant for storing elements of an arbitrary (but uniform) key/value type. Supported operations:
|
||||
*
|
||||
* - Searching
|
||||
* - Insertion
|
||||
* - Deletion
|
||||
* - Iteration
|
||||
*
|
||||
* HashFunc is a functor for hashing keys. Built-in choices for HashFunc are:
|
||||
*
|
||||
* - DefaultHashFunc: Default hash function, selects best hash function based on type of key.
|
||||
* - PointerHashFunc: Good choice when the key is a pointer.
|
||||
* - JenkinsHashFunc: Good choice when the key is arbitrary binary data.
|
||||
* - StringJenkinsHashFunc: Good choice when the key is a C-style string.
|
||||
*
|
||||
* EqualFunc is a functor for comparing keys. Built-in choices for EqualFunc are:
|
||||
*
|
||||
* - DefaultEqualFunc: Determines keys are equal by bitwise comparison.
|
||||
* - StringEqualFunc: Treats keys as a char* and compares them as C-style strings.
|
||||
*
|
||||
* @warning This class is not thread-safe for Insert, FindAllocate, Erase, or iteration!
|
||||
* @warning Init() must be called before using this container. Begin() and Reset() can be safely called before
|
||||
* initialization and Begin() will always return an iterator that points to null.
|
||||
*
|
||||
* For more details please refer to @ref HashBase.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename Key,
|
||||
typename Value,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc = DefaultHashFunc,
|
||||
template<typename> class EqualFunc = DefaultEqualFunc,
|
||||
typename AllocFunc = HashAllocator<Allocator>,
|
||||
size_t GroupSize = PAL_CACHE_LINE_BYTES * 2>
|
||||
class HashMap : public HashBase<Key, HashMapEntry<Key, Value>, Allocator, HashFunc<Key>, EqualFunc<Key>, AllocFunc, GroupSize>
|
||||
{
|
||||
public:
|
||||
/// Convenience typedef for a templated entry of this hash map.
|
||||
typedef HashMapEntry<Key, Value> Entry;
|
||||
|
||||
/// @internal Constructor
|
||||
///
|
||||
/// @param [in] numBuckets Number of buckets to allocate for this hash container. The initial hash container will
|
||||
/// take (buckets * GroupSize) bytes.
|
||||
/// @param [in] pAllocator Pointer to an allocator that will create system memory requested by this hash container.
|
||||
explicit HashMap(uint32 numBuckets, Allocator*const pAllocator): Base::HashBase(numBuckets, pAllocator) { }
|
||||
~HashMap() { }
|
||||
|
||||
/// Finds a given entry; if no entry was found, allocate it.
|
||||
///
|
||||
/// @param [in] key Key to search for.
|
||||
/// @param [out] pExisted True if an entry for the specified key existed before this call was made. False indicates
|
||||
/// that a new entry was allocated as a result of this call.
|
||||
/// @param [out] ppValue Readable/writeable value in the hash map corresponding to the specified key.
|
||||
///
|
||||
/// @returns @ref Success if the operation completed successfully, or @ref ErrorOutOfMemory if the operation failed
|
||||
/// because an internal memory allocation failed.
|
||||
Result FindAllocate(const Key& key, bool* pExisted, Value** ppValue);
|
||||
|
||||
/// Gets a pointer to the value that matches the specified key.
|
||||
///
|
||||
/// @param [in] key Key to search for.
|
||||
///
|
||||
/// @returns A pointer to the value that matches the specified key or null if an entry for the key does not exist.
|
||||
Value* FindKey(const Key& key) const;
|
||||
|
||||
/// Inserts a key/value pair entry if the key doesn't already exist in the hash map.
|
||||
///
|
||||
/// @warning No action will be taken if an entry matching this key already exists, even if the specified value
|
||||
/// differs from the current value stored in the entry matching the specified key.
|
||||
///
|
||||
/// @param [in] key Key of the new entry to insert.
|
||||
/// @param [in] value Value of the new entry to insert.
|
||||
///
|
||||
/// @returns @ref Success if the operation completed successfully, or @ref ErrorOutOfMemory if the operation failed
|
||||
/// because an internal memory allocation failed.
|
||||
Result Insert(const Key& key, const Value& value);
|
||||
|
||||
private:
|
||||
// Typedef for the specialized 'HashBase' object we're inheriting from so we can use properly qualified names when
|
||||
// accessing members of HashBase.
|
||||
typedef HashBase<Key, HashMapEntry<Key, Value>, Allocator, HashFunc<Key>, EqualFunc<Key>, AllocFunc, GroupSize> Base;
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(HashMap);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(HashMap);
|
||||
};
|
||||
|
||||
} // Util
|
||||
|
||||
@@ -1,250 +1,114 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palHashMapImpl.h
|
||||
* @brief PAL utility collection HashMap class implementation.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palHashBaseImpl.h"
|
||||
#include "palHashMap.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
// =====================================================================================================================
|
||||
// Gets a pointer to the value that matches the key. If the key is not present, a pointer to empty space for the value
|
||||
// is returned.
|
||||
template<typename Key,
|
||||
typename Value,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
Result HashMap<Key, Value, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::FindAllocate(
|
||||
const Key& key, // Key to search for.
|
||||
bool* pExisted, // [out] True if a matching key was found.
|
||||
Value** ppValue) // [out] Pointer to the value entry of the hash map's entry for the specified key.
|
||||
{
|
||||
PAL_ASSERT(pExisted != nullptr);
|
||||
PAL_ASSERT(ppValue != nullptr);
|
||||
|
||||
Result result = Result::ErrorOutOfMemory;
|
||||
|
||||
// Get the bucket base address....
|
||||
Entry* pGroup = this->InitAndFindBucket(key);
|
||||
|
||||
*pExisted = false;
|
||||
*ppValue = nullptr;
|
||||
|
||||
Entry* pMatchingEntry = nullptr;
|
||||
|
||||
while (pGroup != nullptr)
|
||||
{
|
||||
const uint32 numEntries = this->GetGroupFooterNumEntries(pGroup);
|
||||
|
||||
// Search this entry group.
|
||||
uint32 i = 0;
|
||||
for (; i < numEntries; i++)
|
||||
{
|
||||
if (this->m_equalFunc(pGroup[i].key, key))
|
||||
{
|
||||
// We've found the entry.
|
||||
pMatchingEntry = &(pGroup[i]);
|
||||
*pExisted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We've reached the end of the allocated buckets and the entry was not found.
|
||||
// Allocate this entry for the key.
|
||||
if ((pMatchingEntry == nullptr) && (i < Base::EntriesInGroup))
|
||||
{
|
||||
pGroup[i].key = key;
|
||||
pMatchingEntry = &(pGroup[i]);
|
||||
this->m_numEntries++;
|
||||
this->SetGroupFooterNumEntries(pGroup, numEntries + 1);
|
||||
}
|
||||
|
||||
if (pMatchingEntry != nullptr)
|
||||
{
|
||||
*ppValue = &(pMatchingEntry->value);
|
||||
result = Result::Success;
|
||||
break;
|
||||
}
|
||||
|
||||
// Chain to the next entry group.
|
||||
pGroup = this->AllocateNextGroup(pGroup);
|
||||
}
|
||||
|
||||
PAL_ASSERT(result == Result::Success);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Gets a pointer to the value that matches the key. Returns null if no entry is present matching the specified key.
|
||||
template<typename Key,
|
||||
typename Value,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
Value* HashMap<Key, Value, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::FindKey(
|
||||
const Key& key
|
||||
) const
|
||||
{
|
||||
// Get the bucket base address.
|
||||
Entry* pGroup = this->FindBucket(key);
|
||||
Entry* pMatchingEntry = nullptr;
|
||||
|
||||
while (pGroup != nullptr)
|
||||
{
|
||||
const uint32 numEntries = this->GetGroupFooterNumEntries(pGroup);
|
||||
|
||||
// Search this entry group
|
||||
uint32 i = 0;
|
||||
for (; i < numEntries; i++)
|
||||
{
|
||||
if (this->m_equalFunc(pGroup[i].key, key))
|
||||
{
|
||||
// We've found the entry.
|
||||
pMatchingEntry = &(pGroup[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pMatchingEntry != nullptr) || (i < Base::EntriesInGroup))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Chain to the next entry group.
|
||||
pGroup = this->GetNextGroup(pGroup);
|
||||
}
|
||||
|
||||
return (pMatchingEntry != nullptr) ? &(pMatchingEntry->value) : nullptr;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Inserts a key/value pair entry if it doesn't already exist.
|
||||
template<typename Key,
|
||||
typename Value,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
Result HashMap<Key, Value, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::Insert(
|
||||
const Key& key,
|
||||
const Value& value)
|
||||
{
|
||||
bool existed = true;
|
||||
Value* pValue = nullptr;
|
||||
|
||||
Result result = FindAllocate(key, &existed, &pValue);
|
||||
|
||||
// Add the new value if it did not exist already. If FindAllocate returns Success, pValue != nullptr.
|
||||
if ((result == Result::Success) && (existed == false))
|
||||
{
|
||||
*pValue = value;
|
||||
}
|
||||
|
||||
PAL_ASSERT(result == Result::Success);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Removes an entry with the specified key.
|
||||
template<typename Key,
|
||||
typename Value,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
bool HashMap<Key, Value, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::Erase(
|
||||
const Key& key)
|
||||
{
|
||||
// Get the bucket base address.
|
||||
Entry* pGroup = this->FindBucket(key);
|
||||
|
||||
Entry* pFoundEntry = nullptr;
|
||||
Entry* pLastEntry = nullptr;
|
||||
Entry* pLastEntryGroup = nullptr;
|
||||
|
||||
// Find the entry to delete
|
||||
while (pGroup != nullptr)
|
||||
{
|
||||
const uint32 numEntries = this->GetGroupFooterNumEntries(pGroup);
|
||||
|
||||
// Search each group
|
||||
uint32 i = 0;
|
||||
for (; i < numEntries; i++)
|
||||
{
|
||||
if (this->m_equalFunc(pGroup[i].key, key) == true)
|
||||
{
|
||||
// We shouldn't find the same key twice.
|
||||
PAL_ASSERT(pFoundEntry == nullptr);
|
||||
|
||||
pFoundEntry = &(pGroup[i]);
|
||||
}
|
||||
|
||||
// keep track of last entry of all groups in bucket
|
||||
pLastEntry = &(pGroup[i]);
|
||||
pLastEntryGroup = pGroup;
|
||||
}
|
||||
|
||||
// Chain to the next entry group.
|
||||
pGroup = this->GetNextGroup(pGroup);
|
||||
}
|
||||
|
||||
// Copy the last entry's data into the entry that we are removing and invalidate the last entry as it now appears
|
||||
// earlier in the list. This also handles the case where the entry to be removed is the last entry.
|
||||
if (pFoundEntry != nullptr)
|
||||
{
|
||||
PAL_ASSERT(pLastEntry != nullptr);
|
||||
|
||||
pFoundEntry->key = pLastEntry->key;
|
||||
pFoundEntry->value = pLastEntry->value;
|
||||
|
||||
memset(pLastEntry, 0, sizeof(Entry));
|
||||
|
||||
PAL_ASSERT(this->m_numEntries > 0);
|
||||
this->m_numEntries--;
|
||||
const uint32 numEntries = this->GetGroupFooterNumEntries(pLastEntryGroup);
|
||||
this->SetGroupFooterNumEntries(pLastEntryGroup, numEntries - 1);
|
||||
}
|
||||
|
||||
return (pFoundEntry != nullptr);
|
||||
}
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palHashMapImpl.h
|
||||
* @brief PAL utility collection HashMap class implementation.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palHashBaseImpl.h"
|
||||
#include "palHashMap.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
// =====================================================================================================================
|
||||
// Gets a pointer to the value that matches the key. If the key is not present, a pointer to empty space for the value
|
||||
// is returned.
|
||||
template<typename Key,
|
||||
typename Value,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
Result HashMap<Key, Value, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::FindAllocate(
|
||||
const Key& key, // Key to search for.
|
||||
bool* pExisted, // [out] True if a matching key was found.
|
||||
Value** ppValue) // [out] Pointer to the value entry of the hash map's entry for the specified key.
|
||||
{
|
||||
PAL_ASSERT(pExisted != nullptr);
|
||||
PAL_ASSERT(ppValue != nullptr);
|
||||
|
||||
Entry* pEntry = nullptr;
|
||||
Result result = Base::FindAllocateEntry(key, pExisted, &pEntry);
|
||||
if (result == Result::Success)
|
||||
{
|
||||
*ppValue = &pEntry->value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Gets a pointer to the value that matches the key. Returns null if no entry is present matching the specified key.
|
||||
template<typename Key,
|
||||
typename Value,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
Value* HashMap<Key, Value, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::FindKey(
|
||||
const Key& key
|
||||
) const
|
||||
{
|
||||
Entry* pEntry = Base::FindEntry(key);
|
||||
return (pEntry != nullptr) ? &pEntry->value : nullptr;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Inserts a key/value pair entry if it doesn't already exist.
|
||||
template<typename Key,
|
||||
typename Value,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
Result HashMap<Key, Value, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::Insert(
|
||||
const Key& key,
|
||||
const Value& value)
|
||||
{
|
||||
bool existed = true;
|
||||
Entry* pEntry = nullptr;
|
||||
|
||||
Result result = Base::FindAllocateEntry(key, &existed, &pEntry);
|
||||
|
||||
// Add the new value if it did not exist already. If FindAllocate returns Success, pValue != nullptr.
|
||||
if ((result == Result::Success) && (existed == false))
|
||||
{
|
||||
pEntry->value = value;
|
||||
}
|
||||
|
||||
PAL_ASSERT(result == Result::Success);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // Util
|
||||
|
||||
@@ -1,144 +1,131 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palHashSet.h
|
||||
* @brief PAL utility collection HashSet class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palHashBase.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// Encapsulates one entry of a hash set.
|
||||
template<typename Key>
|
||||
struct HashSetEntry
|
||||
{
|
||||
Key key; ///< Hash set entry key.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Templated hash set container.
|
||||
*
|
||||
* This is meant for storing elements of an arbitrary (but uniform) key type. Supported operations:
|
||||
*
|
||||
* - Searching
|
||||
* - Insertion
|
||||
* - Deletion
|
||||
* - Iteration
|
||||
*
|
||||
* HashFunc is a functor for hashing keys. Built-in choices for HashFunc are:
|
||||
*
|
||||
* - DefaultHashFunc: Good choice when the key is a pointer.
|
||||
* - JenkinsHashFunc: Good choice when the key is arbitrary binary data.
|
||||
* - StringJenkinsHashFunc: Good choice when the key is a C-style string.
|
||||
*
|
||||
* EqualFunc is a functor for comparing keys. Built-in choices for EqualFunc are:
|
||||
*
|
||||
* - DefaultEqualFunc: Determines keys are equal by bitwise comparison.
|
||||
* - StringEqualFunc: Treats keys as a char* and compares them as C-style strings.
|
||||
*
|
||||
* @warning This class is not thread-safe for Insert, Erase, or iteration!
|
||||
* @warning Init() must be called before using this container. Begin() and Reset() can be safely called before
|
||||
* initialization and Begin() will always return an iterator that points to null.
|
||||
*
|
||||
* For more details please refer to @ref HashBase.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename Key,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc = DefaultHashFunc,
|
||||
template<typename> class EqualFunc = DefaultEqualFunc,
|
||||
typename AllocFunc = HashAllocator<Allocator>,
|
||||
size_t GroupSize = PAL_CACHE_LINE_BYTES * 2>
|
||||
class HashSet : public HashBase<Key,
|
||||
HashSetEntry<Key>,
|
||||
Allocator,
|
||||
HashFunc<Key>,
|
||||
EqualFunc<Key>,
|
||||
AllocFunc,
|
||||
GroupSize>
|
||||
{
|
||||
public:
|
||||
/// Convenience typedef for a templated entry of this hash set.
|
||||
typedef HashSetEntry<Key> Entry;
|
||||
|
||||
/// @internal Constructor
|
||||
///
|
||||
/// @param [in] numBuckets Number of buckets to allocate for this hash container. The initial hash container will
|
||||
/// take (buckets * GroupSize) bytes.
|
||||
/// @param [in] pAllocator Pointer to an allocator that will create system memory requested by this hash container.
|
||||
explicit HashSet(uint32 numBuckets, Allocator*const pAllocator) : Base::HashBase(numBuckets, pAllocator) {}
|
||||
virtual ~HashSet() { }
|
||||
|
||||
/// Finds a given entry; if no entry was found, allocate it.
|
||||
///
|
||||
/// @param [in] ppKey Key to search for.
|
||||
/// @param [out] pExisted True if an entry for the specified key existed before this call was made.
|
||||
/// False indicates that a new entry was allocated as a result of this call.
|
||||
///
|
||||
/// @returns @ref Success if the operation completed successfully
|
||||
/// @ref ErrorOutOfMemory if the operation failed because an internal memory allocation failed.
|
||||
Result FindAllocate(Key** ppKey, bool* pExisted);
|
||||
|
||||
/// Returns true if the specified key exists in the set.
|
||||
///
|
||||
/// @param [in] key Key to search for.
|
||||
///
|
||||
/// @returns True if the specified key exists in the set.
|
||||
bool Contains(const Key& key) const;
|
||||
|
||||
/// Inserts an entry.
|
||||
///
|
||||
/// No action will be taken if an entry matching this key already exists in the set.
|
||||
///
|
||||
/// @param [in] key New entry to insert.
|
||||
///
|
||||
/// @returns @ref Success if the operation completed successfully, or @ref ErrorOutOfMemory if the operation failed
|
||||
/// because an internal memory allocation failed.
|
||||
Result Insert(const Key& key);
|
||||
|
||||
/// Removes an entry that matches the specified key.
|
||||
///
|
||||
/// @param [in] key Key of the entry to erase.
|
||||
///
|
||||
/// @returns True if the erase completed successfully, false if an entry for this key did not exist.
|
||||
bool Erase(const Key& key);
|
||||
|
||||
private:
|
||||
// Typedef for the specialized 'HashBase' object we're inheriting from so we can use properly qualified names when
|
||||
// accessing members of HashBase.
|
||||
typedef HashBase<Key, HashSetEntry<Key>, Allocator, HashFunc<Key>, EqualFunc<Key>, AllocFunc, GroupSize> Base;
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(HashSet);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(HashSet);
|
||||
};
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palHashSet.h
|
||||
* @brief PAL utility collection HashSet class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palHashBase.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// Encapsulates one entry of a hash set.
|
||||
template<typename Key>
|
||||
struct HashSetEntry
|
||||
{
|
||||
Key key; ///< Hash set entry key.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Templated hash set container.
|
||||
*
|
||||
* This is meant for storing elements of an arbitrary (but uniform) key type. Supported operations:
|
||||
*
|
||||
* - Searching
|
||||
* - Insertion
|
||||
* - Deletion
|
||||
* - Iteration
|
||||
*
|
||||
* HashFunc is a functor for hashing keys. Built-in choices for HashFunc are:
|
||||
*
|
||||
* - DefaultHashFunc: Default hash function, selects best hash function based on type of key.
|
||||
* - PointerHashFunc: Good choice when the key is a pointer.
|
||||
* - JenkinsHashFunc: Good choice when the key is arbitrary binary data.
|
||||
* - StringJenkinsHashFunc: Good choice when the key is a C-style string.
|
||||
*
|
||||
* EqualFunc is a functor for comparing keys. Built-in choices for EqualFunc are:
|
||||
*
|
||||
* - DefaultEqualFunc: Determines keys are equal by bitwise comparison.
|
||||
* - StringEqualFunc: Treats keys as a char* and compares them as C-style strings.
|
||||
*
|
||||
* @warning This class is not thread-safe for Insert, Erase, or iteration!
|
||||
* @warning Init() must be called before using this container. Begin() and Reset() can be safely called before
|
||||
* initialization and Begin() will always return an iterator that points to null.
|
||||
*
|
||||
* For more details please refer to @ref HashBase.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename Key,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc = DefaultHashFunc,
|
||||
template<typename> class EqualFunc = DefaultEqualFunc,
|
||||
typename AllocFunc = HashAllocator<Allocator>,
|
||||
size_t GroupSize = PAL_CACHE_LINE_BYTES * 2>
|
||||
class HashSet : public HashBase<Key,
|
||||
HashSetEntry<Key>,
|
||||
Allocator,
|
||||
HashFunc<Key>,
|
||||
EqualFunc<Key>,
|
||||
AllocFunc,
|
||||
GroupSize>
|
||||
{
|
||||
public:
|
||||
/// Convenience typedef for a templated entry of this hash set.
|
||||
typedef HashSetEntry<Key> Entry;
|
||||
|
||||
/// @internal Constructor
|
||||
///
|
||||
/// @param [in] numBuckets Number of buckets to allocate for this hash container. The initial hash container will
|
||||
/// take (buckets * GroupSize) bytes.
|
||||
/// @param [in] pAllocator Pointer to an allocator that will create system memory requested by this hash container.
|
||||
explicit HashSet(uint32 numBuckets, Allocator*const pAllocator) : Base::HashBase(numBuckets, pAllocator) {}
|
||||
~HashSet() { }
|
||||
|
||||
/// Finds a given entry; if no entry was found, allocate it.
|
||||
///
|
||||
/// @param [in] ppKey Key to search for.
|
||||
/// @param [out] pExisted True if an entry for the specified key existed before this call was made.
|
||||
/// False indicates that a new entry was allocated as a result of this call.
|
||||
///
|
||||
/// @returns @ref Success if the operation completed successfully
|
||||
/// @ref ErrorOutOfMemory if the operation failed because an internal memory allocation failed.
|
||||
Result FindAllocate(Key** ppKey, bool* pExisted);
|
||||
|
||||
/// Inserts an entry.
|
||||
///
|
||||
/// No action will be taken if an entry matching this key already exists in the set.
|
||||
///
|
||||
/// @param [in] key New entry to insert.
|
||||
///
|
||||
/// @returns @ref Success if the operation completed successfully, or @ref ErrorOutOfMemory if the operation failed
|
||||
/// because an internal memory allocation failed.
|
||||
Result Insert(const Key& key);
|
||||
|
||||
private:
|
||||
// Typedef for the specialized 'HashBase' object we're inheriting from so we can use properly qualified names when
|
||||
// accessing members of HashBase.
|
||||
typedef HashBase<Key, HashSetEntry<Key>, Allocator, HashFunc<Key>, EqualFunc<Key>, AllocFunc, GroupSize> Base;
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(HashSet);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(HashSet);
|
||||
};
|
||||
|
||||
} // Util
|
||||
|
||||
@@ -1,231 +1,75 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palHashSetImpl.h
|
||||
* @brief PAL utility collection HashSet class implementation.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palHashBaseImpl.h"
|
||||
#include "palHashSet.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
// =====================================================================================================================
|
||||
// Inserts a key if it doesn't already exist.
|
||||
template<typename Key,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
Result HashSet<Key, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::Insert(
|
||||
const Key& key)
|
||||
{
|
||||
Key* pKey = const_cast<Key*>(&key);
|
||||
bool existed;
|
||||
const Result result = FindAllocate(&pKey, &existed);
|
||||
if (existed == false)
|
||||
{
|
||||
*pKey = key;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Finds a given entry; if no entry was found, allocate it.
|
||||
template<typename Key,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
Result HashSet<Key, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::FindAllocate(
|
||||
Key** ppKey,
|
||||
bool* pExisted)
|
||||
{
|
||||
PAL_ASSERT(ppKey != nullptr);
|
||||
PAL_ASSERT(pExisted != nullptr);
|
||||
|
||||
Result result = Result::ErrorOutOfMemory;
|
||||
|
||||
// Get the bucket base address.
|
||||
Entry* pGroup = this->InitAndFindBucket(**ppKey);
|
||||
|
||||
Entry* pMatchingEntry = nullptr;
|
||||
|
||||
while (pGroup != nullptr)
|
||||
{
|
||||
const uint32 numEntries = this->GetGroupFooterNumEntries(pGroup);
|
||||
// Search this entry group.
|
||||
uint32 i = 0;
|
||||
for (; i < numEntries; i++)
|
||||
{
|
||||
if (this->m_equalFunc(pGroup[i].key, **ppKey))
|
||||
{
|
||||
// We've found the entry.
|
||||
pMatchingEntry = &(pGroup[i]);
|
||||
*pExisted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pMatchingEntry == nullptr) && (i < Base::EntriesInGroup))
|
||||
{
|
||||
// We've reached the end of the bucket and the entry was not found. Allocate this entry for the key.
|
||||
*pExisted = false;
|
||||
*ppKey = &pGroup[i].key;
|
||||
pMatchingEntry = &(pGroup[i]);
|
||||
this->m_numEntries++;
|
||||
this->SetGroupFooterNumEntries(pGroup, numEntries + 1);
|
||||
}
|
||||
|
||||
if (pMatchingEntry != nullptr)
|
||||
{
|
||||
result = Result::Success;
|
||||
break;
|
||||
}
|
||||
|
||||
// Chain to the next entry group.
|
||||
pGroup = this->AllocateNextGroup(pGroup);
|
||||
}
|
||||
|
||||
PAL_ASSERT(result == Result::Success);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Searches for the specified key to see if it exists.
|
||||
template<typename Key,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
bool HashSet<Key, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::Contains(
|
||||
const Key& key
|
||||
) const
|
||||
{
|
||||
// Get the bucket base address.
|
||||
Entry* pGroup = this->FindBucket(key);
|
||||
Entry* pMatchingEntry = nullptr;
|
||||
|
||||
while (pGroup != nullptr)
|
||||
{
|
||||
const uint32 numEntries = this->GetGroupFooterNumEntries(pGroup);
|
||||
|
||||
// Search this entry group.
|
||||
uint32 i = 0;
|
||||
for (; i < numEntries; i++)
|
||||
{
|
||||
if (this->m_equalFunc(pGroup[i].key, key))
|
||||
{
|
||||
// We've found the entry.
|
||||
pMatchingEntry = &(pGroup[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pMatchingEntry != nullptr) || (i < Base::EntriesInGroup))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Chain to the next entry group.
|
||||
pGroup = this->GetNextGroup(pGroup);
|
||||
}
|
||||
|
||||
return (pMatchingEntry != nullptr);
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Removes an entry with the specified key.
|
||||
template<typename Key,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
bool HashSet<Key, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::Erase(
|
||||
const Key& key)
|
||||
{
|
||||
// Get the bucket base address.
|
||||
Entry* pGroup = this->FindBucket(key);
|
||||
|
||||
Entry* pFoundEntry = nullptr;
|
||||
Entry* pLastEntry = nullptr;
|
||||
|
||||
Entry* pLastEntryGroup = nullptr;
|
||||
|
||||
// Find the entry to delete.
|
||||
while ((pGroup != nullptr))
|
||||
{
|
||||
const uint32 numEntries = this->GetGroupFooterNumEntries(pGroup);
|
||||
|
||||
// Search this entry
|
||||
uint32 i = 0;
|
||||
for (; i < numEntries; i++)
|
||||
{
|
||||
if (this->m_equalFunc(pGroup[i].key, key) == true)
|
||||
{
|
||||
// We shouldn't find the same key twice.
|
||||
PAL_ASSERT(pFoundEntry == nullptr);
|
||||
|
||||
pFoundEntry = &(pGroup[i]);
|
||||
}
|
||||
|
||||
// keep track of last entry of all groups in bucket
|
||||
pLastEntry = &(pGroup[i]);
|
||||
pLastEntryGroup = pGroup;
|
||||
}
|
||||
|
||||
// Chain to the next entry group
|
||||
pGroup = this->GetNextGroup(pGroup);
|
||||
}
|
||||
|
||||
// Copy the last entry's data into the entry that we are removing and invalidate the last entry as it now appears
|
||||
// earlier in the list. This also handles the case where the entry to be removed is the last entry.
|
||||
if (pFoundEntry != nullptr)
|
||||
{
|
||||
PAL_ASSERT(pLastEntry != nullptr);
|
||||
|
||||
pFoundEntry->key = pLastEntry->key;
|
||||
memset(pLastEntry, 0, sizeof(Entry));
|
||||
|
||||
PAL_ASSERT(this->m_numEntries > 0);
|
||||
this->m_numEntries--;
|
||||
const uint32 numEntries = this->GetGroupFooterNumEntries(pLastEntryGroup);
|
||||
this->SetGroupFooterNumEntries(pLastEntryGroup, numEntries - 1);
|
||||
}
|
||||
|
||||
return (pFoundEntry != nullptr);
|
||||
}
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palHashSetImpl.h
|
||||
* @brief PAL utility collection HashSet class implementation.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palHashBaseImpl.h"
|
||||
#include "palHashSet.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
// =====================================================================================================================
|
||||
// Inserts a key if it doesn't already exist.
|
||||
template<typename Key,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
Result HashSet<Key, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::Insert(
|
||||
const Key& key)
|
||||
{
|
||||
Entry* pEntry = nullptr;
|
||||
bool existed = false;
|
||||
return Base::FindAllocateEntry(key, &existed, &pEntry);
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Finds a given entry; if no entry was found, allocate it.
|
||||
template<typename Key,
|
||||
typename Allocator,
|
||||
template<typename> class HashFunc,
|
||||
template<typename> class EqualFunc,
|
||||
typename AllocFunc,
|
||||
size_t GroupSize>
|
||||
Result HashSet<Key, Allocator, HashFunc, EqualFunc, AllocFunc, GroupSize>::FindAllocate(
|
||||
Key** ppKey,
|
||||
bool* pExisted)
|
||||
{
|
||||
PAL_ASSERT(ppKey != nullptr);
|
||||
PAL_ASSERT(pExisted != nullptr);
|
||||
|
||||
static_assert(offsetof(Entry, key) == 0);
|
||||
return Base::FindAllocateEntry(**ppKey, pExisted, reinterpret_cast<Entry**>(ppKey));
|
||||
}
|
||||
|
||||
} // Util
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,293 +1,293 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palIntrusiveList.h
|
||||
* @brief PAL utility collection IntrusiveList and IntrusiveListIterator class declarations.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palUtil.h"
|
||||
#include "palAssert.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
template<typename T> class IntrusiveList;
|
||||
template<typename T> class IntrusiveListIterator;
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Encapsulates one node of an intrusive double-linked-list.
|
||||
*
|
||||
* A node is associated with one data pointer at construction. The data pointer cannot be changed and must be non-null.
|
||||
*
|
||||
* Note that InList() allows intrusive list users to verify if a given value has been stored in a list without iterating
|
||||
* over the list provided that each node object has been designated for a particular list.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T>
|
||||
class IntrusiveListNode
|
||||
{
|
||||
public:
|
||||
/// @param [in,out] pData Address of the data element which contains this intrusive node.
|
||||
explicit IntrusiveListNode(T* pData);
|
||||
|
||||
/// Returns true if this node is present in an intrusive list.
|
||||
bool InList() const;
|
||||
|
||||
private:
|
||||
// This special constructor is provided for IntrusiveList's sentinel node which must have a null data pointer.
|
||||
IntrusiveListNode();
|
||||
|
||||
T*const m_pData; // The data object that contains this node.
|
||||
IntrusiveListNode<T>* m_pPrev; // Previous node in the list or null if this node is not in a list.
|
||||
IntrusiveListNode<T>* m_pNext; // Next node in the list or null if this node is not in a list.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(IntrusiveListNode);
|
||||
|
||||
// Although this is a transgression of coding standards, it prevents IntrusiveListNode from requiring public
|
||||
// accessor functions. The added encapsulation this provides is worthwhile.
|
||||
friend class IntrusiveList<T>;
|
||||
friend class IntrusiveListIterator<T>;
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Iterator for traversal of elements in a List collection.
|
||||
*
|
||||
* Allows traversal of all elements in a List going either forwards or backwards.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T>
|
||||
class IntrusiveListIterator
|
||||
{
|
||||
public:
|
||||
~IntrusiveListIterator() { }
|
||||
|
||||
/// Returns true unless the iterator has advanced past the end of the list.
|
||||
bool IsValid() const { return m_pCurrent != m_pSentinel; }
|
||||
|
||||
/// Returns a pointer to the current element. Returns null if the iterator is invalid.
|
||||
T* Get() const { return m_pCurrent->m_pData; }
|
||||
|
||||
/// Advances the iterator to the previous position (move backward).
|
||||
void Prev() { m_pCurrent = m_pCurrent->m_pPrev; }
|
||||
|
||||
/// Advances the iterator to the next position (move forward).
|
||||
void Next() { m_pCurrent = m_pCurrent->m_pNext; }
|
||||
|
||||
/// Moves the iterator back to the start of the list.
|
||||
void Restart() { m_pCurrent = m_pSentinel->m_pNext; }
|
||||
|
||||
private:
|
||||
IntrusiveListIterator(const IntrusiveListNode<T>*const pSentinel, IntrusiveListNode<T>* pStart);
|
||||
|
||||
const IntrusiveListNode<T>*const m_pSentinel; // We need the sentinel to locate the list boundaries.
|
||||
IntrusiveListNode<T>* m_pCurrent; // Pointer to the current node.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(IntrusiveListIterator);
|
||||
|
||||
// Although this is a transgression of coding standards, it means that List does not need to have a public interface
|
||||
// specifically to implement this class. The added encapsulation this provides is worthwhile.
|
||||
friend class IntrusiveList<T>;
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Templated, doubly-linked, intrusive, list container.
|
||||
*
|
||||
* This is meant for storing non-null pointers to elements of an arbitrary type using externally managed nodes.
|
||||
* Operations which this class supports are:
|
||||
*
|
||||
* - Insertion at any point
|
||||
* - Deletion at any point
|
||||
* - Forwards and reverse iteration
|
||||
*
|
||||
* @warning This class is not thread-safe.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T>
|
||||
class IntrusiveList
|
||||
{
|
||||
public:
|
||||
/// A convenient shorthand for IntrusiveListNode.
|
||||
typedef IntrusiveListNode<T> Node;
|
||||
|
||||
/// A convenient shorthand for IntrusiveListIterator.
|
||||
typedef IntrusiveListIterator<T> Iter;
|
||||
|
||||
IntrusiveList();
|
||||
|
||||
/// Returns the number of elements in the list, not counting the sentinel.
|
||||
size_t NumElements() const { return m_numElements; }
|
||||
|
||||
/// Returns true if the list is empty.
|
||||
bool IsEmpty() const { return m_sentinel.m_pNext == &m_sentinel; }
|
||||
|
||||
/// Returns an iterator pointing to the first element in the list. If the list is empty, the iterator starts out
|
||||
/// pointing at the permanent sentinel node.
|
||||
///
|
||||
/// @returns An iterator pointing at the front end of the list.
|
||||
Iter Begin() const { return Iter(&m_sentinel, m_sentinel.m_pNext); }
|
||||
|
||||
/// Returns an iterator pointing to the last element in the list. If the list is empty, the iterator starts out
|
||||
/// pointing at the permanent sentinel node.
|
||||
///
|
||||
/// @returns An iterator pointing at the back end of the list.
|
||||
Iter End() const { return Iter(&m_sentinel, m_sentinel.m_pPrev); }
|
||||
|
||||
/// Returns the data pointer at the front of the list.
|
||||
///
|
||||
/// @returns The data pointer at the front of the list or null if the list is empty.
|
||||
T* Front() const { return m_sentinel.m_pNext->m_pData; }
|
||||
|
||||
/// Returns the data pointer at the back of the list.
|
||||
///
|
||||
/// @returns The data pointer at the back of the list or null if the list is empty.
|
||||
T* Back() const { return m_sentinel.m_pPrev->m_pData; }
|
||||
|
||||
/// Pushes the specified node onto the front of the list.
|
||||
///
|
||||
/// @param [in] pNode Externally-owned list node to link into the list.
|
||||
void PushFront(Node* pNode) { InsertBefore(m_sentinel.m_pNext, pNode); }
|
||||
|
||||
/// Pushes the specified node onto the back of the list.
|
||||
///
|
||||
/// @param [in] pNode Externally-owned list node to link into the list.
|
||||
void PushBack(Node* pNode) { InsertBefore(&m_sentinel, pNode); }
|
||||
|
||||
/// Pushes the contents of pSource onto the front of this list. The ordering of pSource is preserved, meaning that
|
||||
/// the front of pSource will be the new front of this list. Note that pSource will be left entirely empty.
|
||||
///
|
||||
/// It is illegal to call this function with an empty pSource.
|
||||
///
|
||||
/// @param [in] pSource The contents of pSource will be pushed in-order onto the front of this list.
|
||||
void PushFrontList(IntrusiveList<T>* pSource);
|
||||
|
||||
/// Pushes the contents of pSource onto the back of this list. The ordering of pSource is preserved, meaning that
|
||||
/// the end of pSource will be the new end of this list. Note that pSource will be left entirely empty.
|
||||
///
|
||||
/// It is illegal to call this function with an empty pSource.
|
||||
///
|
||||
/// @param [in] pSource The contents of pSource will be pushed in-order onto the back of this list.
|
||||
void PushBackList(IntrusiveList<T>* pSource);
|
||||
|
||||
/// Inserts the specified node before a particular node in a list.
|
||||
///
|
||||
/// If the iterator has advanced off the end of the list (i.e., the iterator is invalid), the added node will be the
|
||||
/// new tail node.
|
||||
///
|
||||
/// @param [in] iter Identifies a node where the insertion should take place. The iterator will point to the same
|
||||
/// spot in the list after insertion.
|
||||
/// @param [in] pNode Externally-owned list node to link into the list.
|
||||
void InsertBefore(const Iter& iter, Node* pNode);
|
||||
|
||||
/// Removes the node at the specified position from the list.
|
||||
///
|
||||
/// It is illegal to call this function with an iterator that has already advanced off the end of the list.
|
||||
///
|
||||
/// @param [in,out] pIter Iterator identifying the node to be removed. After the node is removed, this iterator
|
||||
/// will be advanced to the next node. If this call removes the final remaining node in the
|
||||
/// list then the iterator will point at the sentinel and will be invalid.
|
||||
void Erase(Iter* pIter);
|
||||
|
||||
/// Removes the node at the specified position from the list. It is illegal to call this function with a Node that
|
||||
/// not in this list.
|
||||
///
|
||||
/// @param [in] pNode Node to be removed.
|
||||
void Erase(Node* pNode);
|
||||
|
||||
/// Removes all nodes from the list.
|
||||
void EraseAll();
|
||||
|
||||
/// Truncates the list without touching the elements
|
||||
void InvalidateList()
|
||||
{
|
||||
m_sentinel.m_pNext = &m_sentinel;
|
||||
m_sentinel.m_pPrev = &m_sentinel;
|
||||
m_numElements = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void InsertBefore(Node* pBeforeMe, Node* pNode);
|
||||
void Unlink(Node* pNode);
|
||||
|
||||
Node m_sentinel; // Ties the head to the tail and signifies the boundary of the list.
|
||||
size_t m_numElements; // Number of elements.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(IntrusiveList);
|
||||
};
|
||||
|
||||
// =====================================================================================================================
|
||||
// This is the public node constructor; it must be given a non-null data pointer.
|
||||
template<typename T>
|
||||
IntrusiveListNode<T>::IntrusiveListNode(
|
||||
T* pData)
|
||||
:
|
||||
m_pData(pData),
|
||||
m_pPrev(nullptr),
|
||||
m_pNext(nullptr)
|
||||
{
|
||||
PAL_ASSERT(pData != nullptr);
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// This is the private node constructor which is used exclusively for sentinel nodes.
|
||||
template<typename T>
|
||||
IntrusiveListNode<T>::IntrusiveListNode()
|
||||
:
|
||||
m_pData(nullptr),
|
||||
m_pPrev(nullptr),
|
||||
m_pNext(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Returns true if this node is present in an intrusive list.
|
||||
template<typename T>
|
||||
bool IntrusiveListNode<T>::InList() const
|
||||
{
|
||||
// The node pointers should always be null or non-null together.
|
||||
PAL_DEBUG_BUILD_ONLY_ASSERT((m_pPrev == nullptr) == (m_pNext == nullptr));
|
||||
|
||||
return (m_pNext != nullptr);
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename T>
|
||||
IntrusiveListIterator<T>::IntrusiveListIterator(
|
||||
const IntrusiveListNode<T>*const pSentinel,
|
||||
IntrusiveListNode<T>* pStart)
|
||||
:
|
||||
m_pSentinel(pSentinel),
|
||||
m_pCurrent(pStart)
|
||||
{
|
||||
}
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palIntrusiveList.h
|
||||
* @brief PAL utility collection IntrusiveList and IntrusiveListIterator class declarations.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palUtil.h"
|
||||
#include "palAssert.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
template<typename T> class IntrusiveList;
|
||||
template<typename T> class IntrusiveListIterator;
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Encapsulates one node of an intrusive double-linked-list.
|
||||
*
|
||||
* A node is associated with one data pointer at construction. The data pointer cannot be changed and must be non-null.
|
||||
*
|
||||
* Note that InList() allows intrusive list users to verify if a given value has been stored in a list without iterating
|
||||
* over the list provided that each node object has been designated for a particular list.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T>
|
||||
class IntrusiveListNode
|
||||
{
|
||||
public:
|
||||
/// @param [in,out] pData Address of the data element which contains this intrusive node.
|
||||
explicit IntrusiveListNode(T* pData);
|
||||
|
||||
/// Returns true if this node is present in an intrusive list.
|
||||
bool InList() const;
|
||||
|
||||
private:
|
||||
// This special constructor is provided for IntrusiveList's sentinel node which must have a null data pointer.
|
||||
IntrusiveListNode();
|
||||
|
||||
T*const m_pData; // The data object that contains this node.
|
||||
IntrusiveListNode<T>* m_pPrev; // Previous node in the list or null if this node is not in a list.
|
||||
IntrusiveListNode<T>* m_pNext; // Next node in the list or null if this node is not in a list.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(IntrusiveListNode);
|
||||
|
||||
// Although this is a transgression of coding standards, it prevents IntrusiveListNode from requiring public
|
||||
// accessor functions. The added encapsulation this provides is worthwhile.
|
||||
friend class IntrusiveList<T>;
|
||||
friend class IntrusiveListIterator<T>;
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Iterator for traversal of elements in a List collection.
|
||||
*
|
||||
* Allows traversal of all elements in a List going either forwards or backwards.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T>
|
||||
class IntrusiveListIterator
|
||||
{
|
||||
public:
|
||||
~IntrusiveListIterator() { }
|
||||
|
||||
/// Returns true unless the iterator has advanced past the end of the list.
|
||||
bool IsValid() const { return m_pCurrent != m_pSentinel; }
|
||||
|
||||
/// Returns a pointer to the current element. Returns null if the iterator is invalid.
|
||||
T* Get() const { return m_pCurrent->m_pData; }
|
||||
|
||||
/// Advances the iterator to the previous position (move backward).
|
||||
void Prev() { m_pCurrent = m_pCurrent->m_pPrev; }
|
||||
|
||||
/// Advances the iterator to the next position (move forward).
|
||||
void Next() { m_pCurrent = m_pCurrent->m_pNext; }
|
||||
|
||||
/// Moves the iterator back to the start of the list.
|
||||
void Restart() { m_pCurrent = m_pSentinel->m_pNext; }
|
||||
|
||||
private:
|
||||
IntrusiveListIterator(const IntrusiveListNode<T>*const pSentinel, IntrusiveListNode<T>* pStart);
|
||||
|
||||
const IntrusiveListNode<T>*const m_pSentinel; // We need the sentinel to locate the list boundaries.
|
||||
IntrusiveListNode<T>* m_pCurrent; // Pointer to the current node.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(IntrusiveListIterator);
|
||||
|
||||
// Although this is a transgression of coding standards, it means that List does not need to have a public interface
|
||||
// specifically to implement this class. The added encapsulation this provides is worthwhile.
|
||||
friend class IntrusiveList<T>;
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Templated, doubly-linked, intrusive, list container.
|
||||
*
|
||||
* This is meant for storing non-null pointers to elements of an arbitrary type using externally managed nodes.
|
||||
* Operations which this class supports are:
|
||||
*
|
||||
* - Insertion at any point
|
||||
* - Deletion at any point
|
||||
* - Forwards and reverse iteration
|
||||
*
|
||||
* @warning This class is not thread-safe.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T>
|
||||
class IntrusiveList
|
||||
{
|
||||
public:
|
||||
/// A convenient shorthand for IntrusiveListNode.
|
||||
typedef IntrusiveListNode<T> Node;
|
||||
|
||||
/// A convenient shorthand for IntrusiveListIterator.
|
||||
typedef IntrusiveListIterator<T> Iter;
|
||||
|
||||
IntrusiveList();
|
||||
|
||||
/// Returns the number of elements in the list, not counting the sentinel.
|
||||
size_t NumElements() const { return m_numElements; }
|
||||
|
||||
/// Returns true if the list is empty.
|
||||
bool IsEmpty() const { return m_sentinel.m_pNext == &m_sentinel; }
|
||||
|
||||
/// Returns an iterator pointing to the first element in the list. If the list is empty, the iterator starts out
|
||||
/// pointing at the permanent sentinel node.
|
||||
///
|
||||
/// @returns An iterator pointing at the front end of the list.
|
||||
Iter Begin() const { return Iter(&m_sentinel, m_sentinel.m_pNext); }
|
||||
|
||||
/// Returns an iterator pointing to the last element in the list. If the list is empty, the iterator starts out
|
||||
/// pointing at the permanent sentinel node.
|
||||
///
|
||||
/// @returns An iterator pointing at the back end of the list.
|
||||
Iter End() const { return Iter(&m_sentinel, m_sentinel.m_pPrev); }
|
||||
|
||||
/// Returns the data pointer at the front of the list.
|
||||
///
|
||||
/// @returns The data pointer at the front of the list or null if the list is empty.
|
||||
T* Front() const { return m_sentinel.m_pNext->m_pData; }
|
||||
|
||||
/// Returns the data pointer at the back of the list.
|
||||
///
|
||||
/// @returns The data pointer at the back of the list or null if the list is empty.
|
||||
T* Back() const { return m_sentinel.m_pPrev->m_pData; }
|
||||
|
||||
/// Pushes the specified node onto the front of the list.
|
||||
///
|
||||
/// @param [in] pNode Externally-owned list node to link into the list.
|
||||
void PushFront(Node* pNode) { InsertBefore(m_sentinel.m_pNext, pNode); }
|
||||
|
||||
/// Pushes the specified node onto the back of the list.
|
||||
///
|
||||
/// @param [in] pNode Externally-owned list node to link into the list.
|
||||
void PushBack(Node* pNode) { InsertBefore(&m_sentinel, pNode); }
|
||||
|
||||
/// Pushes the contents of pSource onto the front of this list. The ordering of pSource is preserved, meaning that
|
||||
/// the front of pSource will be the new front of this list. Note that pSource will be left entirely empty.
|
||||
///
|
||||
/// It is illegal to call this function with an empty pSource.
|
||||
///
|
||||
/// @param [in] pSource The contents of pSource will be pushed in-order onto the front of this list.
|
||||
void PushFrontList(IntrusiveList<T>* pSource);
|
||||
|
||||
/// Pushes the contents of pSource onto the back of this list. The ordering of pSource is preserved, meaning that
|
||||
/// the end of pSource will be the new end of this list. Note that pSource will be left entirely empty.
|
||||
///
|
||||
/// It is illegal to call this function with an empty pSource.
|
||||
///
|
||||
/// @param [in] pSource The contents of pSource will be pushed in-order onto the back of this list.
|
||||
void PushBackList(IntrusiveList<T>* pSource);
|
||||
|
||||
/// Inserts the specified node before a particular node in a list.
|
||||
///
|
||||
/// If the iterator has advanced off the end of the list (i.e., the iterator is invalid), the added node will be the
|
||||
/// new tail node.
|
||||
///
|
||||
/// @param [in] iter Identifies a node where the insertion should take place. The iterator will point to the same
|
||||
/// spot in the list after insertion.
|
||||
/// @param [in] pNode Externally-owned list node to link into the list.
|
||||
void InsertBefore(const Iter& iter, Node* pNode);
|
||||
|
||||
/// Removes the node at the specified position from the list.
|
||||
///
|
||||
/// It is illegal to call this function with an iterator that has already advanced off the end of the list.
|
||||
///
|
||||
/// @param [in,out] pIter Iterator identifying the node to be removed. After the node is removed, this iterator
|
||||
/// will be advanced to the next node. If this call removes the final remaining node in the
|
||||
/// list then the iterator will point at the sentinel and will be invalid.
|
||||
void Erase(Iter* pIter);
|
||||
|
||||
/// Removes the node at the specified position from the list. It is illegal to call this function with a Node that
|
||||
/// not in this list.
|
||||
///
|
||||
/// @param [in] pNode Node to be removed.
|
||||
void Erase(Node* pNode);
|
||||
|
||||
/// Removes all nodes from the list.
|
||||
void EraseAll();
|
||||
|
||||
/// Truncates the list without touching the elements
|
||||
void InvalidateList()
|
||||
{
|
||||
m_sentinel.m_pNext = &m_sentinel;
|
||||
m_sentinel.m_pPrev = &m_sentinel;
|
||||
m_numElements = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void InsertBefore(Node* pBeforeMe, Node* pNode);
|
||||
void Unlink(Node* pNode);
|
||||
|
||||
Node m_sentinel; // Ties the head to the tail and signifies the boundary of the list.
|
||||
size_t m_numElements; // Number of elements.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(IntrusiveList);
|
||||
};
|
||||
|
||||
// =====================================================================================================================
|
||||
// This is the public node constructor; it must be given a non-null data pointer.
|
||||
template<typename T>
|
||||
IntrusiveListNode<T>::IntrusiveListNode(
|
||||
T* pData)
|
||||
:
|
||||
m_pData(pData),
|
||||
m_pPrev(nullptr),
|
||||
m_pNext(nullptr)
|
||||
{
|
||||
PAL_ASSERT(pData != nullptr);
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// This is the private node constructor which is used exclusively for sentinel nodes.
|
||||
template<typename T>
|
||||
IntrusiveListNode<T>::IntrusiveListNode()
|
||||
:
|
||||
m_pData(nullptr),
|
||||
m_pPrev(nullptr),
|
||||
m_pNext(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Returns true if this node is present in an intrusive list.
|
||||
template<typename T>
|
||||
bool IntrusiveListNode<T>::InList() const
|
||||
{
|
||||
// The node pointers should always be null or non-null together.
|
||||
PAL_DEBUG_BUILD_ONLY_ASSERT((m_pPrev == nullptr) == (m_pNext == nullptr));
|
||||
|
||||
return (m_pNext != nullptr);
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename T>
|
||||
IntrusiveListIterator<T>::IntrusiveListIterator(
|
||||
const IntrusiveListNode<T>*const pSentinel,
|
||||
IntrusiveListNode<T>* pStart)
|
||||
:
|
||||
m_pSentinel(pSentinel),
|
||||
m_pCurrent(pStart)
|
||||
{
|
||||
}
|
||||
|
||||
} // Util
|
||||
|
||||
@@ -1,346 +1,346 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palLinearAllocator.h
|
||||
* @brief * @brief PAL utility allocator LinearAllocator class.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palIntrusiveList.h"
|
||||
#include "palSysMemory.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief A linear allocator that allocates virtual memory.
|
||||
*
|
||||
* To improve performance, a linear allocator can be used in performance-critical areas to avoid unnecessary heap
|
||||
* allocations. The VirtualLinearAllocator will instead reserve a specified amount of virtual address space and will
|
||||
* incrementally back it with real memory as necessary.
|
||||
*
|
||||
* As clients reach a steady state, allocations from this allocator will become "free," essentially just costing a
|
||||
* pointer increment.
|
||||
*
|
||||
* This allocator can be used with any of the memory management macros. @see Allocators for more information about the
|
||||
* Allocation pattern.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class VirtualLinearAllocator
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param [in] size Maximum size, in bytes, of virtual memory that this allocator should reserve.
|
||||
/// Does not need to be aligned to page size.
|
||||
VirtualLinearAllocator(size_t size) :
|
||||
m_pStart(nullptr),
|
||||
m_pCurrent(nullptr),
|
||||
m_size(size),
|
||||
m_pageSize(0) {}
|
||||
|
||||
/// Destructor.
|
||||
virtual ~VirtualLinearAllocator()
|
||||
{
|
||||
if (m_pStart != nullptr)
|
||||
{
|
||||
// Free all of the pages.
|
||||
Result result = VirtualRelease(m_pStart, m_size);
|
||||
PAL_ASSERT(result == Result::_Success);
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the linear allocator by reserving the requested number of pages.
|
||||
///
|
||||
/// @returns Result::Success if memory reservation and committing of the first page is successful.
|
||||
Result Init()
|
||||
{
|
||||
m_pageSize = VirtualPageSize();
|
||||
m_size = Pow2Align(m_size, m_pageSize);
|
||||
|
||||
Result result = VirtualReserve(m_size, &m_pStart);
|
||||
|
||||
if (result == Result::_Success)
|
||||
{
|
||||
result = VirtualCommit(m_pStart, m_pageSize);
|
||||
}
|
||||
|
||||
if (result == Result::_Success)
|
||||
{
|
||||
m_pCurrent = m_pStart;
|
||||
m_pCommittedToPage = VoidPtrInc(m_pCurrent, m_pageSize);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Allocates a block of memory.
|
||||
///
|
||||
/// @param [in] allocInfo Contains information about the requested allocation.
|
||||
///
|
||||
/// @returns Pointer to the allocated memory, nullptr if the allocation failed.
|
||||
void* Alloc(const AllocInfo& allocInfo)
|
||||
{
|
||||
void* pAlignedCurrent = VoidPtrAlign(m_pCurrent, allocInfo.alignment);
|
||||
void* pNextCurrent = VoidPtrInc(pAlignedCurrent, allocInfo.bytes);
|
||||
void* pAlignedEnd = VoidPtrAlign(pNextCurrent, m_pageSize);
|
||||
|
||||
if (allocInfo.bytes > Remaining())
|
||||
{
|
||||
pAlignedCurrent = nullptr;
|
||||
}
|
||||
else if (pAlignedEnd > m_pCommittedToPage)
|
||||
{
|
||||
const size_t commitBytes = VoidPtrDiff(pAlignedEnd, m_pCommittedToPage);
|
||||
|
||||
const Result result = VirtualCommit(m_pCommittedToPage, commitBytes);
|
||||
|
||||
if (result == Result::_Success)
|
||||
{
|
||||
m_pCommittedToPage = VoidPtrInc(m_pCommittedToPage, commitBytes);
|
||||
m_pCurrent = pNextCurrent;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return nullptr if allocation fails.
|
||||
pAlignedCurrent = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pCurrent = pNextCurrent;
|
||||
}
|
||||
|
||||
return pAlignedCurrent;
|
||||
}
|
||||
|
||||
/// Frees a block of memory.
|
||||
///
|
||||
/// @param [in] freeInfo Contains information about the requested free.
|
||||
void Free(const FreeInfo& freeInfo) {}
|
||||
|
||||
/// Rewinds the current pointer to the specified location to reuse already allocated memory.
|
||||
///
|
||||
/// @param pStart Where to reset the m_pCurrent to.
|
||||
/// @param decommit If true, pages that are rewound are freed/decommitted.
|
||||
void Rewind(void* pStart, bool decommit)
|
||||
{
|
||||
PAL_ASSERT((m_pStart <= pStart) && (pStart <= m_pCurrent));
|
||||
|
||||
if (pStart != m_pCurrent)
|
||||
{
|
||||
if (decommit)
|
||||
{
|
||||
void* pStartPage = VoidPtrAlign(VoidPtrInc(pStart, 1), m_pageSize);
|
||||
void* pCurrentPage = VoidPtrAlign(m_pCurrent, m_pageSize);
|
||||
const size_t numPages = VoidPtrDiff(pCurrentPage, pStartPage) / m_pageSize;
|
||||
|
||||
if (numPages > 0)
|
||||
{
|
||||
Result result = VirtualDecommit(pStartPage, m_pageSize * numPages);
|
||||
PAL_ASSERT(result == Result::_Success);
|
||||
|
||||
m_pCommittedToPage = pStartPage;
|
||||
}
|
||||
}
|
||||
#if DEBUG
|
||||
else
|
||||
{
|
||||
void* pStartPage = VoidPtrAlign(VoidPtrInc(pStart, 1), m_pageSize);
|
||||
void* pCurrentPage = VoidPtrAlign(m_pCurrent, m_pageSize);
|
||||
const size_t numDwords = VoidPtrDiff(pCurrentPage, pStartPage) / sizeof(uint32);
|
||||
uint32* pNewCurrent = static_cast<uint32*>(pStartPage);
|
||||
|
||||
for (size_t dword = 0; dword < numDwords; dword++)
|
||||
{
|
||||
pNewCurrent[dword] = 0xDEADBEEF;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m_pCurrent = pStart;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the current pointer to backing memory.
|
||||
///
|
||||
/// @returns Current pointer to backing memory.
|
||||
void* Current() { return m_pCurrent; }
|
||||
|
||||
/// Returns the starting pointer to backing memory.
|
||||
///
|
||||
/// @returns Pointer to the start of backing memory.
|
||||
void* Start() { return m_pStart; }
|
||||
|
||||
/// Returns the number of bytes that have been allocated.
|
||||
///
|
||||
/// @returns Number of bytes allocated through this allocator.
|
||||
size_t BytesAllocated() { return VoidPtrDiff(m_pCurrent, m_pStart); }
|
||||
|
||||
/// Compute remaining unallocated space in the allocator; once this space is exhausted allocations will fail.
|
||||
///
|
||||
/// @returns The size of the remaining unallocated space in bytes.
|
||||
size_t Remaining() const { return m_size - VoidPtrDiff(m_pCurrent, m_pStart); }
|
||||
|
||||
private:
|
||||
void* m_pStart; ///< Pointer to where the backing allocation starts.
|
||||
void* m_pCurrent; ///< Pointer to the current position of backing memory.
|
||||
void* m_pCommittedToPage; ///< Pointer to the end of the last committed page.
|
||||
|
||||
size_t m_size; ///< Size of the allocation.
|
||||
size_t m_pageSize; ///< OS' defined page size.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(VirtualLinearAllocator);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(VirtualLinearAllocator);
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief A "resource acquisition is initialization" (RAII) wrapper for the LinearAllocator classes.
|
||||
*
|
||||
* The RAII paradigm allows critical sections to be automatically acquired during this class' constructor, and
|
||||
* automatically released when a stack-allocated wrapper object goes out-of-scope. As such, it only makes sense to use
|
||||
* this class for stack-allocated objects.
|
||||
*
|
||||
* This object will ensure that anything allocated the object is allocated on the stack and when it goes out of scope
|
||||
* will be properly "rewound" by the allocator. See the below example.
|
||||
*
|
||||
*
|
||||
* {
|
||||
* [Current pointer = 0x10]
|
||||
* LinearAllocatorAuto allocator(pPtrToAllocator);
|
||||
* Allocations occur ...
|
||||
* [Current pointer = 0x80]
|
||||
* }
|
||||
* [Current pointer rewinds = 0x10]
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template <class LinearAllocator>
|
||||
class LinearAllocatorAuto
|
||||
{
|
||||
public:
|
||||
/// Tracks the current start pointer.
|
||||
///
|
||||
/// @param pAllocator The allocator to wrap.
|
||||
/// @param decommit Whether to decommit any pages of memory allocated when this goes out of scope.
|
||||
LinearAllocatorAuto(LinearAllocator* pAllocator, bool decommit)
|
||||
:
|
||||
m_pAllocator(pAllocator),
|
||||
#if PAL_MEMTRACK
|
||||
m_memTracker(pAllocator),
|
||||
#endif
|
||||
m_pStart(nullptr),
|
||||
m_decommit(decommit)
|
||||
{
|
||||
PAL_ASSERT(pAllocator != nullptr);
|
||||
m_pStart = m_pAllocator->Current();
|
||||
|
||||
#if PAL_MEMTRACK
|
||||
Result result = m_memTracker.Init();
|
||||
PAL_ASSERT(result == Result::_Success);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Rewinds any allocations made when this goes out of scope.
|
||||
~LinearAllocatorAuto()
|
||||
{
|
||||
m_pAllocator->Rewind(m_pStart, m_decommit);
|
||||
}
|
||||
|
||||
/// Allocates a block of memory.
|
||||
///
|
||||
/// @param [in] allocInfo Contains information about the requested allocation.
|
||||
///
|
||||
/// @returns Pointer to the allocated memory, nullptr if the allocation failed.
|
||||
void* Alloc(const AllocInfo& allocInfo)
|
||||
{
|
||||
void* pMemory = nullptr;
|
||||
#if PAL_MEMTRACK
|
||||
pMemory = m_memTracker.Alloc(allocInfo);
|
||||
#else
|
||||
pMemory = m_pAllocator->Alloc(allocInfo);
|
||||
#endif
|
||||
|
||||
return pMemory;
|
||||
}
|
||||
|
||||
/// Frees a block of memory.
|
||||
///
|
||||
/// @param [in] freeInfo Contains information about the requested free.
|
||||
void Free(const FreeInfo& freeInfo)
|
||||
{
|
||||
#if PAL_MEMTRACK
|
||||
m_memTracker.Free(freeInfo);
|
||||
#else
|
||||
m_pAllocator->Free(freeInfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
LinearAllocator*const m_pAllocator; ///< The LinearAllocator which this object wraps.
|
||||
|
||||
#if PAL_MEMTRACK
|
||||
MemTracker<LinearAllocator> m_memTracker; ///< Memory tracker for this LinearAllocatorAuto.
|
||||
#endif
|
||||
|
||||
void* m_pStart; ///< Where the LinearAllocator started when wrapped by this.
|
||||
const bool m_decommit; ///< Whether to decommit any pages of memory allocated on destruction.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(LinearAllocatorAuto);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(LinearAllocatorAuto);
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief A simple extension of VirtualLinearAllocator that contains an IntrusiveListNode pointing at itself.
|
||||
* This makes it very easy to create and manage IntrusiveLists of VirtualLinearAllocators.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class VirtualLinearAllocatorWithNode : public VirtualLinearAllocator
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
VirtualLinearAllocatorWithNode(size_t size) : VirtualLinearAllocator(size), m_node(this) {}
|
||||
|
||||
/// Destructor.
|
||||
virtual ~VirtualLinearAllocatorWithNode() {}
|
||||
|
||||
/// Gets this linear allocator's associated IntrusiveListNode.
|
||||
///
|
||||
/// @returns Pointer to this allocator's associated IntrusiveListNode.
|
||||
IntrusiveListNode<VirtualLinearAllocatorWithNode>* GetNode() { return &m_node; }
|
||||
|
||||
private:
|
||||
IntrusiveListNode<VirtualLinearAllocatorWithNode> m_node;
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(VirtualLinearAllocatorWithNode);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(VirtualLinearAllocatorWithNode);
|
||||
};
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palLinearAllocator.h
|
||||
* @brief * @brief PAL utility allocator LinearAllocator class.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palIntrusiveList.h"
|
||||
#include "palSysMemory.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief A linear allocator that allocates virtual memory.
|
||||
*
|
||||
* To improve performance, a linear allocator can be used in performance-critical areas to avoid unnecessary heap
|
||||
* allocations. The VirtualLinearAllocator will instead reserve a specified amount of virtual address space and will
|
||||
* incrementally back it with real memory as necessary.
|
||||
*
|
||||
* As clients reach a steady state, allocations from this allocator will become "free," essentially just costing a
|
||||
* pointer increment.
|
||||
*
|
||||
* This allocator can be used with any of the memory management macros. @see Allocators for more information about the
|
||||
* Allocation pattern.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class VirtualLinearAllocator
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param [in] size Maximum size, in bytes, of virtual memory that this allocator should reserve.
|
||||
/// Does not need to be aligned to page size.
|
||||
VirtualLinearAllocator(size_t size) :
|
||||
m_pStart(nullptr),
|
||||
m_pCurrent(nullptr),
|
||||
m_size(size),
|
||||
m_pageSize(0) {}
|
||||
|
||||
/// Destructor.
|
||||
virtual ~VirtualLinearAllocator()
|
||||
{
|
||||
if (m_pStart != nullptr)
|
||||
{
|
||||
// Free all of the pages.
|
||||
Result result = VirtualRelease(m_pStart, m_size);
|
||||
PAL_ASSERT(result == Result::_Success);
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the linear allocator by reserving the requested number of pages.
|
||||
///
|
||||
/// @returns Result::Success if memory reservation and committing of the first page is successful.
|
||||
Result Init()
|
||||
{
|
||||
m_pageSize = VirtualPageSize();
|
||||
m_size = Pow2Align(m_size, m_pageSize);
|
||||
|
||||
Result result = VirtualReserve(m_size, &m_pStart);
|
||||
|
||||
if (result == Result::_Success)
|
||||
{
|
||||
result = VirtualCommit(m_pStart, m_pageSize);
|
||||
}
|
||||
|
||||
if (result == Result::_Success)
|
||||
{
|
||||
m_pCurrent = m_pStart;
|
||||
m_pCommittedToPage = VoidPtrInc(m_pCurrent, m_pageSize);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Allocates a block of memory.
|
||||
///
|
||||
/// @param [in] allocInfo Contains information about the requested allocation.
|
||||
///
|
||||
/// @returns Pointer to the allocated memory, nullptr if the allocation failed.
|
||||
void* Alloc(const AllocInfo& allocInfo)
|
||||
{
|
||||
void* pAlignedCurrent = VoidPtrAlign(m_pCurrent, allocInfo.alignment);
|
||||
void* pNextCurrent = VoidPtrInc(pAlignedCurrent, allocInfo.bytes);
|
||||
void* pAlignedEnd = VoidPtrAlign(pNextCurrent, m_pageSize);
|
||||
|
||||
if (allocInfo.bytes > Remaining())
|
||||
{
|
||||
pAlignedCurrent = nullptr;
|
||||
}
|
||||
else if (pAlignedEnd > m_pCommittedToPage)
|
||||
{
|
||||
const size_t commitBytes = VoidPtrDiff(pAlignedEnd, m_pCommittedToPage);
|
||||
|
||||
const Result result = VirtualCommit(m_pCommittedToPage, commitBytes);
|
||||
|
||||
if (result == Result::_Success)
|
||||
{
|
||||
m_pCommittedToPage = VoidPtrInc(m_pCommittedToPage, commitBytes);
|
||||
m_pCurrent = pNextCurrent;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return nullptr if allocation fails.
|
||||
pAlignedCurrent = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pCurrent = pNextCurrent;
|
||||
}
|
||||
|
||||
return pAlignedCurrent;
|
||||
}
|
||||
|
||||
/// Frees a block of memory.
|
||||
///
|
||||
/// @param [in] freeInfo Contains information about the requested free.
|
||||
void Free(const FreeInfo& freeInfo) {}
|
||||
|
||||
/// Rewinds the current pointer to the specified location to reuse already allocated memory.
|
||||
///
|
||||
/// @param pStart Where to reset the m_pCurrent to.
|
||||
/// @param decommit If true, pages that are rewound are freed/decommitted.
|
||||
void Rewind(void* pStart, bool decommit)
|
||||
{
|
||||
PAL_ASSERT((m_pStart <= pStart) && (pStart <= m_pCurrent));
|
||||
|
||||
if (pStart != m_pCurrent)
|
||||
{
|
||||
if (decommit)
|
||||
{
|
||||
void* pStartPage = VoidPtrAlign(VoidPtrInc(pStart, 1), m_pageSize);
|
||||
void* pCurrentPage = VoidPtrAlign(m_pCurrent, m_pageSize);
|
||||
const size_t numPages = VoidPtrDiff(pCurrentPage, pStartPage) / m_pageSize;
|
||||
|
||||
if (numPages > 0)
|
||||
{
|
||||
Result result = VirtualDecommit(pStartPage, m_pageSize * numPages);
|
||||
PAL_ASSERT(result == Result::_Success);
|
||||
|
||||
m_pCommittedToPage = pStartPage;
|
||||
}
|
||||
}
|
||||
#if DEBUG
|
||||
else
|
||||
{
|
||||
void* pStartPage = VoidPtrAlign(VoidPtrInc(pStart, 1), m_pageSize);
|
||||
void* pCurrentPage = VoidPtrAlign(m_pCurrent, m_pageSize);
|
||||
const size_t numDwords = VoidPtrDiff(pCurrentPage, pStartPage) / sizeof(uint32);
|
||||
uint32* pNewCurrent = static_cast<uint32*>(pStartPage);
|
||||
|
||||
for (size_t dword = 0; dword < numDwords; dword++)
|
||||
{
|
||||
pNewCurrent[dword] = 0xDEADBEEF;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m_pCurrent = pStart;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the current pointer to backing memory.
|
||||
///
|
||||
/// @returns Current pointer to backing memory.
|
||||
void* Current() { return m_pCurrent; }
|
||||
|
||||
/// Returns the starting pointer to backing memory.
|
||||
///
|
||||
/// @returns Pointer to the start of backing memory.
|
||||
void* Start() { return m_pStart; }
|
||||
|
||||
/// Returns the number of bytes that have been allocated.
|
||||
///
|
||||
/// @returns Number of bytes allocated through this allocator.
|
||||
size_t BytesAllocated() { return VoidPtrDiff(m_pCurrent, m_pStart); }
|
||||
|
||||
/// Compute remaining unallocated space in the allocator; once this space is exhausted allocations will fail.
|
||||
///
|
||||
/// @returns The size of the remaining unallocated space in bytes.
|
||||
size_t Remaining() const { return m_size - VoidPtrDiff(m_pCurrent, m_pStart); }
|
||||
|
||||
private:
|
||||
void* m_pStart; ///< Pointer to where the backing allocation starts.
|
||||
void* m_pCurrent; ///< Pointer to the current position of backing memory.
|
||||
void* m_pCommittedToPage; ///< Pointer to the end of the last committed page.
|
||||
|
||||
size_t m_size; ///< Size of the allocation.
|
||||
size_t m_pageSize; ///< OS' defined page size.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(VirtualLinearAllocator);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(VirtualLinearAllocator);
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief A "resource acquisition is initialization" (RAII) wrapper for the LinearAllocator classes.
|
||||
*
|
||||
* The RAII paradigm allows critical sections to be automatically acquired during this class' constructor, and
|
||||
* automatically released when a stack-allocated wrapper object goes out-of-scope. As such, it only makes sense to use
|
||||
* this class for stack-allocated objects.
|
||||
*
|
||||
* This object will ensure that anything allocated the object is allocated on the stack and when it goes out of scope
|
||||
* will be properly "rewound" by the allocator. See the below example.
|
||||
*
|
||||
*
|
||||
* {
|
||||
* [Current pointer = 0x10]
|
||||
* LinearAllocatorAuto allocator(pPtrToAllocator);
|
||||
* Allocations occur ...
|
||||
* [Current pointer = 0x80]
|
||||
* }
|
||||
* [Current pointer rewinds = 0x10]
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template <class LinearAllocator>
|
||||
class LinearAllocatorAuto
|
||||
{
|
||||
public:
|
||||
/// Tracks the current start pointer.
|
||||
///
|
||||
/// @param pAllocator The allocator to wrap.
|
||||
/// @param decommit Whether to decommit any pages of memory allocated when this goes out of scope.
|
||||
LinearAllocatorAuto(LinearAllocator* pAllocator, bool decommit)
|
||||
:
|
||||
m_pAllocator(pAllocator),
|
||||
#if PAL_MEMTRACK
|
||||
m_memTracker(pAllocator),
|
||||
#endif
|
||||
m_pStart(nullptr),
|
||||
m_decommit(decommit)
|
||||
{
|
||||
PAL_ASSERT(pAllocator != nullptr);
|
||||
m_pStart = m_pAllocator->Current();
|
||||
|
||||
#if PAL_MEMTRACK
|
||||
Result result = m_memTracker.Init();
|
||||
PAL_ASSERT(result == Result::_Success);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Rewinds any allocations made when this goes out of scope.
|
||||
~LinearAllocatorAuto()
|
||||
{
|
||||
m_pAllocator->Rewind(m_pStart, m_decommit);
|
||||
}
|
||||
|
||||
/// Allocates a block of memory.
|
||||
///
|
||||
/// @param [in] allocInfo Contains information about the requested allocation.
|
||||
///
|
||||
/// @returns Pointer to the allocated memory, nullptr if the allocation failed.
|
||||
void* Alloc(const AllocInfo& allocInfo)
|
||||
{
|
||||
void* pMemory = nullptr;
|
||||
#if PAL_MEMTRACK
|
||||
pMemory = m_memTracker.Alloc(allocInfo);
|
||||
#else
|
||||
pMemory = m_pAllocator->Alloc(allocInfo);
|
||||
#endif
|
||||
|
||||
return pMemory;
|
||||
}
|
||||
|
||||
/// Frees a block of memory.
|
||||
///
|
||||
/// @param [in] freeInfo Contains information about the requested free.
|
||||
void Free(const FreeInfo& freeInfo)
|
||||
{
|
||||
#if PAL_MEMTRACK
|
||||
m_memTracker.Free(freeInfo);
|
||||
#else
|
||||
m_pAllocator->Free(freeInfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
LinearAllocator*const m_pAllocator; ///< The LinearAllocator which this object wraps.
|
||||
|
||||
#if PAL_MEMTRACK
|
||||
MemTracker<LinearAllocator> m_memTracker; ///< Memory tracker for this LinearAllocatorAuto.
|
||||
#endif
|
||||
|
||||
void* m_pStart; ///< Where the LinearAllocator started when wrapped by this.
|
||||
const bool m_decommit; ///< Whether to decommit any pages of memory allocated on destruction.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(LinearAllocatorAuto);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(LinearAllocatorAuto);
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief A simple extension of VirtualLinearAllocator that contains an IntrusiveListNode pointing at itself.
|
||||
* This makes it very easy to create and manage IntrusiveLists of VirtualLinearAllocators.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class VirtualLinearAllocatorWithNode : public VirtualLinearAllocator
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
VirtualLinearAllocatorWithNode(size_t size) : VirtualLinearAllocator(size), m_node(this) {}
|
||||
|
||||
/// Destructor.
|
||||
virtual ~VirtualLinearAllocatorWithNode() {}
|
||||
|
||||
/// Gets this linear allocator's associated IntrusiveListNode.
|
||||
///
|
||||
/// @returns Pointer to this allocator's associated IntrusiveListNode.
|
||||
IntrusiveListNode<VirtualLinearAllocatorWithNode>* GetNode() { return &m_node; }
|
||||
|
||||
private:
|
||||
IntrusiveListNode<VirtualLinearAllocatorWithNode> m_node;
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(VirtualLinearAllocatorWithNode);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(VirtualLinearAllocatorWithNode);
|
||||
};
|
||||
|
||||
} // Util
|
||||
|
||||
@@ -1,226 +1,226 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palMath.h
|
||||
* @brief PAL utility collection function/constant declarations for the Math sub-namespace.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palSysMemory.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// Util sub-namespace defining several useful math routines and constants.
|
||||
namespace Math
|
||||
{
|
||||
|
||||
/// Exponent mask of a single-precision IEEE float.
|
||||
constexpr uint32 FloatExponentMask = 0x7F800000;
|
||||
/// Exponent bias of a single-precision IEEE float.
|
||||
constexpr uint32 FloatExponentBias = 127;
|
||||
/// Number of bits in the mantissa of a single-precision IEEE float.
|
||||
constexpr uint32 FloatNumMantissaBits = 23;
|
||||
/// Mantissa mask of a single-precision IEEE float.
|
||||
constexpr uint32 FloatMantissaMask = 0x007FFFFF;
|
||||
/// Sign bit mask of a single precision IEEE float.
|
||||
constexpr uint32 FloatSignBitMask = 0x80000000;
|
||||
/// Mask of all non-sign bits of a single-precision IEEE float.
|
||||
constexpr uint32 FloatMaskOutSignBit = 0x7FFFFFFF;
|
||||
/// Minimum number of float bits in a normalized IEE float.
|
||||
constexpr uint32 MinNormalizedFloatBits = 0x00800000;
|
||||
|
||||
/// Positive one.
|
||||
constexpr float FloatOne = 1.0f;
|
||||
/// Negative one.
|
||||
constexpr float FloatNegOne = -1.0f;
|
||||
/// Zero.
|
||||
constexpr float FloatZero = 0.0f;
|
||||
/// Positive infinity.
|
||||
constexpr float FloatInfinity = std::numeric_limits<float>::infinity();
|
||||
|
||||
/// Fraction structure.
|
||||
struct Fraction
|
||||
{
|
||||
uint32 num; ///< Numerator
|
||||
uint32 den; ///< Denominator
|
||||
};
|
||||
|
||||
/// Returns the bits of a floating point value as an unsigned integer.
|
||||
inline uint32 FloatToBits(float f)
|
||||
{
|
||||
return (*(reinterpret_cast<uint32*>(&f)));
|
||||
}
|
||||
|
||||
/// Assigns the bits contained in an unsigned integer to the float pointer location
|
||||
inline void SetBitsToFloat(float* f, uint32 u)
|
||||
{
|
||||
*(reinterpret_cast<uint32*>(f)) = u;
|
||||
}
|
||||
|
||||
/// Returns true if the specified float is denormalized.
|
||||
extern bool IsDenorm(float f);
|
||||
/// Returns true if the specified float is +/- infinity.
|
||||
extern bool IsInf(float f);
|
||||
/// Returns true if the specified float is a NaN.
|
||||
extern bool IsNaN(float f);
|
||||
|
||||
/// Determines if a floating-point number is either +/-Infinity or NaN.
|
||||
inline bool IsInfOrNaN(float f)
|
||||
{
|
||||
return (IsInf(f) || IsNaN(f));
|
||||
}
|
||||
|
||||
/// @brief Converts a floating point number to a signed fixed point number with the given integer and fractional bits.
|
||||
///
|
||||
/// If the number of integer bits is zero, the incoming value is treated as normalized, i.e. [-1.0, 1.0]. If the
|
||||
/// intBits is zero, the fracBits is assumed to include 1 sign bit, otherwise the sign bit is assumed to be part of the
|
||||
/// intBits. A typical use for enableRounding would be when converting SNORM/UNORM values to fixed point.
|
||||
///
|
||||
/// @param [in] f Floating point value to convert.
|
||||
/// @param [in] intBits Number of integer bits (including the sign bit) in the fixed point output.
|
||||
/// @param [in] fracBits Number of fractional bits in the fixed point output.
|
||||
/// @param [in] enableRounding Round before conversion.
|
||||
///
|
||||
/// @returns Fixed point number in a uint32.
|
||||
extern uint32 FloatToSFixed(float f, uint32 intBits, uint32 fracBits, bool enableRounding = false);
|
||||
|
||||
/// @brief Converts a floating point number to an unsigned fixed point number with the given integer and
|
||||
/// fractional bits.
|
||||
///
|
||||
/// If the number of integer bits is zero, the incoming value is treated as normalized, i.e. [-1.0, 1.0]. A typical use
|
||||
/// for enableRounding would be when converting SNORM/UNORM values to fixed point.
|
||||
///
|
||||
/// @param [in] f Floating point value to convert.
|
||||
/// @param [in] intBits Number of integer bits (including the sign bit) in the fixed point output.
|
||||
/// @param [in] fracBits Number of fractional bits in the fixed point output.
|
||||
/// @param [in] enableRounding Round before conversion.
|
||||
///
|
||||
/// @returns Fixed point number in a uint32.
|
||||
extern uint32 FloatToUFixed(float f, uint32 intBits, uint32 fracBits, bool enableRounding = false);
|
||||
|
||||
/// @brief Converts a signed fixed point number with the given integer and fractional bits to a floating point number.
|
||||
///
|
||||
/// If the number of integer bits is zero, the incoming value is treated as normalized, i.e. [-1.0, 1.0]. If numIntBits
|
||||
/// is 0, numFracBits is assumed to have 1 bit for the sign, otherwise the sign bit is assumed to be part of the integer
|
||||
/// bits.
|
||||
///
|
||||
/// @param [in] fixedPtNum Fixed point number to convert.
|
||||
/// @param [in] intBits Number of integer bits (including the sign bit).
|
||||
/// @param [in] fracBits Number of fractional bits.
|
||||
///
|
||||
/// @returns Converted floating point number.
|
||||
extern float SFixedToFloat(int32 fixedPtNum, uint32 intBits, uint32 fracBits);
|
||||
|
||||
/// @brief Converts a unsigned fixed point number with the given integer and fractional bits to a floating point number.
|
||||
///
|
||||
/// If the number of integer bits is zero, the incoming value is treated as normalized, i.e. [0, 1.0].
|
||||
///
|
||||
/// @param [in] fixedPtNum Fixed point number to convert.
|
||||
/// @param [in] intBits Number of integer bits (including the sign bit).
|
||||
/// @param [in] fracBits Number of fractional bits.
|
||||
///
|
||||
/// @returns Converted floating point number.
|
||||
extern float UFixedToFloat(uint32 fixedPtNum, uint32 intBits, uint32 fracBits);
|
||||
|
||||
/// Converts a 32-bit IEEE floating point number to a 16-bit signed floating point number.
|
||||
extern uint32 Float32ToFloat16(float f);
|
||||
|
||||
/// Converts a 32-bit IEEE floating point number to an 11-bit signed floating point number.
|
||||
extern uint32 Float32ToFloat11(float f);
|
||||
|
||||
/// Converts a 32-bit IEEE floating point number to a 10-bit signed floating point number.
|
||||
extern uint32 Float32ToFloat10(float f);
|
||||
|
||||
/// Converts a 32-bit IEEE floating-point number to a 10-bit unsigned floating-point number.
|
||||
extern uint32 Float32ToFloat10_6e4(float f);
|
||||
|
||||
/// Converts a 10-bit signed floating point number to a 32-bit IEEE floating point number.
|
||||
extern float Float10_6e4ToFloat32(uint32 fBits);
|
||||
|
||||
/// Converts a 32-bit IEEE floating point number to a N-bit signed floating point number.
|
||||
extern uint32 Float32ToNumBits(float float32, uint32 numBits);
|
||||
|
||||
/// Converts a 16-bit signed floating point number to a 32-bit IEEE floating point number.
|
||||
extern float Float16ToFloat32(uint32 fBits);
|
||||
|
||||
/// Converts an 11-bit signed floating point number to a 32-bit IEEE floating point number.
|
||||
extern float Float11ToFloat32(uint32 fBits);
|
||||
|
||||
/// Converts a 10-bit signed floating point number to a 32-bit IEEE floating point number.
|
||||
extern float Float10ToFloat32(uint32 fBits);
|
||||
|
||||
/// Converts an N-bit signed floating point number to a 32-bit IEEE floating point number.
|
||||
extern float FloatNumBitsToFloat32(uint32 input, uint32 numBits);
|
||||
|
||||
/// Converts a 32-bit IEEE floating point number to a fraction.
|
||||
extern Fraction Float32ToFraction(float float32);
|
||||
|
||||
/// Returns the square root of the specified value.
|
||||
extern float Sqrt(float f);
|
||||
|
||||
/// Returns the result of an exponent operation (base^exponent).
|
||||
extern float Pow(float base, float exponent);
|
||||
|
||||
/// Returns the unsigned integer absolute value.
|
||||
extern uint32 Absu(int32 number);
|
||||
|
||||
/// Return sign-preserved zero if input is denorm, otherwise input value
|
||||
extern float FlushDenormToZero(float input);
|
||||
|
||||
/// Return value in 1.7 signed magnitude format. Valid input range is (-127, 127)
|
||||
extern uint8 IntToSignedMagnitude(int8 input);
|
||||
|
||||
/// @brief Performs unsigned fixed-point rounding operation.
|
||||
///
|
||||
/// @param [in] value Fixed point number to convert in Qm.f format.
|
||||
/// @param [in] n Number of fractional bits.
|
||||
///
|
||||
/// @returns rounded fixed point number in Q0 format (unsigned integer).
|
||||
constexpr uint32 UFixedRoundToUint32(uint32 value, uint8 n)
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT((0 < n) && (n < 31));
|
||||
return ((value + (((1 << n) >> 1))) >> n);
|
||||
}
|
||||
|
||||
/// @brief Performs signed fixed-point rounding operation.
|
||||
///
|
||||
/// @param [in] value Fixed point number to convert in Qm.f format.
|
||||
/// @param [in] n Number of fractional bits.
|
||||
///
|
||||
/// @returns rounded fixed point number in Q0 format (signed integer).
|
||||
constexpr int32 SFixedRoundToInt32(int32 value, uint8 n)
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT((0 < n) && (n < 30));
|
||||
return ((value + (((1 << n) >> 1))) >> n);
|
||||
}
|
||||
|
||||
} // Math
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palMath.h
|
||||
* @brief PAL utility collection function/constant declarations for the Math sub-namespace.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palSysMemory.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// Util sub-namespace defining several useful math routines and constants.
|
||||
namespace Math
|
||||
{
|
||||
|
||||
/// Exponent mask of a single-precision IEEE float.
|
||||
constexpr uint32 FloatExponentMask = 0x7F800000;
|
||||
/// Exponent bias of a single-precision IEEE float.
|
||||
constexpr uint32 FloatExponentBias = 127;
|
||||
/// Number of bits in the mantissa of a single-precision IEEE float.
|
||||
constexpr uint32 FloatNumMantissaBits = 23;
|
||||
/// Mantissa mask of a single-precision IEEE float.
|
||||
constexpr uint32 FloatMantissaMask = 0x007FFFFF;
|
||||
/// Sign bit mask of a single precision IEEE float.
|
||||
constexpr uint32 FloatSignBitMask = 0x80000000;
|
||||
/// Mask of all non-sign bits of a single-precision IEEE float.
|
||||
constexpr uint32 FloatMaskOutSignBit = 0x7FFFFFFF;
|
||||
/// Minimum number of float bits in a normalized IEE float.
|
||||
constexpr uint32 MinNormalizedFloatBits = 0x00800000;
|
||||
|
||||
/// Positive one.
|
||||
constexpr float FloatOne = 1.0f;
|
||||
/// Negative one.
|
||||
constexpr float FloatNegOne = -1.0f;
|
||||
/// Zero.
|
||||
constexpr float FloatZero = 0.0f;
|
||||
/// Positive infinity.
|
||||
constexpr float FloatInfinity = std::numeric_limits<float>::infinity();
|
||||
|
||||
/// Fraction structure.
|
||||
struct Fraction
|
||||
{
|
||||
uint32 num; ///< Numerator
|
||||
uint32 den; ///< Denominator
|
||||
};
|
||||
|
||||
/// Returns the bits of a floating point value as an unsigned integer.
|
||||
inline uint32 FloatToBits(float f)
|
||||
{
|
||||
return (*(reinterpret_cast<uint32*>(&f)));
|
||||
}
|
||||
|
||||
/// Assigns the bits contained in an unsigned integer to the float pointer location
|
||||
inline void SetBitsToFloat(float* f, uint32 u)
|
||||
{
|
||||
*(reinterpret_cast<uint32*>(f)) = u;
|
||||
}
|
||||
|
||||
/// Returns true if the specified float is denormalized.
|
||||
extern bool IsDenorm(float f);
|
||||
/// Returns true if the specified float is +/- infinity.
|
||||
extern bool IsInf(float f);
|
||||
/// Returns true if the specified float is a NaN.
|
||||
extern bool IsNaN(float f);
|
||||
|
||||
/// Determines if a floating-point number is either +/-Infinity or NaN.
|
||||
inline bool IsInfOrNaN(float f)
|
||||
{
|
||||
return (IsInf(f) || IsNaN(f));
|
||||
}
|
||||
|
||||
/// @brief Converts a floating point number to a signed fixed point number with the given integer and fractional bits.
|
||||
///
|
||||
/// If the number of integer bits is zero, the incoming value is treated as normalized, i.e. [-1.0, 1.0]. If the
|
||||
/// intBits is zero, the fracBits is assumed to include 1 sign bit, otherwise the sign bit is assumed to be part of the
|
||||
/// intBits. A typical use for enableRounding would be when converting SNORM/UNORM values to fixed point.
|
||||
///
|
||||
/// @param [in] f Floating point value to convert.
|
||||
/// @param [in] intBits Number of integer bits (including the sign bit) in the fixed point output.
|
||||
/// @param [in] fracBits Number of fractional bits in the fixed point output.
|
||||
/// @param [in] enableRounding Round before conversion.
|
||||
///
|
||||
/// @returns Fixed point number in a uint32.
|
||||
extern uint32 FloatToSFixed(float f, uint32 intBits, uint32 fracBits, bool enableRounding = false);
|
||||
|
||||
/// @brief Converts a floating point number to an unsigned fixed point number with the given integer and
|
||||
/// fractional bits.
|
||||
///
|
||||
/// If the number of integer bits is zero, the incoming value is treated as normalized, i.e. [-1.0, 1.0]. A typical use
|
||||
/// for enableRounding would be when converting SNORM/UNORM values to fixed point.
|
||||
///
|
||||
/// @param [in] f Floating point value to convert.
|
||||
/// @param [in] intBits Number of integer bits (including the sign bit) in the fixed point output.
|
||||
/// @param [in] fracBits Number of fractional bits in the fixed point output.
|
||||
/// @param [in] enableRounding Round before conversion.
|
||||
///
|
||||
/// @returns Fixed point number in a uint32.
|
||||
extern uint32 FloatToUFixed(float f, uint32 intBits, uint32 fracBits, bool enableRounding = false);
|
||||
|
||||
/// @brief Converts a signed fixed point number with the given integer and fractional bits to a floating point number.
|
||||
///
|
||||
/// If the number of integer bits is zero, the incoming value is treated as normalized, i.e. [-1.0, 1.0]. If numIntBits
|
||||
/// is 0, numFracBits is assumed to have 1 bit for the sign, otherwise the sign bit is assumed to be part of the integer
|
||||
/// bits.
|
||||
///
|
||||
/// @param [in] fixedPtNum Fixed point number to convert.
|
||||
/// @param [in] intBits Number of integer bits (including the sign bit).
|
||||
/// @param [in] fracBits Number of fractional bits.
|
||||
///
|
||||
/// @returns Converted floating point number.
|
||||
extern float SFixedToFloat(int32 fixedPtNum, uint32 intBits, uint32 fracBits);
|
||||
|
||||
/// @brief Converts a unsigned fixed point number with the given integer and fractional bits to a floating point number.
|
||||
///
|
||||
/// If the number of integer bits is zero, the incoming value is treated as normalized, i.e. [0, 1.0].
|
||||
///
|
||||
/// @param [in] fixedPtNum Fixed point number to convert.
|
||||
/// @param [in] intBits Number of integer bits (including the sign bit).
|
||||
/// @param [in] fracBits Number of fractional bits.
|
||||
///
|
||||
/// @returns Converted floating point number.
|
||||
extern float UFixedToFloat(uint32 fixedPtNum, uint32 intBits, uint32 fracBits);
|
||||
|
||||
/// Converts a 32-bit IEEE floating point number to a 16-bit signed floating point number.
|
||||
extern uint32 Float32ToFloat16(float f);
|
||||
|
||||
/// Converts a 32-bit IEEE floating point number to an 11-bit signed floating point number.
|
||||
extern uint32 Float32ToFloat11(float f);
|
||||
|
||||
/// Converts a 32-bit IEEE floating point number to a 10-bit signed floating point number.
|
||||
extern uint32 Float32ToFloat10(float f);
|
||||
|
||||
/// Converts a 32-bit IEEE floating-point number to a 10-bit unsigned floating-point number.
|
||||
extern uint32 Float32ToFloat10_6e4(float f);
|
||||
|
||||
/// Converts a 10-bit signed floating point number to a 32-bit IEEE floating point number.
|
||||
extern float Float10_6e4ToFloat32(uint32 fBits);
|
||||
|
||||
/// Converts a 32-bit IEEE floating point number to a N-bit signed floating point number.
|
||||
extern uint32 Float32ToNumBits(float float32, uint32 numBits);
|
||||
|
||||
/// Converts a 16-bit signed floating point number to a 32-bit IEEE floating point number.
|
||||
extern float Float16ToFloat32(uint32 fBits);
|
||||
|
||||
/// Converts an 11-bit signed floating point number to a 32-bit IEEE floating point number.
|
||||
extern float Float11ToFloat32(uint32 fBits);
|
||||
|
||||
/// Converts a 10-bit signed floating point number to a 32-bit IEEE floating point number.
|
||||
extern float Float10ToFloat32(uint32 fBits);
|
||||
|
||||
/// Converts an N-bit signed floating point number to a 32-bit IEEE floating point number.
|
||||
extern float FloatNumBitsToFloat32(uint32 input, uint32 numBits);
|
||||
|
||||
/// Converts a 32-bit IEEE floating point number to a fraction.
|
||||
extern Fraction Float32ToFraction(float float32);
|
||||
|
||||
/// Returns the square root of the specified value.
|
||||
extern float Sqrt(float f);
|
||||
|
||||
/// Returns the result of an exponent operation (base^exponent).
|
||||
extern float Pow(float base, float exponent);
|
||||
|
||||
/// Returns the unsigned integer absolute value.
|
||||
extern uint32 Absu(int32 number);
|
||||
|
||||
/// Return sign-preserved zero if input is denorm, otherwise input value
|
||||
extern float FlushDenormToZero(float input);
|
||||
|
||||
/// Return value in 1.7 signed magnitude format. Valid input range is (-127, 127)
|
||||
extern uint8 IntToSignedMagnitude(int8 input);
|
||||
|
||||
/// @brief Performs unsigned fixed-point rounding operation.
|
||||
///
|
||||
/// @param [in] value Fixed point number to convert in Qm.f format.
|
||||
/// @param [in] n Number of fractional bits.
|
||||
///
|
||||
/// @returns rounded fixed point number in Q0 format (unsigned integer).
|
||||
constexpr uint32 UFixedRoundToUint32(uint32 value, uint8 n)
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT((0 < n) && (n < 31));
|
||||
return ((value + (((1 << n) >> 1))) >> n);
|
||||
}
|
||||
|
||||
/// @brief Performs signed fixed-point rounding operation.
|
||||
///
|
||||
/// @param [in] value Fixed point number to convert in Qm.f format.
|
||||
/// @param [in] n Number of fractional bits.
|
||||
///
|
||||
/// @returns rounded fixed point number in Q0 format (signed integer).
|
||||
constexpr int32 SFixedRoundToInt32(int32 value, uint8 n)
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT((0 < n) && (n < 30));
|
||||
return ((value + (((1 << n) >> 1))) >> n);
|
||||
}
|
||||
|
||||
} // Math
|
||||
} // Util
|
||||
|
||||
@@ -1,158 +1,158 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palMemTracker.h
|
||||
* @brief PAL utility collection MemTracker class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if PAL_MEMTRACK
|
||||
|
||||
#include "palIntrusiveList.h"
|
||||
#include "palMutex.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
// Forward declarations
|
||||
struct AllocInfo;
|
||||
struct FreeInfo;
|
||||
struct MemTrackerElem;
|
||||
enum SystemAllocType : uint32;
|
||||
|
||||
/// @internal
|
||||
///
|
||||
/// An alloc-less list used by the MemTracker to keep track of all allocations.
|
||||
typedef IntrusiveList<MemTrackerElem> MemTrackerList;
|
||||
|
||||
/// @internal
|
||||
///
|
||||
/// Specifies whether a particular memory block was allocated with PAL_MALLOC/PAL_CALLOC, PAL_NEW, or PAL_NEW_ARRAY.
|
||||
/// Used to verify correct matching with PAL_FREE, PAL_DELETE, and PAL_DELETE_ARRAY.
|
||||
enum class MemBlkType : uint32
|
||||
{
|
||||
Malloc = 0,
|
||||
New,
|
||||
NewArray,
|
||||
};
|
||||
|
||||
/// @internal
|
||||
///
|
||||
/// Internal structure used by MemTracker to store information on each allocation.
|
||||
struct MemTrackerElem
|
||||
{
|
||||
size_t size; ///< Size of allocation request.
|
||||
MemBlkType blockType; ///< Memory block type (malloc, new, new array).
|
||||
const char* pFilename; ///< File that requested allocation.
|
||||
uint32 lineNumber; ///< Line number that requested allocation.
|
||||
void* pClientMem; ///< Starting "client usable" data address.
|
||||
void* pOrigMem; ///< Original address of the allocation returned from our underlying allocator.
|
||||
size_t allocNum; ///< The number of the memory allocation. 1 based.
|
||||
MemTrackerList* pList; ///< The list this struct is in. It helps check which MemTracker owns this struct.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Class responsible for tracking allocations and frees to notify the developer of memory leaks.
|
||||
*
|
||||
* Tracking is enabled/disabled via the PAL_MEMTRACK define.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template <typename Allocator>
|
||||
class MemTracker
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param [in] pAllocator The allocator that will allocate memory if required.
|
||||
MemTracker(Allocator*const pAllocator);
|
||||
~MemTracker();
|
||||
|
||||
/// Performs any non-safe initialization that cannot be done in the constructor.
|
||||
///
|
||||
/// @returns Result::Success if initialization is successful, otherwise an appropriate error.
|
||||
Result Init();
|
||||
|
||||
/// Allocates a block of memory and track it using the memory tracker.
|
||||
///
|
||||
/// @param [in] allocInfo Contains information about the requested allocation.
|
||||
///
|
||||
/// @returns Pointer to the allocated memory, nullptr if the allocation failed.
|
||||
void* Alloc(
|
||||
const AllocInfo& allocInfo);
|
||||
|
||||
/// Frees a block of memory.
|
||||
///
|
||||
/// @param [in] freeInfo Contains information about the requested free.
|
||||
void Free(
|
||||
const FreeInfo& freeInfo);
|
||||
|
||||
private:
|
||||
void* AddMemElement(
|
||||
void* pMem,
|
||||
size_t bytes,
|
||||
size_t align,
|
||||
MemBlkType blockType,
|
||||
const char* pFilename,
|
||||
uint32 lineNumber);
|
||||
|
||||
void* RemoveMemElement(void* pMem, MemBlkType blockType);
|
||||
|
||||
void MemoryReport();
|
||||
void FreeLeakedMemory();
|
||||
|
||||
// Sentinel patterns used to detect memory underrun.
|
||||
static constexpr uint32 UnderrunSentinel = 0xDEADBEEF;
|
||||
// Sentinel patterns used to detect memory overrun.
|
||||
static constexpr uint32 OverrunSentinel = 0xCAFEBABE;
|
||||
|
||||
// Size of markers for underruns/overruns. Setting this to 0 disables this feature.
|
||||
static constexpr size_t MarkerSizeUints = PAL_CACHE_LINE_BYTES / sizeof(uint32);
|
||||
|
||||
// Size of underrun/overrun markers in bytes.
|
||||
static constexpr size_t MarkerSizeBytes = MarkerSizeUints * sizeof(uint32);
|
||||
|
||||
MemTrackerList m_trackerList; // The list of active allocations.
|
||||
Mutex m_mutex; // Serializes access to list of active allocations.
|
||||
|
||||
const size_t m_markerSizeUints; // Member variable copy of MarkerSizeUints. Only used to prevent compiler
|
||||
// warnings when MarkerSizeUints is 0.
|
||||
const size_t m_markerSizeBytes; // Member variable copy of MarkerSizeBytes. Only used to prevent compiler
|
||||
// warnings when MarkerSizeBytes is 0.
|
||||
|
||||
Allocator*const m_pAllocator; // Allocator for performing the actual allocations.
|
||||
|
||||
size_t m_nextAllocNum; // The allocation number that the next allocated block will receive.
|
||||
const size_t m_breakOnAllocNum; // The allocation number to trigger a debug break on.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(MemTracker);
|
||||
};
|
||||
|
||||
} // Util
|
||||
|
||||
#endif
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palMemTracker.h
|
||||
* @brief PAL utility collection MemTracker class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if PAL_MEMTRACK
|
||||
|
||||
#include "palIntrusiveList.h"
|
||||
#include "palMutex.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
// Forward declarations
|
||||
struct AllocInfo;
|
||||
struct FreeInfo;
|
||||
struct MemTrackerElem;
|
||||
enum SystemAllocType : uint32;
|
||||
|
||||
/// @internal
|
||||
///
|
||||
/// An alloc-less list used by the MemTracker to keep track of all allocations.
|
||||
typedef IntrusiveList<MemTrackerElem> MemTrackerList;
|
||||
|
||||
/// @internal
|
||||
///
|
||||
/// Specifies whether a particular memory block was allocated with PAL_MALLOC/PAL_CALLOC, PAL_NEW, or PAL_NEW_ARRAY.
|
||||
/// Used to verify correct matching with PAL_FREE, PAL_DELETE, and PAL_DELETE_ARRAY.
|
||||
enum class MemBlkType : uint32
|
||||
{
|
||||
Malloc = 0,
|
||||
New,
|
||||
NewArray,
|
||||
};
|
||||
|
||||
/// @internal
|
||||
///
|
||||
/// Internal structure used by MemTracker to store information on each allocation.
|
||||
struct MemTrackerElem
|
||||
{
|
||||
size_t size; ///< Size of allocation request.
|
||||
MemBlkType blockType; ///< Memory block type (malloc, new, new array).
|
||||
const char* pFilename; ///< File that requested allocation.
|
||||
uint32 lineNumber; ///< Line number that requested allocation.
|
||||
void* pClientMem; ///< Starting "client usable" data address.
|
||||
void* pOrigMem; ///< Original address of the allocation returned from our underlying allocator.
|
||||
size_t allocNum; ///< The number of the memory allocation. 1 based.
|
||||
MemTrackerList* pList; ///< The list this struct is in. It helps check which MemTracker owns this struct.
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Class responsible for tracking allocations and frees to notify the developer of memory leaks.
|
||||
*
|
||||
* Tracking is enabled/disabled via the PAL_MEMTRACK define.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template <typename Allocator>
|
||||
class MemTracker
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param [in] pAllocator The allocator that will allocate memory if required.
|
||||
MemTracker(Allocator*const pAllocator);
|
||||
~MemTracker();
|
||||
|
||||
/// Performs any non-safe initialization that cannot be done in the constructor.
|
||||
///
|
||||
/// @returns Result::Success if initialization is successful, otherwise an appropriate error.
|
||||
Result Init();
|
||||
|
||||
/// Allocates a block of memory and track it using the memory tracker.
|
||||
///
|
||||
/// @param [in] allocInfo Contains information about the requested allocation.
|
||||
///
|
||||
/// @returns Pointer to the allocated memory, nullptr if the allocation failed.
|
||||
void* Alloc(
|
||||
const AllocInfo& allocInfo);
|
||||
|
||||
/// Frees a block of memory.
|
||||
///
|
||||
/// @param [in] freeInfo Contains information about the requested free.
|
||||
void Free(
|
||||
const FreeInfo& freeInfo);
|
||||
|
||||
private:
|
||||
void* AddMemElement(
|
||||
void* pMem,
|
||||
size_t bytes,
|
||||
size_t align,
|
||||
MemBlkType blockType,
|
||||
const char* pFilename,
|
||||
uint32 lineNumber);
|
||||
|
||||
void* RemoveMemElement(void* pMem, MemBlkType blockType);
|
||||
|
||||
void MemoryReport();
|
||||
void FreeLeakedMemory();
|
||||
|
||||
// Sentinel patterns used to detect memory underrun.
|
||||
static constexpr uint32 UnderrunSentinel = 0xDEADBEEF;
|
||||
// Sentinel patterns used to detect memory overrun.
|
||||
static constexpr uint32 OverrunSentinel = 0xCAFEBABE;
|
||||
|
||||
// Size of markers for underruns/overruns. Setting this to 0 disables this feature.
|
||||
static constexpr size_t MarkerSizeUints = PAL_CACHE_LINE_BYTES / sizeof(uint32);
|
||||
|
||||
// Size of underrun/overrun markers in bytes.
|
||||
static constexpr size_t MarkerSizeBytes = MarkerSizeUints * sizeof(uint32);
|
||||
|
||||
MemTrackerList m_trackerList; // The list of active allocations.
|
||||
Mutex m_mutex; // Serializes access to list of active allocations.
|
||||
|
||||
const size_t m_markerSizeUints; // Member variable copy of MarkerSizeUints. Only used to prevent compiler
|
||||
// warnings when MarkerSizeUints is 0.
|
||||
const size_t m_markerSizeBytes; // Member variable copy of MarkerSizeBytes. Only used to prevent compiler
|
||||
// warnings when MarkerSizeBytes is 0.
|
||||
|
||||
Allocator*const m_pAllocator; // Allocator for performing the actual allocations.
|
||||
|
||||
size_t m_nextAllocNum; // The allocation number that the next allocated block will receive.
|
||||
const size_t m_breakOnAllocNum; // The allocation number to trigger a debug break on.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(MemTracker);
|
||||
};
|
||||
|
||||
} // Util
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,331 +1,331 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palMemTrackerImpl.h
|
||||
* @brief PAL utility collection MemTracker class implementations.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if PAL_MEMTRACK
|
||||
|
||||
#include "palIntrusiveListImpl.h"
|
||||
#include "palMemTracker.h"
|
||||
#include "palSysMemory.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// Table to convert a blockType to a string. Used by the logging routines.
|
||||
constexpr const char* MemBlkTypeStr[] =
|
||||
{
|
||||
"Malloc", ///< MemBlkType::Malloc
|
||||
"New", ///< MemBlkType::New
|
||||
"NewArray", ///< MemBlkType::NewArray
|
||||
};
|
||||
|
||||
// =====================================================================================================================
|
||||
template <typename Allocator>
|
||||
MemTracker<Allocator>::MemTracker(
|
||||
Allocator*const pAllocator)
|
||||
:
|
||||
m_markerSizeUints(MarkerSizeUints),
|
||||
m_markerSizeBytes(MarkerSizeBytes),
|
||||
m_pAllocator(pAllocator),
|
||||
m_nextAllocNum(1),
|
||||
m_breakOnAllocNum(0)
|
||||
{
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template <typename Allocator>
|
||||
MemTracker<Allocator>::~MemTracker()
|
||||
{
|
||||
// Clean-up leaked memory if needed
|
||||
if (m_trackerList.IsEmpty() == false)
|
||||
{
|
||||
// If the list isn't empty, we have a leak. The leak could either be caused by an internal PAL leak,
|
||||
// a client leak, or even the application not destroying API objects.
|
||||
PAL_ALERT_ALWAYS();
|
||||
|
||||
// Dump out a list of unfreed blocks.
|
||||
MemoryReport();
|
||||
|
||||
FreeLeakedMemory();
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template <typename Allocator>
|
||||
Result MemTracker<Allocator>::Init()
|
||||
{
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Adds the newly allocated memory block to the list of blocks for tracking.
|
||||
//
|
||||
// The tracking information includes things like filename, line numbers, and type of block. Also, given a pointer,
|
||||
// adds the Underrun/Overrun markers to the memory allocated, and return a pointer to the actual client usable memory.
|
||||
//
|
||||
// See MemTracker::Alloc() which is used to allocate memory that is being tracked.
|
||||
template <typename Allocator>
|
||||
void* MemTracker<Allocator>::AddMemElement(
|
||||
void* pMem, // [in,out] Original pointer allocated by MemTracker::Alloc.
|
||||
size_t bytes, // Client requested allocation size in bytes.
|
||||
size_t align, // The max of the client-requested alignment or the internal alignment, in bytes.
|
||||
MemBlkType blockType, // Block type based on calling allocation routine.
|
||||
const char* pFilename, // Client filename that is requesting the memory.
|
||||
uint32 lineNumber) // Line number in client file that is requesting the memory.
|
||||
{
|
||||
// Our internal data is all relative to the client pointer so find that first. See Alloc for more details.
|
||||
// (align1)(MemTrackerList::Node)(MemTrackerElem)(underflow tracker)(client allocation)(align2)(overflow tracker)
|
||||
constexpr size_t InternalSize = sizeof(MemTrackerList::Node) + sizeof(MemTrackerElem);
|
||||
|
||||
void*const pClientMem = VoidPtrAlign(VoidPtrInc(pMem, m_markerSizeBytes + InternalSize), align);
|
||||
uint32* pUnderrun = static_cast<uint32*>(VoidPtrDec(pClientMem, m_markerSizeBytes));
|
||||
uint32* pOverrun = static_cast<uint32*>(VoidPtrInc(pClientMem, Pow2Align(bytes, sizeof(uint32))));
|
||||
|
||||
auto*const pNewElement = static_cast<MemTrackerElem*>(VoidPtrDec(pUnderrun, sizeof(MemTrackerElem)));
|
||||
void*const pNewNodeMem = VoidPtrDec(pNewElement, sizeof(MemTrackerList::Node));
|
||||
auto*const pNewNode = PAL_PLACEMENT_NEW(pNewNodeMem) MemTrackerList::Node(pNewElement);
|
||||
|
||||
// Mark the memory with the underrun/overrun marker.
|
||||
for (uint32 markerUints = 0; markerUints < m_markerSizeUints; ++markerUints)
|
||||
{
|
||||
*pUnderrun++ = UnderrunSentinel;
|
||||
*pOverrun++ = OverrunSentinel;
|
||||
}
|
||||
|
||||
pNewElement->size = bytes;
|
||||
pNewElement->pFilename = pFilename;
|
||||
pNewElement->lineNumber = lineNumber;
|
||||
pNewElement->blockType = blockType;
|
||||
pNewElement->pClientMem = pClientMem;
|
||||
pNewElement->pOrigMem = pMem;
|
||||
pNewElement->pList = &m_trackerList;
|
||||
|
||||
MutexAuto lock(&m_mutex);
|
||||
|
||||
// Trigger an assert if we're about to allocate the break-on-allocation number.
|
||||
if (m_nextAllocNum == m_breakOnAllocNum)
|
||||
{
|
||||
PAL_ASSERT_ALWAYS();
|
||||
}
|
||||
|
||||
pNewElement->allocNum = m_nextAllocNum;
|
||||
++m_nextAllocNum;
|
||||
|
||||
m_trackerList.PushFront(pNewNode);
|
||||
|
||||
return pClientMem;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Removes an allocated block from the list of blocks used for tracking.
|
||||
//
|
||||
// The routine checks for invalid frees (and duplicate frees). Also, the routine is able to detect mismatched alloc/free
|
||||
// usage based on the blockType. The routine is called with the pointer to the client usable memory and returns the
|
||||
// pointer to the allocated memory.
|
||||
//
|
||||
// See MemTracker::Free() which is used to free memory that is being tracked.
|
||||
template <typename Allocator>
|
||||
void* MemTracker<Allocator>::RemoveMemElement(
|
||||
void* pClientMem, // Pointer to client usable memory.
|
||||
MemBlkType blockType) // Block type based on calling deallocation routine.
|
||||
{
|
||||
void* pOrigPtr = nullptr;
|
||||
|
||||
// Recall that this is our internal memory layout. See Alloc for more details.
|
||||
// (align1)(MemTrackerList::Node)(MemTrackerElem)(underflow tracker)(client allocation)(align2)(overflow tracker)
|
||||
uint32* pUnderrun = static_cast<uint32*>(VoidPtrDec(pClientMem, m_markerSizeBytes));
|
||||
auto*const pCurrent = static_cast<MemTrackerElem*>(VoidPtrDec(pUnderrun, sizeof(MemTrackerElem)));
|
||||
auto*const pCurrentNode = static_cast<MemTrackerList::Node*>(VoidPtrDec(pCurrent, sizeof(MemTrackerList::Node)));
|
||||
uint32* pOverrun = static_cast<uint32*>(VoidPtrInc(pClientMem, Pow2Align(pCurrent->size, sizeof(uint32))));
|
||||
|
||||
// We should not be trying to free something twice or trying to free something which has not been allocated
|
||||
// by this MemTracker. We can verify both of these things by checking that the tracker's pList is equal to the
|
||||
// MemTracker's list.
|
||||
if (pCurrent->pList != &m_trackerList)
|
||||
{
|
||||
// A free was attempted on an unrecognized pointer.
|
||||
PAL_DPERROR("Invalid Free Attempted with ptr = : (%#x)", pClientMem);
|
||||
}
|
||||
else if (pCurrent->blockType != blockType)
|
||||
{
|
||||
// We have a mismatch in the alloc/free pair, e.g. PAL_NEW with PAL_FREE etc. return early here without freeing
|
||||
// the memory so it shows up as a leak.
|
||||
PAL_DPERROR("Trying to Free %s as %s.",
|
||||
MemBlkTypeStr[static_cast<uint32>(pCurrent->blockType)],
|
||||
MemBlkTypeStr[static_cast<uint32>(blockType)]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should check for memory corruption due to overflow or underflow before continuing because any underflow
|
||||
// might indicate that our internal state is corrupted. This could lead to a crash in the code below.
|
||||
for (uint32 markerUints = 0; markerUints < m_markerSizeUints; ++markerUints)
|
||||
{
|
||||
PAL_ASSERT(*pUnderrun++ == UnderrunSentinel);
|
||||
PAL_ASSERT(*pOverrun++ == OverrunSentinel);
|
||||
}
|
||||
|
||||
// Remove our tracker from the list and set it's pList to null to detect a double-free in the future.
|
||||
MutexAuto lock(&m_mutex);
|
||||
|
||||
m_trackerList.Erase(pCurrentNode);
|
||||
|
||||
pCurrent->pList = nullptr;
|
||||
pOrigPtr = pCurrent->pOrigMem;
|
||||
}
|
||||
|
||||
// Return a pointer to the actual allocated block.
|
||||
return pOrigPtr;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Allocates a block of memory and tracks it using the memory tracker.
|
||||
template <typename Allocator>
|
||||
void* MemTracker<Allocator>::Alloc(
|
||||
const AllocInfo& allocInfo)
|
||||
{
|
||||
// Allocating zero bytes of memory results in undefined behavior.
|
||||
PAL_ASSERT(allocInfo.bytes > 0);
|
||||
|
||||
void* pMem = nullptr;
|
||||
|
||||
// We want to allocate extra memory from the caller's allocator, in this layout:
|
||||
// (align1)(MemTrackerList::Node)(MemTrackerElem)(underflow tracker)(client allocation)(align2)(overflow tracker)
|
||||
// Here's why we need each of those sections:
|
||||
// 1. align1 is zero or more bytes needed to align the client allocation and our internal data.
|
||||
// 2. The MemTrackerList::Node object, which is used to link this allocation into m_trackerList.
|
||||
// 3. The MemTrackerElem struct contains bookkeeping data we need to report memory errors.
|
||||
// 4. The underflow and overflow trackers detect out of bounds writes. They are optional.
|
||||
// 5. The client allocation, which is actually returned to the caller.
|
||||
// 6. align2 is zero or more bytes needed to DWORD-align the overflow tracker.
|
||||
constexpr size_t InternalAlignment = Max(alignof(MemTrackerList::Node), alignof(MemTrackerElem));
|
||||
const size_t paddedAlignBytes = Max(allocInfo.alignment, InternalAlignment);
|
||||
const size_t paddedSizeBytes = (paddedAlignBytes + // 1
|
||||
sizeof(MemTrackerList::Node) + // 2
|
||||
sizeof(MemTrackerElem) + // 3
|
||||
m_markerSizeBytes + // 4.a
|
||||
Pow2Align(allocInfo.bytes, sizeof(uint32)) + // 5 & 6
|
||||
m_markerSizeBytes); // 4.b
|
||||
|
||||
const AllocInfo memTrackerInfo(paddedSizeBytes, paddedAlignBytes, allocInfo.zeroMem, allocInfo.allocType,
|
||||
allocInfo.blockType, allocInfo.pFilename, allocInfo.lineNumber);
|
||||
|
||||
pMem = m_pAllocator->Alloc(memTrackerInfo);
|
||||
|
||||
if (pMem != nullptr)
|
||||
{
|
||||
// Don't bother adding a failed allocation to the Memtrack list.
|
||||
pMem = AddMemElement(pMem,
|
||||
allocInfo.bytes,
|
||||
paddedAlignBytes,
|
||||
allocInfo.blockType,
|
||||
allocInfo.pFilename,
|
||||
allocInfo.lineNumber);
|
||||
}
|
||||
|
||||
return pMem;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Frees a block of memory. The routine is called with the pointer to the client usable memory.
|
||||
//
|
||||
// See MemTracker::RemoveMemElement() which is used to validate the free.
|
||||
template <typename Allocator>
|
||||
void MemTracker<Allocator>::Free(
|
||||
const FreeInfo& freeInfo)
|
||||
{
|
||||
// Don't want to call RemoveMemElement if the ptr is null.
|
||||
if (freeInfo.pClientMem != nullptr)
|
||||
{
|
||||
void* pMem = RemoveMemElement(freeInfo.pClientMem, freeInfo.blockType);
|
||||
|
||||
// If this free call is valid (RemoveMemElement doesn't return nullptr), release the memory.
|
||||
if (pMem != nullptr)
|
||||
{
|
||||
m_pAllocator->Free(FreeInfo(pMem, freeInfo.blockType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Frees all memory that has not been explicitly freed (in other words, memory that has leaked). This function is only
|
||||
// expected to be called when the memory tracker is being destroyed.
|
||||
template <typename Allocator>
|
||||
void MemTracker<Allocator>::FreeLeakedMemory()
|
||||
{
|
||||
for (MemTrackerList::Iter iter = m_trackerList.Begin(); iter.IsValid(); )
|
||||
{
|
||||
MemTrackerElem*const pCurrent = iter.Get();
|
||||
|
||||
// Free will release the memory for tracking and the actual element. This will invalidate our list iterator
|
||||
// unless we advance the iterator first.
|
||||
iter.Next();
|
||||
|
||||
Free(FreeInfo(pCurrent->pClientMem, pCurrent->blockType));
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Outputs information about leaked memory by traversing the memory tracker list.
|
||||
template <typename Allocator>
|
||||
void MemTracker<Allocator>::MemoryReport()
|
||||
{
|
||||
// When this env var is set to non-zero, don't report leaks.
|
||||
// Useful for crashing apps that don't give us a chance to clean up.
|
||||
const char* pToggle = getenv("AMDPAL_NO_LEAK_REPORT");
|
||||
|
||||
if ((pToggle == nullptr) || (atoi(pToggle) == 0))
|
||||
{
|
||||
PAL_DPWARN("================ List of Leaked Blocks ================");
|
||||
|
||||
for (MemTrackerList::Iter iter = m_trackerList.Begin(); iter.IsValid(); iter.Next())
|
||||
{
|
||||
MemTrackerElem*const pCurrent = iter.Get();
|
||||
|
||||
PAL_DPWARN(
|
||||
"ClientMem = 0x%p, AllocSize = %8d, MemBlkType = %s, File = %-15s, LineNumber = %8d, AllocNum = %8d",
|
||||
pCurrent->pClientMem,
|
||||
pCurrent->size,
|
||||
MemBlkTypeStr[static_cast<uint32>(pCurrent->blockType)],
|
||||
pCurrent->pFilename,
|
||||
pCurrent->lineNumber,
|
||||
pCurrent->allocNum);
|
||||
}
|
||||
|
||||
PAL_DPWARN("================ End of List ===========================");
|
||||
}
|
||||
}
|
||||
|
||||
} // Util
|
||||
|
||||
#endif
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palMemTrackerImpl.h
|
||||
* @brief PAL utility collection MemTracker class implementations.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if PAL_MEMTRACK
|
||||
|
||||
#include "palIntrusiveListImpl.h"
|
||||
#include "palMemTracker.h"
|
||||
#include "palSysMemory.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// Table to convert a blockType to a string. Used by the logging routines.
|
||||
constexpr const char* MemBlkTypeStr[] =
|
||||
{
|
||||
"Malloc", ///< MemBlkType::Malloc
|
||||
"New", ///< MemBlkType::New
|
||||
"NewArray", ///< MemBlkType::NewArray
|
||||
};
|
||||
|
||||
// =====================================================================================================================
|
||||
template <typename Allocator>
|
||||
MemTracker<Allocator>::MemTracker(
|
||||
Allocator*const pAllocator)
|
||||
:
|
||||
m_markerSizeUints(MarkerSizeUints),
|
||||
m_markerSizeBytes(MarkerSizeBytes),
|
||||
m_pAllocator(pAllocator),
|
||||
m_nextAllocNum(1),
|
||||
m_breakOnAllocNum(0)
|
||||
{
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template <typename Allocator>
|
||||
MemTracker<Allocator>::~MemTracker()
|
||||
{
|
||||
// Clean-up leaked memory if needed
|
||||
if (m_trackerList.IsEmpty() == false)
|
||||
{
|
||||
// If the list isn't empty, we have a leak. The leak could either be caused by an internal PAL leak,
|
||||
// a client leak, or even the application not destroying API objects.
|
||||
PAL_ALERT_ALWAYS();
|
||||
|
||||
// Dump out a list of unfreed blocks.
|
||||
MemoryReport();
|
||||
|
||||
FreeLeakedMemory();
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template <typename Allocator>
|
||||
Result MemTracker<Allocator>::Init()
|
||||
{
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Adds the newly allocated memory block to the list of blocks for tracking.
|
||||
//
|
||||
// The tracking information includes things like filename, line numbers, and type of block. Also, given a pointer,
|
||||
// adds the Underrun/Overrun markers to the memory allocated, and return a pointer to the actual client usable memory.
|
||||
//
|
||||
// See MemTracker::Alloc() which is used to allocate memory that is being tracked.
|
||||
template <typename Allocator>
|
||||
void* MemTracker<Allocator>::AddMemElement(
|
||||
void* pMem, // [in,out] Original pointer allocated by MemTracker::Alloc.
|
||||
size_t bytes, // Client requested allocation size in bytes.
|
||||
size_t align, // The max of the client-requested alignment or the internal alignment, in bytes.
|
||||
MemBlkType blockType, // Block type based on calling allocation routine.
|
||||
const char* pFilename, // Client filename that is requesting the memory.
|
||||
uint32 lineNumber) // Line number in client file that is requesting the memory.
|
||||
{
|
||||
// Our internal data is all relative to the client pointer so find that first. See Alloc for more details.
|
||||
// (align1)(MemTrackerList::Node)(MemTrackerElem)(underflow tracker)(client allocation)(align2)(overflow tracker)
|
||||
constexpr size_t InternalSize = sizeof(MemTrackerList::Node) + sizeof(MemTrackerElem);
|
||||
|
||||
void*const pClientMem = VoidPtrAlign(VoidPtrInc(pMem, m_markerSizeBytes + InternalSize), align);
|
||||
uint32* pUnderrun = static_cast<uint32*>(VoidPtrDec(pClientMem, m_markerSizeBytes));
|
||||
uint32* pOverrun = static_cast<uint32*>(VoidPtrInc(pClientMem, Pow2Align(bytes, sizeof(uint32))));
|
||||
|
||||
auto*const pNewElement = static_cast<MemTrackerElem*>(VoidPtrDec(pUnderrun, sizeof(MemTrackerElem)));
|
||||
void*const pNewNodeMem = VoidPtrDec(pNewElement, sizeof(MemTrackerList::Node));
|
||||
auto*const pNewNode = PAL_PLACEMENT_NEW(pNewNodeMem) MemTrackerList::Node(pNewElement);
|
||||
|
||||
// Mark the memory with the underrun/overrun marker.
|
||||
for (uint32 markerUints = 0; markerUints < m_markerSizeUints; ++markerUints)
|
||||
{
|
||||
*pUnderrun++ = UnderrunSentinel;
|
||||
*pOverrun++ = OverrunSentinel;
|
||||
}
|
||||
|
||||
pNewElement->size = bytes;
|
||||
pNewElement->pFilename = pFilename;
|
||||
pNewElement->lineNumber = lineNumber;
|
||||
pNewElement->blockType = blockType;
|
||||
pNewElement->pClientMem = pClientMem;
|
||||
pNewElement->pOrigMem = pMem;
|
||||
pNewElement->pList = &m_trackerList;
|
||||
|
||||
MutexAuto lock(&m_mutex);
|
||||
|
||||
// Trigger an assert if we're about to allocate the break-on-allocation number.
|
||||
if (m_nextAllocNum == m_breakOnAllocNum)
|
||||
{
|
||||
PAL_ASSERT_ALWAYS();
|
||||
}
|
||||
|
||||
pNewElement->allocNum = m_nextAllocNum;
|
||||
++m_nextAllocNum;
|
||||
|
||||
m_trackerList.PushFront(pNewNode);
|
||||
|
||||
return pClientMem;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Removes an allocated block from the list of blocks used for tracking.
|
||||
//
|
||||
// The routine checks for invalid frees (and duplicate frees). Also, the routine is able to detect mismatched alloc/free
|
||||
// usage based on the blockType. The routine is called with the pointer to the client usable memory and returns the
|
||||
// pointer to the allocated memory.
|
||||
//
|
||||
// See MemTracker::Free() which is used to free memory that is being tracked.
|
||||
template <typename Allocator>
|
||||
void* MemTracker<Allocator>::RemoveMemElement(
|
||||
void* pClientMem, // Pointer to client usable memory.
|
||||
MemBlkType blockType) // Block type based on calling deallocation routine.
|
||||
{
|
||||
void* pOrigPtr = nullptr;
|
||||
|
||||
// Recall that this is our internal memory layout. See Alloc for more details.
|
||||
// (align1)(MemTrackerList::Node)(MemTrackerElem)(underflow tracker)(client allocation)(align2)(overflow tracker)
|
||||
uint32* pUnderrun = static_cast<uint32*>(VoidPtrDec(pClientMem, m_markerSizeBytes));
|
||||
auto*const pCurrent = static_cast<MemTrackerElem*>(VoidPtrDec(pUnderrun, sizeof(MemTrackerElem)));
|
||||
auto*const pCurrentNode = static_cast<MemTrackerList::Node*>(VoidPtrDec(pCurrent, sizeof(MemTrackerList::Node)));
|
||||
uint32* pOverrun = static_cast<uint32*>(VoidPtrInc(pClientMem, Pow2Align(pCurrent->size, sizeof(uint32))));
|
||||
|
||||
// We should not be trying to free something twice or trying to free something which has not been allocated
|
||||
// by this MemTracker. We can verify both of these things by checking that the tracker's pList is equal to the
|
||||
// MemTracker's list.
|
||||
if (pCurrent->pList != &m_trackerList)
|
||||
{
|
||||
// A free was attempted on an unrecognized pointer.
|
||||
PAL_DPERROR("Invalid Free Attempted with ptr = : (%#x)", pClientMem);
|
||||
}
|
||||
else if (pCurrent->blockType != blockType)
|
||||
{
|
||||
// We have a mismatch in the alloc/free pair, e.g. PAL_NEW with PAL_FREE etc. return early here without freeing
|
||||
// the memory so it shows up as a leak.
|
||||
PAL_DPERROR("Trying to Free %s as %s.",
|
||||
MemBlkTypeStr[static_cast<uint32>(pCurrent->blockType)],
|
||||
MemBlkTypeStr[static_cast<uint32>(blockType)]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should check for memory corruption due to overflow or underflow before continuing because any underflow
|
||||
// might indicate that our internal state is corrupted. This could lead to a crash in the code below.
|
||||
for (uint32 markerUints = 0; markerUints < m_markerSizeUints; ++markerUints)
|
||||
{
|
||||
PAL_ASSERT(*pUnderrun++ == UnderrunSentinel);
|
||||
PAL_ASSERT(*pOverrun++ == OverrunSentinel);
|
||||
}
|
||||
|
||||
// Remove our tracker from the list and set it's pList to null to detect a double-free in the future.
|
||||
MutexAuto lock(&m_mutex);
|
||||
|
||||
m_trackerList.Erase(pCurrentNode);
|
||||
|
||||
pCurrent->pList = nullptr;
|
||||
pOrigPtr = pCurrent->pOrigMem;
|
||||
}
|
||||
|
||||
// Return a pointer to the actual allocated block.
|
||||
return pOrigPtr;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Allocates a block of memory and tracks it using the memory tracker.
|
||||
template <typename Allocator>
|
||||
void* MemTracker<Allocator>::Alloc(
|
||||
const AllocInfo& allocInfo)
|
||||
{
|
||||
// Allocating zero bytes of memory results in undefined behavior.
|
||||
PAL_ASSERT(allocInfo.bytes > 0);
|
||||
|
||||
void* pMem = nullptr;
|
||||
|
||||
// We want to allocate extra memory from the caller's allocator, in this layout:
|
||||
// (align1)(MemTrackerList::Node)(MemTrackerElem)(underflow tracker)(client allocation)(align2)(overflow tracker)
|
||||
// Here's why we need each of those sections:
|
||||
// 1. align1 is zero or more bytes needed to align the client allocation and our internal data.
|
||||
// 2. The MemTrackerList::Node object, which is used to link this allocation into m_trackerList.
|
||||
// 3. The MemTrackerElem struct contains bookkeeping data we need to report memory errors.
|
||||
// 4. The underflow and overflow trackers detect out of bounds writes. They are optional.
|
||||
// 5. The client allocation, which is actually returned to the caller.
|
||||
// 6. align2 is zero or more bytes needed to DWORD-align the overflow tracker.
|
||||
constexpr size_t InternalAlignment = Max(alignof(MemTrackerList::Node), alignof(MemTrackerElem));
|
||||
const size_t paddedAlignBytes = Max(allocInfo.alignment, InternalAlignment);
|
||||
const size_t paddedSizeBytes = (paddedAlignBytes + // 1
|
||||
sizeof(MemTrackerList::Node) + // 2
|
||||
sizeof(MemTrackerElem) + // 3
|
||||
m_markerSizeBytes + // 4.a
|
||||
Pow2Align(allocInfo.bytes, sizeof(uint32)) + // 5 & 6
|
||||
m_markerSizeBytes); // 4.b
|
||||
|
||||
const AllocInfo memTrackerInfo(paddedSizeBytes, paddedAlignBytes, allocInfo.zeroMem, allocInfo.allocType,
|
||||
allocInfo.blockType, allocInfo.pFilename, allocInfo.lineNumber);
|
||||
|
||||
pMem = m_pAllocator->Alloc(memTrackerInfo);
|
||||
|
||||
if (pMem != nullptr)
|
||||
{
|
||||
// Don't bother adding a failed allocation to the Memtrack list.
|
||||
pMem = AddMemElement(pMem,
|
||||
allocInfo.bytes,
|
||||
paddedAlignBytes,
|
||||
allocInfo.blockType,
|
||||
allocInfo.pFilename,
|
||||
allocInfo.lineNumber);
|
||||
}
|
||||
|
||||
return pMem;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Frees a block of memory. The routine is called with the pointer to the client usable memory.
|
||||
//
|
||||
// See MemTracker::RemoveMemElement() which is used to validate the free.
|
||||
template <typename Allocator>
|
||||
void MemTracker<Allocator>::Free(
|
||||
const FreeInfo& freeInfo)
|
||||
{
|
||||
// Don't want to call RemoveMemElement if the ptr is null.
|
||||
if (freeInfo.pClientMem != nullptr)
|
||||
{
|
||||
void* pMem = RemoveMemElement(freeInfo.pClientMem, freeInfo.blockType);
|
||||
|
||||
// If this free call is valid (RemoveMemElement doesn't return nullptr), release the memory.
|
||||
if (pMem != nullptr)
|
||||
{
|
||||
m_pAllocator->Free(FreeInfo(pMem, freeInfo.blockType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Frees all memory that has not been explicitly freed (in other words, memory that has leaked). This function is only
|
||||
// expected to be called when the memory tracker is being destroyed.
|
||||
template <typename Allocator>
|
||||
void MemTracker<Allocator>::FreeLeakedMemory()
|
||||
{
|
||||
for (MemTrackerList::Iter iter = m_trackerList.Begin(); iter.IsValid(); )
|
||||
{
|
||||
MemTrackerElem*const pCurrent = iter.Get();
|
||||
|
||||
// Free will release the memory for tracking and the actual element. This will invalidate our list iterator
|
||||
// unless we advance the iterator first.
|
||||
iter.Next();
|
||||
|
||||
Free(FreeInfo(pCurrent->pClientMem, pCurrent->blockType));
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Outputs information about leaked memory by traversing the memory tracker list.
|
||||
template <typename Allocator>
|
||||
void MemTracker<Allocator>::MemoryReport()
|
||||
{
|
||||
// When this env var is set to non-zero, don't report leaks.
|
||||
// Useful for crashing apps that don't give us a chance to clean up.
|
||||
const char* pToggle = getenv("AMDPAL_NO_LEAK_REPORT");
|
||||
|
||||
if ((pToggle == nullptr) || (atoi(pToggle) == 0))
|
||||
{
|
||||
PAL_DPWARN("================ List of Leaked Blocks ================");
|
||||
|
||||
for (MemTrackerList::Iter iter = m_trackerList.Begin(); iter.IsValid(); iter.Next())
|
||||
{
|
||||
MemTrackerElem*const pCurrent = iter.Get();
|
||||
|
||||
PAL_DPWARN(
|
||||
"ClientMem = 0x%p, AllocSize = %8d, MemBlkType = %s, File = %-15s, LineNumber = %8d, AllocNum = %8d",
|
||||
pCurrent->pClientMem,
|
||||
pCurrent->size,
|
||||
MemBlkTypeStr[static_cast<uint32>(pCurrent->blockType)],
|
||||
pCurrent->pFilename,
|
||||
pCurrent->lineNumber,
|
||||
pCurrent->allocNum);
|
||||
}
|
||||
|
||||
PAL_DPWARN("================ End of List ===========================");
|
||||
}
|
||||
}
|
||||
|
||||
} // Util
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,398 +1,398 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palMutex.h
|
||||
* @brief PAL utility collection Mutex and MutexAuto class declarations.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palAssert.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
// WIN32_NO_STATUS prevents winnt.h from re-defining NTSTATUS macros that cause build warnings if
|
||||
// ntstatus.h is also included.
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
#endif
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Platform-agnostic mutex primitive.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class Mutex
|
||||
{
|
||||
public:
|
||||
#if defined(_WIN32)
|
||||
/// Defines MutexData as a Windows CRITICAL_SECTION
|
||||
typedef CRITICAL_SECTION MutexData;
|
||||
Mutex() noexcept : m_osMutex {} { InitializeCriticalSection(&m_osMutex); }
|
||||
~Mutex() { DeleteCriticalSection(&m_osMutex); };
|
||||
#else
|
||||
/// Defines MutexData as a unix pthread_mutex_t
|
||||
typedef pthread_mutex_t MutexData;
|
||||
Mutex() noexcept : m_osMutex {} { pthread_mutex_init(&m_osMutex, nullptr); }
|
||||
~Mutex() { pthread_mutex_destroy(&m_osMutex); };
|
||||
#endif
|
||||
|
||||
/// Enters the critical section if it is not contended. If it is contended, wait for the critical section to become
|
||||
/// available, then enter it.
|
||||
void Lock();
|
||||
|
||||
/// Enters the critical section if it is not contended. Does not wait for the critical section to become available
|
||||
/// if it is contended.
|
||||
///
|
||||
/// @returns True if the critical section was entered, false otherwise.
|
||||
bool TryLock();
|
||||
|
||||
/// Leaves the critical section.
|
||||
void Unlock();
|
||||
|
||||
/// Returns the OS specific mutex data.
|
||||
MutexData* GetMutexData() { return &m_osMutex; }
|
||||
|
||||
private:
|
||||
MutexData m_osMutex; ///< Opaque structure to the OS-specific Mutex data
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(Mutex);
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief A "resource acquisition is initialization" (RAII) wrapper for the Mutex class.
|
||||
*
|
||||
* The RAII paradigm allows critical sections to be automatically acquired during this class' constructor, and
|
||||
* automatically released when a stack-allocated wrapper object goes out-of-scope. As such, it only makes sense to use
|
||||
* this class for stack-allocated objects.
|
||||
*
|
||||
* This object will ensure that anything between when the object is allocated on the stack and when it goes out of scope
|
||||
* will be protected from access by multiple threads. See the below example.
|
||||
*
|
||||
* [Code not protected]
|
||||
* {
|
||||
* [Code not protected]
|
||||
* MutexAuto lock(pPtrToMutex);
|
||||
* [Code is protected]
|
||||
* }
|
||||
* [Code not protected]
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class MutexAuto
|
||||
{
|
||||
public:
|
||||
/// Locks the given Mutex.
|
||||
explicit MutexAuto(Mutex* pMutex) : m_pMutex(pMutex)
|
||||
{
|
||||
PAL_ASSERT(m_pMutex != nullptr);
|
||||
m_pMutex->Lock();
|
||||
}
|
||||
|
||||
/// Unlocks the Mutex we locked in the constructor.
|
||||
~MutexAuto()
|
||||
{
|
||||
m_pMutex->Unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex* const m_pMutex; ///< The Mutex which this object wraps.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(MutexAuto);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(MutexAuto);
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Platform-agnostic rw lock primitive.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class RWLock
|
||||
{
|
||||
public:
|
||||
#if defined(_WIN32)
|
||||
/// Defines RWLockData as a Windows RWLOCK
|
||||
typedef SRWLOCK RWLockData;
|
||||
RWLock() noexcept : m_osRWLock {} { InitializeSRWLock(&m_osRWLock); }
|
||||
~RWLock() noexcept { /* No Win32 destory function */ };
|
||||
#else
|
||||
/// Defines RWLockData as a unix pthread_rwlock_t
|
||||
typedef pthread_rwlock_t RWLockData;
|
||||
/// @note pthread_rwlock_init will not fail as called
|
||||
RWLock() noexcept : m_osRWLock {} { pthread_rwlock_init(&m_osRWLock, nullptr); }
|
||||
~RWLock() noexcept { pthread_rwlock_destroy(&m_osRWLock); };
|
||||
#endif
|
||||
|
||||
/// Enumerates the lock type of RWLockAuto
|
||||
enum LockType
|
||||
{
|
||||
ReadOnly = 0, ///< Lock in readonly mode, in other words shared mode.
|
||||
ReadWrite ///< Lock in readwrite mode, in other words exclusive mode.
|
||||
};
|
||||
|
||||
/// Acquires a rw lock in shared mode if it is not contended in exclusive mode.
|
||||
/// If it is contended, wait for rw lock to become available, then enter it.
|
||||
void LockForRead();
|
||||
|
||||
/// Acquires a rw lock in exclusive mode if it is not contended.
|
||||
/// If it is contended, wait for rw lock to become available, then enter it.
|
||||
void LockForWrite();
|
||||
|
||||
/// Try to acquires a rw lock in shared mode if it is not contended in exclusive mode.
|
||||
/// Does not wait for the rw lock to become available.
|
||||
/// @returns True if the rw lock was acquired, false otherwise.
|
||||
bool TryLockForRead();
|
||||
|
||||
/// Try to acquires a rw lock in exclusive mode if it is not contended.
|
||||
/// Does not wait for the rw lock to become available.
|
||||
/// @returns True if the rw lock was acquired, false otherwise.
|
||||
bool TryLockForWrite();
|
||||
|
||||
/// Release the rw lock which is previously contended in shared mode.
|
||||
void UnlockForRead();
|
||||
|
||||
/// Release the rw lock which is previously contended in exclusive mode.
|
||||
void UnlockForWrite();
|
||||
|
||||
/// Returns the OS specific RWLOCK data.
|
||||
RWLockData* GetRWLockData() { return &m_osRWLock; }
|
||||
|
||||
private:
|
||||
RWLockData m_osRWLock; ///< Opaque structure to the OS-specific RWLock data
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(RWLock);
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief A "resource acquisition is initialization" (RAII) wrapper for the RWLock class.
|
||||
*
|
||||
* The RAII paradigm allows rw lcok to be automatically acquired during this class' constructor, and
|
||||
* automatically released when a stack-allocated wrapper object goes out-of-scope. As such, it only makes sense to use
|
||||
* this class for stack-allocated objects.
|
||||
*
|
||||
* This object will ensure that anything between when the object is allocated on the stack and when it goes out of scope
|
||||
* will be protected from access by multiple threads. See the below example.
|
||||
*
|
||||
* [Code not protected]
|
||||
* {
|
||||
* [Code not protected]
|
||||
* RWLockAuto lock(pPtrToMutex, type);
|
||||
* [Code is protected]
|
||||
* }
|
||||
* [Code not protected]
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template <RWLock::LockType type>
|
||||
class RWLockAuto
|
||||
{
|
||||
public:
|
||||
/// Locks the given RWLock.
|
||||
explicit RWLockAuto(RWLock* pRWLock) : m_pRWLock(pRWLock)
|
||||
{
|
||||
PAL_ASSERT(m_pRWLock != nullptr);
|
||||
if (type == RWLock::ReadOnly)
|
||||
{
|
||||
m_pRWLock->LockForRead();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pRWLock->LockForWrite();
|
||||
}
|
||||
}
|
||||
|
||||
/// Unlocks the RWLock we locked in the constructor.
|
||||
~RWLockAuto()
|
||||
{
|
||||
if (type == RWLock::ReadOnly)
|
||||
{
|
||||
m_pRWLock->UnlockForRead();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pRWLock->UnlockForWrite();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RWLock* const m_pRWLock; ///< The RWLock which this object wraps.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(RWLockAuto);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(RWLockAuto);
|
||||
};
|
||||
|
||||
/// Yields the current thread to another thread in the ready state (if available).
|
||||
extern void YieldThread();
|
||||
|
||||
/// Atomic write of 64-bit unsigned integer, using a relaxed memory ordering policy.
|
||||
/// If you need to synchronize more than just pTarget, you may need a new function.
|
||||
///
|
||||
/// @param [in] pTarget Pointer to the value to be read.
|
||||
///
|
||||
/// @returns The original value of *pTarget.
|
||||
extern void AtomicWriteRelaxed64(volatile uint64* pTarget, uint64 newValue);
|
||||
|
||||
/// Atomic read of 64-bit unsigned integer, using a relaxed memory ordering policy.
|
||||
/// If you need to synchronize more than just pTarget, you may need a new function.
|
||||
///
|
||||
/// @param [in] pTarget Pointer to the value to be read.
|
||||
///
|
||||
/// @returns The original value of *pTarget.
|
||||
extern uint64 AtomicReadRelaxed64(const volatile uint64* pTarget);
|
||||
|
||||
/// Atomically increments the specified 32-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pValue Pointer to the value to be incremented.
|
||||
///
|
||||
/// @returns Result of the increment operation.
|
||||
extern uint32 AtomicIncrement(volatile uint32* pValue);
|
||||
|
||||
/// Atomically increment a 64-bit-unsigned integer
|
||||
///
|
||||
/// @param [in,out] pAddend Pointer to the value to be incremented
|
||||
///
|
||||
/// @returns Result of the increment operation.
|
||||
extern uint64 AtomicIncrement64(volatile uint64* pAddend);
|
||||
|
||||
/// Atomically decrements the specified 32-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pValue Pointer to the value to be decremented.
|
||||
///
|
||||
/// @returns Result of the decrement operation.
|
||||
extern uint32 AtomicDecrement(volatile uint32* pValue);
|
||||
|
||||
/// Atomically decrements the specified 64-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pValue Pointer to the value to be decremented.
|
||||
///
|
||||
/// @returns Result of the decrement operation.
|
||||
extern uint32 AtomicDecrement64(volatile uint64* pValue);
|
||||
|
||||
/// Performs an atomic compare and swap operation on two 32-bit unsigned integers. This operation compares *pTarget
|
||||
/// with oldValue and replaces it with newValue if they match. If the values don't match, no action is taken.
|
||||
/// The original value of *pTarget is returned as a result.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the destination value of the operation.
|
||||
/// @param [in] oldValue Value to compare *pTarget to.
|
||||
/// @param [in] newValue Value to replace *pTarget with if *pTarget matches oldValue.
|
||||
///
|
||||
/// @returns Previous value at *pTarget.
|
||||
extern uint32 AtomicCompareAndSwap(volatile uint32* pTarget, uint32 oldValue, uint32 newValue);
|
||||
|
||||
/// Atomically exchanges a pair of 32-bit unsigned integers.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the destination value of the operation.
|
||||
/// @param [in] value New value to be stored in *pTarget.
|
||||
///
|
||||
/// @returns Previous value at *pTarget.
|
||||
extern uint32 AtomicExchange(volatile uint32* pTarget, uint32 value);
|
||||
|
||||
/// Atomically exchanges a pair of 64-bit unsigned integers.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the destination value of the operation.
|
||||
/// @param [in] value New value to be stored in *pTarget.
|
||||
///
|
||||
/// @returns Previous value at *pTarget.
|
||||
extern uint64 AtomicExchange64(volatile uint64* pTarget, uint64 value);
|
||||
|
||||
/// Atomically exchanges a pair of pointers.
|
||||
///
|
||||
/// @param [in,out] ppTarget Pointer to the address to exchange. The function sets the address pointed to by *ppTarget
|
||||
/// to pValue.
|
||||
/// @param [in] pValue New pointer to be stored in *ppTarget.
|
||||
///
|
||||
/// @returns Previous value at *ppTarget.
|
||||
extern void* AtomicExchangePointer(void*volatile* ppTarget, void* pValue);
|
||||
|
||||
/// Performs an atomic compare and swap operation on a pair of pointers. This operation compares *ppTarget
|
||||
/// with pOldValue and replaces it with pNewValue if they match. If the values don't match, no action is taken.
|
||||
/// The original value of *ppTarget is returned as a result.
|
||||
///
|
||||
/// @param [in,out] ppTarget Pointer to the destination value of the operation.
|
||||
|
||||
/// @param [in] pOldValue Old pointer to compare *ppTarget to.
|
||||
/// @param [in] pNewValue New pointer to replace *ppTarget with if *ppTarget matches pOldValue.
|
||||
///
|
||||
/// @returns Previous value at *ppTarget.
|
||||
extern void* AtomicCompareExchangePointer(void*volatile* ppTarget, void* pOldValue, void* pNewValue);
|
||||
|
||||
/// Atomically add a value to the specific 32-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pAddend Pointer to the value to be modified.
|
||||
/// @param [in] value Value to add to *pAddend.
|
||||
///
|
||||
/// @returns Result of the add operation.
|
||||
extern uint32 AtomicAdd(volatile uint32* pAddend, uint32 value);
|
||||
|
||||
/// Atomically add a value to the specified 64-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pAddend Pointer to the value to be modified.
|
||||
/// @param [in] value Value to add to *pAddend.
|
||||
///
|
||||
/// @returns Result of the add operation.
|
||||
extern uint64 AtomicAdd64(volatile uint64* pAddend, uint64 value);
|
||||
|
||||
/// Atomically OR a value to the specific 32-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the value to be modified.
|
||||
/// @param [in] value Value to OR to *pTarget.
|
||||
///
|
||||
/// @returns The original value of *pTarget.
|
||||
extern uint32 AtomicOr(volatile uint32* pTarget, uint32 value);
|
||||
|
||||
/// Atomically OR a value to the specified 64-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the value to be modified.
|
||||
/// @param [in] value Value to OR to *pTarget.
|
||||
///
|
||||
/// @returns The original value of *pTarget.
|
||||
extern uint64 AtomicOr64(volatile uint64* pTarget, uint64 value);
|
||||
|
||||
/// Atomically AND a value to the specific 32-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the value to be modified.
|
||||
/// @param [in] value Value to AND to *pTarget.
|
||||
///
|
||||
/// @returns The original value of *pTarget.
|
||||
extern uint32 AtomicAnd(volatile uint32* pTarget, uint32 value);
|
||||
|
||||
/// Atomically AND a value to the specified 64-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the value to be modified.
|
||||
/// @param [in] value Value to AND to *pTarget.
|
||||
///
|
||||
/// @returns The original value of *pTarget.
|
||||
extern uint64 AtomicAnd64(volatile uint64* pTarget, uint64 value);
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palMutex.h
|
||||
* @brief PAL utility collection Mutex and MutexAuto class declarations.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palAssert.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
// WIN32_NO_STATUS prevents winnt.h from re-defining NTSTATUS macros that cause build warnings if
|
||||
// ntstatus.h is also included.
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
#endif
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Platform-agnostic mutex primitive.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class Mutex
|
||||
{
|
||||
public:
|
||||
#if defined(_WIN32)
|
||||
/// Defines MutexData as a Windows CRITICAL_SECTION
|
||||
typedef CRITICAL_SECTION MutexData;
|
||||
Mutex() noexcept : m_osMutex {} { InitializeCriticalSection(&m_osMutex); }
|
||||
~Mutex() { DeleteCriticalSection(&m_osMutex); };
|
||||
#else
|
||||
/// Defines MutexData as a unix pthread_mutex_t
|
||||
typedef pthread_mutex_t MutexData;
|
||||
Mutex() noexcept : m_osMutex {} { pthread_mutex_init(&m_osMutex, nullptr); }
|
||||
~Mutex() { pthread_mutex_destroy(&m_osMutex); };
|
||||
#endif
|
||||
|
||||
/// Enters the critical section if it is not contended. If it is contended, wait for the critical section to become
|
||||
/// available, then enter it.
|
||||
void Lock();
|
||||
|
||||
/// Enters the critical section if it is not contended. Does not wait for the critical section to become available
|
||||
/// if it is contended.
|
||||
///
|
||||
/// @returns True if the critical section was entered, false otherwise.
|
||||
bool TryLock();
|
||||
|
||||
/// Leaves the critical section.
|
||||
void Unlock();
|
||||
|
||||
/// Returns the OS specific mutex data.
|
||||
MutexData* GetMutexData() { return &m_osMutex; }
|
||||
|
||||
private:
|
||||
MutexData m_osMutex; ///< Opaque structure to the OS-specific Mutex data
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(Mutex);
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief A "resource acquisition is initialization" (RAII) wrapper for the Mutex class.
|
||||
*
|
||||
* The RAII paradigm allows critical sections to be automatically acquired during this class' constructor, and
|
||||
* automatically released when a stack-allocated wrapper object goes out-of-scope. As such, it only makes sense to use
|
||||
* this class for stack-allocated objects.
|
||||
*
|
||||
* This object will ensure that anything between when the object is allocated on the stack and when it goes out of scope
|
||||
* will be protected from access by multiple threads. See the below example.
|
||||
*
|
||||
* [Code not protected]
|
||||
* {
|
||||
* [Code not protected]
|
||||
* MutexAuto lock(pPtrToMutex);
|
||||
* [Code is protected]
|
||||
* }
|
||||
* [Code not protected]
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class MutexAuto
|
||||
{
|
||||
public:
|
||||
/// Locks the given Mutex.
|
||||
explicit MutexAuto(Mutex* pMutex) : m_pMutex(pMutex)
|
||||
{
|
||||
PAL_ASSERT(m_pMutex != nullptr);
|
||||
m_pMutex->Lock();
|
||||
}
|
||||
|
||||
/// Unlocks the Mutex we locked in the constructor.
|
||||
~MutexAuto()
|
||||
{
|
||||
m_pMutex->Unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex* const m_pMutex; ///< The Mutex which this object wraps.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(MutexAuto);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(MutexAuto);
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Platform-agnostic rw lock primitive.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
class RWLock
|
||||
{
|
||||
public:
|
||||
#if defined(_WIN32)
|
||||
/// Defines RWLockData as a Windows RWLOCK
|
||||
typedef SRWLOCK RWLockData;
|
||||
RWLock() noexcept : m_osRWLock {} { InitializeSRWLock(&m_osRWLock); }
|
||||
~RWLock() noexcept { /* No Win32 destory function */ };
|
||||
#else
|
||||
/// Defines RWLockData as a unix pthread_rwlock_t
|
||||
typedef pthread_rwlock_t RWLockData;
|
||||
/// @note pthread_rwlock_init will not fail as called
|
||||
RWLock() noexcept : m_osRWLock {} { pthread_rwlock_init(&m_osRWLock, nullptr); }
|
||||
~RWLock() noexcept { pthread_rwlock_destroy(&m_osRWLock); };
|
||||
#endif
|
||||
|
||||
/// Enumerates the lock type of RWLockAuto
|
||||
enum LockType
|
||||
{
|
||||
ReadOnly = 0, ///< Lock in readonly mode, in other words shared mode.
|
||||
ReadWrite ///< Lock in readwrite mode, in other words exclusive mode.
|
||||
};
|
||||
|
||||
/// Acquires a rw lock in shared mode if it is not contended in exclusive mode.
|
||||
/// If it is contended, wait for rw lock to become available, then enter it.
|
||||
void LockForRead();
|
||||
|
||||
/// Acquires a rw lock in exclusive mode if it is not contended.
|
||||
/// If it is contended, wait for rw lock to become available, then enter it.
|
||||
void LockForWrite();
|
||||
|
||||
/// Try to acquires a rw lock in shared mode if it is not contended in exclusive mode.
|
||||
/// Does not wait for the rw lock to become available.
|
||||
/// @returns True if the rw lock was acquired, false otherwise.
|
||||
bool TryLockForRead();
|
||||
|
||||
/// Try to acquires a rw lock in exclusive mode if it is not contended.
|
||||
/// Does not wait for the rw lock to become available.
|
||||
/// @returns True if the rw lock was acquired, false otherwise.
|
||||
bool TryLockForWrite();
|
||||
|
||||
/// Release the rw lock which is previously contended in shared mode.
|
||||
void UnlockForRead();
|
||||
|
||||
/// Release the rw lock which is previously contended in exclusive mode.
|
||||
void UnlockForWrite();
|
||||
|
||||
/// Returns the OS specific RWLOCK data.
|
||||
RWLockData* GetRWLockData() { return &m_osRWLock; }
|
||||
|
||||
private:
|
||||
RWLockData m_osRWLock; ///< Opaque structure to the OS-specific RWLock data
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(RWLock);
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief A "resource acquisition is initialization" (RAII) wrapper for the RWLock class.
|
||||
*
|
||||
* The RAII paradigm allows rw lcok to be automatically acquired during this class' constructor, and
|
||||
* automatically released when a stack-allocated wrapper object goes out-of-scope. As such, it only makes sense to use
|
||||
* this class for stack-allocated objects.
|
||||
*
|
||||
* This object will ensure that anything between when the object is allocated on the stack and when it goes out of scope
|
||||
* will be protected from access by multiple threads. See the below example.
|
||||
*
|
||||
* [Code not protected]
|
||||
* {
|
||||
* [Code not protected]
|
||||
* RWLockAuto lock(pPtrToMutex, type);
|
||||
* [Code is protected]
|
||||
* }
|
||||
* [Code not protected]
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template <RWLock::LockType type>
|
||||
class RWLockAuto
|
||||
{
|
||||
public:
|
||||
/// Locks the given RWLock.
|
||||
explicit RWLockAuto(RWLock* pRWLock) : m_pRWLock(pRWLock)
|
||||
{
|
||||
PAL_ASSERT(m_pRWLock != nullptr);
|
||||
if (type == RWLock::ReadOnly)
|
||||
{
|
||||
m_pRWLock->LockForRead();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pRWLock->LockForWrite();
|
||||
}
|
||||
}
|
||||
|
||||
/// Unlocks the RWLock we locked in the constructor.
|
||||
~RWLockAuto()
|
||||
{
|
||||
if (type == RWLock::ReadOnly)
|
||||
{
|
||||
m_pRWLock->UnlockForRead();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pRWLock->UnlockForWrite();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RWLock* const m_pRWLock; ///< The RWLock which this object wraps.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(RWLockAuto);
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(RWLockAuto);
|
||||
};
|
||||
|
||||
/// Yields the current thread to another thread in the ready state (if available).
|
||||
extern void YieldThread();
|
||||
|
||||
/// Atomic write of 64-bit unsigned integer, using a relaxed memory ordering policy.
|
||||
/// If you need to synchronize more than just pTarget, you may need a new function.
|
||||
///
|
||||
/// @param [in] pTarget Pointer to the value to be read.
|
||||
///
|
||||
/// @returns The original value of *pTarget.
|
||||
extern void AtomicWriteRelaxed64(volatile uint64* pTarget, uint64 newValue);
|
||||
|
||||
/// Atomic read of 64-bit unsigned integer, using a relaxed memory ordering policy.
|
||||
/// If you need to synchronize more than just pTarget, you may need a new function.
|
||||
///
|
||||
/// @param [in] pTarget Pointer to the value to be read.
|
||||
///
|
||||
/// @returns The original value of *pTarget.
|
||||
extern uint64 AtomicReadRelaxed64(const volatile uint64* pTarget);
|
||||
|
||||
/// Atomically increments the specified 32-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pValue Pointer to the value to be incremented.
|
||||
///
|
||||
/// @returns Result of the increment operation.
|
||||
extern uint32 AtomicIncrement(volatile uint32* pValue);
|
||||
|
||||
/// Atomically increment a 64-bit-unsigned integer
|
||||
///
|
||||
/// @param [in,out] pAddend Pointer to the value to be incremented
|
||||
///
|
||||
/// @returns Result of the increment operation.
|
||||
extern uint64 AtomicIncrement64(volatile uint64* pAddend);
|
||||
|
||||
/// Atomically decrements the specified 32-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pValue Pointer to the value to be decremented.
|
||||
///
|
||||
/// @returns Result of the decrement operation.
|
||||
extern uint32 AtomicDecrement(volatile uint32* pValue);
|
||||
|
||||
/// Atomically decrements the specified 64-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pValue Pointer to the value to be decremented.
|
||||
///
|
||||
/// @returns Result of the decrement operation.
|
||||
extern uint32 AtomicDecrement64(volatile uint64* pValue);
|
||||
|
||||
/// Performs an atomic compare and swap operation on two 32-bit unsigned integers. This operation compares *pTarget
|
||||
/// with oldValue and replaces it with newValue if they match. If the values don't match, no action is taken.
|
||||
/// The original value of *pTarget is returned as a result.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the destination value of the operation.
|
||||
/// @param [in] oldValue Value to compare *pTarget to.
|
||||
/// @param [in] newValue Value to replace *pTarget with if *pTarget matches oldValue.
|
||||
///
|
||||
/// @returns Previous value at *pTarget.
|
||||
extern uint32 AtomicCompareAndSwap(volatile uint32* pTarget, uint32 oldValue, uint32 newValue);
|
||||
|
||||
/// Atomically exchanges a pair of 32-bit unsigned integers.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the destination value of the operation.
|
||||
/// @param [in] value New value to be stored in *pTarget.
|
||||
///
|
||||
/// @returns Previous value at *pTarget.
|
||||
extern uint32 AtomicExchange(volatile uint32* pTarget, uint32 value);
|
||||
|
||||
/// Atomically exchanges a pair of 64-bit unsigned integers.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the destination value of the operation.
|
||||
/// @param [in] value New value to be stored in *pTarget.
|
||||
///
|
||||
/// @returns Previous value at *pTarget.
|
||||
extern uint64 AtomicExchange64(volatile uint64* pTarget, uint64 value);
|
||||
|
||||
/// Atomically exchanges a pair of pointers.
|
||||
///
|
||||
/// @param [in,out] ppTarget Pointer to the address to exchange. The function sets the address pointed to by *ppTarget
|
||||
/// to pValue.
|
||||
/// @param [in] pValue New pointer to be stored in *ppTarget.
|
||||
///
|
||||
/// @returns Previous value at *ppTarget.
|
||||
extern void* AtomicExchangePointer(void*volatile* ppTarget, void* pValue);
|
||||
|
||||
/// Performs an atomic compare and swap operation on a pair of pointers. This operation compares *ppTarget
|
||||
/// with pOldValue and replaces it with pNewValue if they match. If the values don't match, no action is taken.
|
||||
/// The original value of *ppTarget is returned as a result.
|
||||
///
|
||||
/// @param [in,out] ppTarget Pointer to the destination value of the operation.
|
||||
|
||||
/// @param [in] pOldValue Old pointer to compare *ppTarget to.
|
||||
/// @param [in] pNewValue New pointer to replace *ppTarget with if *ppTarget matches pOldValue.
|
||||
///
|
||||
/// @returns Previous value at *ppTarget.
|
||||
extern void* AtomicCompareExchangePointer(void*volatile* ppTarget, void* pOldValue, void* pNewValue);
|
||||
|
||||
/// Atomically add a value to the specific 32-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pAddend Pointer to the value to be modified.
|
||||
/// @param [in] value Value to add to *pAddend.
|
||||
///
|
||||
/// @returns Result of the add operation.
|
||||
extern uint32 AtomicAdd(volatile uint32* pAddend, uint32 value);
|
||||
|
||||
/// Atomically add a value to the specified 64-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pAddend Pointer to the value to be modified.
|
||||
/// @param [in] value Value to add to *pAddend.
|
||||
///
|
||||
/// @returns Result of the add operation.
|
||||
extern uint64 AtomicAdd64(volatile uint64* pAddend, uint64 value);
|
||||
|
||||
/// Atomically OR a value to the specific 32-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the value to be modified.
|
||||
/// @param [in] value Value to OR to *pTarget.
|
||||
///
|
||||
/// @returns The original value of *pTarget.
|
||||
extern uint32 AtomicOr(volatile uint32* pTarget, uint32 value);
|
||||
|
||||
/// Atomically OR a value to the specified 64-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the value to be modified.
|
||||
/// @param [in] value Value to OR to *pTarget.
|
||||
///
|
||||
/// @returns The original value of *pTarget.
|
||||
extern uint64 AtomicOr64(volatile uint64* pTarget, uint64 value);
|
||||
|
||||
/// Atomically AND a value to the specific 32-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the value to be modified.
|
||||
/// @param [in] value Value to AND to *pTarget.
|
||||
///
|
||||
/// @returns The original value of *pTarget.
|
||||
extern uint32 AtomicAnd(volatile uint32* pTarget, uint32 value);
|
||||
|
||||
/// Atomically AND a value to the specified 64-bit unsigned integer.
|
||||
///
|
||||
/// @param [in,out] pTarget Pointer to the value to be modified.
|
||||
/// @param [in] value Value to AND to *pTarget.
|
||||
///
|
||||
/// @returns The original value of *pTarget.
|
||||
extern uint64 AtomicAnd64(volatile uint64* pTarget, uint64 value);
|
||||
|
||||
} // Util
|
||||
|
||||
@@ -1,447 +1,447 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palSpan.h
|
||||
* @brief PAL utility collection Span class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palUtil.h"
|
||||
#include "palAssert.h"
|
||||
#include "palSysMemory.h"
|
||||
#include "palInlineFuncs.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Span container
|
||||
*
|
||||
* Span is an array with a length, where the data is not owned by the Span object. It is similar to C++20 std::span,
|
||||
* but only the dynamic extent variant. It is similar to LLVM MutableArrayRef and ArrayRef. A Span is intended to
|
||||
* be passed around by value.
|
||||
*
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T>
|
||||
class Span
|
||||
{
|
||||
public:
|
||||
/// Constructor from nothing. This allows you to use {} to mean an empty Span.
|
||||
constexpr Span() : m_pData(nullptr), m_numElements(0) {}
|
||||
|
||||
/// Constructor from pointer and length
|
||||
///
|
||||
/// @param [in] data Pointer to the start of the array
|
||||
/// @param numElements Number of elements in the array
|
||||
constexpr Span(T* pData, size_t numElements) : m_pData(pData), m_numElements(numElements) {}
|
||||
|
||||
/// Copy constructor
|
||||
///
|
||||
/// @param [in] src Other Span to copy from
|
||||
constexpr Span(const Span<T>& src) : m_pData(src.m_pData), m_numElements(src.m_numElements) {}
|
||||
|
||||
/// Constructor from C++ array
|
||||
///
|
||||
/// @param [in] src C++ array
|
||||
template<size_t NumElements> constexpr Span(T(& src)[NumElements]) : m_pData(&src[0]), m_numElements(NumElements) {}
|
||||
|
||||
/// Constructor from single element
|
||||
///
|
||||
/// @param [in] src Single element
|
||||
constexpr Span(T& src) : m_pData(&src), m_numElements(1) {}
|
||||
|
||||
/// Implicitly convert a Span to its const-element equivalent.
|
||||
///
|
||||
/// @returns The same span, but with const element type
|
||||
constexpr operator Span<const T>() const { return Span<const T>(m_pData, m_numElements); }
|
||||
|
||||
/// Assignment operator
|
||||
///
|
||||
/// @param [in] src Other Span to copy from
|
||||
constexpr Span<T>& operator=(const Span<T>& src) {
|
||||
m_pData = src.m_pData;
|
||||
m_numElements = src.m_numElements;
|
||||
return *this;
|
||||
}
|
||||
|
||||
///@{
|
||||
/// Returns the element at the location specified.
|
||||
///
|
||||
/// @param [in] index Integer location of the element needed.
|
||||
///
|
||||
/// @returns The element at location specified by index by reference
|
||||
constexpr T& At(size_t index) const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT(index < m_numElements);
|
||||
return *(m_pData + index);
|
||||
}
|
||||
|
||||
constexpr T& operator[](size_t index) const noexcept { return At(index); }
|
||||
///@}
|
||||
|
||||
/// Returns the data at the front of the vector.
|
||||
///
|
||||
/// @returns The data at the front of the vector.
|
||||
constexpr T& Front() const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT(IsEmpty() == false);
|
||||
return *m_pData;
|
||||
}
|
||||
|
||||
/// Returns the data at the back of the vector.
|
||||
///
|
||||
/// @returns The data at the back of the vector.
|
||||
constexpr T& Back() const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT(IsEmpty() == false);
|
||||
return *(m_pData + (m_numElements - 1));
|
||||
}
|
||||
|
||||
/// Returns an iterator to the first element of the vector.
|
||||
///
|
||||
/// @returns An iterator to first element of the vector.
|
||||
constexpr T* Begin() const { return m_pData; }
|
||||
|
||||
/// Returns an iterator beyond the last element of the vector. (NOT at the last element like Util::Vector::End()!)
|
||||
///
|
||||
/// @warning Accessing an element using an iterator of an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns VectorIterator An iterator to last element of the vector.
|
||||
constexpr T* End() const { return m_pData + m_numElements; }
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage.
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage.
|
||||
/// For a non-empty span, the returned pointer contains address of the first element.
|
||||
/// For an empty span, the returned pointer may or may not be a null pointer.
|
||||
constexpr T* Data() const { return m_pData; }
|
||||
|
||||
/// Returns the extent of the span.
|
||||
///
|
||||
/// @returns An unsigned integer equal to the number of elements currently present in the span.
|
||||
constexpr size_t NumElements() const { return m_numElements; }
|
||||
|
||||
/// Returns the size in bytes the Span represents.
|
||||
///
|
||||
/// @returns An unsigned integer equal to the size in bytes the entire span represents.
|
||||
constexpr size_t SizeInBytes() const { return ElementSize() * m_numElements; }
|
||||
|
||||
/// Returns true if the number of elements present in the vector is equal to zero.
|
||||
///
|
||||
/// @returns True if the span is empty.
|
||||
constexpr bool IsEmpty() const { return (m_numElements == 0); }
|
||||
|
||||
/// Returns a "subspan", a view over a subset range of the elements.
|
||||
///
|
||||
/// @warning Behavior is undefined if either
|
||||
/// - offset is greater than NumElements(), or
|
||||
/// - count is not size_t(-1) and is greater than NumElements()-offset.
|
||||
///
|
||||
/// Note that size_t(-1) is equivalent to C++20 std::dynamic_extent, which the C++20 std::span::subspan uses
|
||||
/// in the same way to mean "take the remainder of the elements from offset".
|
||||
///
|
||||
/// @param offset Zero-based offset to start the subspan at
|
||||
/// @param count Number of elements in the subspan, or size_t(-1) for the remainder of the elements from offset
|
||||
///
|
||||
/// @returns The subspan
|
||||
constexpr Span Subspan(
|
||||
size_t offset,
|
||||
size_t count) const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT((offset <= NumElements())
|
||||
&& ((count == size_t(-1)) || (count <= NumElements() - offset)));
|
||||
if (count == size_t(-1))
|
||||
{
|
||||
count = NumElements() - offset;
|
||||
}
|
||||
return Span(Data() + offset, count);
|
||||
}
|
||||
|
||||
/// Returns a subspan dropping the specified number (default 1) of elements from the front.
|
||||
/// Returns an empty Span if there were no more elements than that to start with.
|
||||
///
|
||||
/// @param count Number of elements to drop from the front
|
||||
///
|
||||
/// @returns The subspan
|
||||
constexpr Span DropFront(
|
||||
size_t count = 1) const
|
||||
{
|
||||
Span retVal;
|
||||
if (count < NumElements())
|
||||
{
|
||||
retVal = Subspan(count, size_t(-1));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/// Returns a subspan dropping the specified number (default 1) of elements from the back.
|
||||
/// Returns an empty Span if there were no more elements than that to start with.
|
||||
///
|
||||
/// @param count Number of elements to drop from the back
|
||||
///
|
||||
/// @returns The subspan
|
||||
constexpr Span DropBack(
|
||||
size_t count = 1) const
|
||||
{
|
||||
Span retVal;
|
||||
if (count < NumElements())
|
||||
{
|
||||
retVal = Subspan(0, NumElements() - count);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
///@{
|
||||
/// @internal Satisfies concept `range_expression`, using T* as `iterator` and 32-bit size and difference types
|
||||
///
|
||||
/// @note - These are a convenience intended to be used by c++ language features such as `range for`.
|
||||
/// These should not be called directly as they do not adhere to PAL coding standards.
|
||||
using value_type = T;
|
||||
using reference = T&;
|
||||
using iterator = T*;
|
||||
using difference_type = size_t;
|
||||
using size_type = size_t;
|
||||
|
||||
constexpr iterator begin() const noexcept { return m_pData; }
|
||||
constexpr iterator end() const noexcept { return (m_pData + m_numElements); }
|
||||
constexpr bool empty() const noexcept { return IsEmpty(); }
|
||||
constexpr size_type size() const noexcept { return m_numElements; }
|
||||
///@}
|
||||
|
||||
protected:
|
||||
template<typename U = T, typename R = std::conditional_t<std::is_void_v<U>, char, U>>
|
||||
static constexpr size_t ElementSize() { return sizeof(R); }
|
||||
|
||||
template<typename R = T, bool Condition = true>
|
||||
using IfConst = std::enable_if_t<std::is_const_v<R> == Condition>;
|
||||
|
||||
template<typename R = T, bool Condition = true>
|
||||
using IfPtr = std::enable_if_t<std::is_pointer_v<R> == Condition>;
|
||||
|
||||
T* m_pData; // Pointer to the current data.
|
||||
size_t m_numElements; // Number of elements present.
|
||||
};
|
||||
|
||||
/// ====================================================================================================================
|
||||
/// Span template specialization for const void byte buffers.
|
||||
template<>
|
||||
class Span<const void> : public Span<const char>
|
||||
{
|
||||
using Byte = const char;
|
||||
using Base = Span<Byte>;
|
||||
|
||||
public:
|
||||
/// Constructor from nothing. This allows you to use {} to mean an empty Span.
|
||||
constexpr Span() : Base() {}
|
||||
|
||||
/// Template constructor from any pointer and length
|
||||
///
|
||||
/// @param [in] data Pointer to the start of the buffer or array
|
||||
/// @param numElements Number of bytes or elements in the buffer or array
|
||||
template<typename T>
|
||||
Span(const T* pData, size_t numElements) : Base(reinterpret_cast<Byte*>(pData), ElementSize<T>() * numElements) {}
|
||||
|
||||
/// Template copy constructor
|
||||
///
|
||||
/// @param [in] src Other Span<T> to copy from
|
||||
template<typename T = const void>
|
||||
Span(const Span<T>& src) : Span(src.Data(), src.NumElements()) {}
|
||||
|
||||
/// Template constructor from any C++ array
|
||||
///
|
||||
/// @param [in] src C++ array
|
||||
template<typename T, size_t NumElements>
|
||||
Span(const T(& src)[NumElements]) : Span(&src[0], NumElements) {}
|
||||
|
||||
/// Constructor from any single element
|
||||
///
|
||||
/// @param [in] src Single element
|
||||
template<typename T, typename Enabled = IfPtr<T, false>>
|
||||
Span(const T& src) : Span(&src, 1) {}
|
||||
|
||||
/// Templated conversion of this typeless Span to a typed Subspan
|
||||
///
|
||||
/// @returns A subspan with typed elemeents and NumElements truncated down to the nearest sizeof(type)
|
||||
template<typename T>
|
||||
operator Span<const T>() const
|
||||
{ return Span<const T>(static_cast<const T*>(Data()), SizeInBytes() / ElementSize<T>()); }
|
||||
|
||||
/// Returns the element at the location specified.
|
||||
///
|
||||
/// @param [in] index Integer location of the element needed.
|
||||
///
|
||||
/// @returns The element at location specified by index by reference
|
||||
template<typename T = Byte>
|
||||
const T& At(size_t index) const { return reinterpret_cast<const T&>(Base::At(index)); }
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage.
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage.
|
||||
/// For a non-empty span, the returned pointer contains address of the first element.
|
||||
/// For an empty span, the returned pointer may or may not be a null pointer.
|
||||
template<typename T = void>
|
||||
constexpr const T* Data() const { return reinterpret_cast<const T*>(Base::Data()); }
|
||||
|
||||
/// Returns a "subspan", a view over a subset range of the elements.
|
||||
///
|
||||
/// @warning Behavior is undefined if either
|
||||
/// - offset is greater than NumElements(), or
|
||||
/// - count is not size_t(-1) and is greater than NumElements()-offset.
|
||||
///
|
||||
/// Note that size_t(-1) is equivalent to C++20 std::dynamic_extent, which the C++20 std::span::subspan uses
|
||||
/// in the same way to mean "take the remainder of the elements from offset".
|
||||
///
|
||||
/// @param offset Zero-based offset to start the subspan at
|
||||
/// @param count Number of elements in the subspan, or size_t(-1) for the remainder of the elements from offset
|
||||
///
|
||||
/// @returns The subspan
|
||||
template<typename T = void>
|
||||
Span<const T> Subspan(size_t offset, size_t count) const { return Span<const void>(Base::Subspan(offset, count)); }
|
||||
|
||||
/// Returns a subspan dropping the specified number (default 1) of elements from the front.
|
||||
/// Returns an empty Span if there were no more elements than that to start with.
|
||||
///
|
||||
/// @param count Number of elements to drop from the front
|
||||
///
|
||||
/// @returns The subspan
|
||||
template<typename T = void>
|
||||
Span<const T> DropFront(size_t count = 1) const { return Span<const void>(Base::DropFront(count)); }
|
||||
|
||||
/// Returns a subspan dropping the specified number (default 1) of elements from the back.
|
||||
/// Returns an empty Span if there were no more elements than that to start with.
|
||||
///
|
||||
/// @param count Number of elements to drop from the back
|
||||
///
|
||||
/// @returns The subspan
|
||||
template<typename T = void>
|
||||
Span<const T> DropBack(size_t count = 1) const { return Span<const void>(Base::DropBack(count)); }
|
||||
};
|
||||
|
||||
/// ====================================================================================================================
|
||||
/// Span template specialization for mutable void byte buffers.
|
||||
template<>
|
||||
class Span<void> : public Span<char>
|
||||
{
|
||||
using Byte = char;
|
||||
using Base = Span<Byte>;
|
||||
|
||||
public:
|
||||
/// Constructor from nothing. This allows you to use {} to mean an empty Span.
|
||||
constexpr Span() : Base() {}
|
||||
|
||||
/// Template constructor from any pointer and length
|
||||
///
|
||||
/// @param [in] data Pointer to the start of the buffer or array
|
||||
/// @param sizeInBytes,numElements Number of bytes or elements in the buffer or array
|
||||
template<typename T, typename Enabled = IfConst<T, false>>
|
||||
Span(T* pData, size_t numElements) : Base(reinterpret_cast<Byte*>(pData), ElementSize<T>() * numElements) { }
|
||||
|
||||
/// Template copy constructor
|
||||
///
|
||||
/// @param [in] src Other Span<T> to copy from
|
||||
template<typename T = void, typename Enabled = IfConst<T, false>>
|
||||
Span(const Span<T>& src) : Span(src.Data(), src.NumElements()) {}
|
||||
|
||||
/// Template constructor from any C++ array
|
||||
///
|
||||
/// @param [in] src C++ array
|
||||
template<typename T, size_t NumElements, typename Enabled = IfConst<T, false>>
|
||||
Span(T(& src)[NumElements]) : Span(&src[0], NumElements) {}
|
||||
|
||||
/// Constructor from any single element
|
||||
///
|
||||
/// @param [in] src Single element
|
||||
template<typename T, typename Enabled = IfConst<T, false>, typename = IfPtr<T, false>>
|
||||
Span(T& src) : Span(&src, 1) {}
|
||||
|
||||
/// Templated conversion of this typeless Span to a typed Subspan
|
||||
///
|
||||
/// @returns A subspan with typed elemeents and NumElements truncated down to the nearest sizeof(type)
|
||||
template<typename T>
|
||||
operator Span<T>() const { return Span<T>(static_cast<T*>(Data()), SizeInBytes() / ElementSize<T>()); }
|
||||
|
||||
/// Returns the element at the location specified.
|
||||
///
|
||||
/// @param [in] index Integer location of the element needed.
|
||||
///
|
||||
/// @returns The element at location specified by index by reference
|
||||
template<typename T = Byte>
|
||||
T& At(size_t index) const { return reinterpret_cast<T&>(Base::At(index)); }
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage.
|
||||
/// For a non-empty span, the returned pointer contains address of the first element.
|
||||
/// For an empty span, the returned pointer may or may not be a null pointer.
|
||||
template<typename T = void>
|
||||
constexpr T* Data() const { return reinterpret_cast<T*>(Base::Data()); }
|
||||
|
||||
/// Implicitly convert this void Span to its const void equivalent
|
||||
///
|
||||
/// @returns The same span, but of const void type
|
||||
operator Span<const void>() const { return Span<const void>(Data(), NumElements()); }
|
||||
|
||||
/// Returns a "subspan", a view over a subset range of the elements.
|
||||
///
|
||||
/// @warning Behavior is undefined if either
|
||||
/// - offset is greater than NumElements(), or
|
||||
/// - count is not size_t(-1) and is greater than NumElements()-offset.
|
||||
///
|
||||
/// Note that size_t(-1) is equivalent to C++20 std::dynamic_extent, which the C++20 std::span::subspan uses
|
||||
/// in the same way to mean "take the remainder of the elements from offset".
|
||||
///
|
||||
/// @param offset Zero-based offset to start the subspan at
|
||||
/// @param count Number of elements in the subspan, or size_t(-1) for the remainder of the elements from offset
|
||||
///
|
||||
/// @returns The subspan
|
||||
template<typename T = void>
|
||||
Span<T> Subspan(size_t offset, size_t count) const { return Span<void>(Base::Subspan(offset, count)); }
|
||||
|
||||
/// Returns a subspan dropping the specified number (default 1) of elements from the front.
|
||||
/// Returns an empty Span if there were no more elements than that to start with.
|
||||
///
|
||||
/// @param count Number of elements to drop from the front
|
||||
///
|
||||
/// @returns The subspan
|
||||
template<typename T = void>
|
||||
Span<T> DropFront(size_t count = 1) const { return Span<void>(Base::DropFront(count)); }
|
||||
|
||||
/// Returns a subspan dropping the specified number (default 1) of elements from the back.
|
||||
/// Returns an empty Span if there were no more elements than that to start with.
|
||||
///
|
||||
/// @param count Number of elements to drop from the back
|
||||
///
|
||||
/// @returns The subspan
|
||||
template<typename T = void>
|
||||
Span<T> DropBack(size_t count = 1) const { return Span<void>(Base::DropBack(count)); }
|
||||
};
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palSpan.h
|
||||
* @brief PAL utility collection Span class declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palUtil.h"
|
||||
#include "palAssert.h"
|
||||
#include "palSysMemory.h"
|
||||
#include "palInlineFuncs.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Span container
|
||||
*
|
||||
* Span is an array with a length, where the data is not owned by the Span object. It is similar to C++20 std::span,
|
||||
* but only the dynamic extent variant. It is similar to LLVM MutableArrayRef and ArrayRef. A Span is intended to
|
||||
* be passed around by value.
|
||||
*
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T>
|
||||
class Span
|
||||
{
|
||||
public:
|
||||
/// Constructor from nothing. This allows you to use {} to mean an empty Span.
|
||||
constexpr Span() : m_pData(nullptr), m_numElements(0) {}
|
||||
|
||||
/// Constructor from pointer and length
|
||||
///
|
||||
/// @param [in] data Pointer to the start of the array
|
||||
/// @param numElements Number of elements in the array
|
||||
constexpr Span(T* pData, size_t numElements) : m_pData(pData), m_numElements(numElements) {}
|
||||
|
||||
/// Copy constructor
|
||||
///
|
||||
/// @param [in] src Other Span to copy from
|
||||
constexpr Span(const Span<T>& src) : m_pData(src.m_pData), m_numElements(src.m_numElements) {}
|
||||
|
||||
/// Constructor from C++ array
|
||||
///
|
||||
/// @param [in] src C++ array
|
||||
template<size_t NumElements> constexpr Span(T(& src)[NumElements]) : m_pData(&src[0]), m_numElements(NumElements) {}
|
||||
|
||||
/// Constructor from single element
|
||||
///
|
||||
/// @param [in] src Single element
|
||||
constexpr Span(T& src) : m_pData(&src), m_numElements(1) {}
|
||||
|
||||
/// Implicitly convert a Span to its const-element equivalent.
|
||||
///
|
||||
/// @returns The same span, but with const element type
|
||||
constexpr operator Span<const T>() const { return Span<const T>(m_pData, m_numElements); }
|
||||
|
||||
/// Assignment operator
|
||||
///
|
||||
/// @param [in] src Other Span to copy from
|
||||
constexpr Span<T>& operator=(const Span<T>& src) {
|
||||
m_pData = src.m_pData;
|
||||
m_numElements = src.m_numElements;
|
||||
return *this;
|
||||
}
|
||||
|
||||
///@{
|
||||
/// Returns the element at the location specified.
|
||||
///
|
||||
/// @param [in] index Integer location of the element needed.
|
||||
///
|
||||
/// @returns The element at location specified by index by reference
|
||||
constexpr T& At(size_t index) const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT(index < m_numElements);
|
||||
return *(m_pData + index);
|
||||
}
|
||||
|
||||
constexpr T& operator[](size_t index) const noexcept { return At(index); }
|
||||
///@}
|
||||
|
||||
/// Returns the data at the front of the vector.
|
||||
///
|
||||
/// @returns The data at the front of the vector.
|
||||
constexpr T& Front() const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT(IsEmpty() == false);
|
||||
return *m_pData;
|
||||
}
|
||||
|
||||
/// Returns the data at the back of the vector.
|
||||
///
|
||||
/// @returns The data at the back of the vector.
|
||||
constexpr T& Back() const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT(IsEmpty() == false);
|
||||
return *(m_pData + (m_numElements - 1));
|
||||
}
|
||||
|
||||
/// Returns an iterator to the first element of the vector.
|
||||
///
|
||||
/// @returns An iterator to first element of the vector.
|
||||
constexpr T* Begin() const { return m_pData; }
|
||||
|
||||
/// Returns an iterator beyond the last element of the vector. (NOT at the last element like Util::Vector::End()!)
|
||||
///
|
||||
/// @warning Accessing an element using an iterator of an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns VectorIterator An iterator to last element of the vector.
|
||||
constexpr T* End() const { return m_pData + m_numElements; }
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage.
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage.
|
||||
/// For a non-empty span, the returned pointer contains address of the first element.
|
||||
/// For an empty span, the returned pointer may or may not be a null pointer.
|
||||
constexpr T* Data() const { return m_pData; }
|
||||
|
||||
/// Returns the extent of the span.
|
||||
///
|
||||
/// @returns An unsigned integer equal to the number of elements currently present in the span.
|
||||
constexpr size_t NumElements() const { return m_numElements; }
|
||||
|
||||
/// Returns the size in bytes the Span represents.
|
||||
///
|
||||
/// @returns An unsigned integer equal to the size in bytes the entire span represents.
|
||||
constexpr size_t SizeInBytes() const { return ElementSize() * m_numElements; }
|
||||
|
||||
/// Returns true if the number of elements present in the vector is equal to zero.
|
||||
///
|
||||
/// @returns True if the span is empty.
|
||||
constexpr bool IsEmpty() const { return (m_numElements == 0); }
|
||||
|
||||
/// Returns a "subspan", a view over a subset range of the elements.
|
||||
///
|
||||
/// @warning Behavior is undefined if either
|
||||
/// - offset is greater than NumElements(), or
|
||||
/// - count is not size_t(-1) and is greater than NumElements()-offset.
|
||||
///
|
||||
/// Note that size_t(-1) is equivalent to C++20 std::dynamic_extent, which the C++20 std::span::subspan uses
|
||||
/// in the same way to mean "take the remainder of the elements from offset".
|
||||
///
|
||||
/// @param offset Zero-based offset to start the subspan at
|
||||
/// @param count Number of elements in the subspan, or size_t(-1) for the remainder of the elements from offset
|
||||
///
|
||||
/// @returns The subspan
|
||||
constexpr Span Subspan(
|
||||
size_t offset,
|
||||
size_t count) const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT((offset <= NumElements())
|
||||
&& ((count == size_t(-1)) || (count <= NumElements() - offset)));
|
||||
if (count == size_t(-1))
|
||||
{
|
||||
count = NumElements() - offset;
|
||||
}
|
||||
return Span(Data() + offset, count);
|
||||
}
|
||||
|
||||
/// Returns a subspan dropping the specified number (default 1) of elements from the front.
|
||||
/// Returns an empty Span if there were no more elements than that to start with.
|
||||
///
|
||||
/// @param count Number of elements to drop from the front
|
||||
///
|
||||
/// @returns The subspan
|
||||
constexpr Span DropFront(
|
||||
size_t count = 1) const
|
||||
{
|
||||
Span retVal;
|
||||
if (count < NumElements())
|
||||
{
|
||||
retVal = Subspan(count, size_t(-1));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/// Returns a subspan dropping the specified number (default 1) of elements from the back.
|
||||
/// Returns an empty Span if there were no more elements than that to start with.
|
||||
///
|
||||
/// @param count Number of elements to drop from the back
|
||||
///
|
||||
/// @returns The subspan
|
||||
constexpr Span DropBack(
|
||||
size_t count = 1) const
|
||||
{
|
||||
Span retVal;
|
||||
if (count < NumElements())
|
||||
{
|
||||
retVal = Subspan(0, NumElements() - count);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
///@{
|
||||
/// @internal Satisfies concept `range_expression`, using T* as `iterator` and 32-bit size and difference types
|
||||
///
|
||||
/// @note - These are a convenience intended to be used by c++ language features such as `range for`.
|
||||
/// These should not be called directly as they do not adhere to PAL coding standards.
|
||||
using value_type = T;
|
||||
using reference = T&;
|
||||
using iterator = T*;
|
||||
using difference_type = size_t;
|
||||
using size_type = size_t;
|
||||
|
||||
constexpr iterator begin() const noexcept { return m_pData; }
|
||||
constexpr iterator end() const noexcept { return (m_pData + m_numElements); }
|
||||
constexpr bool empty() const noexcept { return IsEmpty(); }
|
||||
constexpr size_type size() const noexcept { return m_numElements; }
|
||||
///@}
|
||||
|
||||
protected:
|
||||
template<typename U = T, typename R = std::conditional_t<std::is_void_v<U>, char, U>>
|
||||
static constexpr size_t ElementSize() { return sizeof(R); }
|
||||
|
||||
template<typename R = T, bool Condition = true>
|
||||
using IfConst = std::enable_if_t<std::is_const_v<R> == Condition>;
|
||||
|
||||
template<typename R = T, bool Condition = true>
|
||||
using IfPtr = std::enable_if_t<std::is_pointer_v<R> == Condition>;
|
||||
|
||||
T* m_pData; // Pointer to the current data.
|
||||
size_t m_numElements; // Number of elements present.
|
||||
};
|
||||
|
||||
/// ====================================================================================================================
|
||||
/// Span template specialization for const void byte buffers.
|
||||
template<>
|
||||
class Span<const void> : public Span<const char>
|
||||
{
|
||||
using Byte = const char;
|
||||
using Base = Span<Byte>;
|
||||
|
||||
public:
|
||||
/// Constructor from nothing. This allows you to use {} to mean an empty Span.
|
||||
constexpr Span() : Base() {}
|
||||
|
||||
/// Template constructor from any pointer and length
|
||||
///
|
||||
/// @param [in] data Pointer to the start of the buffer or array
|
||||
/// @param numElements Number of bytes or elements in the buffer or array
|
||||
template<typename T>
|
||||
Span(const T* pData, size_t numElements) : Base(reinterpret_cast<Byte*>(pData), ElementSize<T>() * numElements) {}
|
||||
|
||||
/// Template copy constructor
|
||||
///
|
||||
/// @param [in] src Other Span<T> to copy from
|
||||
template<typename T = const void>
|
||||
Span(const Span<T>& src) : Span(src.Data(), src.NumElements()) {}
|
||||
|
||||
/// Template constructor from any C++ array
|
||||
///
|
||||
/// @param [in] src C++ array
|
||||
template<typename T, size_t NumElements>
|
||||
Span(const T(& src)[NumElements]) : Span(&src[0], NumElements) {}
|
||||
|
||||
/// Constructor from any single element
|
||||
///
|
||||
/// @param [in] src Single element
|
||||
template<typename T, typename Enabled = IfPtr<T, false>>
|
||||
Span(const T& src) : Span(&src, 1) {}
|
||||
|
||||
/// Templated conversion of this typeless Span to a typed Subspan
|
||||
///
|
||||
/// @returns A subspan with typed elemeents and NumElements truncated down to the nearest sizeof(type)
|
||||
template<typename T>
|
||||
operator Span<const T>() const
|
||||
{ return Span<const T>(static_cast<const T*>(Data()), SizeInBytes() / ElementSize<T>()); }
|
||||
|
||||
/// Returns the element at the location specified.
|
||||
///
|
||||
/// @param [in] index Integer location of the element needed.
|
||||
///
|
||||
/// @returns The element at location specified by index by reference
|
||||
template<typename T = Byte>
|
||||
const T& At(size_t index) const { return reinterpret_cast<const T&>(Base::At(index)); }
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage.
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage.
|
||||
/// For a non-empty span, the returned pointer contains address of the first element.
|
||||
/// For an empty span, the returned pointer may or may not be a null pointer.
|
||||
template<typename T = void>
|
||||
constexpr const T* Data() const { return reinterpret_cast<const T*>(Base::Data()); }
|
||||
|
||||
/// Returns a "subspan", a view over a subset range of the elements.
|
||||
///
|
||||
/// @warning Behavior is undefined if either
|
||||
/// - offset is greater than NumElements(), or
|
||||
/// - count is not size_t(-1) and is greater than NumElements()-offset.
|
||||
///
|
||||
/// Note that size_t(-1) is equivalent to C++20 std::dynamic_extent, which the C++20 std::span::subspan uses
|
||||
/// in the same way to mean "take the remainder of the elements from offset".
|
||||
///
|
||||
/// @param offset Zero-based offset to start the subspan at
|
||||
/// @param count Number of elements in the subspan, or size_t(-1) for the remainder of the elements from offset
|
||||
///
|
||||
/// @returns The subspan
|
||||
template<typename T = void>
|
||||
Span<const T> Subspan(size_t offset, size_t count) const { return Span<const void>(Base::Subspan(offset, count)); }
|
||||
|
||||
/// Returns a subspan dropping the specified number (default 1) of elements from the front.
|
||||
/// Returns an empty Span if there were no more elements than that to start with.
|
||||
///
|
||||
/// @param count Number of elements to drop from the front
|
||||
///
|
||||
/// @returns The subspan
|
||||
template<typename T = void>
|
||||
Span<const T> DropFront(size_t count = 1) const { return Span<const void>(Base::DropFront(count)); }
|
||||
|
||||
/// Returns a subspan dropping the specified number (default 1) of elements from the back.
|
||||
/// Returns an empty Span if there were no more elements than that to start with.
|
||||
///
|
||||
/// @param count Number of elements to drop from the back
|
||||
///
|
||||
/// @returns The subspan
|
||||
template<typename T = void>
|
||||
Span<const T> DropBack(size_t count = 1) const { return Span<const void>(Base::DropBack(count)); }
|
||||
};
|
||||
|
||||
/// ====================================================================================================================
|
||||
/// Span template specialization for mutable void byte buffers.
|
||||
template<>
|
||||
class Span<void> : public Span<char>
|
||||
{
|
||||
using Byte = char;
|
||||
using Base = Span<Byte>;
|
||||
|
||||
public:
|
||||
/// Constructor from nothing. This allows you to use {} to mean an empty Span.
|
||||
constexpr Span() : Base() {}
|
||||
|
||||
/// Template constructor from any pointer and length
|
||||
///
|
||||
/// @param [in] data Pointer to the start of the buffer or array
|
||||
/// @param sizeInBytes,numElements Number of bytes or elements in the buffer or array
|
||||
template<typename T, typename Enabled = IfConst<T, false>>
|
||||
Span(T* pData, size_t numElements) : Base(reinterpret_cast<Byte*>(pData), ElementSize<T>() * numElements) { }
|
||||
|
||||
/// Template copy constructor
|
||||
///
|
||||
/// @param [in] src Other Span<T> to copy from
|
||||
template<typename T = void, typename Enabled = IfConst<T, false>>
|
||||
Span(const Span<T>& src) : Span(src.Data(), src.NumElements()) {}
|
||||
|
||||
/// Template constructor from any C++ array
|
||||
///
|
||||
/// @param [in] src C++ array
|
||||
template<typename T, size_t NumElements, typename Enabled = IfConst<T, false>>
|
||||
Span(T(& src)[NumElements]) : Span(&src[0], NumElements) {}
|
||||
|
||||
/// Constructor from any single element
|
||||
///
|
||||
/// @param [in] src Single element
|
||||
template<typename T, typename Enabled = IfConst<T, false>, typename = IfPtr<T, false>>
|
||||
Span(T& src) : Span(&src, 1) {}
|
||||
|
||||
/// Templated conversion of this typeless Span to a typed Subspan
|
||||
///
|
||||
/// @returns A subspan with typed elemeents and NumElements truncated down to the nearest sizeof(type)
|
||||
template<typename T>
|
||||
operator Span<T>() const { return Span<T>(static_cast<T*>(Data()), SizeInBytes() / ElementSize<T>()); }
|
||||
|
||||
/// Returns the element at the location specified.
|
||||
///
|
||||
/// @param [in] index Integer location of the element needed.
|
||||
///
|
||||
/// @returns The element at location specified by index by reference
|
||||
template<typename T = Byte>
|
||||
T& At(size_t index) const { return reinterpret_cast<T&>(Base::At(index)); }
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage.
|
||||
/// For a non-empty span, the returned pointer contains address of the first element.
|
||||
/// For an empty span, the returned pointer may or may not be a null pointer.
|
||||
template<typename T = void>
|
||||
constexpr T* Data() const { return reinterpret_cast<T*>(Base::Data()); }
|
||||
|
||||
/// Implicitly convert this void Span to its const void equivalent
|
||||
///
|
||||
/// @returns The same span, but of const void type
|
||||
operator Span<const void>() const { return Span<const void>(Data(), NumElements()); }
|
||||
|
||||
/// Returns a "subspan", a view over a subset range of the elements.
|
||||
///
|
||||
/// @warning Behavior is undefined if either
|
||||
/// - offset is greater than NumElements(), or
|
||||
/// - count is not size_t(-1) and is greater than NumElements()-offset.
|
||||
///
|
||||
/// Note that size_t(-1) is equivalent to C++20 std::dynamic_extent, which the C++20 std::span::subspan uses
|
||||
/// in the same way to mean "take the remainder of the elements from offset".
|
||||
///
|
||||
/// @param offset Zero-based offset to start the subspan at
|
||||
/// @param count Number of elements in the subspan, or size_t(-1) for the remainder of the elements from offset
|
||||
///
|
||||
/// @returns The subspan
|
||||
template<typename T = void>
|
||||
Span<T> Subspan(size_t offset, size_t count) const { return Span<void>(Base::Subspan(offset, count)); }
|
||||
|
||||
/// Returns a subspan dropping the specified number (default 1) of elements from the front.
|
||||
/// Returns an empty Span if there were no more elements than that to start with.
|
||||
///
|
||||
/// @param count Number of elements to drop from the front
|
||||
///
|
||||
/// @returns The subspan
|
||||
template<typename T = void>
|
||||
Span<T> DropFront(size_t count = 1) const { return Span<void>(Base::DropFront(count)); }
|
||||
|
||||
/// Returns a subspan dropping the specified number (default 1) of elements from the back.
|
||||
/// Returns an empty Span if there were no more elements than that to start with.
|
||||
///
|
||||
/// @param count Number of elements to drop from the back
|
||||
///
|
||||
/// @returns The subspan
|
||||
template<typename T = void>
|
||||
Span<T> DropBack(size_t count = 1) const { return Span<void>(Base::DropBack(count)); }
|
||||
};
|
||||
|
||||
} // Util
|
||||
|
||||
@@ -1,188 +1,188 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2020-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palStringUtil.h
|
||||
* @brief PAL String utility collection functions.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
#include <type_traits>
|
||||
|
||||
#include "palUtil.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION < 919
|
||||
/// Returns the length of a wchar_t based string.
|
||||
///
|
||||
/// @param [in] wide string to query
|
||||
///
|
||||
/// @returns The length of the given string in wide characters
|
||||
extern size_t PalWcslen(
|
||||
const wchar_t* pWideStr);
|
||||
|
||||
/// Performs a reverse string find of wide character wc.
|
||||
///
|
||||
/// @param [in] wide string to scan
|
||||
/// @param [in] wide character to find
|
||||
///
|
||||
/// @returns The matching character at the end of the string or nullptr if not found.
|
||||
extern wchar_t* PalWcsrchr(
|
||||
wchar_t *pStr,
|
||||
wchar_t wc);
|
||||
#endif
|
||||
|
||||
/// When the -fshort-char compiler option is specified, wchar_t is 16 bits, but mbstowcs still treats the dest
|
||||
/// as 32 bit so we provide our own implementation.
|
||||
///
|
||||
/// @param [out] dst string
|
||||
/// @param [in] src string
|
||||
/// @param [in] size of the destination buffer in words
|
||||
///
|
||||
/// @returns Returns whether or not the conversion was successful.
|
||||
extern bool ConvertCharStringToUtf16(
|
||||
wchar_t* pDst,
|
||||
const char* pSrc,
|
||||
size_t dstSizeInWords);
|
||||
|
||||
/// When the -fshort-char compiler option is specified, wchar_t is 16 bits, but wcstombs still treats the src
|
||||
/// as 32 bit so we provide our own implementation.
|
||||
///
|
||||
/// @param [out] dst string
|
||||
/// @param [in] src string
|
||||
/// @param [in] size of the destination buffer in bytes
|
||||
///
|
||||
/// @returns Returns whether or not the conversion was successful.
|
||||
extern bool ConvertUtf16StringToUtf8(
|
||||
char* pDst,
|
||||
const wchar_t* pSrc,
|
||||
size_t dstSizeInBytes);
|
||||
|
||||
/// Convert wchar_t string to UTF-8 string. Works whether wchar_t is 16 or 32 bits.
|
||||
/// If wchar_t is 16 bits, this decodes UTF-16.
|
||||
///
|
||||
/// @param [out] dst string
|
||||
/// @param [in] src string
|
||||
/// @param [in] size of the destination buffer in bytes
|
||||
///
|
||||
/// @returns Returns whether or not the conversion was successful.
|
||||
bool ConvertWcharStringToUtf8(char* pDst, const wchar_t* pSrc, size_t dstSizeInBytes);
|
||||
|
||||
/// When the -fshort-char compiler option is specified, wchar_t is 16 bits, but wcsncpy still treats its arguments
|
||||
/// as 32 bit so we provide our own implementation.
|
||||
///
|
||||
/// @param [out] pDst Destination string.
|
||||
/// @param [in] pSrc Source string to copy.
|
||||
/// @param [in] dstSize Length of the destination buffer, in wchar_t's.
|
||||
extern void CopyUtf16String(
|
||||
wchar_t* pDst,
|
||||
const wchar_t* pSrc,
|
||||
size_t dstSize);
|
||||
|
||||
/// A shared helper function which takes an arbitrary blob of data and formats it into a human readable "memory view"
|
||||
/// string. This is intended to be used by logging code.
|
||||
///
|
||||
/// Imagine your input buffer is: { 0xef, 0xbe, 0xad, 0xde, 0x78, 0x56, 0x34, 0x12, 0xab }, then the string looks like
|
||||
/// this with a blockSize of 4: "0xdeadbeef 0x12345678 0xab". So the block size determines how many bytes are combined
|
||||
/// into one "0x" character block. The whole block is effetively cast into an integer of that size and printed in big
|
||||
/// endian. Trailing bytes are printed without being size-extended. If a block won't fit at the end of the string it
|
||||
/// is skipped (update your buffer pointer and call again to continue).
|
||||
///
|
||||
/// The return value is the number of bytes consumed from pBuffer. The idea is that you can loop until the full size
|
||||
/// is consumed, printing a new line for each call.
|
||||
///
|
||||
/// @param [out] pDst The caller-provided destination string.
|
||||
/// @param [in] dstSize The length of pDst in bytes.
|
||||
/// @param [in] pBuffer The arbitrary data blob to turn into a string.
|
||||
/// @param [in] bufferSize The length of pBuffer in bytes.
|
||||
/// @param [in] blockSize How many bytes to combine into one hexidecimal big endian string.
|
||||
///
|
||||
/// @returns The number of bytes from pBuffer that were formatted into pDst.
|
||||
extern size_t BytesToStr(
|
||||
char* pDst,
|
||||
size_t dstSize,
|
||||
const void* pBuffer,
|
||||
size_t bufferSize,
|
||||
size_t blockSize);
|
||||
|
||||
/// Returns the length of the string.
|
||||
///
|
||||
/// @returns String length.
|
||||
constexpr uint32 StringLength(
|
||||
const char* pString)
|
||||
{
|
||||
// TODO: On C++23 we can replace this with consteval-if.
|
||||
// TODO: When we upgrade PAL_CPLUSPLUS then we can rely that std::is_constant_evaluated() is always defined.
|
||||
#if defined(__cpp_lib_is_constant_evaluated)
|
||||
if (std::is_constant_evaluated())
|
||||
#else
|
||||
if (__builtin_is_constant_evaluated())
|
||||
#endif
|
||||
{
|
||||
uint32 length = 0;
|
||||
while (pString[length] != '\0')
|
||||
{
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
else
|
||||
{
|
||||
return uint32(std::strlen(pString));
|
||||
}
|
||||
}
|
||||
/// Returns the length of the string.
|
||||
///
|
||||
/// @returns String length.
|
||||
constexpr uint32 StringLength(
|
||||
const wchar_t* pString)
|
||||
{
|
||||
// TODO: On C++23 we can replace this with consteval-if.
|
||||
// TODO: When we upgrade PAL_CPLUSPLUS then we can rely that std::is_constant_evaluated() is always defined.
|
||||
#if defined(__cpp_lib_is_constant_evaluated)
|
||||
if (std::is_constant_evaluated())
|
||||
#else
|
||||
if (__builtin_is_constant_evaluated())
|
||||
#endif
|
||||
{
|
||||
uint32 length = 0;
|
||||
while (pString[length] != L'\0')
|
||||
{
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
else
|
||||
{
|
||||
return uint32(std::wcslen(pString));
|
||||
}
|
||||
}
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2020-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palStringUtil.h
|
||||
* @brief PAL String utility collection functions.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
#include <type_traits>
|
||||
|
||||
#include "palUtil.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION < 919
|
||||
/// Returns the length of a wchar_t based string.
|
||||
///
|
||||
/// @param [in] wide string to query
|
||||
///
|
||||
/// @returns The length of the given string in wide characters
|
||||
extern size_t PalWcslen(
|
||||
const wchar_t* pWideStr);
|
||||
|
||||
/// Performs a reverse string find of wide character wc.
|
||||
///
|
||||
/// @param [in] wide string to scan
|
||||
/// @param [in] wide character to find
|
||||
///
|
||||
/// @returns The matching character at the end of the string or nullptr if not found.
|
||||
extern wchar_t* PalWcsrchr(
|
||||
wchar_t *pStr,
|
||||
wchar_t wc);
|
||||
#endif
|
||||
|
||||
/// When the -fshort-char compiler option is specified, wchar_t is 16 bits, but mbstowcs still treats the dest
|
||||
/// as 32 bit so we provide our own implementation.
|
||||
///
|
||||
/// @param [out] dst string
|
||||
/// @param [in] src string
|
||||
/// @param [in] size of the destination buffer in words
|
||||
///
|
||||
/// @returns Returns whether or not the conversion was successful.
|
||||
extern bool ConvertCharStringToUtf16(
|
||||
wchar_t* pDst,
|
||||
const char* pSrc,
|
||||
size_t dstSizeInWords);
|
||||
|
||||
/// When the -fshort-char compiler option is specified, wchar_t is 16 bits, but wcstombs still treats the src
|
||||
/// as 32 bit so we provide our own implementation.
|
||||
///
|
||||
/// @param [out] dst string
|
||||
/// @param [in] src string
|
||||
/// @param [in] size of the destination buffer in bytes
|
||||
///
|
||||
/// @returns Returns whether or not the conversion was successful.
|
||||
extern bool ConvertUtf16StringToUtf8(
|
||||
char* pDst,
|
||||
const wchar_t* pSrc,
|
||||
size_t dstSizeInBytes);
|
||||
|
||||
/// Convert wchar_t string to UTF-8 string. Works whether wchar_t is 16 or 32 bits.
|
||||
/// If wchar_t is 16 bits, this decodes UTF-16.
|
||||
///
|
||||
/// @param [out] dst string
|
||||
/// @param [in] src string
|
||||
/// @param [in] size of the destination buffer in bytes
|
||||
///
|
||||
/// @returns Returns whether or not the conversion was successful.
|
||||
bool ConvertWcharStringToUtf8(char* pDst, const wchar_t* pSrc, size_t dstSizeInBytes);
|
||||
|
||||
/// When the -fshort-char compiler option is specified, wchar_t is 16 bits, but wcsncpy still treats its arguments
|
||||
/// as 32 bit so we provide our own implementation.
|
||||
///
|
||||
/// @param [out] pDst Destination string.
|
||||
/// @param [in] pSrc Source string to copy.
|
||||
/// @param [in] dstSize Length of the destination buffer, in wchar_t's.
|
||||
extern void CopyUtf16String(
|
||||
wchar_t* pDst,
|
||||
const wchar_t* pSrc,
|
||||
size_t dstSize);
|
||||
|
||||
/// A shared helper function which takes an arbitrary blob of data and formats it into a human readable "memory view"
|
||||
/// string. This is intended to be used by logging code.
|
||||
///
|
||||
/// Imagine your input buffer is: { 0xef, 0xbe, 0xad, 0xde, 0x78, 0x56, 0x34, 0x12, 0xab }, then the string looks like
|
||||
/// this with a blockSize of 4: "0xdeadbeef 0x12345678 0xab". So the block size determines how many bytes are combined
|
||||
/// into one "0x" character block. The whole block is effetively cast into an integer of that size and printed in big
|
||||
/// endian. Trailing bytes are printed without being size-extended. If a block won't fit at the end of the string it
|
||||
/// is skipped (update your buffer pointer and call again to continue).
|
||||
///
|
||||
/// The return value is the number of bytes consumed from pBuffer. The idea is that you can loop until the full size
|
||||
/// is consumed, printing a new line for each call.
|
||||
///
|
||||
/// @param [out] pDst The caller-provided destination string.
|
||||
/// @param [in] dstSize The length of pDst in bytes.
|
||||
/// @param [in] pBuffer The arbitrary data blob to turn into a string.
|
||||
/// @param [in] bufferSize The length of pBuffer in bytes.
|
||||
/// @param [in] blockSize How many bytes to combine into one hexidecimal big endian string.
|
||||
///
|
||||
/// @returns The number of bytes from pBuffer that were formatted into pDst.
|
||||
extern size_t BytesToStr(
|
||||
char* pDst,
|
||||
size_t dstSize,
|
||||
const void* pBuffer,
|
||||
size_t bufferSize,
|
||||
size_t blockSize);
|
||||
|
||||
/// Returns the length of the string.
|
||||
///
|
||||
/// @returns String length.
|
||||
constexpr uint32 StringLength(
|
||||
const char* pString)
|
||||
{
|
||||
// TODO: On C++23 we can replace this with consteval-if.
|
||||
// TODO: When we upgrade PAL_CPLUSPLUS then we can rely that std::is_constant_evaluated() is always defined.
|
||||
#if defined(__cpp_lib_is_constant_evaluated)
|
||||
if (std::is_constant_evaluated())
|
||||
#else
|
||||
if (__builtin_is_constant_evaluated())
|
||||
#endif
|
||||
{
|
||||
uint32 length = 0;
|
||||
while (pString[length] != '\0')
|
||||
{
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
else
|
||||
{
|
||||
return uint32(std::strlen(pString));
|
||||
}
|
||||
}
|
||||
/// Returns the length of the string.
|
||||
///
|
||||
/// @returns String length.
|
||||
constexpr uint32 StringLength(
|
||||
const wchar_t* pString)
|
||||
{
|
||||
// TODO: On C++23 we can replace this with consteval-if.
|
||||
// TODO: When we upgrade PAL_CPLUSPLUS then we can rely that std::is_constant_evaluated() is always defined.
|
||||
#if defined(__cpp_lib_is_constant_evaluated)
|
||||
if (std::is_constant_evaluated())
|
||||
#else
|
||||
if (__builtin_is_constant_evaluated())
|
||||
#endif
|
||||
{
|
||||
uint32 length = 0;
|
||||
while (pString[length] != L'\0')
|
||||
{
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
else
|
||||
{
|
||||
return uint32(std::wcslen(pString));
|
||||
}
|
||||
}
|
||||
|
||||
} // Util
|
||||
|
||||
@@ -1,228 +1,228 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palStringView.h
|
||||
* @brief PAL utility collection string view declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palAssert.h"
|
||||
#include "palInlineFuncs.h"
|
||||
#include "palStringUtil.h"
|
||||
#include "palUtil.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief String view.
|
||||
*
|
||||
* A StringView is a templated view over a constant contiguous sequence of characters.
|
||||
*
|
||||
* @warning The string view assumes that its lifetime does not extend past that of the pointed-to character sequence.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename CharT>
|
||||
class StringView
|
||||
{
|
||||
static_assert((std::is_same<CharT, char>::value || std::is_same<CharT, wchar_t>::value),
|
||||
"StringView type T must be either char or wchar_t.");
|
||||
public:
|
||||
/// Constructs an empty StringView.
|
||||
constexpr StringView()
|
||||
:
|
||||
m_pData{},
|
||||
m_length{}
|
||||
{}
|
||||
|
||||
constexpr StringView(
|
||||
const CharT* s,
|
||||
uint32 count)
|
||||
:
|
||||
m_pData{s},
|
||||
m_length{count}
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT((s != nullptr) || (count == 0));
|
||||
}
|
||||
|
||||
StringView(
|
||||
const CharT* s)
|
||||
:
|
||||
StringView()
|
||||
{
|
||||
if (s != nullptr)
|
||||
{
|
||||
m_length = StringLength(s);
|
||||
m_pData = s;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr StringView(std::nullptr_t) = delete;
|
||||
|
||||
///@{
|
||||
/// Returns the element at the location specified.
|
||||
///
|
||||
/// @warning Calling this function with an out-of-bounds index will cause an access violation!
|
||||
///
|
||||
/// @param [in] index Integer location of the element needed.
|
||||
///
|
||||
/// @returns The element at location specified by index by reference
|
||||
constexpr const CharT& At(uint32 index) const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT(index < Length());
|
||||
return m_pData[index];
|
||||
}
|
||||
|
||||
constexpr const CharT& operator[](uint32 index) const { return At(index); }
|
||||
///@}
|
||||
|
||||
/// Returns pointer to the underlying string serving as data storage.
|
||||
/// The returned pointer defines always valid range [Data(), Data() + Length()),
|
||||
/// even if the view does not point to any data storage (Data() is not dereferenceable in that case).
|
||||
///
|
||||
/// @warning Dereferencing pointer returned by Data() from a view that does not point to a data storage will cause
|
||||
/// an access violation!
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage for read access.
|
||||
/// For a view to a valid data storage, the returned pointer contains address of the first element.
|
||||
/// For a view without a valid data storage, the returned pointer will be a @c nullptr.
|
||||
constexpr const CharT* Data() const noexcept { return m_pData; }
|
||||
|
||||
/// Returns the data at the front of the view.
|
||||
///
|
||||
/// @warning Calling this function on an empty view will cause an access violation!
|
||||
///
|
||||
/// @returns The data at the front of the view.
|
||||
constexpr const CharT& Front() const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT(IsEmpty() == false);
|
||||
return m_pData[0];
|
||||
}
|
||||
|
||||
/// Returns the data at the back of the view.
|
||||
///
|
||||
/// @warning Calling this function on an empty view will cause an access violation!
|
||||
///
|
||||
/// @returns The data at the back of the view.
|
||||
constexpr const CharT& Back() const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT(IsEmpty() == false);
|
||||
return m_pData[Length() - 1];
|
||||
}
|
||||
|
||||
/// Returns the length of the string.
|
||||
///
|
||||
/// @returns An unsigned integer equal to the length of the string.
|
||||
constexpr uint32 Length() const { return m_length; }
|
||||
|
||||
/// Returns true if the number of characters the view points to is equal to zero.
|
||||
///
|
||||
/// @returns True if the view points to an empty or non-existing data storage.
|
||||
constexpr bool IsEmpty() const { return (m_length == 0); }
|
||||
|
||||
///@{
|
||||
/// @internal Satisfies concept `range_expression`, using CharT* as `iterator`.
|
||||
///
|
||||
/// @note - These are a convenience intended to be used by C++ language features such as `range-based for`.
|
||||
/// These should not be called directly as they do not adhere to PAL coding standards.
|
||||
using const_iterator = const CharT*;
|
||||
|
||||
constexpr const_iterator begin() const noexcept { return m_pData; }
|
||||
constexpr const_iterator end() const noexcept { return m_pData + Length(); }
|
||||
///@}
|
||||
|
||||
private:
|
||||
const CharT* m_pData;
|
||||
uint32 m_length;
|
||||
};
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename CharT>
|
||||
constexpr bool operator==(
|
||||
StringView<CharT> x,
|
||||
StringView<CharT> y)
|
||||
{
|
||||
bool equal = (x.Length() == y.Length());
|
||||
if (equal)
|
||||
{
|
||||
if (x.Data() != y.Data())
|
||||
{
|
||||
// they are not pointing to the same storage, so we need to compare the contents
|
||||
for (uint32 index = 0; equal && (index < x.Length()); ++index)
|
||||
{
|
||||
equal = (x[index] == y[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename CharT>
|
||||
constexpr bool operator!=(StringView<CharT> x, StringView<CharT> y) { return (x == y) == false; }
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename CharT>
|
||||
bool operator<(
|
||||
StringView<CharT> x,
|
||||
StringView<CharT> y)
|
||||
{
|
||||
const uint32 minLength = Min(x.Length(), y.Length());
|
||||
int compare = strncmp(x.Data(), y.Data(), minLength);
|
||||
if (compare == 0)
|
||||
{
|
||||
// strings are equal up to minLength, so check which is shorter
|
||||
compare = int(x.Length()) - int(y.Length());
|
||||
}
|
||||
|
||||
return compare < 0;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename CharT>
|
||||
bool operator<=(StringView<CharT> x, StringView<CharT> y) { return (y < x) == false; }
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename CharT>
|
||||
bool operator>(StringView<CharT> x, StringView<CharT> y) { return y < x; }
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename CharT>
|
||||
bool operator>=(StringView<CharT> x, StringView<CharT> y) { return (x < y) == false; }
|
||||
|
||||
/// Specialization of @ref HashString(const char*,size_t) for @ref StringView.
|
||||
template<typename T>
|
||||
constexpr uint32 HashString(
|
||||
StringView<T> sv)
|
||||
{
|
||||
return HashString(sv.Data(), sv.Length());
|
||||
}
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palStringView.h
|
||||
* @brief PAL utility collection string view declaration.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palAssert.h"
|
||||
#include "palInlineFuncs.h"
|
||||
#include "palStringUtil.h"
|
||||
#include "palUtil.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief String view.
|
||||
*
|
||||
* A StringView is a templated view over a constant contiguous sequence of characters.
|
||||
*
|
||||
* @warning The string view assumes that its lifetime does not extend past that of the pointed-to character sequence.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename CharT>
|
||||
class StringView
|
||||
{
|
||||
static_assert((std::is_same<CharT, char>::value || std::is_same<CharT, wchar_t>::value),
|
||||
"StringView type T must be either char or wchar_t.");
|
||||
public:
|
||||
/// Constructs an empty StringView.
|
||||
constexpr StringView()
|
||||
:
|
||||
m_pData{},
|
||||
m_length{}
|
||||
{}
|
||||
|
||||
constexpr StringView(
|
||||
const CharT* s,
|
||||
uint32 count)
|
||||
:
|
||||
m_pData{s},
|
||||
m_length{count}
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT((s != nullptr) || (count == 0));
|
||||
}
|
||||
|
||||
StringView(
|
||||
const CharT* s)
|
||||
:
|
||||
StringView()
|
||||
{
|
||||
if (s != nullptr)
|
||||
{
|
||||
m_length = StringLength(s);
|
||||
m_pData = s;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr StringView(std::nullptr_t) = delete;
|
||||
|
||||
///@{
|
||||
/// Returns the element at the location specified.
|
||||
///
|
||||
/// @warning Calling this function with an out-of-bounds index will cause an access violation!
|
||||
///
|
||||
/// @param [in] index Integer location of the element needed.
|
||||
///
|
||||
/// @returns The element at location specified by index by reference
|
||||
constexpr const CharT& At(uint32 index) const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT(index < Length());
|
||||
return m_pData[index];
|
||||
}
|
||||
|
||||
constexpr const CharT& operator[](uint32 index) const { return At(index); }
|
||||
///@}
|
||||
|
||||
/// Returns pointer to the underlying string serving as data storage.
|
||||
/// The returned pointer defines always valid range [Data(), Data() + Length()),
|
||||
/// even if the view does not point to any data storage (Data() is not dereferenceable in that case).
|
||||
///
|
||||
/// @warning Dereferencing pointer returned by Data() from a view that does not point to a data storage will cause
|
||||
/// an access violation!
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage for read access.
|
||||
/// For a view to a valid data storage, the returned pointer contains address of the first element.
|
||||
/// For a view without a valid data storage, the returned pointer will be a @c nullptr.
|
||||
constexpr const CharT* Data() const noexcept { return m_pData; }
|
||||
|
||||
/// Returns the data at the front of the view.
|
||||
///
|
||||
/// @warning Calling this function on an empty view will cause an access violation!
|
||||
///
|
||||
/// @returns The data at the front of the view.
|
||||
constexpr const CharT& Front() const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT(IsEmpty() == false);
|
||||
return m_pData[0];
|
||||
}
|
||||
|
||||
/// Returns the data at the back of the view.
|
||||
///
|
||||
/// @warning Calling this function on an empty view will cause an access violation!
|
||||
///
|
||||
/// @returns The data at the back of the view.
|
||||
constexpr const CharT& Back() const
|
||||
{
|
||||
PAL_CONSTEXPR_ASSERT(IsEmpty() == false);
|
||||
return m_pData[Length() - 1];
|
||||
}
|
||||
|
||||
/// Returns the length of the string.
|
||||
///
|
||||
/// @returns An unsigned integer equal to the length of the string.
|
||||
constexpr uint32 Length() const { return m_length; }
|
||||
|
||||
/// Returns true if the number of characters the view points to is equal to zero.
|
||||
///
|
||||
/// @returns True if the view points to an empty or non-existing data storage.
|
||||
constexpr bool IsEmpty() const { return (m_length == 0); }
|
||||
|
||||
///@{
|
||||
/// @internal Satisfies concept `range_expression`, using CharT* as `iterator`.
|
||||
///
|
||||
/// @note - These are a convenience intended to be used by C++ language features such as `range-based for`.
|
||||
/// These should not be called directly as they do not adhere to PAL coding standards.
|
||||
using const_iterator = const CharT*;
|
||||
|
||||
constexpr const_iterator begin() const noexcept { return m_pData; }
|
||||
constexpr const_iterator end() const noexcept { return m_pData + Length(); }
|
||||
///@}
|
||||
|
||||
private:
|
||||
const CharT* m_pData;
|
||||
uint32 m_length;
|
||||
};
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename CharT>
|
||||
constexpr bool operator==(
|
||||
StringView<CharT> x,
|
||||
StringView<CharT> y)
|
||||
{
|
||||
bool equal = (x.Length() == y.Length());
|
||||
if (equal)
|
||||
{
|
||||
if (x.Data() != y.Data())
|
||||
{
|
||||
// they are not pointing to the same storage, so we need to compare the contents
|
||||
for (uint32 index = 0; equal && (index < x.Length()); ++index)
|
||||
{
|
||||
equal = (x[index] == y[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename CharT>
|
||||
constexpr bool operator!=(StringView<CharT> x, StringView<CharT> y) { return (x == y) == false; }
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename CharT>
|
||||
bool operator<(
|
||||
StringView<CharT> x,
|
||||
StringView<CharT> y)
|
||||
{
|
||||
const uint32 minLength = Min(x.Length(), y.Length());
|
||||
int compare = strncmp(x.Data(), y.Data(), minLength);
|
||||
if (compare == 0)
|
||||
{
|
||||
// strings are equal up to minLength, so check which is shorter
|
||||
compare = int(x.Length()) - int(y.Length());
|
||||
}
|
||||
|
||||
return compare < 0;
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename CharT>
|
||||
bool operator<=(StringView<CharT> x, StringView<CharT> y) { return (y < x) == false; }
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename CharT>
|
||||
bool operator>(StringView<CharT> x, StringView<CharT> y) { return y < x; }
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename CharT>
|
||||
bool operator>=(StringView<CharT> x, StringView<CharT> y) { return (x < y) == false; }
|
||||
|
||||
/// Specialization of @ref HashString(const char*,size_t) for @ref StringView.
|
||||
template<typename T>
|
||||
constexpr uint32 HashString(
|
||||
StringView<T> sv)
|
||||
{
|
||||
return HashString(sv.Data(), sv.Length());
|
||||
}
|
||||
|
||||
} // Util
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,87 +1,87 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palTime.h
|
||||
* @brief PAL time-related utility collection.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// Specifies a class that implements a timestamp.
|
||||
class Timestamp
|
||||
{
|
||||
public:
|
||||
/// Creates a new timestamp object that records the time it was created.
|
||||
Timestamp();
|
||||
|
||||
/// Returns the timestamp as a C-string.
|
||||
const char* CStr() const { return m_data; }
|
||||
|
||||
private:
|
||||
char m_data[64];
|
||||
};
|
||||
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 873
|
||||
/// Seconds stored as a float instead of an integer.
|
||||
using fseconds = std::chrono::duration<float>;
|
||||
/// Milliseconds stored as a float instead of an integer.
|
||||
using fmilliseconds = std::chrono::duration<float, std::milli>;
|
||||
/// Microseconds stored as a float instead of an integer.
|
||||
using fmicroseconds = std::chrono::duration<float, std::micro>;
|
||||
/// Nanoseconds stored as a float instead of an integer.
|
||||
using fnanoseconds = std::chrono::duration<float, std::nano>;
|
||||
|
||||
/// A time_point who's epoch is January 1st 1970 and uses seconds for the duration.
|
||||
/// C++20 guarantees us that system_clock's epoch is always January 1st 1970 on all platforms.
|
||||
/// system_clock's internal duration is still implementation defined.
|
||||
/// On Windows it's hundreds-of-nanoseconds and on Linux it's seconds.
|
||||
/// However time_point has it's own duration type.
|
||||
/// As long as we go through the time_point to interpret the duration then everything should be in terms of seconds.
|
||||
using SecondsSinceEpoch = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
|
||||
|
||||
/// Like std::chrono::duration_cast, but it preserves the special 'infinite' value used in timeouts.
|
||||
template<class DestDuration, class Rep, class Period>
|
||||
constexpr DestDuration TimeoutCast(
|
||||
const std::chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
if (d == (std::chrono::duration<Rep, Period>::max)())
|
||||
{
|
||||
return (DestDuration::max)();
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::chrono::duration_cast<DestDuration, Rep, Period>(d);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palTime.h
|
||||
* @brief PAL time-related utility collection.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// Specifies a class that implements a timestamp.
|
||||
class Timestamp
|
||||
{
|
||||
public:
|
||||
/// Creates a new timestamp object that records the time it was created.
|
||||
Timestamp();
|
||||
|
||||
/// Returns the timestamp as a C-string.
|
||||
const char* CStr() const { return m_data; }
|
||||
|
||||
private:
|
||||
char m_data[64];
|
||||
};
|
||||
|
||||
#if PAL_CLIENT_INTERFACE_MAJOR_VERSION >= 873
|
||||
/// Seconds stored as a float instead of an integer.
|
||||
using fseconds = std::chrono::duration<float>;
|
||||
/// Milliseconds stored as a float instead of an integer.
|
||||
using fmilliseconds = std::chrono::duration<float, std::milli>;
|
||||
/// Microseconds stored as a float instead of an integer.
|
||||
using fmicroseconds = std::chrono::duration<float, std::micro>;
|
||||
/// Nanoseconds stored as a float instead of an integer.
|
||||
using fnanoseconds = std::chrono::duration<float, std::nano>;
|
||||
|
||||
/// A time_point who's epoch is January 1st 1970 and uses seconds for the duration.
|
||||
/// C++20 guarantees us that system_clock's epoch is always January 1st 1970 on all platforms.
|
||||
/// system_clock's internal duration is still implementation defined.
|
||||
/// On Windows it's hundreds-of-nanoseconds and on Linux it's seconds.
|
||||
/// However time_point has it's own duration type.
|
||||
/// As long as we go through the time_point to interpret the duration then everything should be in terms of seconds.
|
||||
using SecondsSinceEpoch = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
|
||||
|
||||
/// Like std::chrono::duration_cast, but it preserves the special 'infinite' value used in timeouts.
|
||||
template<class DestDuration, class Rep, class Period>
|
||||
constexpr DestDuration TimeoutCast(
|
||||
const std::chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
if (d == (std::chrono::duration<Rep, Period>::max)())
|
||||
{
|
||||
return (DestDuration::max)();
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::chrono::duration_cast<DestDuration, Rep, Period>(d);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // Util
|
||||
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,455 +1,455 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palVector.h
|
||||
* @brief PAL utility collection Vector and VectorIterator class declarations.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palUtil.h"
|
||||
#include "palAssert.h"
|
||||
#include "palSpan.h"
|
||||
#include "palSysMemory.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator> class Vector;
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Iterator for traversal of elements in Vector.
|
||||
*
|
||||
* Supports forward traversal.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator>
|
||||
class VectorIterator
|
||||
{
|
||||
public:
|
||||
/// Checks if the current index is within bounds of the number of elements in the vector.
|
||||
///
|
||||
/// @returns True if the current element this iterator is pointing to is within the permitted range.
|
||||
bool IsValid() const { return (m_curIndex < m_srcVector.m_numElements); }
|
||||
|
||||
/// Returns the element the iterator is currently pointing to as a reference.
|
||||
///
|
||||
/// @warning This may cause an access violation if the iterator is not valid.
|
||||
///
|
||||
/// @returns The element the iterator is currently pointing to.
|
||||
T& Get() const
|
||||
{
|
||||
PAL_ASSERT(IsValid());
|
||||
return (*(m_srcVector.m_pData + m_curIndex));
|
||||
}
|
||||
|
||||
/// Advances the iterator to point to the next element.
|
||||
///
|
||||
/// @warning Does not do bounds checking.
|
||||
void Next() { ++m_curIndex; }
|
||||
|
||||
/// Retrieves the current vector position of this iterator.
|
||||
///
|
||||
/// @returns The location in the vector of the element the iterator is currently pointing to.
|
||||
uint32 Position() const { return m_curIndex; }
|
||||
|
||||
private:
|
||||
VectorIterator(uint32 index, const Vector<T, defaultCapacity, Allocator>& srcVec);
|
||||
|
||||
uint32 m_curIndex; // The current index of the vector iterator.
|
||||
const Vector<T, defaultCapacity, Allocator>& m_srcVector; // The vector container this iterator is used for.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(VectorIterator);
|
||||
|
||||
// Although this is a transgression of coding standards, it means that Vector does not need to have a public
|
||||
// interface specifically to implement this class. The added encapsulation this provides is worthwhile.
|
||||
friend class Vector<T, defaultCapacity, Allocator>;
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Vector container.
|
||||
*
|
||||
* Vector is a templated array based storage that starts with a default-size allocation in the stack. If more space is
|
||||
* needed it then resorts to dynamic allocation by doubling the size every time the capacity is exceeded.
|
||||
* Operations which this class supports are:
|
||||
*
|
||||
* - Insertion at the end of the array.
|
||||
* - Forward iteration.
|
||||
* - Random access.
|
||||
*
|
||||
* @warning This class is not thread-safe.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator>
|
||||
class Vector
|
||||
{
|
||||
public:
|
||||
/// A convenient shorthand for VectorIterator.
|
||||
typedef VectorIterator<T, defaultCapacity, Allocator> Iter;
|
||||
|
||||
/// When this allocates, it doubles the old size of memory
|
||||
static constexpr uint32 GrowthFactor = 2;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param [in] pAllocator The allocator that will allocate memory if required.
|
||||
Vector(Allocator*const pAllocator);
|
||||
|
||||
/// Destructor.
|
||||
~Vector();
|
||||
|
||||
/// Move constructor.
|
||||
///
|
||||
/// @param [in] vector Reference to a dying vector, from which resources will be stolen.
|
||||
Vector(Vector&& vector);
|
||||
|
||||
/// Increases maximal capacity to value greater or equal to the newCapacity.
|
||||
/// If newCapacity is greater than the maximal capacity, new storage is allocated,
|
||||
/// otherwise the method does nothing.
|
||||
///
|
||||
/// @note All existing iterators will not get invalidated, even in case new storage is allocated,
|
||||
/// because iterators are referencing vector, rather than elements of that vector.
|
||||
///
|
||||
/// @warning All pointers and references to elements of a vector will be invalidated,
|
||||
/// in case new storage is allocated.
|
||||
///
|
||||
/// @param [in] newCapacity The new capacity of a vector, which is lower limit of the maximal capacity.
|
||||
///
|
||||
/// @returns Result ErrorOutOfMemory if the operation failed.
|
||||
Result Reserve(uint32 newCapacity);
|
||||
|
||||
/// Increases maximum capacity to the number of elements in the vector, plus the specified increment amount.
|
||||
/// Equivalent to this->Reserve(this->NumElements() + amount);
|
||||
///
|
||||
/// @param [in] amount Number of items beyond the current element count to increas the capacity to.
|
||||
///
|
||||
/// @returns Result ErrorOutOfMemory if the operation failed.
|
||||
Result Grow(uint32 amount) { return Reserve(NumElements() + amount); }
|
||||
|
||||
/// Set size to newSize.
|
||||
/// If size is decreased, elements at the end of the vector will be removed.
|
||||
/// If size is increased, new elements will be set to newVal.
|
||||
/// If newSize requires a higher capacity, a new allocation is made. See notes on Reserve.
|
||||
///
|
||||
/// @note If size is decreased, any iterators referencing removed elements will become invalid. All other
|
||||
/// iterators will remain valid. Otherwise, all iterators will still be valid.
|
||||
///
|
||||
/// @warning All pointers and references to elements of a vector will be invalidated,
|
||||
/// in case new storage is allocated.
|
||||
///
|
||||
/// @param [in] newSize The new size of a vector.
|
||||
///
|
||||
/// @returns Result ErrorOutOfMemory if the operation failed.
|
||||
Result Resize(uint32 newSize, const T& newVal = T());
|
||||
|
||||
/// Copy/Move an element to end of the vector. If not enough space is available, new space will be allocated and
|
||||
/// the old data will be copied to the new space.
|
||||
///
|
||||
/// @param [in] data The element to be pushed to the vector. The element will become the last element.
|
||||
///
|
||||
/// @returns Result ErrorOutOfMemory if the operation failed.
|
||||
Result PushBack(const T& data);
|
||||
Result PushBack(T&& data);
|
||||
|
||||
/// Constructs an object in-place at the end of the vector. If not enough space is available, new space will be
|
||||
/// allocated and the old data will be copied to the new space.
|
||||
///
|
||||
/// @param [in] args... The arguments passed to the constructor
|
||||
///
|
||||
/// @returns Result ErrorOutOfMemory if the operation failed.
|
||||
template <typename... Args>
|
||||
Result EmplaceBack(Args&&... args);
|
||||
|
||||
/// Returns the element at the end of the vector and destroys it.
|
||||
///
|
||||
/// @param [out] pData The element at the end of the vector.
|
||||
/// It is expected that pData is uninitialized as it will be overwritten and not destructed.
|
||||
void PopBack(T* pData);
|
||||
|
||||
/// Destroys all elements stored in the vector. All dynamically allocated memory will be saved for reuse.
|
||||
void Clear();
|
||||
|
||||
///@{
|
||||
/// Returns the element at the location specified.
|
||||
///
|
||||
/// @warning Calling this function with an out-of-bounds index will cause an access violation!
|
||||
///
|
||||
/// @param [in] index Integer location of the element needed.
|
||||
///
|
||||
/// @returns The element at location specified by index by reference
|
||||
T& At(uint32 index)
|
||||
{
|
||||
PAL_ASSERT(index < m_numElements);
|
||||
return *(m_pData + index);
|
||||
}
|
||||
|
||||
const T& At(uint32 index) const
|
||||
{
|
||||
PAL_ASSERT(index < m_numElements);
|
||||
return *(m_pData + index);
|
||||
}
|
||||
|
||||
T& operator[](uint32 index) noexcept { return At(index); }
|
||||
const T& operator[](uint32 index) const noexcept { return At(index); }
|
||||
///@}
|
||||
|
||||
/// Returns the data at the front of the vector.
|
||||
///
|
||||
/// @warning Calling this function on an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns The data at the front of the vector.
|
||||
T& Front() const
|
||||
{
|
||||
PAL_ASSERT(IsEmpty() == false);
|
||||
return *m_pData;
|
||||
}
|
||||
|
||||
/// Returns the data at the back of the vector.
|
||||
///
|
||||
/// @warning Calling this function on an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns The data at the back of the vector.
|
||||
T& Back() const
|
||||
{
|
||||
PAL_ASSERT(IsEmpty() == false);
|
||||
return *(m_pData + (m_numElements - 1));
|
||||
}
|
||||
|
||||
/// Returns an iterator to the first element of the vector.
|
||||
///
|
||||
/// @warning Accessing an element using an iterator of an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns An iterator to first element of the vector.
|
||||
Iter Begin() const { return Iter(0, *this); }
|
||||
|
||||
/// Returns an iterator to the last element of the vector.
|
||||
///
|
||||
/// @warning Accessing an element using an iterator of an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns VectorIterator An iterator to last element of the vector.
|
||||
Iter End() const { return Iter((m_numElements - 1), *this); }
|
||||
|
||||
///@{
|
||||
/// Implicitly gets the current contents of the vector as a Span.
|
||||
///
|
||||
/// @returns The contents of the vector as a Span; same as Span<T>(Data(), NumElements()).
|
||||
operator Span<T>() { return Span<T>(Data(), NumElements()); }
|
||||
operator Span<const T>() const { return Span<const T>(Data(), NumElements()); }
|
||||
///@}
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage.
|
||||
/// The returned pointer defines always valid range [Data(), Data() + NumElements()),
|
||||
/// even if the container is empty (Data() is not dereferenceable in that case).
|
||||
///
|
||||
/// @warning Dereferencing pointer returned by Data() from an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage for read & write access.
|
||||
/// For a non-empty vector, the returned pointer contains address of the first element.
|
||||
/// For an empty vector, the returned pointer may or may not be a null pointer.
|
||||
T* Data() { return m_pData; }
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage.
|
||||
/// The returned pointer defines always valid range [Data(), Data() + NumElements()),
|
||||
/// even if the container is empty (Data() is not dereferenceable in that case).
|
||||
///
|
||||
/// @warning Dereferencing pointer returned by Data() from an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage for read only access.
|
||||
/// For a non-empty vector, the returned pointer contains address of the first element.
|
||||
/// For an empty vector, the returned pointer may or may not be a null pointer.
|
||||
const T* Data() const { return m_pData; }
|
||||
|
||||
/// Returns the size of the vector.
|
||||
///
|
||||
/// @returns An unsigned integer equal to the number of elements currently present in the vector.
|
||||
uint32 NumElements() const { return m_numElements; }
|
||||
|
||||
/// Returns true if the number of elements present in the vector is equal to zero.
|
||||
///
|
||||
/// @returns True if the vector is empty.
|
||||
bool IsEmpty() const { return (m_numElements == 0); }
|
||||
|
||||
/// Returns a pointer to the allocator used for this container's memory management.
|
||||
///
|
||||
/// @returns Allocator pointer.
|
||||
Allocator* GetAllocator() const { return m_pAllocator; }
|
||||
|
||||
///@{
|
||||
/// @internal Satisfies concept `range_expression`, using T* as `iterator` and 32-bit size and difference types
|
||||
///
|
||||
/// @note - These are a convenience intended to be used by c++ language features such as `range for`.
|
||||
/// These should not be called directly as they do not adhere to PAL coding standards.
|
||||
using value_type = T;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
using iterator = T*;
|
||||
using const_iterator = const T*;
|
||||
using difference_type = int32;
|
||||
using size_type = uint32;
|
||||
|
||||
iterator begin() noexcept { return m_pData; }
|
||||
iterator end() noexcept { return (m_pData + m_numElements); }
|
||||
const_iterator begin() const noexcept { return m_pData; }
|
||||
const_iterator end() const noexcept { return (m_pData + m_numElements); }
|
||||
const_iterator cbegin() const noexcept { return m_pData; }
|
||||
const_iterator cend() const noexcept { return (m_pData + m_numElements); }
|
||||
[[nodiscard]] bool empty() const noexcept { return IsEmpty(); }
|
||||
size_type size() const noexcept { return m_numElements; }
|
||||
///@}
|
||||
|
||||
/// Erases the element at the specified iterator.
|
||||
void Erase(Iter it);
|
||||
|
||||
/// Erases the element at the specified iterator.
|
||||
void Erase(iterator it);
|
||||
|
||||
/// Erases the element at the specified index.
|
||||
void Erase(uint32 index);
|
||||
|
||||
/// Erase the element at the specified iterator, and swap last element to that position.
|
||||
/// If the element to erase is the last element, erase directly and no swap operation.
|
||||
void EraseAndSwapLast(Iter it);
|
||||
|
||||
/// Erase the element at the specified iterator, and swap last element to that position.
|
||||
/// If the element to erase is the last element, erase directly and no swap operation.
|
||||
void EraseAndSwapLast(iterator it);
|
||||
|
||||
/// Erases the element at the specified index, and swap last element to that position.
|
||||
/// If the element to erase is the last element, erase directly and no swap operation.
|
||||
void EraseAndSwapLast(uint32 index);
|
||||
|
||||
private:
|
||||
// This is a POD-type that exactly fits one T value.
|
||||
typedef typename std::aligned_storage<sizeof(T), alignof(T)>::type ValueStorage;
|
||||
|
||||
ValueStorage m_data[defaultCapacity]; // The initial data buffer stored within the vector object.
|
||||
T* m_pData; // Pointer to the current data buffer.
|
||||
uint32 m_numElements; // Number of elements present.
|
||||
uint32 m_maxCapacity; // Maximum size it can hold.
|
||||
Allocator*const m_pAllocator; // Allocator for this Vector.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(Vector);
|
||||
|
||||
// Although this is a transgression of coding standards, it prevents VectorIterator requiring a public constructor;
|
||||
// constructing a 'bare' VectorIterator (i.e. without calling Vector::GetIterator) can never be a legal operation,
|
||||
// so this means that these two classes are much safer to use.
|
||||
friend class VectorIterator<T, defaultCapacity, Allocator>;
|
||||
};
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator>
|
||||
VectorIterator<T, defaultCapacity, Allocator>::VectorIterator(
|
||||
uint32 index,
|
||||
const Vector<T, defaultCapacity, Allocator>& srcVec)
|
||||
:
|
||||
m_curIndex(index),
|
||||
m_srcVector(srcVec)
|
||||
{
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator>
|
||||
Vector<T, defaultCapacity, Allocator>::Vector(
|
||||
Allocator*const pAllocator)
|
||||
:
|
||||
m_pData(reinterpret_cast<T*>(m_data)),
|
||||
m_numElements(0),
|
||||
m_maxCapacity(defaultCapacity),
|
||||
m_pAllocator(pAllocator)
|
||||
{
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator>
|
||||
Vector<T, defaultCapacity, Allocator>::~Vector()
|
||||
{
|
||||
// Explicitly destroy all non-trivial types.
|
||||
if (!std::is_trivial<T>::value)
|
||||
{
|
||||
for (uint32 idx = 0; idx < m_numElements; ++idx)
|
||||
{
|
||||
m_pData[idx].~T();
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have dynamically allocated memory.
|
||||
if (m_pData != reinterpret_cast<T*>(m_data))
|
||||
{
|
||||
// Free the memory that was allocated dynamically.
|
||||
PAL_FREE(m_pData, m_pAllocator);
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Steals allocation from a dying vector, if data buffer uses storage from heap allocation.
|
||||
// Moves objects between local buffers of new and dying vectors (for non-trivial types) or
|
||||
// copies local buffer from a dying vector to a new vector (for trivial types),
|
||||
// if data buffer uses storage from local buffer.
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator>
|
||||
Vector<T, defaultCapacity, Allocator>::Vector(
|
||||
Vector&& vector)
|
||||
:
|
||||
m_numElements(vector.m_numElements),
|
||||
m_maxCapacity(vector.m_maxCapacity),
|
||||
m_pAllocator(vector.m_pAllocator)
|
||||
{
|
||||
if (vector.m_pData == reinterpret_cast<T*>(vector.m_data)) // Local buffer
|
||||
{
|
||||
// Data buffer will be using storage from local buffer.
|
||||
m_pData = reinterpret_cast<T*>(m_data);
|
||||
|
||||
if (std::is_trivial<T>::value)
|
||||
{
|
||||
// Optimize trivial types by copying local buffer.
|
||||
std::memcpy(m_pData, vector.m_pData, sizeof(T) * m_numElements);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move objects from local buffer of a dying vector to local buffer of a new vector.
|
||||
for (uint32 idx = 0; idx < m_numElements; ++idx)
|
||||
{
|
||||
PAL_PLACEMENT_NEW(m_pData + idx) T(Move(vector.m_pData[idx]));
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Heap allocation
|
||||
{
|
||||
// Steal heap allocation from dying vector.
|
||||
m_pData = vector.m_pData;
|
||||
|
||||
// After the allocation has been stolen, dying vector is just an empty shell.
|
||||
vector.m_pData = nullptr;
|
||||
vector.m_numElements = 0;
|
||||
vector.m_maxCapacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // Util
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @file palVector.h
|
||||
* @brief PAL utility collection Vector and VectorIterator class declarations.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "palUtil.h"
|
||||
#include "palAssert.h"
|
||||
#include "palSpan.h"
|
||||
#include "palSysMemory.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator> class Vector;
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Iterator for traversal of elements in Vector.
|
||||
*
|
||||
* Supports forward traversal.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator>
|
||||
class VectorIterator
|
||||
{
|
||||
public:
|
||||
/// Checks if the current index is within bounds of the number of elements in the vector.
|
||||
///
|
||||
/// @returns True if the current element this iterator is pointing to is within the permitted range.
|
||||
bool IsValid() const { return (m_curIndex < m_srcVector.m_numElements); }
|
||||
|
||||
/// Returns the element the iterator is currently pointing to as a reference.
|
||||
///
|
||||
/// @warning This may cause an access violation if the iterator is not valid.
|
||||
///
|
||||
/// @returns The element the iterator is currently pointing to.
|
||||
T& Get() const
|
||||
{
|
||||
PAL_ASSERT(IsValid());
|
||||
return (*(m_srcVector.m_pData + m_curIndex));
|
||||
}
|
||||
|
||||
/// Advances the iterator to point to the next element.
|
||||
///
|
||||
/// @warning Does not do bounds checking.
|
||||
void Next() { ++m_curIndex; }
|
||||
|
||||
/// Retrieves the current vector position of this iterator.
|
||||
///
|
||||
/// @returns The location in the vector of the element the iterator is currently pointing to.
|
||||
uint32 Position() const { return m_curIndex; }
|
||||
|
||||
private:
|
||||
VectorIterator(uint32 index, const Vector<T, defaultCapacity, Allocator>& srcVec);
|
||||
|
||||
uint32 m_curIndex; // The current index of the vector iterator.
|
||||
const Vector<T, defaultCapacity, Allocator>& m_srcVector; // The vector container this iterator is used for.
|
||||
|
||||
PAL_DISALLOW_DEFAULT_CTOR(VectorIterator);
|
||||
|
||||
// Although this is a transgression of coding standards, it means that Vector does not need to have a public
|
||||
// interface specifically to implement this class. The added encapsulation this provides is worthwhile.
|
||||
friend class Vector<T, defaultCapacity, Allocator>;
|
||||
};
|
||||
|
||||
/**
|
||||
***********************************************************************************************************************
|
||||
* @brief Vector container.
|
||||
*
|
||||
* Vector is a templated array based storage that starts with a default-size allocation in the stack. If more space is
|
||||
* needed it then resorts to dynamic allocation by doubling the size every time the capacity is exceeded.
|
||||
* Operations which this class supports are:
|
||||
*
|
||||
* - Insertion at the end of the array.
|
||||
* - Forward iteration.
|
||||
* - Random access.
|
||||
*
|
||||
* @warning This class is not thread-safe.
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator>
|
||||
class Vector
|
||||
{
|
||||
public:
|
||||
/// A convenient shorthand for VectorIterator.
|
||||
typedef VectorIterator<T, defaultCapacity, Allocator> Iter;
|
||||
|
||||
/// When this allocates, it doubles the old size of memory
|
||||
static constexpr uint32 GrowthFactor = 2;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param [in] pAllocator The allocator that will allocate memory if required.
|
||||
Vector(Allocator*const pAllocator);
|
||||
|
||||
/// Destructor.
|
||||
~Vector();
|
||||
|
||||
/// Move constructor.
|
||||
///
|
||||
/// @param [in] vector Reference to a dying vector, from which resources will be stolen.
|
||||
Vector(Vector&& vector);
|
||||
|
||||
/// Increases maximal capacity to value greater or equal to the newCapacity.
|
||||
/// If newCapacity is greater than the maximal capacity, new storage is allocated,
|
||||
/// otherwise the method does nothing.
|
||||
///
|
||||
/// @note All existing iterators will not get invalidated, even in case new storage is allocated,
|
||||
/// because iterators are referencing vector, rather than elements of that vector.
|
||||
///
|
||||
/// @warning All pointers and references to elements of a vector will be invalidated,
|
||||
/// in case new storage is allocated.
|
||||
///
|
||||
/// @param [in] newCapacity The new capacity of a vector, which is lower limit of the maximal capacity.
|
||||
///
|
||||
/// @returns Result ErrorOutOfMemory if the operation failed.
|
||||
Result Reserve(uint32 newCapacity);
|
||||
|
||||
/// Increases maximum capacity to the number of elements in the vector, plus the specified increment amount.
|
||||
/// Equivalent to this->Reserve(this->NumElements() + amount);
|
||||
///
|
||||
/// @param [in] amount Number of items beyond the current element count to increas the capacity to.
|
||||
///
|
||||
/// @returns Result ErrorOutOfMemory if the operation failed.
|
||||
Result Grow(uint32 amount) { return Reserve(NumElements() + amount); }
|
||||
|
||||
/// Set size to newSize.
|
||||
/// If size is decreased, elements at the end of the vector will be removed.
|
||||
/// If size is increased, new elements will be set to newVal.
|
||||
/// If newSize requires a higher capacity, a new allocation is made. See notes on Reserve.
|
||||
///
|
||||
/// @note If size is decreased, any iterators referencing removed elements will become invalid. All other
|
||||
/// iterators will remain valid. Otherwise, all iterators will still be valid.
|
||||
///
|
||||
/// @warning All pointers and references to elements of a vector will be invalidated,
|
||||
/// in case new storage is allocated.
|
||||
///
|
||||
/// @param [in] newSize The new size of a vector.
|
||||
///
|
||||
/// @returns Result ErrorOutOfMemory if the operation failed.
|
||||
Result Resize(uint32 newSize, const T& newVal = T());
|
||||
|
||||
/// Copy/Move an element to end of the vector. If not enough space is available, new space will be allocated and
|
||||
/// the old data will be copied to the new space.
|
||||
///
|
||||
/// @param [in] data The element to be pushed to the vector. The element will become the last element.
|
||||
///
|
||||
/// @returns Result ErrorOutOfMemory if the operation failed.
|
||||
Result PushBack(const T& data);
|
||||
Result PushBack(T&& data);
|
||||
|
||||
/// Constructs an object in-place at the end of the vector. If not enough space is available, new space will be
|
||||
/// allocated and the old data will be copied to the new space.
|
||||
///
|
||||
/// @param [in] args... The arguments passed to the constructor
|
||||
///
|
||||
/// @returns Result ErrorOutOfMemory if the operation failed.
|
||||
template <typename... Args>
|
||||
Result EmplaceBack(Args&&... args);
|
||||
|
||||
/// Returns the element at the end of the vector and destroys it.
|
||||
///
|
||||
/// @param [out] pData The element at the end of the vector.
|
||||
/// It is expected that pData is uninitialized as it will be overwritten and not destructed.
|
||||
void PopBack(T* pData);
|
||||
|
||||
/// Destroys all elements stored in the vector. All dynamically allocated memory will be saved for reuse.
|
||||
void Clear();
|
||||
|
||||
///@{
|
||||
/// Returns the element at the location specified.
|
||||
///
|
||||
/// @warning Calling this function with an out-of-bounds index will cause an access violation!
|
||||
///
|
||||
/// @param [in] index Integer location of the element needed.
|
||||
///
|
||||
/// @returns The element at location specified by index by reference
|
||||
T& At(uint32 index)
|
||||
{
|
||||
PAL_ASSERT(index < m_numElements);
|
||||
return *(m_pData + index);
|
||||
}
|
||||
|
||||
const T& At(uint32 index) const
|
||||
{
|
||||
PAL_ASSERT(index < m_numElements);
|
||||
return *(m_pData + index);
|
||||
}
|
||||
|
||||
T& operator[](uint32 index) noexcept { return At(index); }
|
||||
const T& operator[](uint32 index) const noexcept { return At(index); }
|
||||
///@}
|
||||
|
||||
/// Returns the data at the front of the vector.
|
||||
///
|
||||
/// @warning Calling this function on an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns The data at the front of the vector.
|
||||
T& Front() const
|
||||
{
|
||||
PAL_ASSERT(IsEmpty() == false);
|
||||
return *m_pData;
|
||||
}
|
||||
|
||||
/// Returns the data at the back of the vector.
|
||||
///
|
||||
/// @warning Calling this function on an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns The data at the back of the vector.
|
||||
T& Back() const
|
||||
{
|
||||
PAL_ASSERT(IsEmpty() == false);
|
||||
return *(m_pData + (m_numElements - 1));
|
||||
}
|
||||
|
||||
/// Returns an iterator to the first element of the vector.
|
||||
///
|
||||
/// @warning Accessing an element using an iterator of an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns An iterator to first element of the vector.
|
||||
Iter Begin() const { return Iter(0, *this); }
|
||||
|
||||
/// Returns an iterator to the last element of the vector.
|
||||
///
|
||||
/// @warning Accessing an element using an iterator of an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns VectorIterator An iterator to last element of the vector.
|
||||
Iter End() const { return Iter((m_numElements - 1), *this); }
|
||||
|
||||
///@{
|
||||
/// Implicitly gets the current contents of the vector as a Span.
|
||||
///
|
||||
/// @returns The contents of the vector as a Span; same as Span<T>(Data(), NumElements()).
|
||||
operator Span<T>() { return Span<T>(Data(), NumElements()); }
|
||||
operator Span<const T>() const { return Span<const T>(Data(), NumElements()); }
|
||||
///@}
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage.
|
||||
/// The returned pointer defines always valid range [Data(), Data() + NumElements()),
|
||||
/// even if the container is empty (Data() is not dereferenceable in that case).
|
||||
///
|
||||
/// @warning Dereferencing pointer returned by Data() from an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage for read & write access.
|
||||
/// For a non-empty vector, the returned pointer contains address of the first element.
|
||||
/// For an empty vector, the returned pointer may or may not be a null pointer.
|
||||
T* Data() { return m_pData; }
|
||||
|
||||
/// Returns pointer to the underlying buffer serving as data storage.
|
||||
/// The returned pointer defines always valid range [Data(), Data() + NumElements()),
|
||||
/// even if the container is empty (Data() is not dereferenceable in that case).
|
||||
///
|
||||
/// @warning Dereferencing pointer returned by Data() from an empty vector will cause an access violation!
|
||||
///
|
||||
/// @returns Pointer to the underlying data storage for read only access.
|
||||
/// For a non-empty vector, the returned pointer contains address of the first element.
|
||||
/// For an empty vector, the returned pointer may or may not be a null pointer.
|
||||
const T* Data() const { return m_pData; }
|
||||
|
||||
/// Returns the size of the vector.
|
||||
///
|
||||
/// @returns An unsigned integer equal to the number of elements currently present in the vector.
|
||||
uint32 NumElements() const { return m_numElements; }
|
||||
|
||||
/// Returns true if the number of elements present in the vector is equal to zero.
|
||||
///
|
||||
/// @returns True if the vector is empty.
|
||||
bool IsEmpty() const { return (m_numElements == 0); }
|
||||
|
||||
/// Returns a pointer to the allocator used for this container's memory management.
|
||||
///
|
||||
/// @returns Allocator pointer.
|
||||
Allocator* GetAllocator() const { return m_pAllocator; }
|
||||
|
||||
///@{
|
||||
/// @internal Satisfies concept `range_expression`, using T* as `iterator` and 32-bit size and difference types
|
||||
///
|
||||
/// @note - These are a convenience intended to be used by c++ language features such as `range for`.
|
||||
/// These should not be called directly as they do not adhere to PAL coding standards.
|
||||
using value_type = T;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
using iterator = T*;
|
||||
using const_iterator = const T*;
|
||||
using difference_type = int32;
|
||||
using size_type = uint32;
|
||||
|
||||
iterator begin() noexcept { return m_pData; }
|
||||
iterator end() noexcept { return (m_pData + m_numElements); }
|
||||
const_iterator begin() const noexcept { return m_pData; }
|
||||
const_iterator end() const noexcept { return (m_pData + m_numElements); }
|
||||
const_iterator cbegin() const noexcept { return m_pData; }
|
||||
const_iterator cend() const noexcept { return (m_pData + m_numElements); }
|
||||
[[nodiscard]] bool empty() const noexcept { return IsEmpty(); }
|
||||
size_type size() const noexcept { return m_numElements; }
|
||||
///@}
|
||||
|
||||
/// Erases the element at the specified iterator.
|
||||
void Erase(Iter it);
|
||||
|
||||
/// Erases the element at the specified iterator.
|
||||
void Erase(iterator it);
|
||||
|
||||
/// Erases the element at the specified index.
|
||||
void Erase(uint32 index);
|
||||
|
||||
/// Erase the element at the specified iterator, and swap last element to that position.
|
||||
/// If the element to erase is the last element, erase directly and no swap operation.
|
||||
void EraseAndSwapLast(Iter it);
|
||||
|
||||
/// Erase the element at the specified iterator, and swap last element to that position.
|
||||
/// If the element to erase is the last element, erase directly and no swap operation.
|
||||
void EraseAndSwapLast(iterator it);
|
||||
|
||||
/// Erases the element at the specified index, and swap last element to that position.
|
||||
/// If the element to erase is the last element, erase directly and no swap operation.
|
||||
void EraseAndSwapLast(uint32 index);
|
||||
|
||||
private:
|
||||
// This is a POD-type that exactly fits one T value.
|
||||
typedef typename std::aligned_storage<sizeof(T), alignof(T)>::type ValueStorage;
|
||||
|
||||
ValueStorage m_data[defaultCapacity]; // The initial data buffer stored within the vector object.
|
||||
T* m_pData; // Pointer to the current data buffer.
|
||||
uint32 m_numElements; // Number of elements present.
|
||||
uint32 m_maxCapacity; // Maximum size it can hold.
|
||||
Allocator*const m_pAllocator; // Allocator for this Vector.
|
||||
|
||||
PAL_DISALLOW_COPY_AND_ASSIGN(Vector);
|
||||
|
||||
// Although this is a transgression of coding standards, it prevents VectorIterator requiring a public constructor;
|
||||
// constructing a 'bare' VectorIterator (i.e. without calling Vector::GetIterator) can never be a legal operation,
|
||||
// so this means that these two classes are much safer to use.
|
||||
friend class VectorIterator<T, defaultCapacity, Allocator>;
|
||||
};
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator>
|
||||
VectorIterator<T, defaultCapacity, Allocator>::VectorIterator(
|
||||
uint32 index,
|
||||
const Vector<T, defaultCapacity, Allocator>& srcVec)
|
||||
:
|
||||
m_curIndex(index),
|
||||
m_srcVector(srcVec)
|
||||
{
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator>
|
||||
Vector<T, defaultCapacity, Allocator>::Vector(
|
||||
Allocator*const pAllocator)
|
||||
:
|
||||
m_pData(reinterpret_cast<T*>(m_data)),
|
||||
m_numElements(0),
|
||||
m_maxCapacity(defaultCapacity),
|
||||
m_pAllocator(pAllocator)
|
||||
{
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator>
|
||||
Vector<T, defaultCapacity, Allocator>::~Vector()
|
||||
{
|
||||
// Explicitly destroy all non-trivial types.
|
||||
if (!std::is_trivial<T>::value)
|
||||
{
|
||||
for (uint32 idx = 0; idx < m_numElements; ++idx)
|
||||
{
|
||||
m_pData[idx].~T();
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have dynamically allocated memory.
|
||||
if (m_pData != reinterpret_cast<T*>(m_data))
|
||||
{
|
||||
// Free the memory that was allocated dynamically.
|
||||
PAL_FREE(m_pData, m_pAllocator);
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// Steals allocation from a dying vector, if data buffer uses storage from heap allocation.
|
||||
// Moves objects between local buffers of new and dying vectors (for non-trivial types) or
|
||||
// copies local buffer from a dying vector to a new vector (for trivial types),
|
||||
// if data buffer uses storage from local buffer.
|
||||
template<typename T, uint32 defaultCapacity, typename Allocator>
|
||||
Vector<T, defaultCapacity, Allocator>::Vector(
|
||||
Vector&& vector)
|
||||
:
|
||||
m_numElements(vector.m_numElements),
|
||||
m_maxCapacity(vector.m_maxCapacity),
|
||||
m_pAllocator(vector.m_pAllocator)
|
||||
{
|
||||
if (vector.m_pData == reinterpret_cast<T*>(vector.m_data)) // Local buffer
|
||||
{
|
||||
// Data buffer will be using storage from local buffer.
|
||||
m_pData = reinterpret_cast<T*>(m_data);
|
||||
|
||||
if (std::is_trivial<T>::value)
|
||||
{
|
||||
// Optimize trivial types by copying local buffer.
|
||||
std::memcpy(m_pData, vector.m_pData, sizeof(T) * m_numElements);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move objects from local buffer of a dying vector to local buffer of a new vector.
|
||||
for (uint32 idx = 0; idx < m_numElements; ++idx)
|
||||
{
|
||||
PAL_PLACEMENT_NEW(m_pData + idx) T(Move(vector.m_pData[idx]));
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Heap allocation
|
||||
{
|
||||
// Steal heap allocation from dying vector.
|
||||
m_pData = vector.m_pData;
|
||||
|
||||
// After the allocation has been stolen, dying vector is just an empty shell.
|
||||
vector.m_pData = nullptr;
|
||||
vector.m_numElements = 0;
|
||||
vector.m_maxCapacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // Util
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: fd5f7481a122f40f73d1f638e3b9b027
|
||||
- md5: 95d96350d29e5d7ee8249b13f8344bfa
|
||||
size: 16738
|
||||
hash: md5
|
||||
path: DriverUtilsService.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: e09dbb1896128ac2b2bcac2b35878a40
|
||||
- md5: 456e1346e62388d873836eee241c2ecc
|
||||
size: 9460
|
||||
hash: md5
|
||||
path: SettingsRpcService2.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 364bc94b5b81ef5bb337e6afb0060c55
|
||||
- md5: 26144175ebf644e9c406a84cac291898
|
||||
size: 13912
|
||||
hash: md5
|
||||
path: UberTraceService.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 56362998d9feb9b0ce6ccad8441bf1c8
|
||||
size: 820446
|
||||
- md5: 82c883995b5833b7c1e3456da645f1c7
|
||||
size: 976846
|
||||
hash: md5
|
||||
path: addrlib.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 35af646710d883bfe6184113cb88e96a
|
||||
- md5: b752c646510e1b854e86d2180ce91cbb
|
||||
size: 702568
|
||||
hash: md5
|
||||
path: amdrdf.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 06c7697ce380a8127e7478041aed7fc8
|
||||
- md5: 25f322e041c71e95504e49333ba711c4
|
||||
size: 27894
|
||||
hash: md5
|
||||
path: cwpack.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 7c6ba83c44ee8bd70397a1458dbea7e0
|
||||
- md5: 8638cb376e4098e11bbd3a96d9de126d
|
||||
size: 82210
|
||||
hash: md5
|
||||
path: ddCommon.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 32f4aa9943ab5fde0da6f09bcbacf9be
|
||||
- md5: 429ad9f4c0eb7a231c97fff83ed3aac9
|
||||
size: 72778
|
||||
hash: md5
|
||||
path: ddCore.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 09fc5ce2eb8653cbd8ddda5d983ce836
|
||||
size: 137794
|
||||
- md5: 1c256136b2c4b0ac352156910e159df9
|
||||
size: 138010
|
||||
hash: md5
|
||||
path: ddEventClient.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 2f5e7eb06485bebea0ec2779d8df9f97
|
||||
- md5: 1370a8b4f3697241d7dac7d43aa9dd79
|
||||
size: 46862
|
||||
hash: md5
|
||||
path: ddEventParser.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: bdb3738c5bbd4ac6abd3a805930b89fe
|
||||
- md5: b8622eb38d6c1468301489f98fef8e4d
|
||||
size: 30582
|
||||
hash: md5
|
||||
path: ddEventServer.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 43ea2bd7328593fab054754f9fd1a7c9
|
||||
- md5: 9bfec5d057726ec5d03213ede38ae4a2
|
||||
size: 35768
|
||||
hash: md5
|
||||
path: ddEventStreamer.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: d91f19ed479fd51b481f6b25566dfd31
|
||||
- md5: ce4b653d66b86c8f6f8e11bbfffea54f
|
||||
size: 13230
|
||||
hash: md5
|
||||
path: ddNet.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 5b37ae9cc29dfaba3cb0d08a30bd684a
|
||||
- md5: 20bba474c25d34bad7c675c0d774017c
|
||||
size: 23224
|
||||
hash: md5
|
||||
path: ddRpcClient.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: b3f63ef6d9a9d6bfb3e5934a9a34465e
|
||||
- md5: a0f3d781dc7358b33f693ad6f19284ab
|
||||
size: 179024
|
||||
hash: md5
|
||||
path: ddRpcServer.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: db87375bafb0d667ac054dbf7dc0dc36
|
||||
- md5: 78c64bc9c07804300f848425908f3443
|
||||
size: 16268
|
||||
hash: md5
|
||||
path: ddRpcShared.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: f88897c7d989d95f0352cf6e1a21df99
|
||||
- md5: 4f16385611ba26f28374e11d9421269d
|
||||
size: 106228
|
||||
hash: md5
|
||||
path: ddSocket.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 4d64cf4c3b034f09a8a3abd1b7e657b4
|
||||
- md5: c4bed6f36417e25fdb069616b2ef7edd
|
||||
size: 35902
|
||||
hash: md5
|
||||
path: ddYaml.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 2394b7141b71f0b738dd3ad024dcbfc0
|
||||
size: 661222
|
||||
- md5: cb9ece645ccf22601a53d532614422c8
|
||||
size: 663402
|
||||
hash: md5
|
||||
path: dd_common.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 2b9f0af04b216527b49338cc1b8fa1a5
|
||||
- md5: 5d4c03c414cd2661e27a9d661b2aaaa0
|
||||
size: 264022
|
||||
hash: md5
|
||||
path: dd_libyaml.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: d9a1105679db9411bf2365aae2b6d2a5
|
||||
size: 212936
|
||||
- md5: 5de26d6d7739cdad888688eb4937fcb1
|
||||
size: 213370
|
||||
hash: md5
|
||||
path: dd_settings.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 18e7d04c4ecc9fb872de2e0ac9dffd61
|
||||
size: 2700190
|
||||
- md5: 25a99e1ae065b735a3644ece1fc9c0c4
|
||||
size: 2701484
|
||||
hash: md5
|
||||
path: devdriver.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 64dbdb1c2d7c68e7ae3083ea35878a83
|
||||
- md5: 53cad99c6cd2848fb4e283db250e1148
|
||||
size: 28682
|
||||
hash: md5
|
||||
path: metrohash.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 43f91cf1e53eef1411a6e4a40776cd79
|
||||
- md5: 8c5d464f8f60a4285770e7994a74ba70
|
||||
size: 218874
|
||||
hash: md5
|
||||
path: mpack.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 852e161ac4115309a2591db0b80f13dd
|
||||
size: 24025742
|
||||
- md5: 5800da924b60abf1b7ca111ac2fb1aae
|
||||
size: 20625154
|
||||
hash: md5
|
||||
path: pal.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: a929ad3103021925d382e419b0e5343d
|
||||
size: 433780
|
||||
- md5: 59a339d6330fa360eb7452a15851d2d4
|
||||
size: 440980
|
||||
hash: md5
|
||||
path: palCompilerDeps.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 3cca5923fa12cf564360058254c2c6db
|
||||
size: 799750
|
||||
- md5: b35b947076fbb8821eab7252511049e2
|
||||
size: 831218
|
||||
hash: md5
|
||||
path: palUtil.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 36731971681f4a89f4e89b5ad44473ac
|
||||
- md5: d5ebea86c9821bd43006bea5e8fd1ce3
|
||||
size: 291664
|
||||
hash: md5
|
||||
path: pal_lz4.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 1ad5de7ebbb13b41f7d7dc0367d7d1d8
|
||||
- md5: 8551962e3709c5da05736df2959b074f
|
||||
size: 3460
|
||||
hash: md5
|
||||
path: pal_uuid.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: b2a1cd0f59d07aaa0cf21afa9235dbda
|
||||
- md5: cb6d2ce450c3869437fc090fa06eb1c5
|
||||
size: 25990
|
||||
hash: md5
|
||||
path: stb_sprintf.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 02784ea9d25a9a9c94c20acca001456c
|
||||
- md5: 709400309f890ea3e16cf2c816dead42
|
||||
size: 215198
|
||||
hash: md5
|
||||
path: vam.lib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: 6a1ac31db298434da1573cda69d9e4d3
|
||||
- md5: 6af43c37bb2018208ba884ca155a3cf6
|
||||
size: 1356642
|
||||
hash: md5
|
||||
path: zstd.lib
|
||||
|
||||
+269
-269
@@ -1,269 +1,269 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ddLegacyDefs.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Macros for conditional language support.
|
||||
#ifdef _MSVC_LANG
|
||||
#define DD_CPLUSPLUS _MSVC_LANG
|
||||
#else
|
||||
#define DD_CPLUSPLUS __cplusplus
|
||||
#endif
|
||||
// Denotes versions of the C++ standard from __cplusplus.
|
||||
#define CPP98 (199711L)
|
||||
#define CPP11 (201103L)
|
||||
#define CPP14 (201402L)
|
||||
#define CPP17 (201703L)
|
||||
#define CPP20 (202002L)
|
||||
#define DD_CPLUSPLUS_SUPPORTS(x) (DD_CPLUSPLUS >= (x))
|
||||
|
||||
static_assert(DD_CPLUSPLUS_SUPPORTS(CPP11), "C++11 is required to build devdriver.");
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define DD_ALIGNAS(x)__declspec(align(x))
|
||||
#if _MSC_VER < 1900
|
||||
#define DD_STATIC_CONST static const
|
||||
#else
|
||||
#define DD_STATIC_CONST static constexpr
|
||||
#endif
|
||||
#ifndef va_copy
|
||||
#define va_copy(d,s) ((d) = (s))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(DD_STATIC_CONST)
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
#define DD_STATIC_CONST static constexpr
|
||||
#else
|
||||
#define DD_STATIC_CONST static const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if DD_CPLUSPLUS_SUPPORTS(CPP14)
|
||||
#define DD_CPP14_CONSTEXPR_FN constexpr
|
||||
#define DD_CPP14_STATIC_ASSERT(a, b) static_assert(a, b)
|
||||
#else
|
||||
#define DD_CPP14_CONSTEXPR_FN inline
|
||||
#define DD_CPP14_STATIC_ASSERT(a, b)
|
||||
#endif
|
||||
|
||||
#if !defined(DD_ALIGNAS)
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
#define DD_ALIGNAS(x) alignas(x)
|
||||
#else
|
||||
static_assert(false, "Error: unsupported compiler detected. Support is required to build.");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// Remove the __FILE__ macro for release builds
|
||||
#ifndef DD_FILE
|
||||
#ifdef NDEBUG
|
||||
#define DD_FILE ""
|
||||
#else
|
||||
#define DD_FILE __FILE__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Creates a structure with the specified name and alignment.
|
||||
#define DD_ALIGNED_STRUCT(name, alignment) struct DD_ALIGNAS(alignment) name
|
||||
|
||||
// Creates a structure with the specified alignment, and mark it as final to ensure it cannot be used as a parent class
|
||||
#define DD_NETWORK_STRUCT(name, alignment) struct DD_ALIGNAS(alignment) name final
|
||||
|
||||
#define DD_CHECK_SIZE(x, size) static_assert(sizeof(x) == size_t(size), "sizeof(" # x ") should be " # size " bytes but has changed recently")
|
||||
|
||||
#define DD_UNUSED(x) (static_cast<void>(x))
|
||||
|
||||
#define _DD_STRINGIFY(str) #str
|
||||
#define DD_STRINGIFY(x) _DD_STRINGIFY(x)
|
||||
|
||||
#if DD_CPLUSPLUS_SUPPORTS(CPP17)
|
||||
// Require that a function's return value, or an entire type, be used.
|
||||
#define DD_NODISCARD [[nodiscard]]
|
||||
|
||||
// Do not warn about switch statement cases falling through. Place this macro as the case body, e.g.
|
||||
// switch (x)
|
||||
// {
|
||||
// case 0: DD_FALLTHROUGH();
|
||||
// case 1: DD_FALLTHROUGH();
|
||||
// case 2:
|
||||
// printf("0, 1, or 2");
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
#define DD_FALLTHROUGH() [[fallthrough]]
|
||||
#else
|
||||
// Require that a function's return value, or an entire type, be used.
|
||||
// This option is aggressive enough that we do not enable it when C++17 is not enabled
|
||||
#define DD_NODISCARD
|
||||
|
||||
// Do not warn about switch statement cases falling through. Place this macro as the case body, e.g.
|
||||
// switch (x)
|
||||
// {
|
||||
// case 0: DD_FALLTHROUGH();
|
||||
// case 1: DD_FALLTHROUGH();
|
||||
// case 2:
|
||||
// printf("0, 1, or 2");
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
#if defined(__clang__)
|
||||
#define DD_FALLTHROUGH() [[clang::fallthrough]]
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ >= 7
|
||||
// gnu::fallthrough isn't supported until GCC 7+
|
||||
#define DD_FALLTHROUGH() [[gnu::fallthrough]]
|
||||
#else
|
||||
// Not supported on older versions of GCC
|
||||
#define DD_FALLTHROUGH()
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
// Not supported on MSVC - who doesn't warn about this issue in the first place.
|
||||
#define DD_FALLTHROUGH()
|
||||
#else
|
||||
// We don't know what compiler this is, so just no-op the macro.
|
||||
#define DD_FALLTHROUGH()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Include in the private section of a class declaration in order to disallow use of the copy and assignment operator
|
||||
#define DD_DISALLOW_COPY_AND_ASSIGN(_typename) \
|
||||
_typename(const _typename&); \
|
||||
_typename& operator =(const _typename&);
|
||||
|
||||
// Include in the private section of a class declaration in order to disallow use of the default constructor
|
||||
#define DD_DISALLOW_DEFAULT_CTOR(_typename) \
|
||||
_typename();
|
||||
|
||||
// Detect the CPU architecture for the target.
|
||||
// These are often evaluated during the preprocessor stage, so it's important that we don't rely on things like sizeof.
|
||||
#if UINTPTR_MAX == 0xFFFFFFFF
|
||||
#define DEVDRIVER_ARCHITECTURE_BITS 32
|
||||
#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF
|
||||
#define DEVDRIVER_ARCHITECTURE_BITS 64
|
||||
#else
|
||||
static_assert(false, "Unknown or unsupported target architecture.");
|
||||
#endif
|
||||
static_assert(DEVDRIVER_ARCHITECTURE_BITS == (8 * sizeof(void*)), // Assume 8-bits-per-byte.
|
||||
"DEVDRIVER_ARCHITECTURE_BITS does not match sizeof(void*).");
|
||||
|
||||
// Add a detailed function name macro
|
||||
// These vary across platforms, so we'll just pick the first one that's defined
|
||||
#if defined(__FUNCSIG__)
|
||||
#define DD_FUNCTION_NAME __FUNCSIG__
|
||||
#elif defined(__PRETTY_FUNCTION__)
|
||||
#define DD_FUNCTION_NAME __PRETTY_FUNCTION__
|
||||
#else
|
||||
#define DD_FUNCTION_NAME __FUNCTION__
|
||||
#endif
|
||||
|
||||
// Common Typedefs
|
||||
// These types are shared between all platforms,
|
||||
// and need to be defined before including a specific platform header.
|
||||
|
||||
namespace DevDriver
|
||||
{
|
||||
|
||||
typedef int8_t int8; ///< 8-bit integer.
|
||||
typedef int16_t int16; ///< 16-bit integer.
|
||||
typedef int32_t int32; ///< 32-bit integer.
|
||||
typedef int64_t int64; ///< 64-bit integer.
|
||||
typedef uint8_t uint8; ///< Unsigned 8-bit integer.
|
||||
typedef uint16_t uint16; ///< Unsigned 16-bit integer.
|
||||
typedef uint32_t uint32; ///< Unsigned 32-bit integer.
|
||||
typedef uint64_t uint64; ///< Unsigned 64-bit integer.
|
||||
|
||||
typedef uint32_t ProcessId;
|
||||
typedef uint32_t Size;
|
||||
typedef uint64_t Handle;
|
||||
|
||||
DD_STATIC_CONST Handle kNullPtr = 0;
|
||||
DD_STATIC_CONST Handle kInvalidHandle = 0;
|
||||
|
||||
////////////////////////////
|
||||
// Common result codes
|
||||
enum struct Result : uint32
|
||||
{
|
||||
//// Generic Result Code ////
|
||||
Success = 0,
|
||||
Error = 1,
|
||||
NotReady = 2,
|
||||
VersionMismatch = 3,
|
||||
Unavailable = 4,
|
||||
Rejected = 5,
|
||||
EndOfStream = 6,
|
||||
Aborted = 7,
|
||||
InsufficientMemory = 8,
|
||||
InvalidParameter = 9,
|
||||
InvalidClientId = 10,
|
||||
ConnectionExists = 11,
|
||||
FileNotFound = 12,
|
||||
FunctionNotFound = 13,
|
||||
InterfaceNotFound = 14,
|
||||
EntryExists = 15,
|
||||
FileAccessError = 16,
|
||||
FileIoError = 17,
|
||||
LimitReached = 18,
|
||||
MemoryOverLimit = 19,
|
||||
|
||||
//// URI PROTOCOL ////
|
||||
UriServiceRegistrationError = 1000,
|
||||
UriStringParseError = 1001,
|
||||
UriInvalidParameters = 1002,
|
||||
UriInvalidPostDataBlock = 1003,
|
||||
UriInvalidPostDataSize = 1004,
|
||||
UriFailedToAcquirePostBlock = 1005,
|
||||
UriFailedToOpenResponseBlock = 1006,
|
||||
UriRequestFailed = 1007,
|
||||
UriPendingRequestError = 1008,
|
||||
UriInvalidChar = 1009,
|
||||
UriInvalidJson = 1010,
|
||||
|
||||
//// Settings URI Service ////
|
||||
SettingsUriInvalidComponent = 2000,
|
||||
SettingsUriInvalidSettingName = 2001,
|
||||
SettingsUriInvalidSettingValue = 2002,
|
||||
SettingsUriInvalidSettingValueSize = 2003,
|
||||
|
||||
//// Info URI Service ////
|
||||
InfoUriSourceNameInvalid = 3000,
|
||||
InfoUriSourceCallbackInvalid = 3001,
|
||||
InfoUriSourceAlreadyRegistered = 3002,
|
||||
InfoUriSourceWriteFailed = 3003,
|
||||
|
||||
//// Settings Service ////
|
||||
SettingsInvalidComponent = 4000,
|
||||
SettingsInvalidSettingName = 4001,
|
||||
SettingsInvalidSettingValue = 4002,
|
||||
SettingsInsufficientValueSize = 4003,
|
||||
SettingsInvalidSettingValueSize = 4004,
|
||||
};
|
||||
|
||||
} // namespace DevDriver
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ddLegacyDefs.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Macros for conditional language support.
|
||||
#ifdef _MSVC_LANG
|
||||
#define DD_CPLUSPLUS _MSVC_LANG
|
||||
#else
|
||||
#define DD_CPLUSPLUS __cplusplus
|
||||
#endif
|
||||
// Denotes versions of the C++ standard from __cplusplus.
|
||||
#define CPP98 (199711L)
|
||||
#define CPP11 (201103L)
|
||||
#define CPP14 (201402L)
|
||||
#define CPP17 (201703L)
|
||||
#define CPP20 (202002L)
|
||||
#define DD_CPLUSPLUS_SUPPORTS(x) (DD_CPLUSPLUS >= (x))
|
||||
|
||||
static_assert(DD_CPLUSPLUS_SUPPORTS(CPP11), "C++11 is required to build devdriver.");
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define DD_ALIGNAS(x)__declspec(align(x))
|
||||
#if _MSC_VER < 1900
|
||||
#define DD_STATIC_CONST static const
|
||||
#else
|
||||
#define DD_STATIC_CONST static constexpr
|
||||
#endif
|
||||
#ifndef va_copy
|
||||
#define va_copy(d,s) ((d) = (s))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(DD_STATIC_CONST)
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
#define DD_STATIC_CONST static constexpr
|
||||
#else
|
||||
#define DD_STATIC_CONST static const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if DD_CPLUSPLUS_SUPPORTS(CPP14)
|
||||
#define DD_CPP14_CONSTEXPR_FN constexpr
|
||||
#define DD_CPP14_STATIC_ASSERT(a, b) static_assert(a, b)
|
||||
#else
|
||||
#define DD_CPP14_CONSTEXPR_FN inline
|
||||
#define DD_CPP14_STATIC_ASSERT(a, b)
|
||||
#endif
|
||||
|
||||
#if !defined(DD_ALIGNAS)
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
#define DD_ALIGNAS(x) alignas(x)
|
||||
#else
|
||||
static_assert(false, "Error: unsupported compiler detected. Support is required to build.");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// Remove the __FILE__ macro for release builds
|
||||
#ifndef DD_FILE
|
||||
#ifdef NDEBUG
|
||||
#define DD_FILE ""
|
||||
#else
|
||||
#define DD_FILE __FILE__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Creates a structure with the specified name and alignment.
|
||||
#define DD_ALIGNED_STRUCT(name, alignment) struct DD_ALIGNAS(alignment) name
|
||||
|
||||
// Creates a structure with the specified alignment, and mark it as final to ensure it cannot be used as a parent class
|
||||
#define DD_NETWORK_STRUCT(name, alignment) struct DD_ALIGNAS(alignment) name final
|
||||
|
||||
#define DD_CHECK_SIZE(x, size) static_assert(sizeof(x) == size_t(size), "sizeof(" # x ") should be " # size " bytes but has changed recently")
|
||||
|
||||
#define DD_UNUSED(x) (static_cast<void>(x))
|
||||
|
||||
#define _DD_STRINGIFY(str) #str
|
||||
#define DD_STRINGIFY(x) _DD_STRINGIFY(x)
|
||||
|
||||
#if DD_CPLUSPLUS_SUPPORTS(CPP17)
|
||||
// Require that a function's return value, or an entire type, be used.
|
||||
#define DD_NODISCARD [[nodiscard]]
|
||||
|
||||
// Do not warn about switch statement cases falling through. Place this macro as the case body, e.g.
|
||||
// switch (x)
|
||||
// {
|
||||
// case 0: DD_FALLTHROUGH();
|
||||
// case 1: DD_FALLTHROUGH();
|
||||
// case 2:
|
||||
// printf("0, 1, or 2");
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
#define DD_FALLTHROUGH() [[fallthrough]]
|
||||
#else
|
||||
// Require that a function's return value, or an entire type, be used.
|
||||
// This option is aggressive enough that we do not enable it when C++17 is not enabled
|
||||
#define DD_NODISCARD
|
||||
|
||||
// Do not warn about switch statement cases falling through. Place this macro as the case body, e.g.
|
||||
// switch (x)
|
||||
// {
|
||||
// case 0: DD_FALLTHROUGH();
|
||||
// case 1: DD_FALLTHROUGH();
|
||||
// case 2:
|
||||
// printf("0, 1, or 2");
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
#if defined(__clang__)
|
||||
#define DD_FALLTHROUGH() [[clang::fallthrough]]
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ >= 7
|
||||
// gnu::fallthrough isn't supported until GCC 7+
|
||||
#define DD_FALLTHROUGH() [[gnu::fallthrough]]
|
||||
#else
|
||||
// Not supported on older versions of GCC
|
||||
#define DD_FALLTHROUGH()
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
// Not supported on MSVC - who doesn't warn about this issue in the first place.
|
||||
#define DD_FALLTHROUGH()
|
||||
#else
|
||||
// We don't know what compiler this is, so just no-op the macro.
|
||||
#define DD_FALLTHROUGH()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Include in the private section of a class declaration in order to disallow use of the copy and assignment operator
|
||||
#define DD_DISALLOW_COPY_AND_ASSIGN(_typename) \
|
||||
_typename(const _typename&); \
|
||||
_typename& operator =(const _typename&);
|
||||
|
||||
// Include in the private section of a class declaration in order to disallow use of the default constructor
|
||||
#define DD_DISALLOW_DEFAULT_CTOR(_typename) \
|
||||
_typename();
|
||||
|
||||
// Detect the CPU architecture for the target.
|
||||
// These are often evaluated during the preprocessor stage, so it's important that we don't rely on things like sizeof.
|
||||
#if UINTPTR_MAX == 0xFFFFFFFF
|
||||
#define DEVDRIVER_ARCHITECTURE_BITS 32
|
||||
#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF
|
||||
#define DEVDRIVER_ARCHITECTURE_BITS 64
|
||||
#else
|
||||
static_assert(false, "Unknown or unsupported target architecture.");
|
||||
#endif
|
||||
static_assert(DEVDRIVER_ARCHITECTURE_BITS == (8 * sizeof(void*)), // Assume 8-bits-per-byte.
|
||||
"DEVDRIVER_ARCHITECTURE_BITS does not match sizeof(void*).");
|
||||
|
||||
// Add a detailed function name macro
|
||||
// These vary across platforms, so we'll just pick the first one that's defined
|
||||
#if defined(__FUNCSIG__)
|
||||
#define DD_FUNCTION_NAME __FUNCSIG__
|
||||
#elif defined(__PRETTY_FUNCTION__)
|
||||
#define DD_FUNCTION_NAME __PRETTY_FUNCTION__
|
||||
#else
|
||||
#define DD_FUNCTION_NAME __FUNCTION__
|
||||
#endif
|
||||
|
||||
// Common Typedefs
|
||||
// These types are shared between all platforms,
|
||||
// and need to be defined before including a specific platform header.
|
||||
|
||||
namespace DevDriver
|
||||
{
|
||||
|
||||
typedef int8_t int8; ///< 8-bit integer.
|
||||
typedef int16_t int16; ///< 16-bit integer.
|
||||
typedef int32_t int32; ///< 32-bit integer.
|
||||
typedef int64_t int64; ///< 64-bit integer.
|
||||
typedef uint8_t uint8; ///< Unsigned 8-bit integer.
|
||||
typedef uint16_t uint16; ///< Unsigned 16-bit integer.
|
||||
typedef uint32_t uint32; ///< Unsigned 32-bit integer.
|
||||
typedef uint64_t uint64; ///< Unsigned 64-bit integer.
|
||||
|
||||
typedef uint32_t ProcessId;
|
||||
typedef uint32_t Size;
|
||||
typedef uint64_t Handle;
|
||||
|
||||
DD_STATIC_CONST Handle kNullPtr = 0;
|
||||
DD_STATIC_CONST Handle kInvalidHandle = 0;
|
||||
|
||||
////////////////////////////
|
||||
// Common result codes
|
||||
enum struct Result : uint32
|
||||
{
|
||||
//// Generic Result Code ////
|
||||
Success = 0,
|
||||
Error = 1,
|
||||
NotReady = 2,
|
||||
VersionMismatch = 3,
|
||||
Unavailable = 4,
|
||||
Rejected = 5,
|
||||
EndOfStream = 6,
|
||||
Aborted = 7,
|
||||
InsufficientMemory = 8,
|
||||
InvalidParameter = 9,
|
||||
InvalidClientId = 10,
|
||||
ConnectionExists = 11,
|
||||
FileNotFound = 12,
|
||||
FunctionNotFound = 13,
|
||||
InterfaceNotFound = 14,
|
||||
EntryExists = 15,
|
||||
FileAccessError = 16,
|
||||
FileIoError = 17,
|
||||
LimitReached = 18,
|
||||
MemoryOverLimit = 19,
|
||||
|
||||
//// URI PROTOCOL ////
|
||||
UriServiceRegistrationError = 1000,
|
||||
UriStringParseError = 1001,
|
||||
UriInvalidParameters = 1002,
|
||||
UriInvalidPostDataBlock = 1003,
|
||||
UriInvalidPostDataSize = 1004,
|
||||
UriFailedToAcquirePostBlock = 1005,
|
||||
UriFailedToOpenResponseBlock = 1006,
|
||||
UriRequestFailed = 1007,
|
||||
UriPendingRequestError = 1008,
|
||||
UriInvalidChar = 1009,
|
||||
UriInvalidJson = 1010,
|
||||
|
||||
//// Settings URI Service ////
|
||||
SettingsUriInvalidComponent = 2000,
|
||||
SettingsUriInvalidSettingName = 2001,
|
||||
SettingsUriInvalidSettingValue = 2002,
|
||||
SettingsUriInvalidSettingValueSize = 2003,
|
||||
|
||||
//// Info URI Service ////
|
||||
InfoUriSourceNameInvalid = 3000,
|
||||
InfoUriSourceCallbackInvalid = 3001,
|
||||
InfoUriSourceAlreadyRegistered = 3002,
|
||||
InfoUriSourceWriteFailed = 3003,
|
||||
|
||||
//// Settings Service ////
|
||||
SettingsInvalidComponent = 4000,
|
||||
SettingsInvalidSettingName = 4001,
|
||||
SettingsInvalidSettingValue = 4002,
|
||||
SettingsInsufficientValueSize = 4003,
|
||||
SettingsInvalidSettingValueSize = 4004,
|
||||
};
|
||||
|
||||
} // namespace DevDriver
|
||||
|
||||
+824
-824
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
+378
-378
@@ -1,378 +1,378 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
namespace DevDriver
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
/// Templated LockGuard class. Works with any type that implements Lock() and Unlock()
|
||||
template <typename T>
|
||||
class LockGuard
|
||||
{
|
||||
public:
|
||||
explicit LockGuard(T &lock) : m_lock(lock) { lock.Lock(); }
|
||||
~LockGuard() { m_lock.Unlock(); }
|
||||
private:
|
||||
T &m_lock;
|
||||
};
|
||||
|
||||
/// Computes the base-2 logarithm of an unsigned 64-bit integer.
|
||||
///
|
||||
/// If the given integer is not a power of 2, this function will not provide an exact answer.
|
||||
///
|
||||
/// @returns log_2(u)
|
||||
template<typename T>
|
||||
inline uint32 Log2(T u) ///< Value to compute the logarithm of.
|
||||
{
|
||||
uint32 logValue = 0;
|
||||
|
||||
while (u > 1)
|
||||
{
|
||||
++logValue;
|
||||
u >>= 1;
|
||||
}
|
||||
return logValue;
|
||||
}
|
||||
|
||||
/// Computes the base-2 logarithm of an unsigned 64-bit integer.
|
||||
///
|
||||
/// If the given integer is not a power of 2, this function will not provide an exact answer.
|
||||
///
|
||||
/// @returns log_2(u)
|
||||
template<typename T>
|
||||
inline constexpr uint32 _ConstLog2(T u, uint32 logValue) ///< Value to compute the logarithm of.
|
||||
{
|
||||
return (u > 1) ? _ConstLog2(u >> 1, logValue + 1) : logValue;
|
||||
}
|
||||
|
||||
/// Computes the base-2 logarithm of an unsigned 64-bit integer.
|
||||
///
|
||||
/// If the given integer is not a power of 2, this function will not provide an exact answer.
|
||||
///
|
||||
/// @returns log_2(u)
|
||||
template<typename T>
|
||||
inline constexpr uint32 ConstLog2(T u) ///< Value to compute the logarithm of.
|
||||
{
|
||||
return _ConstLog2(u, 0);
|
||||
}
|
||||
|
||||
static_assert(ConstLog2(1) == 0, "ConstLog2 failure");
|
||||
static_assert(ConstLog2(2) == 1, "ConstLog2 failure");
|
||||
static_assert(ConstLog2(128) == 7, "ConstLog2 failure");
|
||||
static_assert(ConstLog2(255) == 7, "ConstLog2 failure");
|
||||
|
||||
/// Computes 2 ^ value provided
|
||||
///
|
||||
/// @returns 2 ^ (u)
|
||||
template<typename T>
|
||||
inline constexpr T Pow2(T u)
|
||||
{
|
||||
return ((T)1 << u);
|
||||
}
|
||||
|
||||
static_assert(Pow2(0) == 1, "Pow2 failure");
|
||||
static_assert(Pow2(1) == 2, "Pow2 failure");
|
||||
static_assert(Pow2(7) == 128, "Pow2 failure");
|
||||
|
||||
/// Determines if a value is a power of two.
|
||||
///
|
||||
/// @returns True if it is a power of two, false otherwise.
|
||||
inline constexpr bool IsPowerOfTwo(uint64 value)
|
||||
{
|
||||
return (value == 0) ? false : ((value & (value - 1)) == 0);
|
||||
}
|
||||
|
||||
/// Rounds the specified uint 'value' up to the nearest value meeting the specified 'alignment'. Only power of 2
|
||||
/// alignments are supported by this function.
|
||||
///
|
||||
/// returns Aligned value.
|
||||
template<typename T>
|
||||
inline constexpr T Pow2Align(
|
||||
T value, ///< Value to align.
|
||||
uint64 alignment) ///< Desired alignment (must be a power of 2).
|
||||
{
|
||||
return ((value + static_cast<T>(alignment) - 1) & ~(static_cast<T>(alignment) - 1));
|
||||
}
|
||||
|
||||
/// Rounds the specified uint 'value' up to the nearest power of 2
|
||||
///
|
||||
/// @returns Power of 2 padded value.
|
||||
template<typename T>
|
||||
inline T Pow2Pad(T value) ///< Value to pad.
|
||||
{
|
||||
T ret = 1;
|
||||
if (IsPowerOfTwo(value))
|
||||
{
|
||||
ret = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (ret < value)
|
||||
{
|
||||
ret <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Rounds the specified uint 'value' up to the nearest power of 2. Constexpr varient.
|
||||
///
|
||||
/// @returns Power of 2 padded value.
|
||||
template<typename T>
|
||||
inline constexpr T _ConstPow2Pad(T value, T padded) ///< Value to pad.
|
||||
{
|
||||
return (padded < value) ? _ConstPow2Pad(value, padded << 1) : padded;
|
||||
}
|
||||
|
||||
/// Rounds the specified uint 'value' up to the nearest power of 2. Constexpr varient.
|
||||
///
|
||||
/// @returns Power of 2 padded value.
|
||||
template<typename T>
|
||||
inline constexpr T ConstPow2Pad(T value) ///< Value to pad.
|
||||
{
|
||||
return (IsPowerOfTwo(value)) ? value : _ConstPow2Pad(value, (T)1);
|
||||
}
|
||||
|
||||
static_assert(ConstPow2Pad(512) == 512, "ConstPow2Pad failure");
|
||||
static_assert(ConstPow2Pad(511) == 512, "ConstPow2Pad failure");
|
||||
static_assert(ConstPow2Pad(257) == 512, "ConstPow2Pad failure");
|
||||
|
||||
/// Finds the smallest of two values
|
||||
///
|
||||
/// @returns a if a < b, otherwise b.
|
||||
template <typename T>
|
||||
inline constexpr T Min(const T &a, const T &b)
|
||||
{
|
||||
return ((a < b) ? a : b);
|
||||
}
|
||||
|
||||
/// Finds the larger of two values
|
||||
///
|
||||
/// @returns a if a > b, otherwise b.
|
||||
template <typename T>
|
||||
inline constexpr T Max(const T &a, const T &b)
|
||||
{
|
||||
return ((a > b) ? a : b);
|
||||
}
|
||||
|
||||
// Given a type T, set Type equal to T
|
||||
template <typename T>
|
||||
struct RemoveRef
|
||||
{
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
// Given a type T&, set Type equal to T
|
||||
template <typename T>
|
||||
struct RemoveRef<T &>
|
||||
{
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
// Given a type T&&, set Type equal to T
|
||||
template <typename T>
|
||||
struct RemoveRef<T &&>
|
||||
{
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
// std::move equivalent
|
||||
template <typename T>
|
||||
inline typename RemoveRef<T>::Type&& Move(T&& obj)
|
||||
{
|
||||
return static_cast<typename RemoveRef<T>::Type&&>(obj);
|
||||
}
|
||||
|
||||
// std::forward equivalent
|
||||
template <typename T>
|
||||
inline T&& Forward(typename RemoveRef<T>::Type&& args)
|
||||
{
|
||||
return static_cast<T&&>(args);
|
||||
}
|
||||
|
||||
// std::forward equivalent
|
||||
template <typename T>
|
||||
inline T&& Forward(typename RemoveRef<T>::Type& args)
|
||||
{
|
||||
return static_cast<T&&>(args);
|
||||
}
|
||||
|
||||
// Returns the contents of Value in a new variable, and assign newValue into the memory occupied by value.
|
||||
template <typename T, typename U = T>
|
||||
inline T Exchange(T& value, U&& newValue)
|
||||
{
|
||||
T oldValue = Move(value);
|
||||
value = Forward<U>(newValue);
|
||||
return (oldValue);
|
||||
}
|
||||
|
||||
// Convenience structure that defined Value as either true or false, and Type as either TrueType or FalseType
|
||||
template <bool value>
|
||||
struct BoolType
|
||||
{
|
||||
static const bool Value = value;
|
||||
using Type = BoolType<value>;
|
||||
};
|
||||
|
||||
using FalseType = BoolType<false>;
|
||||
using TrueType = BoolType<true>;
|
||||
|
||||
// Struct whose ::Type member is undefined if the first condition is not true
|
||||
template<bool Enable,
|
||||
class Type = void>
|
||||
struct EnableIf
|
||||
{
|
||||
};
|
||||
|
||||
// Struct whose ::Type member is equal to T if the first condition is true.
|
||||
template<class T>
|
||||
struct EnableIf<true, T>
|
||||
{
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct IsPointer : FalseType
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct IsPointer<T*> : TrueType
|
||||
{
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// If we are building with MSVC we want to use the compiler intrinsics here. This is primarily because building with
|
||||
// the /kernel precludes the use of the C++ type traits library. For all other compilers we simply implement this
|
||||
// using the standard C++ library.
|
||||
|
||||
// Struct whose ::Value member is equal to true if you can cast from T to U, and false otherwise.
|
||||
template <class T, class U>
|
||||
struct IsConvertible : BoolType<__is_convertible_to(T, U)>
|
||||
{
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if you can construct an object of type T using the arguments
|
||||
// provided.
|
||||
template<typename T, typename... Args>
|
||||
struct IsConstructible : BoolType<__is_constructible(T, Args...)>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is an abstract class, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsAbstract : BoolType<__is_abstract(T)>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is an abstract class, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsPod : BoolType<__is_pod(T)>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is has a standard layout, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsStandardLayout : BoolType<__is_standard_layout(T)>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is trivially destructable, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsTriviallyDestructible : BoolType<__is_trivially_destructible(T)>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is an enumeration type, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsEnum : BoolType<__is_enum(T)>
|
||||
{
|
||||
|
||||
};
|
||||
#else
|
||||
// Struct whose ::Value member is equal to true if you can cast from T to U, and false otherwise.
|
||||
template <class T, class U>
|
||||
struct IsConvertible : BoolType<std::is_convertible<T, U>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if you can construct an object of type T using the arguments
|
||||
// provided.
|
||||
template<typename T, typename... Args>
|
||||
struct IsConstructible : BoolType<std::is_constructible<T, Args...>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is an abstract class, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsAbstract : BoolType<std::is_abstract<T>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is an abstract class, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsPod : BoolType<std::is_trivial<T>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is has a standard layout, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsStandardLayout : BoolType<std::is_standard_layout<T>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is trivially destructable, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsTriviallyDestructible : BoolType<std::is_trivially_destructible<T>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is an enumeration type, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsEnum : BoolType<std::is_enum<T>::value>
|
||||
{
|
||||
|
||||
};
|
||||
#endif
|
||||
}
|
||||
} // DevDriver
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
namespace DevDriver
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
/// Templated LockGuard class. Works with any type that implements Lock() and Unlock()
|
||||
template <typename T>
|
||||
class LockGuard
|
||||
{
|
||||
public:
|
||||
explicit LockGuard(T &lock) : m_lock(lock) { lock.Lock(); }
|
||||
~LockGuard() { m_lock.Unlock(); }
|
||||
private:
|
||||
T &m_lock;
|
||||
};
|
||||
|
||||
/// Computes the base-2 logarithm of an unsigned 64-bit integer.
|
||||
///
|
||||
/// If the given integer is not a power of 2, this function will not provide an exact answer.
|
||||
///
|
||||
/// @returns log_2(u)
|
||||
template<typename T>
|
||||
inline uint32 Log2(T u) ///< Value to compute the logarithm of.
|
||||
{
|
||||
uint32 logValue = 0;
|
||||
|
||||
while (u > 1)
|
||||
{
|
||||
++logValue;
|
||||
u >>= 1;
|
||||
}
|
||||
return logValue;
|
||||
}
|
||||
|
||||
/// Computes the base-2 logarithm of an unsigned 64-bit integer.
|
||||
///
|
||||
/// If the given integer is not a power of 2, this function will not provide an exact answer.
|
||||
///
|
||||
/// @returns log_2(u)
|
||||
template<typename T>
|
||||
inline constexpr uint32 _ConstLog2(T u, uint32 logValue) ///< Value to compute the logarithm of.
|
||||
{
|
||||
return (u > 1) ? _ConstLog2(u >> 1, logValue + 1) : logValue;
|
||||
}
|
||||
|
||||
/// Computes the base-2 logarithm of an unsigned 64-bit integer.
|
||||
///
|
||||
/// If the given integer is not a power of 2, this function will not provide an exact answer.
|
||||
///
|
||||
/// @returns log_2(u)
|
||||
template<typename T>
|
||||
inline constexpr uint32 ConstLog2(T u) ///< Value to compute the logarithm of.
|
||||
{
|
||||
return _ConstLog2(u, 0);
|
||||
}
|
||||
|
||||
static_assert(ConstLog2(1) == 0, "ConstLog2 failure");
|
||||
static_assert(ConstLog2(2) == 1, "ConstLog2 failure");
|
||||
static_assert(ConstLog2(128) == 7, "ConstLog2 failure");
|
||||
static_assert(ConstLog2(255) == 7, "ConstLog2 failure");
|
||||
|
||||
/// Computes 2 ^ value provided
|
||||
///
|
||||
/// @returns 2 ^ (u)
|
||||
template<typename T>
|
||||
inline constexpr T Pow2(T u)
|
||||
{
|
||||
return ((T)1 << u);
|
||||
}
|
||||
|
||||
static_assert(Pow2(0) == 1, "Pow2 failure");
|
||||
static_assert(Pow2(1) == 2, "Pow2 failure");
|
||||
static_assert(Pow2(7) == 128, "Pow2 failure");
|
||||
|
||||
/// Determines if a value is a power of two.
|
||||
///
|
||||
/// @returns True if it is a power of two, false otherwise.
|
||||
inline constexpr bool IsPowerOfTwo(uint64 value)
|
||||
{
|
||||
return (value == 0) ? false : ((value & (value - 1)) == 0);
|
||||
}
|
||||
|
||||
/// Rounds the specified uint 'value' up to the nearest value meeting the specified 'alignment'. Only power of 2
|
||||
/// alignments are supported by this function.
|
||||
///
|
||||
/// returns Aligned value.
|
||||
template<typename T>
|
||||
inline constexpr T Pow2Align(
|
||||
T value, ///< Value to align.
|
||||
uint64 alignment) ///< Desired alignment (must be a power of 2).
|
||||
{
|
||||
return ((value + static_cast<T>(alignment) - 1) & ~(static_cast<T>(alignment) - 1));
|
||||
}
|
||||
|
||||
/// Rounds the specified uint 'value' up to the nearest power of 2
|
||||
///
|
||||
/// @returns Power of 2 padded value.
|
||||
template<typename T>
|
||||
inline T Pow2Pad(T value) ///< Value to pad.
|
||||
{
|
||||
T ret = 1;
|
||||
if (IsPowerOfTwo(value))
|
||||
{
|
||||
ret = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (ret < value)
|
||||
{
|
||||
ret <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Rounds the specified uint 'value' up to the nearest power of 2. Constexpr varient.
|
||||
///
|
||||
/// @returns Power of 2 padded value.
|
||||
template<typename T>
|
||||
inline constexpr T _ConstPow2Pad(T value, T padded) ///< Value to pad.
|
||||
{
|
||||
return (padded < value) ? _ConstPow2Pad(value, padded << 1) : padded;
|
||||
}
|
||||
|
||||
/// Rounds the specified uint 'value' up to the nearest power of 2. Constexpr varient.
|
||||
///
|
||||
/// @returns Power of 2 padded value.
|
||||
template<typename T>
|
||||
inline constexpr T ConstPow2Pad(T value) ///< Value to pad.
|
||||
{
|
||||
return (IsPowerOfTwo(value)) ? value : _ConstPow2Pad(value, (T)1);
|
||||
}
|
||||
|
||||
static_assert(ConstPow2Pad(512) == 512, "ConstPow2Pad failure");
|
||||
static_assert(ConstPow2Pad(511) == 512, "ConstPow2Pad failure");
|
||||
static_assert(ConstPow2Pad(257) == 512, "ConstPow2Pad failure");
|
||||
|
||||
/// Finds the smallest of two values
|
||||
///
|
||||
/// @returns a if a < b, otherwise b.
|
||||
template <typename T>
|
||||
inline constexpr T Min(const T &a, const T &b)
|
||||
{
|
||||
return ((a < b) ? a : b);
|
||||
}
|
||||
|
||||
/// Finds the larger of two values
|
||||
///
|
||||
/// @returns a if a > b, otherwise b.
|
||||
template <typename T>
|
||||
inline constexpr T Max(const T &a, const T &b)
|
||||
{
|
||||
return ((a > b) ? a : b);
|
||||
}
|
||||
|
||||
// Given a type T, set Type equal to T
|
||||
template <typename T>
|
||||
struct RemoveRef
|
||||
{
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
// Given a type T&, set Type equal to T
|
||||
template <typename T>
|
||||
struct RemoveRef<T &>
|
||||
{
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
// Given a type T&&, set Type equal to T
|
||||
template <typename T>
|
||||
struct RemoveRef<T &&>
|
||||
{
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
// std::move equivalent
|
||||
template <typename T>
|
||||
inline typename RemoveRef<T>::Type&& Move(T&& obj)
|
||||
{
|
||||
return static_cast<typename RemoveRef<T>::Type&&>(obj);
|
||||
}
|
||||
|
||||
// std::forward equivalent
|
||||
template <typename T>
|
||||
inline T&& Forward(typename RemoveRef<T>::Type&& args)
|
||||
{
|
||||
return static_cast<T&&>(args);
|
||||
}
|
||||
|
||||
// std::forward equivalent
|
||||
template <typename T>
|
||||
inline T&& Forward(typename RemoveRef<T>::Type& args)
|
||||
{
|
||||
return static_cast<T&&>(args);
|
||||
}
|
||||
|
||||
// Returns the contents of Value in a new variable, and assign newValue into the memory occupied by value.
|
||||
template <typename T, typename U = T>
|
||||
inline T Exchange(T& value, U&& newValue)
|
||||
{
|
||||
T oldValue = Move(value);
|
||||
value = Forward<U>(newValue);
|
||||
return (oldValue);
|
||||
}
|
||||
|
||||
// Convenience structure that defined Value as either true or false, and Type as either TrueType or FalseType
|
||||
template <bool value>
|
||||
struct BoolType
|
||||
{
|
||||
static const bool Value = value;
|
||||
using Type = BoolType<value>;
|
||||
};
|
||||
|
||||
using FalseType = BoolType<false>;
|
||||
using TrueType = BoolType<true>;
|
||||
|
||||
// Struct whose ::Type member is undefined if the first condition is not true
|
||||
template<bool Enable,
|
||||
class Type = void>
|
||||
struct EnableIf
|
||||
{
|
||||
};
|
||||
|
||||
// Struct whose ::Type member is equal to T if the first condition is true.
|
||||
template<class T>
|
||||
struct EnableIf<true, T>
|
||||
{
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct IsPointer : FalseType
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct IsPointer<T*> : TrueType
|
||||
{
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// If we are building with MSVC we want to use the compiler intrinsics here. This is primarily because building with
|
||||
// the /kernel precludes the use of the C++ type traits library. For all other compilers we simply implement this
|
||||
// using the standard C++ library.
|
||||
|
||||
// Struct whose ::Value member is equal to true if you can cast from T to U, and false otherwise.
|
||||
template <class T, class U>
|
||||
struct IsConvertible : BoolType<__is_convertible_to(T, U)>
|
||||
{
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if you can construct an object of type T using the arguments
|
||||
// provided.
|
||||
template<typename T, typename... Args>
|
||||
struct IsConstructible : BoolType<__is_constructible(T, Args...)>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is an abstract class, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsAbstract : BoolType<__is_abstract(T)>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is an abstract class, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsPod : BoolType<__is_pod(T)>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is has a standard layout, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsStandardLayout : BoolType<__is_standard_layout(T)>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is trivially destructable, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsTriviallyDestructible : BoolType<__is_trivially_destructible(T)>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is an enumeration type, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsEnum : BoolType<__is_enum(T)>
|
||||
{
|
||||
|
||||
};
|
||||
#else
|
||||
// Struct whose ::Value member is equal to true if you can cast from T to U, and false otherwise.
|
||||
template <class T, class U>
|
||||
struct IsConvertible : BoolType<std::is_convertible<T, U>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if you can construct an object of type T using the arguments
|
||||
// provided.
|
||||
template<typename T, typename... Args>
|
||||
struct IsConstructible : BoolType<std::is_constructible<T, Args...>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is an abstract class, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsAbstract : BoolType<std::is_abstract<T>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is an abstract class, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsPod : BoolType<std::is_trivial<T>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is has a standard layout, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsStandardLayout : BoolType<std::is_standard_layout<T>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is trivially destructable, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsTriviallyDestructible : BoolType<std::is_trivially_destructible<T>::value>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// Struct whose ::Value member is equal to true if T is an enumeration type, and false otherwise.
|
||||
template<typename T>
|
||||
struct IsEnum : BoolType<std::is_enum<T>::value>
|
||||
{
|
||||
|
||||
};
|
||||
#endif
|
||||
}
|
||||
} // DevDriver
|
||||
|
||||
+115
-115
@@ -1,115 +1,115 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#if defined(_KERNEL_MODE)
|
||||
static_assert(false, "This header is for user mode windows, and it does not work in kernel mode.");
|
||||
#endif
|
||||
|
||||
// Our code expects these defined before including Windows.h.
|
||||
// However, we need to guard against clients defining them too.
|
||||
#ifndef _CRT_RAND_S
|
||||
#define _CRT_RAND_S
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
// WIN32_NO_STATUS makes Windows.h not include macro definitions from winnt.h
|
||||
// which collide with those from ntstatus.h. This avoids compilation errors
|
||||
// when other files that include ntstatus.h also include this file.
|
||||
#define WIN32_NO_STATUS
|
||||
#include <Windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
#define DD_RESTRICT __restrict
|
||||
|
||||
#define DD_DEBUG_BREAK() __debugbreak()
|
||||
|
||||
namespace DevDriver
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
/* platform functions for performing atomic operations */
|
||||
typedef volatile LONG Atomic;
|
||||
DD_CHECK_SIZE(Atomic, sizeof(int32));
|
||||
|
||||
typedef volatile LONG64 Atomic64;
|
||||
DD_CHECK_SIZE(Atomic64, sizeof(int64));
|
||||
|
||||
struct EmptyStruct {};
|
||||
|
||||
struct MutexStorage
|
||||
{
|
||||
CRITICAL_SECTION criticalSection;
|
||||
#if !defined(NDEBUG)
|
||||
Atomic lockCount;
|
||||
#endif
|
||||
};
|
||||
typedef Handle SemaphoreStorage;
|
||||
typedef HANDLE EventStorage;
|
||||
typedef HANDLE ThreadHandle;
|
||||
typedef DWORD ThreadReturnType;
|
||||
typedef HMODULE LibraryHandle;
|
||||
|
||||
constexpr ThreadHandle kInvalidThreadHandle = NULL;
|
||||
|
||||
// Maximum supported size for thread names, including NULL byte
|
||||
// This exists because some platforms have hard limits on thread name size.
|
||||
// Windows doesn't seem to have a thread name size limit, but we use this variable to control
|
||||
// a formatting buffer as well and we want to keep it reasonably small since it's stack allocated.
|
||||
static constexpr size_t kThreadNameMaxLength = 64;
|
||||
|
||||
#define DD_APIENTRY APIENTRY
|
||||
|
||||
namespace Windows
|
||||
{
|
||||
// Windows specific functions required for in-memory communication
|
||||
Handle CreateSharedSemaphore(uint32 initialCount, uint32 maxCount);
|
||||
Handle CopySemaphoreFromProcess(ProcessId processId, Handle hObject);
|
||||
Result SignalSharedSemaphore(Handle pSemaphore);
|
||||
Result WaitSharedSemaphore(Handle pSemaphore, uint32 millisecTimeout);
|
||||
void CloseSharedSemaphore(Handle pSemaphore);
|
||||
|
||||
Handle CreateSharedBuffer(Size bufferSizeInBytes);
|
||||
void CloseSharedBuffer(Handle hSharedBuffer);
|
||||
|
||||
Handle MapSystemBufferView(Handle hBuffer, Size bufferSizeInBytes);
|
||||
Handle MapProcessBufferView(Handle hBuffer, ProcessId processId);
|
||||
void UnmapBufferView(Handle hSharedBuffer, Handle hSharedBufferView);
|
||||
|
||||
// Whether or not the user has enabled Windows Developer Mode on their system
|
||||
// See: https://github.com/MicrosoftDocs/windows-uwp/blob/docs/hub/apps/get-started/enable-your-device-for-development.md
|
||||
bool IsWin10DeveloperModeEnabled();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#if defined(_KERNEL_MODE)
|
||||
static_assert(false, "This header is for user mode windows, and it does not work in kernel mode.");
|
||||
#endif
|
||||
|
||||
// Our code expects these defined before including Windows.h.
|
||||
// However, we need to guard against clients defining them too.
|
||||
#ifndef _CRT_RAND_S
|
||||
#define _CRT_RAND_S
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
// WIN32_NO_STATUS makes Windows.h not include macro definitions from winnt.h
|
||||
// which collide with those from ntstatus.h. This avoids compilation errors
|
||||
// when other files that include ntstatus.h also include this file.
|
||||
#define WIN32_NO_STATUS
|
||||
#include <Windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
#define DD_RESTRICT __restrict
|
||||
|
||||
#define DD_DEBUG_BREAK() __debugbreak()
|
||||
|
||||
namespace DevDriver
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
/* platform functions for performing atomic operations */
|
||||
typedef volatile LONG Atomic;
|
||||
DD_CHECK_SIZE(Atomic, sizeof(int32));
|
||||
|
||||
typedef volatile LONG64 Atomic64;
|
||||
DD_CHECK_SIZE(Atomic64, sizeof(int64));
|
||||
|
||||
struct EmptyStruct {};
|
||||
|
||||
struct MutexStorage
|
||||
{
|
||||
CRITICAL_SECTION criticalSection;
|
||||
#if !defined(NDEBUG)
|
||||
Atomic lockCount;
|
||||
#endif
|
||||
};
|
||||
typedef Handle SemaphoreStorage;
|
||||
typedef HANDLE EventStorage;
|
||||
typedef HANDLE ThreadHandle;
|
||||
typedef DWORD ThreadReturnType;
|
||||
typedef HMODULE LibraryHandle;
|
||||
|
||||
constexpr ThreadHandle kInvalidThreadHandle = NULL;
|
||||
|
||||
// Maximum supported size for thread names, including NULL byte
|
||||
// This exists because some platforms have hard limits on thread name size.
|
||||
// Windows doesn't seem to have a thread name size limit, but we use this variable to control
|
||||
// a formatting buffer as well and we want to keep it reasonably small since it's stack allocated.
|
||||
static constexpr size_t kThreadNameMaxLength = 64;
|
||||
|
||||
#define DD_APIENTRY APIENTRY
|
||||
|
||||
namespace Windows
|
||||
{
|
||||
// Windows specific functions required for in-memory communication
|
||||
Handle CreateSharedSemaphore(uint32 initialCount, uint32 maxCount);
|
||||
Handle CopySemaphoreFromProcess(ProcessId processId, Handle hObject);
|
||||
Result SignalSharedSemaphore(Handle pSemaphore);
|
||||
Result WaitSharedSemaphore(Handle pSemaphore, uint32 millisecTimeout);
|
||||
void CloseSharedSemaphore(Handle pSemaphore);
|
||||
|
||||
Handle CreateSharedBuffer(Size bufferSizeInBytes);
|
||||
void CloseSharedBuffer(Handle hSharedBuffer);
|
||||
|
||||
Handle MapSystemBufferView(Handle hBuffer, Size bufferSizeInBytes);
|
||||
Handle MapProcessBufferView(Handle hBuffer, ProcessId processId);
|
||||
void UnmapBufferView(Handle hSharedBuffer, Handle hSharedBufferView);
|
||||
|
||||
// Whether or not the user has enabled Windows Developer Mode on their system
|
||||
// See: https://github.com/MicrosoftDocs/windows-uwp/blob/docs/hub/apps/get-started/enable-your-device-for-development.md
|
||||
bool IsWin10DeveloperModeEnabled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+62
-62
@@ -1,62 +1,62 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "protocolServer.h"
|
||||
|
||||
namespace DevDriver
|
||||
{
|
||||
class IMsgChannel;
|
||||
|
||||
class BaseProtocolServer : public IProtocolServer
|
||||
{
|
||||
public:
|
||||
virtual ~BaseProtocolServer();
|
||||
|
||||
Protocol GetProtocol() const override final { return m_protocol; };
|
||||
SessionType GetType() const override final { return SessionType::Server; };
|
||||
Version GetMinVersion() const override final { return m_minVersion; };
|
||||
Version GetMaxVersion() const override final { return m_maxVersion; };
|
||||
|
||||
bool GetSupportedVersion(Version minVersion, Version maxVersion, Version * version) const override final;
|
||||
|
||||
virtual void Finalize() override;
|
||||
protected:
|
||||
BaseProtocolServer(IMsgChannel* pMsgChannel, Protocol protocol, Version minVersion, Version maxVersion);
|
||||
|
||||
// Helper functions for working with SizedPayloadContainers
|
||||
Result SendPayload(ISession* pSession, const SizedPayloadContainer* pPayload, uint32 timeoutInMs);
|
||||
Result ReceivePayload(ISession* pSession, SizedPayloadContainer* pPayload, uint32 timeoutInMs);
|
||||
|
||||
IMsgChannel* const m_pMsgChannel;
|
||||
const Protocol m_protocol;
|
||||
const Version m_minVersion;
|
||||
const Version m_maxVersion;
|
||||
|
||||
bool m_isFinalized;
|
||||
};
|
||||
|
||||
} // DevDriver
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "protocolServer.h"
|
||||
|
||||
namespace DevDriver
|
||||
{
|
||||
class IMsgChannel;
|
||||
|
||||
class BaseProtocolServer : public IProtocolServer
|
||||
{
|
||||
public:
|
||||
virtual ~BaseProtocolServer();
|
||||
|
||||
Protocol GetProtocol() const override final { return m_protocol; };
|
||||
SessionType GetType() const override final { return SessionType::Server; };
|
||||
Version GetMinVersion() const override final { return m_minVersion; };
|
||||
Version GetMaxVersion() const override final { return m_maxVersion; };
|
||||
|
||||
bool GetSupportedVersion(Version minVersion, Version maxVersion, Version * version) const override final;
|
||||
|
||||
virtual void Finalize() override;
|
||||
protected:
|
||||
BaseProtocolServer(IMsgChannel* pMsgChannel, Protocol protocol, Version minVersion, Version maxVersion);
|
||||
|
||||
// Helper functions for working with SizedPayloadContainers
|
||||
Result SendPayload(ISession* pSession, const SizedPayloadContainer* pPayload, uint32 timeoutInMs);
|
||||
Result ReceivePayload(ISession* pSession, SizedPayloadContainer* pPayload, uint32 timeoutInMs);
|
||||
|
||||
IMsgChannel* const m_pMsgChannel;
|
||||
const Protocol m_protocol;
|
||||
const Version m_minVersion;
|
||||
const Version m_maxVersion;
|
||||
|
||||
bool m_isFinalized;
|
||||
};
|
||||
|
||||
} // DevDriver
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../core/inc/ddcDefs.h"
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../core/inc/ddcDefs.h"
|
||||
|
||||
+48
-48
@@ -1,48 +1,48 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef DD_PLATFORM_WINDOWS_UM
|
||||
#if _WIN32 && !_KERNEL_MODE
|
||||
#define DD_PLATFORM_WINDOWS_UM 1
|
||||
#define DD_PLATFORM_IS_UM 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DD_PLATFORM_WINDOWS_KM
|
||||
#if _WIN32 && _KERNEL_MODE
|
||||
#define DD_PLATFORM_WINDOWS_KM 1
|
||||
#define DD_PLATFORM_IS_KM 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DD_PLATFORM_LINUX_UM
|
||||
#ifdef __linux__
|
||||
#define DD_PLATFORM_LINUX_UM 1
|
||||
#define DD_PLATFORM_IS_UM 1
|
||||
#define DD_PLATFORM_IS_GNU 1
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef DD_PLATFORM_WINDOWS_UM
|
||||
#if _WIN32 && !_KERNEL_MODE
|
||||
#define DD_PLATFORM_WINDOWS_UM 1
|
||||
#define DD_PLATFORM_IS_UM 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DD_PLATFORM_WINDOWS_KM
|
||||
#if _WIN32 && _KERNEL_MODE
|
||||
#define DD_PLATFORM_WINDOWS_KM 1
|
||||
#define DD_PLATFORM_IS_KM 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DD_PLATFORM_LINUX_UM
|
||||
#ifdef __linux__
|
||||
#define DD_PLATFORM_LINUX_UM 1
|
||||
#define DD_PLATFORM_IS_UM 1
|
||||
#define DD_PLATFORM_IS_GNU 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+28
-28
@@ -1,28 +1,28 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../core/inc/ddcPlatform.h"
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../core/inc/ddcPlatform.h"
|
||||
|
||||
+28
-28
@@ -1,28 +1,28 @@
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../core/inc/ddcTemplate.h"
|
||||
/*
|
||||
***********************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../core/inc/ddcTemplate.h"
|
||||
|
||||
برخی از فایل ها نشان داده نشدند زیرا تعداد زیادی فایل در این تفاوت تغییر کرده اند نمایش بیشتر
مرجع در شماره جدید
Block a user