Revert "Revert "Update amdgpu-windows-interop with latest changes 20251105 (#…" (#1886)
Reverts ROCm/rocm-systems#1866 (re-landing https://github.com/ROCm/rocm-systems/pull/1728) This broke Windows builds at https://github.com/ROCm/rocm-systems/actions/workflows/therock-ci.yml?query=branch%3Adevelop+event%3Apush, I think intentionally? We need a plan for rolling out such changes without build breaks. Sample logs: https://github.com/ROCm/rocm-systems/actions/runs/19371422209/job/55428130376#step:14:6597 ``` [ocl-clr] [134/153] Building CXX object rocclr\CMakeFiles\rocclr.dir\device\pal\palubercapturemgr.cpp.obj [ocl-clr] FAILED: rocclr/CMakeFiles/rocclr.dir/device/pal/palubercapturemgr.cpp.obj [ocl-clr] ccache "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\bin\Hostx64\x64\cl.exe" /nologo /TP -DATI_OS_WIN -DCL_TARGET_OPENCL_VERSION=220 -DCL_USE_DEPRECATED_OPENCL_1_0_APIS -DCL_USE_DEPRECATED_OPENCL_1_1_APIS -DCL_USE_DEPRECATED_OPENCL_1_2_APIS -DCL_USE_DEPRECATED_OPENCL_2_0_APIS -DCOMGR_DYN_DLL -DGPUOPEN_CLIENT_INTERFACE_MAJOR_VERSION=42 -DHAVE_CL2_HPP -DLITTLEENDIAN_CPU -DOPENCL_C_MAJOR=2 -DOPENCL_C_MINOR=0 -DOPENCL_MAJOR=2 -DOPENCL_MINOR=1 -DPAL_BUILD_RDF=1 -DPAL_CLIENT_INTERFACE_MAJOR_VERSION=932 -DPAL_DEVELOPER_BUILD=0 -DPAL_GPUOPEN_OCL -DPAL_KMT_BUILD=1 -DROCCLR_VERSION_GITHASH=\"38294ab\" -DWITH_PAL_DEVICE -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\rocclr\.. -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\rocclr -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\rocclr\compiler\lib -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\rocclr\compiler\lib\include -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\rocclr\compiler\lib\backends\common -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\rocclr\device -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\rocclr\elf -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\rocclr\include -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\opencl\khronos\headers\opencl2.2\CL -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\opencl\khronos\headers\opencl2.2\CL\.. -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\opencl\khronos\headers\opencl2.2\CL\..\.. -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\opencl\khronos\headers\opencl2.2\CL\..\..\.. -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\opencl\khronos\headers\opencl2.2\CL\..\..\..\.. -IC:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\opencl\khronos\headers\opencl2.2\CL\..\..\..\..\amdocl -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\pal\inc -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\pal\inc\core -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\pal\inc\gpuUtil -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\pal\inc\util -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\pal\shared\inc -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\pal\shared\devdriver\shared\legacy\inc -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\pal\shared\devdriver\third_party\dd_crc32\inc -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\pal\shared\metrohash\src -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\sc\HSAIL\ext\loader -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\hsail-compiler\lib\loaders\elf\utils\libelf\..\..\..\..\..\lib\loaders\elf\utils\common -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\hsail-compiler\lib\loaders\elf\utils\libelf\..\..\..\..\..\lib\loaders\elf\utils\common\win32 -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\hsail-compiler\lib\loaders\elf\utils\libelf\..\..\..\..\..\lib\loaders\elf\utils\libelf -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\sc\HSAIL\ext\libamdhsacode -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\sc\HSAIL\ext\libamdhsacode\..\..\include -IC:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\sc\HSAIL\ext\libamdhsacode\..\..\hsail-tools\libHSAIL -external:IB:\build\compiler\amd-comgr\dist\include -external:W0 /DWIN32 /D_WINDOWS /EHsc /DWIN32 /D_WINDOWS /EHsc /O2 /Ob2 /DNDEBUG -std:c++20 -MD /wd4267 /wd4244 /wd4996 /MT /showIncludes /Forocclr\CMakeFiles\rocclr.dir\device\pal\palubercapturemgr.cpp.obj /Fdrocclr\CMakeFiles\rocclr.dir\rocclr.pdb /FS -c C:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\rocclr\device\pal\palubercapturemgr.cpp [ocl-clr] cl : Command line warning D9025 : overriding '/MD' with '/MT' [ocl-clr] C:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\rocclr\device\pal\palubercapturemgr.cpp(152): error C2039: 'RegisterTraceStateChangeCallback': is not a member of 'GpuUtil::TraceSession' [ocl-clr] C:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\pal\inc\gpuUtil\palTraceSession.h(372): note: see declaration of 'GpuUtil::TraceSession' [ocl-clr] C:\home\runner\_work\rocm-systems\rocm-systems\projects\clr\rocclr\device\pal\palubercapturemgr.cpp(195): error C2039: 'UnregisterTraceStateChangeCallback': is not a member of 'GpuUtil::TraceSession' [ocl-clr] C:\home\runner\_work\rocm-systems\rocm-systems\shared\amdgpu-windows-interop\pal\inc\gpuUtil\palTraceSession.h(372): note: see declaration of 'GpuUtil::TraceSession' [ocl-clr] [135/153] Building CXX object rocclr\CMakeFiles\rocclr.dir\device\pal\paldevicegl.cpp.obj ```
Bu işleme şunda yer alıyor:
@@ -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.
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
|
||||
+214
-212
@@ -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
|
||||
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
***********************************************************************************************************************
|
||||
*/
|
||||
|
||||
+238
-236
@@ -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
|
||||
|
||||
+155
-150
@@ -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
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
|
||||
|
||||
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
@@ -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
-1
@@ -1,5 +1,5 @@
|
||||
outs:
|
||||
- md5: fd5f7481a122f40f73d1f638e3b9b027
|
||||
- md5: 95d96350d29e5d7ee8249b13f8344bfa
|
||||
size: 16738
|
||||
hash: md5
|
||||
path: DriverUtilsService.lib
|
||||
|
||||
+1
-1
@@ -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
Dosya farkı çok büyük olduğundan ihmal edildi
Fark Yükle
+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
|
||||
|
||||
+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/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"
|
||||
|
||||
Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor Daha Fazla Göster
Yeni konuda referans
Bir kullanıcı engelle