Migrate amdgpu-windows-interop to rocm-systems (#808)

Tá an tiomantas seo le fáil i:
Joseph Macaranas
2025-09-05 10:32:44 -04:00
tiomanta ag GitHub
tuismitheoir 3d9d35a1f8
tiomantas 5ca7af2d30
D'athraigh 261 comhad le 86831 breiseanna agus 2 scriosta
@@ -0,0 +1,263 @@
////////////////////////////////////////////////////////////////////////////////
//
// The University of Illinois/NCSA
// Open Source License (NCSA)
//
// Copyright (c) 2014-2020, Advanced Micro Devices, Inc. All rights reserved.
//
// Developed by:
//
// AMD Research and AMD HSA Software Development
//
// Advanced Micro Devices, Inc.
//
// www.amd.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal with 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:
//
// - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimers.
// - Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimers in
// the documentation and/or other materials provided with the distribution.
// - Neither the names of Advanced Micro Devices, Inc,
// nor the names of its contributors may be used to endorse or promote
// products derived from this Software without specific prior written
// permission.
//
// 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 CONTRIBUTORS 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 WITH THE SOFTWARE.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef LLVM_SUPPORT_AMDHSAKERNELDESCRIPTOR_H
#define LLVM_SUPPORT_AMDHSAKERNELDESCRIPTOR_H
#include <cstddef>
#include <cstdint>
// Gets offset of specified member in specified type.
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER)
#endif // offsetof
// Creates enumeration entries used for packing bits into integers. Enumeration
// entries include bit shift amount, bit width, and bit mask.
#ifndef AMDHSA_BITS_ENUM_ENTRY
#define AMDHSA_BITS_ENUM_ENTRY(NAME, SHIFT, WIDTH) \
NAME ## _SHIFT = (SHIFT), \
NAME ## _WIDTH = (WIDTH), \
NAME = (((1 << (WIDTH)) - 1) << (SHIFT))
#endif // AMDHSA_BITS_ENUM_ENTRY
// Gets bits for specified bit mask from specified source.
#ifndef AMDHSA_BITS_GET
#define AMDHSA_BITS_GET(SRC, MSK) ((SRC & MSK) >> MSK ## _SHIFT)
#endif // AMDHSA_BITS_GET
// Sets bits for specified bit mask in specified destination.
#ifndef AMDHSA_BITS_SET
#define AMDHSA_BITS_SET(DST, MSK, VAL) \
DST &= ~MSK; \
DST |= ((VAL << MSK ## _SHIFT) & MSK)
#endif // AMDHSA_BITS_SET
namespace llvm {
namespace amdhsa {
// Floating point rounding modes. Must match hardware definition.
enum : uint8_t {
FLOAT_ROUND_MODE_NEAR_EVEN = 0,
FLOAT_ROUND_MODE_PLUS_INFINITY = 1,
FLOAT_ROUND_MODE_MINUS_INFINITY = 2,
FLOAT_ROUND_MODE_ZERO = 3,
};
// Floating point denorm modes. Must match hardware definition.
enum : uint8_t {
FLOAT_DENORM_MODE_FLUSH_SRC_DST = 0,
FLOAT_DENORM_MODE_FLUSH_DST = 1,
FLOAT_DENORM_MODE_FLUSH_SRC = 2,
FLOAT_DENORM_MODE_FLUSH_NONE = 3,
};
// System VGPR workitem IDs. Must match hardware definition.
enum : uint8_t {
SYSTEM_VGPR_WORKITEM_ID_X = 0,
SYSTEM_VGPR_WORKITEM_ID_X_Y = 1,
SYSTEM_VGPR_WORKITEM_ID_X_Y_Z = 2,
SYSTEM_VGPR_WORKITEM_ID_UNDEFINED = 3,
};
// Compute program resource register 1. Must match hardware definition.
#define COMPUTE_PGM_RSRC1(NAME, SHIFT, WIDTH) \
AMDHSA_BITS_ENUM_ENTRY(COMPUTE_PGM_RSRC1_ ## NAME, SHIFT, WIDTH)
enum : int32_t {
COMPUTE_PGM_RSRC1(GRANULATED_WORKITEM_VGPR_COUNT, 0, 6),
COMPUTE_PGM_RSRC1(GRANULATED_WAVEFRONT_SGPR_COUNT, 6, 4),
COMPUTE_PGM_RSRC1(PRIORITY, 10, 2),
COMPUTE_PGM_RSRC1(FLOAT_ROUND_MODE_32, 12, 2),
COMPUTE_PGM_RSRC1(FLOAT_ROUND_MODE_16_64, 14, 2),
COMPUTE_PGM_RSRC1(FLOAT_DENORM_MODE_32, 16, 2),
COMPUTE_PGM_RSRC1(FLOAT_DENORM_MODE_16_64, 18, 2),
COMPUTE_PGM_RSRC1(PRIV, 20, 1),
COMPUTE_PGM_RSRC1(ENABLE_DX10_CLAMP, 21, 1),
COMPUTE_PGM_RSRC1(DEBUG_MODE, 22, 1),
COMPUTE_PGM_RSRC1(ENABLE_IEEE_MODE, 23, 1),
COMPUTE_PGM_RSRC1(BULKY, 24, 1),
COMPUTE_PGM_RSRC1(CDBG_USER, 25, 1),
COMPUTE_PGM_RSRC1(FP16_OVFL, 26, 1), // GFX9+
COMPUTE_PGM_RSRC1(RESERVED0, 27, 2),
COMPUTE_PGM_RSRC1(WGP_MODE, 29, 1), // GFX10+
COMPUTE_PGM_RSRC1(MEM_ORDERED, 30, 1), // GFX10+
COMPUTE_PGM_RSRC1(FWD_PROGRESS, 31, 1), // GFX10+
};
#undef COMPUTE_PGM_RSRC1
// Compute program resource register 2. Must match hardware definition.
#define COMPUTE_PGM_RSRC2(NAME, SHIFT, WIDTH) \
AMDHSA_BITS_ENUM_ENTRY(COMPUTE_PGM_RSRC2_ ## NAME, SHIFT, WIDTH)
enum : int32_t {
COMPUTE_PGM_RSRC2(ENABLE_PRIVATE_SEGMENT, 0, 1),
COMPUTE_PGM_RSRC2(USER_SGPR_COUNT, 1, 5),
COMPUTE_PGM_RSRC2(ENABLE_TRAP_HANDLER, 6, 1),
COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_ID_X, 7, 1),
COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_ID_Y, 8, 1),
COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_ID_Z, 9, 1),
COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_INFO, 10, 1),
COMPUTE_PGM_RSRC2(ENABLE_VGPR_WORKITEM_ID, 11, 2),
COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_ADDRESS_WATCH, 13, 1),
COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_MEMORY, 14, 1),
COMPUTE_PGM_RSRC2(GRANULATED_LDS_SIZE, 15, 9),
COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, 24, 1),
COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_FP_DENORMAL_SOURCE, 25, 1),
COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, 26, 1),
COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW, 27, 1),
COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW, 28, 1),
COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_INEXACT, 29, 1),
COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO, 30, 1),
COMPUTE_PGM_RSRC2(RESERVED0, 31, 1),
};
#undef COMPUTE_PGM_RSRC2
// Compute program resource register 3 for GFX90A+. Must match hardware
// definition.
#define COMPUTE_PGM_RSRC3_GFX90A(NAME, SHIFT, WIDTH) \
AMDHSA_BITS_ENUM_ENTRY(COMPUTE_PGM_RSRC3_GFX90A_ ## NAME, SHIFT, WIDTH)
enum : int32_t {
COMPUTE_PGM_RSRC3_GFX90A(ACCUM_OFFSET, 0, 6),
COMPUTE_PGM_RSRC3_GFX90A(RESERVED0, 6, 10),
COMPUTE_PGM_RSRC3_GFX90A(TG_SPLIT, 16, 1),
COMPUTE_PGM_RSRC3_GFX90A(RESERVED1, 17, 15),
};
#undef COMPUTE_PGM_RSRC3_GFX90A
// Compute program resource register 3 for GFX10+. Must match hardware
// definition.
#define COMPUTE_PGM_RSRC3_GFX10_PLUS(NAME, SHIFT, WIDTH) \
AMDHSA_BITS_ENUM_ENTRY(COMPUTE_PGM_RSRC3_GFX10_PLUS_ ## NAME, SHIFT, WIDTH)
enum : int32_t {
COMPUTE_PGM_RSRC3_GFX10_PLUS(SHARED_VGPR_COUNT, 0, 4), // GFX10+
COMPUTE_PGM_RSRC3_GFX10_PLUS(INST_PREF_SIZE, 4, 6),
COMPUTE_PGM_RSRC3_GFX10_PLUS(TRAP_ON_START, 10, 1),
COMPUTE_PGM_RSRC3_GFX10_PLUS(TRAP_ON_END, 11, 1),
COMPUTE_PGM_RSRC3_GFX10_PLUS(RESERVED0, 12, 19),
COMPUTE_PGM_RSRC3_GFX10_PLUS(IMAGE_OP, 31, 1),
};
#undef COMPUTE_PGM_RSRC3_GFX10_PLUS
// Kernel code properties. Must be kept backwards compatible.
#define KERNEL_CODE_PROPERTY(NAME, SHIFT, WIDTH) \
AMDHSA_BITS_ENUM_ENTRY(KERNEL_CODE_PROPERTY_ ## NAME, SHIFT, WIDTH)
enum : int32_t {
KERNEL_CODE_PROPERTY(ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER, 0, 1),
KERNEL_CODE_PROPERTY(ENABLE_SGPR_DISPATCH_PTR, 1, 1),
KERNEL_CODE_PROPERTY(ENABLE_SGPR_QUEUE_PTR, 2, 1),
KERNEL_CODE_PROPERTY(ENABLE_SGPR_KERNARG_SEGMENT_PTR, 3, 1),
KERNEL_CODE_PROPERTY(ENABLE_SGPR_DISPATCH_ID, 4, 1),
KERNEL_CODE_PROPERTY(ENABLE_SGPR_FLAT_SCRATCH_INIT, 5, 1),
KERNEL_CODE_PROPERTY(ENABLE_SGPR_PRIVATE_SEGMENT_SIZE, 6, 1),
KERNEL_CODE_PROPERTY(RESERVED0, 7, 3),
KERNEL_CODE_PROPERTY(ENABLE_WAVEFRONT_SIZE32, 10, 1), // GFX10+
KERNEL_CODE_PROPERTY(USES_DYNAMIC_STACK, 11, 1),
KERNEL_CODE_PROPERTY(RESERVED1, 12, 4),
};
#undef KERNEL_CODE_PROPERTY
// Kernel descriptor. Must be kept backwards compatible.
struct kernel_descriptor_t {
uint32_t group_segment_fixed_size;
uint32_t private_segment_fixed_size;
uint32_t kernarg_size;
uint8_t reserved0[4];
int64_t kernel_code_entry_byte_offset;
uint8_t reserved1[20];
uint32_t compute_pgm_rsrc3; // GFX10+ and GFX90A+
uint32_t compute_pgm_rsrc1;
uint32_t compute_pgm_rsrc2;
uint16_t kernel_code_properties;
uint8_t reserved2[6];
};
enum : uint32_t {
GROUP_SEGMENT_FIXED_SIZE_OFFSET = 0,
PRIVATE_SEGMENT_FIXED_SIZE_OFFSET = 4,
KERNARG_SIZE_OFFSET = 8,
RESERVED0_OFFSET = 12,
KERNEL_CODE_ENTRY_BYTE_OFFSET_OFFSET = 16,
RESERVED1_OFFSET = 24,
COMPUTE_PGM_RSRC3_OFFSET = 44,
COMPUTE_PGM_RSRC1_OFFSET = 48,
COMPUTE_PGM_RSRC2_OFFSET = 52,
KERNEL_CODE_PROPERTIES_OFFSET = 56,
RESERVED2_OFFSET = 58,
};
static_assert(
sizeof(kernel_descriptor_t) == 64,
"invalid size for kernel_descriptor_t");
static_assert(offsetof(kernel_descriptor_t, group_segment_fixed_size) ==
GROUP_SEGMENT_FIXED_SIZE_OFFSET,
"invalid offset for group_segment_fixed_size");
static_assert(offsetof(kernel_descriptor_t, private_segment_fixed_size) ==
PRIVATE_SEGMENT_FIXED_SIZE_OFFSET,
"invalid offset for private_segment_fixed_size");
static_assert(offsetof(kernel_descriptor_t, kernarg_size) ==
KERNARG_SIZE_OFFSET,
"invalid offset for kernarg_size");
static_assert(offsetof(kernel_descriptor_t, reserved0) == RESERVED0_OFFSET,
"invalid offset for reserved0");
static_assert(offsetof(kernel_descriptor_t, kernel_code_entry_byte_offset) ==
KERNEL_CODE_ENTRY_BYTE_OFFSET_OFFSET,
"invalid offset for kernel_code_entry_byte_offset");
static_assert(offsetof(kernel_descriptor_t, reserved1) == RESERVED1_OFFSET,
"invalid offset for reserved1");
static_assert(offsetof(kernel_descriptor_t, compute_pgm_rsrc3) ==
COMPUTE_PGM_RSRC3_OFFSET,
"invalid offset for compute_pgm_rsrc3");
static_assert(offsetof(kernel_descriptor_t, compute_pgm_rsrc1) ==
COMPUTE_PGM_RSRC1_OFFSET,
"invalid offset for compute_pgm_rsrc1");
static_assert(offsetof(kernel_descriptor_t, compute_pgm_rsrc2) ==
COMPUTE_PGM_RSRC2_OFFSET,
"invalid offset for compute_pgm_rsrc2");
static_assert(offsetof(kernel_descriptor_t, kernel_code_properties) ==
KERNEL_CODE_PROPERTIES_OFFSET,
"invalid offset for kernel_code_properties");
static_assert(offsetof(kernel_descriptor_t, reserved2) == RESERVED2_OFFSET,
"invalid offset for reserved2");
} // end namespace amdhsa
} // end namespace llvm
#endif // LLVM_SUPPORT_AMDHSAKERNELDESCRIPTOR_H
@@ -0,0 +1,31 @@
#-----------------------------------------------------------------------------
# Copyright (c) 2015 - 2023 Advanced Micro Devices, Inc. All rights reserved.
#-----------------------------------------------------------------------------
# loader library
#
# This file is expected to be included from top-level CMakeLists.txt.
#
# Dependencies:
# - Compiler definitions
# - amdhsacode library
#
# Defines:
# - amdhsaloader library and target include directories
file(GLOB sources *.cpp *.hpp)
add_library(amdhsaloader STATIC ${sources})
set_target_properties(amdhsaloader PROPERTIES
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>"
POSITION_INDEPENDENT_CODE ON
)
if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|(Apple)?Clang)$")
target_compile_options(amdhsaloader PRIVATE
-Werror
-Wno-inconsistent-missing-override
)
endif()
target_include_directories(amdhsaloader PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(amdhsaloader amdhsacode)
Tá difríocht comhad cosc orthu toisc go bhfuil sé ró-mhór Difríocht Luchtaigh
@@ -0,0 +1,686 @@
////////////////////////////////////////////////////////////////////////////////
//
// The University of Illinois/NCSA
// Open Source License (NCSA)
//
// Copyright (c) 2014-2020, Advanced Micro Devices, Inc. All rights reserved.
//
// Developed by:
//
// AMD Research and AMD HSA Software Development
//
// Advanced Micro Devices, Inc.
//
// www.amd.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal with 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:
//
// - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimers.
// - Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimers in
// the documentation and/or other materials provided with the distribution.
// - Neither the names of Advanced Micro Devices, Inc,
// nor the names of its contributors may be used to endorse or promote
// products derived from this Software without specific prior written
// permission.
//
// 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 CONTRIBUTORS 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 WITH THE SOFTWARE.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef HSA_RUNTIME_CORE_LOADER_EXECUTABLE_HPP_
#define HSA_RUNTIME_CORE_LOADER_EXECUTABLE_HPP_
#include <array>
#include <cassert>
#include <cstdint>
#include <iostream>
#include <libelf.h>
#include <limits.h>
#include <list>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <cstring>
#include "hsa.h"
#include "hsa_ext_image.h"
#include "amd_hsa_loader.hpp"
#include "amd_hsa_code.hpp"
#include "amd_hsa_kernel_code.h"
#include "amd_hsa_locks.hpp"
#if defined(_WIN32) || defined(_WIN64)
#if _WIN64
#define __WORDSIZE 64
#else
#define __WORDSIZE 32
#endif
#endif
#define __ELF_NATIVE_CLASS __WORDSIZE
/* We use this macro to refer to ELF types independent of the native wordsize.
`ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */
#define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type)
#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
#define _ElfW_1(e,w,t) e##w##t
/* Structure describing a loaded shared object. The `l_next' and `l_prev'
members form a chain of all the shared objects loaded at startup.
These data structures exist in space used by the run-time dynamic linker;
modifying them may have disastrous results. */
struct link_map
{
/* These first few members are part of the protocol with the debugger.
This is the same format used in SVR4. */
ElfW(Addr) l_addr; /* Difference between the address in the ELF
file and the addresses in memory. */
char *l_name; /* Absolute file name object was found in. */
ElfW(Dyn) *l_ld; /* Dynamic section of the shared object. */
struct link_map *l_next, *l_prev; /* Chain of loaded objects. */
};
/* The legacy rendezvous structure used by the run-time dynamic linker to
communicate details of shared object loading to the debugger. */
struct r_debug
{
/* Version number for this protocol. It should be greater than 0. */
int r_version;
struct link_map *r_map; /* Head of the chain of loaded objects. */
/* This is the address of a function internal to the run-time linker,
that will always be called when the linker begins to map in a
library or unmap it, and again when the mapping change is complete.
The debugger can set a breakpoint at this address if it wants to
notice shared object mapping changes. */
ElfW(Addr) r_brk;
enum RT
{
/* This state value describes the mapping change taking place when
the `r_brk' address is called. */
RT_CONSISTENT, /* Mapping change is complete. */
RT_ADD, /* Beginning to add a new object. */
RT_DELETE /* Beginning to remove an object mapping. */
} r_state;
ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */
};
/* This is the symbol of that structure provided by the dynamic linker. */
extern struct r_debug _r_debug;
namespace amd {
namespace hsa {
namespace loader {
class MemoryAddress;
class SymbolImpl;
class KernelSymbol;
class VariableSymbol;
class ExecutableImpl;
//===----------------------------------------------------------------------===//
// SymbolImpl. //
//===----------------------------------------------------------------------===//
typedef uint32_t symbol_attribute32_t;
class SymbolImpl: public Symbol {
public:
virtual ~SymbolImpl() {}
bool IsKernel() const {
return HSA_SYMBOL_KIND_KERNEL == kind;
}
bool IsVariable() const {
return HSA_SYMBOL_KIND_VARIABLE == kind;
}
bool is_loaded;
hsa_symbol_kind_t kind;
std::string module_name;
std::string symbol_name;
hsa_symbol_linkage_t linkage;
bool is_definition;
uint64_t address;
hsa_agent_t agent;
hsa_agent_t GetAgent() override {
return agent;
}
protected:
SymbolImpl(const bool &_is_loaded,
const hsa_symbol_kind_t &_kind,
const std::string &_module_name,
const std::string &_symbol_name,
const hsa_symbol_linkage_t &_linkage,
const bool &_is_definition,
const uint64_t &_address = 0)
: is_loaded(_is_loaded)
, kind(_kind)
, module_name(_module_name)
, symbol_name(_symbol_name)
, linkage(_linkage)
, is_definition(_is_definition)
, address(_address) {}
virtual bool GetInfo(hsa_symbol_info32_t symbol_info, void* value) override;
private:
SymbolImpl(const SymbolImpl &s);
SymbolImpl& operator=(const SymbolImpl &s);
};
//===----------------------------------------------------------------------===//
// KernelSymbol. //
//===----------------------------------------------------------------------===//
class KernelSymbol final: public SymbolImpl {
public:
KernelSymbol(const bool &_is_loaded,
const std::string &_module_name,
const std::string &_symbol_name,
const hsa_symbol_linkage_t &_linkage,
const bool &_is_definition,
const uint32_t &_kernarg_segment_size,
const uint32_t &_kernarg_segment_alignment,
const uint32_t &_group_segment_size,
const uint32_t &_private_segment_size,
const bool &_is_dynamic_callstack,
const uint32_t &_size,
const uint32_t &_alignment,
const uint64_t &_address = 0)
: SymbolImpl(_is_loaded,
HSA_SYMBOL_KIND_KERNEL,
_module_name,
_symbol_name,
_linkage,
_is_definition,
_address)
, full_name(_module_name.empty() ? _symbol_name : _module_name + "::" + _symbol_name)
, kernarg_segment_size(_kernarg_segment_size)
, kernarg_segment_alignment(_kernarg_segment_alignment)
, group_segment_size(_group_segment_size)
, private_segment_size(_private_segment_size)
, is_dynamic_callstack(_is_dynamic_callstack)
, size(_size)
, alignment(_alignment) {}
~KernelSymbol() {}
bool GetInfo(hsa_symbol_info32_t symbol_info, void *value);
std::string full_name;
uint32_t kernarg_segment_size;
uint32_t kernarg_segment_alignment;
uint32_t group_segment_size;
uint32_t private_segment_size;
bool is_dynamic_callstack;
uint32_t size;
uint32_t alignment;
amd_runtime_loader_debug_info_t debug_info;
private:
KernelSymbol(const KernelSymbol &ks);
KernelSymbol& operator=(const KernelSymbol &ks);
};
//===----------------------------------------------------------------------===//
// VariableSymbol. //
//===----------------------------------------------------------------------===//
class VariableSymbol final: public SymbolImpl {
public:
VariableSymbol(const bool &_is_loaded,
const std::string &_module_name,
const std::string &_symbol_name,
const hsa_symbol_linkage_t &_linkage,
const bool &_is_definition,
const hsa_variable_allocation_t &_allocation,
const hsa_variable_segment_t &_segment,
const uint32_t &_size,
const uint32_t &_alignment,
const bool &_is_constant,
const bool &_is_external = false,
const uint64_t &_address = 0)
: SymbolImpl(_is_loaded,
HSA_SYMBOL_KIND_VARIABLE,
_module_name,
_symbol_name,
_linkage,
_is_definition,
_address)
, allocation(_allocation)
, segment(_segment)
, size(_size)
, alignment(_alignment)
, is_constant(_is_constant)
, is_external(_is_external) {}
~VariableSymbol() {}
bool GetInfo(hsa_symbol_info32_t symbol_info, void *value);
hsa_variable_allocation_t allocation;
hsa_variable_segment_t segment;
uint32_t size;
uint32_t alignment;
bool is_constant;
bool is_external;
private:
VariableSymbol(const VariableSymbol &vs);
VariableSymbol& operator=(const VariableSymbol &vs);
};
//===----------------------------------------------------------------------===//
// Logger. //
//===----------------------------------------------------------------------===//
class Logger final {
public:
Logger(std::ostream &Stream = std::cerr) : OutStream(Stream) {}
template <typename T>
Logger &operator<<(const T &Data) {
if (!IsLoggingEnabled())
return *this;
OutStream << Data;
std::stringstream ss;
ss << Data;
printf("=================== %s\n", ss.str().c_str());
return *this;
}
private:
Logger(const Logger &L);
Logger& operator=(const Logger &L);
bool IsLoggingEnabled() const {
const char *enable_logging = getenv("LOADER_ENABLE_LOGGING");
if (!enable_logging)
return false;
if (std::string(enable_logging) == "0")
return false;
return true;
}
std::ostream &OutStream;
};
//===----------------------------------------------------------------------===//
// Executable. //
//===----------------------------------------------------------------------===//
class ExecutableImpl;
class LoadedCodeObjectImpl;
class Segment;
class ExecutableObject {
protected:
ExecutableImpl *owner;
hsa_agent_t agent;
public:
ExecutableObject(ExecutableImpl *owner_, hsa_agent_t agent_)
: owner(owner_), agent(agent_) { }
ExecutableImpl* Owner() const { return owner; }
hsa_agent_t Agent() const { return agent; }
virtual void Print(std::ostream& out) = 0;
virtual void Destroy() = 0;
virtual ~ExecutableObject() { }
};
class LoadedCodeObjectImpl : public LoadedCodeObject, public ExecutableObject {
friend class AmdHsaCodeLoader;
private:
LoadedCodeObjectImpl(const LoadedCodeObjectImpl&);
LoadedCodeObjectImpl& operator=(const LoadedCodeObjectImpl&);
const void *elf_data;
const size_t elf_size;
std::vector<Segment*> loaded_segments;
public:
LoadedCodeObjectImpl(ExecutableImpl *owner_, hsa_agent_t agent_, const void *elf_data_, size_t elf_size_)
: ExecutableObject(owner_, agent_), elf_data(elf_data_), elf_size(elf_size_) {
memset(&r_debug_info, 0, sizeof(r_debug_info));
}
const void* ElfData() const { return elf_data; }
size_t ElfSize() const { return elf_size; }
std::vector<Segment*>& LoadedSegments() { return loaded_segments; }
bool GetInfo(amd_loaded_code_object_info_t attribute, void *value) override;
hsa_status_t IterateLoadedSegments(
hsa_status_t (*callback)(
amd_loaded_segment_t loaded_segment,
void *data),
void *data) override;
void Print(std::ostream& out) override;
void Destroy() override {}
hsa_agent_t getAgent() const override;
hsa_executable_t getExecutable() const override;
uint64_t getElfData() const override;
uint64_t getElfSize() const override;
uint64_t getStorageOffset() const override;
uint64_t getLoadBase() const override;
uint64_t getLoadSize() const override;
int64_t getDelta() const override;
std::string getUri() const override;
link_map r_debug_info;
};
class Segment : public LoadedSegment, public ExecutableObject {
private:
amdgpu_hsa_elf_segment_t segment;
void *ptr;
size_t size;
uint64_t vaddr;
bool frozen;
size_t storage_offset;
public:
Segment(ExecutableImpl *owner_, hsa_agent_t agent_, amdgpu_hsa_elf_segment_t segment_, void* ptr_, size_t size_, uint64_t vaddr_, size_t storage_offset_)
: ExecutableObject(owner_, agent_), segment(segment_),
ptr(ptr_), size(size_), vaddr(vaddr_), frozen(false), storage_offset(storage_offset_) { }
amdgpu_hsa_elf_segment_t ElfSegment() const { return segment; }
void* Ptr() const { return ptr; }
size_t Size() const { return size; }
uint64_t VAddr() const { return vaddr; }
size_t StorageOffset() const { return storage_offset; }
bool GetInfo(amd_loaded_segment_info_t attribute, void *value) override;
uint64_t Offset(uint64_t addr); // Offset within segment. Used together with ptr with loader context functions.
void* Address(uint64_t addr); // Address in segment. Used for relocations and valid on agent.
bool Freeze();
bool IsAddressInSegment(uint64_t addr);
void Copy(uint64_t addr, const void* src, size_t size);
void Print(std::ostream& out) override;
void Destroy() override;
};
class Sampler : public ExecutableObject {
private:
hsa_ext_sampler_t samp;
public:
Sampler(ExecutableImpl *owner, hsa_agent_t agent, hsa_ext_sampler_t samp_)
: ExecutableObject(owner, agent), samp(samp_) { }
void Print(std::ostream& out) override;
void Destroy() override;
};
class Image : public ExecutableObject {
private:
hsa_ext_image_t img;
public:
Image(ExecutableImpl *owner, hsa_agent_t agent, hsa_ext_image_t img_)
: ExecutableObject(owner, agent), img(img_) { }
void Print(std::ostream& out) override;
void Destroy() override;
};
typedef std::string ProgramSymbol;
typedef std::unordered_map<ProgramSymbol, SymbolImpl*> ProgramSymbolMap;
typedef std::pair<std::string, hsa_agent_t> AgentSymbol;
struct ASC {
bool operator()(const AgentSymbol &las, const AgentSymbol &ras) const {
return las.first == ras.first && las.second.handle == ras.second.handle;
}
};
struct ASH {
size_t operator()(const AgentSymbol &as) const {
size_t h = std::hash<std::string>()(as.first);
size_t i = std::hash<uint64_t>()(as.second.handle);
return h ^ (i << 1);
}
};
typedef std::unordered_map<AgentSymbol, SymbolImpl*, ASH, ASC> AgentSymbolMap;
class ExecutableImpl final: public Executable {
friend class AmdHsaCodeLoader;
public:
const hsa_profile_t& profile() const {
return profile_;
}
const hsa_executable_state_t& state() const {
return state_;
}
ExecutableImpl(
const hsa_profile_t &_profile,
Context *context,
size_t id,
hsa_default_float_rounding_mode_t default_float_rounding_mode);
~ExecutableImpl();
hsa_status_t GetInfo(hsa_executable_info_t executable_info, void *value) override;
hsa_status_t DefineProgramExternalVariable(
const char *name, void *address) override;
hsa_status_t DefineAgentExternalVariable(
const char *name,
hsa_agent_t agent,
hsa_variable_segment_t segment,
void *address) override;
hsa_status_t LoadCodeObject(
hsa_agent_t agent,
hsa_code_object_t code_object,
const char *options,
hsa_loaded_code_object_t *loaded_code_object) override;
hsa_status_t LoadCodeObject(
hsa_agent_t agent,
hsa_code_object_t code_object,
size_t code_object_size,
const char *options,
hsa_loaded_code_object_t *loaded_code_object) override;
hsa_status_t LoadCodeObject(
hsa_agent_t agent,
hsa_code_object_t code_object,
const char *options,
const std::string &uri,
hsa_loaded_code_object_t *loaded_code_object) override;
hsa_status_t LoadCodeObject(
hsa_agent_t agent,
hsa_code_object_t code_object,
size_t code_object_size,
const char *options,
const std::string &uri,
hsa_loaded_code_object_t *loaded_code_object) override;
hsa_status_t Freeze(const char *options) override;
hsa_status_t Validate(uint32_t *result) override {
amd::hsa::common::ReaderLockGuard<amd::hsa::common::ReaderWriterLock> reader_lock(rw_lock_);
assert(result);
*result = 0;
return HSA_STATUS_SUCCESS;
}
/// @note needed for hsa v1.0.
/// @todo remove during loader refactoring.
bool IsProgramSymbol(const char *symbol_name) override;
Symbol* GetSymbol(
const char *symbol_name,
const hsa_agent_t *agent) override;
hsa_status_t IterateSymbols(
iterate_symbols_f callback, void *data) override;
/// @since hsa v1.1.
hsa_status_t IterateAgentSymbols(
hsa_agent_t agent,
hsa_status_t (*callback)(hsa_executable_t exec,
hsa_agent_t agent,
hsa_executable_symbol_t symbol,
void *data),
void *data) override;
/// @since hsa v1.1.
hsa_status_t IterateProgramSymbols(
hsa_status_t (*callback)(hsa_executable_t exec,
hsa_executable_symbol_t symbol,
void *data),
void *data) override;
hsa_status_t IterateLoadedCodeObjects(
hsa_status_t (*callback)(
hsa_executable_t executable,
hsa_loaded_code_object_t loaded_code_object,
void *data),
void *data) override;
size_t GetNumSegmentDescriptors() override;
size_t QuerySegmentDescriptors(
hsa_ven_amd_loader_segment_descriptor_t *segment_descriptors,
size_t total_num_segment_descriptors,
size_t first_empty_segment_descriptor) override;
uint64_t FindHostAddress(uint64_t device_address) override;
void EnableReadOnlyMode();
void DisableReadOnlyMode();
void Print(std::ostream& out) override;
bool PrintToFile(const std::string& filename) override;
Context* context() { return context_; }
size_t id() { return id_; }
private:
ExecutableImpl(const ExecutableImpl &e);
ExecutableImpl& operator=(const ExecutableImpl &e);
std::unique_ptr<amd::hsa::code::AmdHsaCode> code;
Symbol* GetSymbolInternal(
const char *symbol_name,
const hsa_agent_t *agent);
hsa_status_t LoadSegments(hsa_agent_t agent, const code::AmdHsaCode *c,
uint32_t majorVersion);
hsa_status_t LoadSegmentsV1(hsa_agent_t agent, const code::AmdHsaCode *c);
hsa_status_t LoadSegmentsV2(hsa_agent_t agent, const code::AmdHsaCode *c);
hsa_status_t LoadSegmentV1(hsa_agent_t agent, const code::Segment *s);
hsa_status_t LoadSegmentV2(const code::Segment *data_segment,
loader::Segment *load_segment);
hsa_status_t LoadSymbol(hsa_agent_t agent, amd::hsa::code::Symbol* sym, uint32_t majorVersion);
hsa_status_t LoadDefinitionSymbol(hsa_agent_t agent, amd::hsa::code::Symbol* sym, uint32_t majorVersion);
hsa_status_t LoadDeclarationSymbol(hsa_agent_t agent, amd::hsa::code::Symbol* sym, uint32_t majorVersion);
hsa_status_t ApplyRelocations(hsa_agent_t agent, amd::hsa::code::AmdHsaCode *c);
hsa_status_t ApplyStaticRelocationSection(hsa_agent_t agent, amd::hsa::code::RelocationSection* sec);
hsa_status_t ApplyStaticRelocation(hsa_agent_t agent, amd::hsa::code::Relocation *rel);
hsa_status_t ApplyDynamicRelocationSection(hsa_agent_t agent, amd::hsa::code::RelocationSection* sec);
hsa_status_t ApplyDynamicRelocation(hsa_agent_t agent, amd::hsa::code::Relocation *rel);
Segment* VirtualAddressSegment(uint64_t vaddr);
uint64_t SymbolAddress(hsa_agent_t agent, amd::hsa::code::Symbol* sym);
uint64_t SymbolAddress(hsa_agent_t agent, amd::elf::Symbol* sym);
Segment* SymbolSegment(hsa_agent_t agent, amd::hsa::code::Symbol* sym);
Segment* SectionSegment(hsa_agent_t agent, amd::hsa::code::Section* sec);
amd::hsa::common::ReaderWriterLock rw_lock_;
hsa_profile_t profile_;
Context *context_;
Logger logger_;
const size_t id_;
hsa_default_float_rounding_mode_t default_float_rounding_mode_;
hsa_executable_state_t state_;
ProgramSymbolMap program_symbols_;
AgentSymbolMap agent_symbols_;
std::vector<ExecutableObject*> objects;
Segment *program_allocation_segment;
std::vector<LoadedCodeObjectImpl*> loaded_code_objects;
};
class AmdHsaCodeLoader : public Loader {
private:
Context* context;
std::vector<Executable*> executables;
amd::hsa::common::ReaderWriterLock rw_lock_;
public:
AmdHsaCodeLoader(Context* context_)
: context(context_) { assert(context); }
Context* GetContext() const override { return context; }
Executable* CreateExecutable(
hsa_profile_t profile,
const char *options,
hsa_default_float_rounding_mode_t default_float_rounding_mode = HSA_DEFAULT_FLOAT_ROUNDING_MODE_DEFAULT) override;
hsa_status_t FreezeExecutable(Executable *executable, const char *options) override;
void DestroyExecutable(Executable *executable) override;
hsa_status_t IterateExecutables(
hsa_status_t (*callback)(
hsa_executable_t executable,
void *data),
void *data) override;
hsa_status_t QuerySegmentDescriptors(
hsa_ven_amd_loader_segment_descriptor_t *segment_descriptors,
size_t *num_segment_descriptors) override;
hsa_executable_t FindExecutable(uint64_t device_address) override;
uint64_t FindHostAddress(uint64_t device_address) override;
void PrintHelp(std::ostream& out) override;
void EnableReadOnlyMode();
void DisableReadOnlyMode();
};
} // namespace loader
} // namespace hsa
} // namespace amd
#endif // HSA_RUNTIME_CORE_LOADER_EXECUTABLE_HPP_
@@ -0,0 +1,307 @@
////////////////////////////////////////////////////////////////////////////////
//
// The University of Illinois/NCSA
// Open Source License (NCSA)
//
// Copyright (c) 2014-2016, Advanced Micro Devices, Inc. All rights reserved.
//
// Developed by:
//
// AMD Research and AMD HSA Software Development
//
// Advanced Micro Devices, Inc.
//
// www.amd.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal with 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:
//
// - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimers.
// - Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimers in
// the documentation and/or other materials provided with the distribution.
// - Neither the names of Advanced Micro Devices, Inc,
// nor the names of its contributors may be used to endorse or promote
// products derived from this Software without specific prior written
// permission.
//
// 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 CONTRIBUTORS 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 WITH THE SOFTWARE.
//
////////////////////////////////////////////////////////////////////////////////
#include <cstring>
#include <cassert>
#include "loaders.hpp"
namespace amd {
namespace hsa {
namespace loader {
// Helper function that allocates an aligned memory.
static inline void*
alignedMalloc(size_t size, size_t alignment)
{
#if defined(_WIN32)
return ::_aligned_malloc(size, alignment);
#else
void * ptr = NULL;
alignment = (std::max)(alignment, sizeof(void*));
if (0 == ::posix_memalign(&ptr, alignment, size)) {
return ptr;
}
return NULL;
#endif
}
// Helper function that frees an aligned memory.
static inline void
alignedFree(void *ptr)
{
#if defined(_WIN32)
::_aligned_free(ptr);
#else
free(ptr);
#endif
}
OfflineLoaderContext::OfflineLoaderContext()
: out(std::cout)
{
invalid.handle = 0;
gfx700.handle = 700;
gfx701.handle = 701;
gfx800.handle = 800;
gfx801.handle = 801;
gfx802.handle = 802;
gfx803.handle = 803;
gfx804.handle = 804;
gfx810.handle = 810;
gfx900.handle = 900;
gfx901.handle = 901;
gfx902.handle = 902;
gfx903.handle = 903;
gfx904.handle = 904;
gfx905.handle = 905;
gfx906.handle = 906;
gfx907.handle = 907;
gfx1000.handle = 1000;
gfx1001.handle = 1001;
gfx1010.handle = 1010;
gfx1011.handle = 1011;
gfx1012.handle = 1012;
gfx1030.handle = 1030;
gfx4000.handle = 4000;
#if defined(GFX11_BUILD)
gfx1100.handle = 1100;
gfx1101.handle = 1101;
gfx1102.handle = 1102;
gfx1103.handle = 1103;
gfx1150.handle = 1150;
gfx1151.handle = 1151;
#endif // GFX11_BUILD
}
hsa_isa_t OfflineLoaderContext::IsaFromName(const char *name)
{
std::string sname(name);
if (sname == "AMD:AMDGPU:7:0:0") {
return gfx700;
} else if (sname == "AMD:AMDGPU:7:0:1") {
return gfx701;
} else if (sname == "AMD:AMDGPU:8:0:0") {
return gfx800;
} else if (sname == "AMD:AMDGPU:8:0:1") {
return gfx801;
} else if (sname == "AMD:AMDGPU:8:0:2") {
return gfx802;
} else if (sname == "AMD:AMDGPU:8:0:3") {
return gfx803;
} else if (sname == "AMD:AMDGPU:8:0:4") {
return gfx804;
} else if (sname == "AMD:AMDGPU:8:1:0") {
return gfx810;
} else if (sname == "AMD:AMDGPU:9:0:0") {
return gfx900;
} else if (sname == "AMD:AMDGPU:9:0:1") {
return gfx901;
} else if (sname == "AMD:AMDGPU:9:0:2") {
return gfx902;
} else if (sname == "AMD:AMDGPU:9:0:3") {
return gfx903;
}
else if (sname == "AMD:AMDGPU:9:0:4") {
return gfx904;
} else if (sname == "AMD:AMDGPU:9:0:5") {
return gfx905;
}
else if (sname == "AMD:AMDGPU:9:0:6") {
return gfx906;
} else if (sname == "AMD:AMDGPU:9:0:7") {
return gfx907;
}
else if (sname == "AMD:AMDGPU:10:0:0") {
return gfx1000;
} else if (sname == "AMD:AMDGPU:10:0:1") {
return gfx1001;
} else if (sname == "AMD:AMDGPU:10:1:0") {
return gfx1010;
} else if (sname == "AMD:AMDGPU:10:1:1") {
return gfx1011;
} else if (sname == "AMD:AMDGPU:10:1:2") {
return gfx1012;
}
else if (sname == "AMD:AMDGPU:10:3:0") {
return gfx1030;
}
else if (sname == "AMD:AMDGPU:40:0:0") {
return gfx4000;
}
#if defined(GFX11_BUILD)
else if (sname == "AMD:AMDGPU:11:0:0") {
return gfx1100;
} else if (sname == "AMD:AMDGPU:11:0:1") {
return gfx1101;
} else if (sname == "AMD:AMDGPU:11:0:2") {
return gfx1102;
} else if (sname == "AMD:AMDGPU:11:0:3") {
return gfx1103;
} else if (sname == "AMD:AMDGPU:11:5:0") {
return gfx1150;
} else if (sname == "AMD:AMDGPU:11:5:1") {
return gfx1151;
}
#endif // GFX11_BUILD
assert(0);
return invalid;
}
bool OfflineLoaderContext::IsaSupportedByAgent(hsa_agent_t agent, hsa_isa_t isa)
{
return true;
}
void* OfflineLoaderContext::SegmentAlloc(amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, size_t size, size_t align, bool zero)
{
void* ptr = alignedMalloc(size, align);
if (zero) { memset(ptr, 0, size); }
out << "SegmentAlloc: " << segment << ": " << "size=" << size << " align=" << align << " zero=" << zero << " result=" << ptr << std::endl;
pointers.insert(ptr);
return ptr;
}
bool OfflineLoaderContext::SegmentCopy(amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* dst, size_t offset, const void* src, size_t size)
{
out << "SegmentCopy: " << segment << ": " << "dst=" << dst << " offset=" << offset << " src=" << src << " size=" << size << std::endl;
if (!dst || !src || dst == src) {
return false;
}
if (0 == size) {
return true;
}
memcpy((char *) dst + offset, src, size);
return true;
}
void OfflineLoaderContext::SegmentFree(amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* seg, size_t size)
{
out << "SegmentFree: " << segment << ": " << " ptr=" << seg << " size=" << size << std::endl;
pointers.erase(seg);
alignedFree(seg);
}
void* OfflineLoaderContext::SegmentAddress(amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* seg, size_t offset)
{
out << "SegmentAddress: " << segment << ": " << " ptr=" << seg << " offset=" << offset << std::endl;
return (char*) seg + offset;
}
void* OfflineLoaderContext::SegmentHostAddress(amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* seg, size_t offset)
{
out << "SegmentHostAddress: " << segment << ": " << " ptr=" << seg << " offset=" << offset << std::endl;
return (char*) seg + offset;
}
bool OfflineLoaderContext::SegmentFreeze(amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* seg, size_t size)
{
out << "SegmentFreeze: " << segment << ": " << " ptr=" << seg << " size=" << size << std::endl;
return true;
}
bool OfflineLoaderContext::ImageExtensionSupported()
{
return true;
}
hsa_status_t OfflineLoaderContext::ImageCreate(
hsa_agent_t agent,
hsa_access_permission_t image_permission,
const hsa_ext_image_descriptor_t *image_descriptor,
const void *image_data,
hsa_ext_image_t *image_handle)
{
void* ptr = alignedMalloc(256, 8);
out << "ImageCreate" << ":" <<
" permission=" << image_permission <<
" geometry=" << image_descriptor->geometry <<
" width=" << image_descriptor->width <<
" height=" << image_descriptor->height <<
" depth=" << image_descriptor->depth <<
" array_size=" << image_descriptor->array_size <<
" channel_type=" << image_descriptor->format.channel_type <<
" channel_order=" << image_descriptor->format.channel_order<<
" data=" << image_data <<
std::endl;
pointers.insert(ptr);
image_handle->handle = reinterpret_cast<uint64_t>(ptr);
return HSA_STATUS_SUCCESS;
}
hsa_status_t OfflineLoaderContext::ImageDestroy(
hsa_agent_t agent, hsa_ext_image_t image_handle)
{
void* ptr = reinterpret_cast<void*>(image_handle.handle);
pointers.erase(ptr);
alignedFree(ptr);
return HSA_STATUS_SUCCESS;
}
hsa_status_t OfflineLoaderContext::SamplerCreate(
hsa_agent_t agent,
const hsa_ext_sampler_descriptor_t *sampler_descriptor,
hsa_ext_sampler_t *sampler_handle)
{
void* ptr = alignedMalloc(256, 8);
out << "SamplerCreate" << ":" <<
" coordinate_mode=" << sampler_descriptor->coordinate_mode <<
" filter_mode=" << sampler_descriptor->filter_mode <<
" address_mode=" << sampler_descriptor->address_mode <<
std::endl;
pointers.insert(ptr);
sampler_handle->handle = reinterpret_cast<uint64_t>(ptr);
return HSA_STATUS_SUCCESS;
}
hsa_status_t OfflineLoaderContext::SamplerDestroy(
hsa_agent_t agent, hsa_ext_sampler_t sampler_handle)
{
void* ptr = reinterpret_cast<void*>(sampler_handle.handle);
pointers.erase(ptr);
alignedFree(ptr);
return HSA_STATUS_SUCCESS;
}
}
}
}
@@ -0,0 +1,114 @@
////////////////////////////////////////////////////////////////////////////////
//
// The University of Illinois/NCSA
// Open Source License (NCSA)
//
// Copyright (c) 2014-2016, Advanced Micro Devices, Inc. All rights reserved.
//
// Developed by:
//
// AMD Research and AMD HSA Software Development
//
// Advanced Micro Devices, Inc.
//
// www.amd.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal with 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:
//
// - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimers.
// - Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimers in
// the documentation and/or other materials provided with the distribution.
// - Neither the names of Advanced Micro Devices, Inc,
// nor the names of its contributors may be used to endorse or promote
// products derived from this Software without specific prior written
// permission.
//
// 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 CONTRIBUTORS 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 WITH THE SOFTWARE.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef LOADERS_HPP_
#define LOADERS_HPP_
#include "amd_hsa_loader.hpp"
#include <set>
#include <iostream>
namespace amd {
namespace hsa {
namespace loader {
class OfflineLoaderContext : public amd::hsa::loader::Context {
private:
hsa_isa_t invalid;
hsa_isa_t gfx700, gfx701, gfx800, gfx801, gfx802, gfx803, gfx804, gfx810;
hsa_isa_t gfx900, gfx901, gfx902, gfx903;
hsa_isa_t gfx904, gfx905;
hsa_isa_t gfx906, gfx907;
hsa_isa_t gfx1000, gfx1001, gfx1010, gfx1011, gfx1012;
hsa_isa_t gfx1030;
hsa_isa_t gfx4000;
#if defined(GFX11_BUILD)
hsa_isa_t gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151;
#endif // GFX11_BUILD
std::ostream& out;
typedef std::set<void*> PointerSet;
PointerSet pointers;
public:
OfflineLoaderContext();
hsa_isa_t IsaFromName(const char *name) override;
bool IsaSupportedByAgent(hsa_agent_t agent, hsa_isa_t isa) override;
void* SegmentAlloc(amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, size_t size, size_t align, bool zero) override;
bool SegmentCopy(amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* dst, size_t offset, const void* src, size_t size) override;
void SegmentFree(amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* seg, size_t size = 0) override;
void* SegmentAddress(amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* seg, size_t offset) override;
void* SegmentHostAddress(amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* seg, size_t offset) override;
bool SegmentFreeze(amdgpu_hsa_elf_segment_t segment, hsa_agent_t agent, void* seg, size_t size) override;
bool ImageExtensionSupported() override;
hsa_status_t ImageCreate(
hsa_agent_t agent,
hsa_access_permission_t image_permission,
const hsa_ext_image_descriptor_t *image_descriptor,
const void *image_data,
hsa_ext_image_t *image_handle) override;
hsa_status_t ImageDestroy(
hsa_agent_t agent, hsa_ext_image_t image_handle) override;
hsa_status_t SamplerCreate(
hsa_agent_t agent,
const hsa_ext_sampler_descriptor_t *sampler_descriptor,
hsa_ext_sampler_t *sampler_handle) override;
hsa_status_t SamplerDestroy(
hsa_agent_t agent, hsa_ext_sampler_t sampler_handle) override;
};
}
}
}
#endif // LOADERS_HPP_