SWDEV-288707 - Merge HIP refactored code to staging
These changes move-
- rocclr based implementation inside src/hipamd/src
- platform specific (both nvidia and amd) headers inside
src/hipamd/include/hip
Change-Id: Ia29791a727244952591fe1d813dcef0303b73a9e
[ROCm/hip commit: ce76ec8b88]
This commit is contained in:
1 szülő
7a932782e2
commit
4cd9afebe9
119 files changed
+3943
-97
No files matched your search
Executable
+286
@@ -0,0 +1,286 @@
|
||||
# Copyright (c) 2020-2021 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.5.1)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if(ADDRESS_SANITIZER)
|
||||
set(ASAN_LINKER_FLAGS "-fsanitize=address")
|
||||
set(ASAN_COMPILER_FLAGS "-fno-omit-frame-pointer -fsanitize=address")
|
||||
|
||||
if(NOT CMAKE_COMPILER_IS_GNUCC)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(ASAN_LINKER_FLAGS "${ASAN_LINKER_FLAGS} -shared-libsan")
|
||||
else()
|
||||
set(ASAN_LINKER_FLAGS "${ASAN_LINKER_FLAGS} -static-libsan")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ASAN_COMPILER_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ASAN_COMPILER_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${ASAN_LINKER_FLAGS} -s")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${ASAN_LINKER_FLAGS}")
|
||||
endif()
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build the shared library" ON)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
find_package(ROCclr)
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
add_library(amdhip64 SHARED)
|
||||
# Windows doesn't have a strip utility, so CMAKE_STRIP won't be set.
|
||||
if((CMAKE_BUILD_TYPE STREQUAL "Release") AND NOT ("${CMAKE_STRIP}" STREQUAL ""))
|
||||
add_custom_command(TARGET amdhip64 POST_BUILD COMMAND ${CMAKE_STRIP} $<TARGET_FILE:amdhip64>)
|
||||
endif()
|
||||
else()
|
||||
add_library(amdhip64 STATIC $<TARGET_OBJECTS:rocclr>)
|
||||
endif()
|
||||
|
||||
set_target_properties(amdhip64 PROPERTIES
|
||||
CXX_STANDARD 14
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CXX_EXTENSIONS OFF
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
# Workaround for many places in the HIP project
|
||||
# having hardcoded references to build/lib/libamdhip64.so
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set_target_properties(amdhip64 PROPERTIES OUTPUT_NAME "amdhip64")
|
||||
else()
|
||||
set_target_properties(amdhip64 PROPERTIES OUTPUT_NAME "amdhip32")
|
||||
endif()
|
||||
|
||||
# Disable versioning for Windows
|
||||
# as currently HIP_LIB_VERSION_STRING and HIP_LIB_VERSION_MAJOR
|
||||
# are not being populated
|
||||
if(NOT WIN32)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set_target_properties(amdhip64 PROPERTIES
|
||||
VERSION ${HIP_LIB_VERSION_STRING}
|
||||
SOVERSION ${HIP_LIB_VERSION_MAJOR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_sources(amdhip64 PRIVATE
|
||||
src/cl_gl.cpp
|
||||
src/cl_lqdflash_amd.cpp
|
||||
src/fixme.cpp
|
||||
src/hip_activity.cpp
|
||||
src/hip_code_object.cpp
|
||||
src/hip_context.cpp
|
||||
src/hip_device_runtime.cpp
|
||||
src/hip_device.cpp
|
||||
src/hip_error.cpp
|
||||
src/hip_event.cpp
|
||||
src/hip_fatbin.cpp
|
||||
src/hip_global.cpp
|
||||
src/hip_graph_internal.cpp
|
||||
src/hip_graph.cpp
|
||||
src/hip_hmm.cpp
|
||||
src/hip_intercept.cpp
|
||||
src/hip_memory.cpp
|
||||
src/hip_module.cpp
|
||||
src/hip_peer.cpp
|
||||
src/hip_platform.cpp
|
||||
src/hip_profile.cpp
|
||||
src/hip_rtc.cpp
|
||||
src/hip_stream_ops.cpp
|
||||
src/hip_stream.cpp
|
||||
src/hip_surface.cpp
|
||||
src/hip_texture.cpp)
|
||||
|
||||
if(WIN32)
|
||||
target_sources(amdhip64 PRIVATE
|
||||
src/cl_d3d9.cpp
|
||||
src/cl_d3d10.cpp
|
||||
src/cl_d3d11.cpp)
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
if(WIN32)
|
||||
target_sources(amdhip64 PRIVATE amdhip.def)
|
||||
else()
|
||||
target_link_libraries(amdhip64 PRIVATE "-Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/src/hip_hcc.map.in")
|
||||
set_target_properties(amdhip64 PROPERTIES LINK_DEPENDS "${CMAKE_CURRENT_LIST_DIR}/src/hip_hcc.map.in")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_include_directories(amdhip64
|
||||
PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/src/hipamd/include
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
${PROJECT_BINARY_DIR}/include)
|
||||
|
||||
target_compile_definitions(amdhip64 PRIVATE __HIP_PLATFORM_AMD__)
|
||||
|
||||
target_link_libraries(amdhip64 PRIVATE ${CMAKE_DL_LIBS})
|
||||
# Additional dependencies for hipRTC
|
||||
if(WIN32)
|
||||
target_link_libraries(amdhip64 PRIVATE Dbghelp.lib)
|
||||
endif()
|
||||
|
||||
# Note in static case we cannot link against rocclr.
|
||||
# If we would, we'd also have to export rocclr and have hipcc pass it to the linker.
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_link_libraries(amdhip64 PRIVATE rocclr)
|
||||
else()
|
||||
target_compile_definitions(amdhip64 PRIVATE $<TARGET_PROPERTY:rocclr,COMPILE_DEFINITIONS>)
|
||||
target_include_directories(amdhip64 PRIVATE $<TARGET_PROPERTY:rocclr,INCLUDE_DIRECTORIES>)
|
||||
endif()
|
||||
|
||||
# Short-Term solution for pre-compiled headers for online compilation
|
||||
# Enable pre compiled header
|
||||
if(__HIP_ENABLE_PCH)
|
||||
find_package(LLVM REQUIRED CONFIG
|
||||
PATHS
|
||||
/opt/rocm/llvm)
|
||||
# find_package(LLVM) returns the lib/cmake/llvm location. We require the root.
|
||||
set(HIP_LLVM_ROOT "${LLVM_DIR}/../../..")
|
||||
|
||||
# execute_process(COMMAND sh -c "${CMAKE_CURRENT_SOURCE_DIR}/../bin/hip_embed_pch.sh ${PROJECT_BINARY_DIR}/include ${PROJECT_SOURCE_DIR}/include ${HIP_LLVM_ROOT}" COMMAND_ECHO STDERR RESULT_VARIABLE EMBED_PCH_RC)
|
||||
execute_process(COMMAND sh -c "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/hip_embed_pch.sh ${PROJECT_BINARY_DIR}/include ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/src/hipamd/include ${HIP_LLVM_ROOT}" COMMAND_ECHO STDERR RESULT_VARIABLE EMBED_PCH_RC)
|
||||
if (EMBED_PCH_RC AND NOT EMBED_PCH_RC EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to embed PCH")
|
||||
endif()
|
||||
|
||||
target_compile_definitions(amdhip64 PRIVATE __HIP_ENABLE_PCH)
|
||||
target_sources(amdhip64 PRIVATE ${CMAKE_BINARY_DIR}/hip_pch.o)
|
||||
endif()
|
||||
|
||||
# Enable preprocessed hiprtc-builtins library
|
||||
if(__HIP_ENABLE_RTC)
|
||||
find_package(LLVM REQUIRED CONFIG
|
||||
PATHS
|
||||
/opt/rocm/llvm)
|
||||
# find_package(LLVM) returns the lib/cmake/llvm location. We require the root.
|
||||
set(HIP_LLVM_ROOT "${LLVM_DIR}/../../..")
|
||||
|
||||
if(WIN32)
|
||||
set(HIPRTC_LIB_NAME "hiprtc-builtins64_${HIP_LIB_VERSION_MAJOR}${HIP_LIB_VERSION_MINOR}.dll")
|
||||
else()
|
||||
set(HIPRTC_LIB_NAME "libhiprtc-builtins.so.${HIP_LIB_VERSION_MAJOR}.${HIP_LIB_VERSION_MINOR}")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND sh -c "mkdir -p ${PROJECT_BINARY_DIR}/lib; ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/hip_embed_pch.sh ${PROJECT_BINARY_DIR}/include ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/src/hipamd/include ${HIP_LLVM_ROOT} -r ${PROJECT_BINARY_DIR}/lib/${HIPRTC_LIB_NAME}"
|
||||
COMMAND_ECHO STDERR
|
||||
RESULT_VARIABLE EMBED_RTC_RC
|
||||
)
|
||||
if (EMBED_RTC_RC AND NOT EMBED_RTC_RC EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to create hiprtc shared lib")
|
||||
endif()
|
||||
install(FILES ${PROJECT_BINARY_DIR}/lib/${HIPRTC_LIB_NAME} DESTINATION lib)
|
||||
endif()
|
||||
|
||||
#############################
|
||||
# Profiling API support
|
||||
#############################
|
||||
# Generate profiling API macros/structures header
|
||||
set(PROF_API_STR "${PROJECT_BINARY_DIR}/include/hip/amd_detail/hip_prof_str.h")
|
||||
set(PROF_API_HDR "${PROJECT_SOURCE_DIR}/include/hip/hip_runtime_api.h")
|
||||
set(PROF_API_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||
set(PROF_API_GEN "${CMAKE_CURRENT_SOURCE_DIR}/src/hip_prof_gen.py")
|
||||
set(PROF_API_LOG "${PROJECT_BINARY_DIR}/hip_prof_gen.log.txt")
|
||||
|
||||
find_package(PythonInterp REQUIRED)
|
||||
add_custom_command(OUTPUT ${PROF_API_STR}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${PROF_API_GEN} -v -t --priv ${OPT_PROF_API} ${PROF_API_HDR} ${PROF_API_SRC} ${PROF_API_STR}
|
||||
OUTPUT_FILE ${PROF_API_LOG}
|
||||
DEPENDS ${PROF_API_HDR} ${PROF_API_GEN}
|
||||
COMMENT "Generating profiling primitives: ${PROF_API_STR}")
|
||||
|
||||
add_custom_target(gen-prof-api-str-header ALL
|
||||
DEPENDS ${PROF_API_STR}
|
||||
SOURCES ${PROF_API_HDR})
|
||||
|
||||
set_target_properties(amdhip64 PROPERTIES PUBLIC_HEADER ${PROF_API_STR})
|
||||
|
||||
option(USE_PROF_API ON "Enable roctracer integration")
|
||||
# Enable profiling API
|
||||
if(USE_PROF_API)
|
||||
find_path(PROF_API_HEADER_DIR prof_protocol.h
|
||||
HINTS
|
||||
${PROF_API_HEADER_PATH}
|
||||
PATHS
|
||||
${ROCM_PATH}/roctracer
|
||||
PATH_SUFFIXES
|
||||
include/ext)
|
||||
|
||||
if(NOT PROF_API_HEADER_DIR)
|
||||
message(WARNING "Profiling API header not found. Disabling roctracer integration. Use -DPROF_API_HEADER_PATH=<path to prof_protocol.h header>")
|
||||
else()
|
||||
target_compile_definitions(amdhip64 PUBLIC USE_PROF_API=1)
|
||||
target_include_directories(amdhip64 PUBLIC ${PROF_API_HEADER_DIR})
|
||||
message(STATUS "Profiling API: ${PROF_API_HEADER_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_dependencies(amdhip64 gen-prof-api-str-header)
|
||||
|
||||
add_custom_command(TARGET amdhip64 POST_BUILD COMMAND
|
||||
${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/.hipInfo ${PROJECT_BINARY_DIR}/lib/.hipInfo)
|
||||
add_custom_command(TARGET amdhip64 POST_BUILD COMMAND
|
||||
${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include)
|
||||
|
||||
add_library(host INTERFACE)
|
||||
target_link_libraries(host INTERFACE amdhip64)
|
||||
|
||||
add_library(device INTERFACE)
|
||||
target_link_libraries(device INTERFACE host)
|
||||
|
||||
INSTALL(TARGETS amdhip64 host device
|
||||
EXPORT hip-targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
INSTALL(EXPORT hip-targets DESTINATION ${CONFIG_PACKAGE_INSTALL_DIR} NAMESPACE hip::)
|
||||
|
||||
INSTALL(TARGETS amdhip64 host device
|
||||
EXPORT hip-lang-targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
INSTALL(EXPORT hip-lang-targets DESTINATION ${CONFIG_LANG_PACKAGE_INSTALL_DIR} NAMESPACE hip-lang::)
|
||||
|
||||
if(NOT WIN32)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
configure_package_config_file(
|
||||
${PROJECT_SOURCE_DIR}/hip-lang-config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/hip-lang-config.cmake
|
||||
INSTALL_DESTINATION ${CONFIG_LANG_PACKAGE_INSTALL_DIR}
|
||||
PATH_VARS LIB_INSTALL_DIR INCLUDE_INSTALL_DIR BIN_INSTALL_DIR)
|
||||
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/hip-lang-config-version.cmake
|
||||
VERSION "${HIP_VERSION_MAJOR}.${HIP_VERSION_MINOR}.${HIP_VERSION_GITDATE}"
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/hip-lang-config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/hip-lang-config-version.cmake
|
||||
DESTINATION
|
||||
${CONFIG_LANG_PACKAGE_INSTALL_DIR}/
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,51 @@
|
||||
# Copyright (c) 2020-2021 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.
|
||||
|
||||
if(ROCCLR_FOUND)
|
||||
return()
|
||||
endif()
|
||||
|
||||
find_path(ROCCLR_INCLUDE_DIR top.hpp
|
||||
HINTS
|
||||
${ROCCLR_PATH}
|
||||
PATHS
|
||||
# gerrit repo name
|
||||
${CMAKE_SOURCE_DIR}/vdi
|
||||
${CMAKE_SOURCE_DIR}/../vdi
|
||||
${CMAKE_SOURCE_DIR}/../../vdi
|
||||
# github repo name
|
||||
${CMAKE_SOURCE_DIR}/ROCclr
|
||||
${CMAKE_SOURCE_DIR}/../ROCclr
|
||||
${CMAKE_SOURCE_DIR}/../../ROCclr
|
||||
# jenkins repo name
|
||||
${CMAKE_SOURCE_DIR}/rocclr
|
||||
${CMAKE_SOURCE_DIR}/../rocclr
|
||||
${CMAKE_SOURCE_DIR}/../../rocclr
|
||||
PATH_SUFFIXES
|
||||
include)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ROCclr
|
||||
"\nROCclr not found"
|
||||
ROCCLR_INCLUDE_DIR)
|
||||
mark_as_advanced(ROCCLR_INCLUDE_DIR)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${ROCCLR_INCLUDE_DIR}/../cmake")
|
||||
include(ROCclr)
|
||||
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_CHANNEL_DESCRIPTOR_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_CHANNEL_DESCRIPTOR_H
|
||||
|
||||
#include <hip/hip_common.h>
|
||||
#include <hip/amd_detail/amd_driver_types.h>
|
||||
#include <hip/amd_detail/amd_hip_vector_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
extern "C" HIP_PUBLIC_API
|
||||
hipChannelFormatDesc hipCreateChannelDesc(int x, int y, int z, int w, hipChannelFormatKind f);
|
||||
|
||||
static inline hipChannelFormatDesc hipCreateChannelDescHalf() {
|
||||
int e = (int)sizeof(unsigned short) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindFloat);
|
||||
}
|
||||
|
||||
static inline hipChannelFormatDesc hipCreateChannelDescHalf1() {
|
||||
int e = (int)sizeof(unsigned short) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindFloat);
|
||||
}
|
||||
|
||||
static inline hipChannelFormatDesc hipCreateChannelDescHalf2() {
|
||||
int e = (int)sizeof(unsigned short) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindFloat);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline hipChannelFormatDesc hipCreateChannelDesc() {
|
||||
return hipCreateChannelDesc(0, 0, 0, 0, hipChannelFormatKindNone);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<char>() {
|
||||
int e = (int)sizeof(char) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<signed char>() {
|
||||
int e = (int)sizeof(signed char) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<unsigned char>() {
|
||||
int e = (int)sizeof(unsigned char) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<uchar1>() {
|
||||
int e = (int)sizeof(unsigned char) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<char1>() {
|
||||
int e = (int)sizeof(signed char) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<uchar2>() {
|
||||
int e = (int)sizeof(unsigned char) * 8;
|
||||
return hipCreateChannelDesc(e, e, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<char2>() {
|
||||
int e = (int)sizeof(signed char) * 8;
|
||||
return hipCreateChannelDesc(e, e, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
#ifndef __GNUC__ // vector3 is the same as vector4
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<uchar3>() {
|
||||
int e = (int)sizeof(unsigned char) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<char3>() {
|
||||
int e = (int)sizeof(signed char) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<uchar4>() {
|
||||
int e = (int)sizeof(unsigned char) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, e, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<char4>() {
|
||||
int e = (int)sizeof(signed char) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, e, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<unsigned short>() {
|
||||
int e = (int)sizeof(unsigned short) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<signed short>() {
|
||||
int e = (int)sizeof(signed short) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<ushort1>() {
|
||||
int e = (int)sizeof(unsigned short) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<short1>() {
|
||||
int e = (int)sizeof(signed short) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<ushort2>() {
|
||||
int e = (int)sizeof(unsigned short) * 8;
|
||||
return hipCreateChannelDesc(e, e, 0, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<short2>() {
|
||||
int e = (int)sizeof(signed short) * 8;
|
||||
return hipCreateChannelDesc(e, e, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<ushort3>() {
|
||||
int e = (int)sizeof(unsigned short) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<short3>() {
|
||||
int e = (int)sizeof(signed short) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<ushort4>() {
|
||||
int e = (int)sizeof(unsigned short) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, e, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<short4>() {
|
||||
int e = (int)sizeof(signed short) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, e, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<unsigned int>() {
|
||||
int e = (int)sizeof(unsigned int) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<signed int>() {
|
||||
int e = (int)sizeof(signed int) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<uint1>() {
|
||||
int e = (int)sizeof(unsigned int) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<int1>() {
|
||||
int e = (int)sizeof(signed int) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<uint2>() {
|
||||
int e = (int)sizeof(unsigned int) * 8;
|
||||
return hipCreateChannelDesc(e, e, 0, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<int2>() {
|
||||
int e = (int)sizeof(signed int) * 8;
|
||||
return hipCreateChannelDesc(e, e, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<uint3>() {
|
||||
int e = (int)sizeof(unsigned int) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<int3>() {
|
||||
int e = (int)sizeof(signed int) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<uint4>() {
|
||||
int e = (int)sizeof(unsigned int) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, e, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<int4>() {
|
||||
int e = (int)sizeof(signed int) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, e, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<float>() {
|
||||
int e = (int)sizeof(float) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindFloat);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<float1>() {
|
||||
int e = (int)sizeof(float) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindFloat);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<float2>() {
|
||||
int e = (int)sizeof(float) * 8;
|
||||
return hipCreateChannelDesc(e, e, 0, 0, hipChannelFormatKindFloat);
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<float3>() {
|
||||
int e = (int)sizeof(float) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, 0, hipChannelFormatKindFloat);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<float4>() {
|
||||
int e = (int)sizeof(float) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, e, hipChannelFormatKindFloat);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<unsigned long>() {
|
||||
int e = (int)sizeof(unsigned long) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<signed long>() {
|
||||
int e = (int)sizeof(signed long) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<ulong1>() {
|
||||
int e = (int)sizeof(unsigned long) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<long1>() {
|
||||
int e = (int)sizeof(signed long) * 8;
|
||||
return hipCreateChannelDesc(e, 0, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<ulong2>() {
|
||||
int e = (int)sizeof(unsigned long) * 8;
|
||||
return hipCreateChannelDesc(e, e, 0, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<long2>() {
|
||||
int e = (int)sizeof(signed long) * 8;
|
||||
return hipCreateChannelDesc(e, e, 0, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<ulong3>() {
|
||||
int e = (int)sizeof(unsigned long) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, 0, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<long3>() {
|
||||
int e = (int)sizeof(signed long) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, 0, hipChannelFormatKindSigned);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<ulong4>() {
|
||||
int e = (int)sizeof(unsigned long) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, e, hipChannelFormatKindUnsigned);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline hipChannelFormatDesc hipCreateChannelDesc<long4>() {
|
||||
int e = (int)sizeof(signed long) * 8;
|
||||
return hipCreateChannelDesc(e, e, e, e, hipChannelFormatKindSigned);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct hipChannelFormatDesc hipCreateChannelDesc(int x, int y, int z, int w,
|
||||
enum hipChannelFormatKind f);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_DRIVER_TYPES_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_DRIVER_TYPES_H
|
||||
|
||||
// The follow macro should be removed after upstream updation.
|
||||
// It's defined here for workarround of rocThrust building failure.
|
||||
#define HIP_INCLUDE_HIP_HCC_DETAIL_DRIVER_TYPES_H
|
||||
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
|
||||
typedef void* hipDeviceptr_t;
|
||||
typedef enum hipChannelFormatKind {
|
||||
hipChannelFormatKindSigned = 0,
|
||||
hipChannelFormatKindUnsigned = 1,
|
||||
hipChannelFormatKindFloat = 2,
|
||||
hipChannelFormatKindNone = 3
|
||||
}hipChannelFormatKind;
|
||||
|
||||
typedef struct hipChannelFormatDesc {
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
int w;
|
||||
enum hipChannelFormatKind f;
|
||||
}hipChannelFormatDesc;
|
||||
|
||||
#define HIP_TRSA_OVERRIDE_FORMAT 0x01
|
||||
#define HIP_TRSF_READ_AS_INTEGER 0x01
|
||||
#define HIP_TRSF_NORMALIZED_COORDINATES 0x02
|
||||
#define HIP_TRSF_SRGB 0x10
|
||||
|
||||
typedef enum hipArray_Format {
|
||||
HIP_AD_FORMAT_UNSIGNED_INT8 = 0x01,
|
||||
HIP_AD_FORMAT_UNSIGNED_INT16 = 0x02,
|
||||
HIP_AD_FORMAT_UNSIGNED_INT32 = 0x03,
|
||||
HIP_AD_FORMAT_SIGNED_INT8 = 0x08,
|
||||
HIP_AD_FORMAT_SIGNED_INT16 = 0x09,
|
||||
HIP_AD_FORMAT_SIGNED_INT32 = 0x0a,
|
||||
HIP_AD_FORMAT_HALF = 0x10,
|
||||
HIP_AD_FORMAT_FLOAT = 0x20
|
||||
}hipArray_Format;
|
||||
|
||||
typedef struct HIP_ARRAY_DESCRIPTOR {
|
||||
size_t Width;
|
||||
size_t Height;
|
||||
enum hipArray_Format Format;
|
||||
unsigned int NumChannels;
|
||||
}HIP_ARRAY_DESCRIPTOR;
|
||||
|
||||
typedef struct HIP_ARRAY3D_DESCRIPTOR {
|
||||
size_t Width;
|
||||
size_t Height;
|
||||
size_t Depth;
|
||||
enum hipArray_Format Format;
|
||||
unsigned int NumChannels;
|
||||
unsigned int Flags;
|
||||
}HIP_ARRAY3D_DESCRIPTOR;
|
||||
|
||||
typedef struct hipArray {
|
||||
void* data; // FIXME: generalize this
|
||||
struct hipChannelFormatDesc desc;
|
||||
unsigned int type;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int depth;
|
||||
enum hipArray_Format Format;
|
||||
unsigned int NumChannels;
|
||||
bool isDrv;
|
||||
unsigned int textureType;
|
||||
}hipArray;
|
||||
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
typedef struct hip_Memcpy2D {
|
||||
size_t srcXInBytes;
|
||||
size_t srcY;
|
||||
hipMemoryType srcMemoryType;
|
||||
const void* srcHost;
|
||||
hipDeviceptr_t srcDevice;
|
||||
hipArray* srcArray;
|
||||
size_t srcPitch;
|
||||
size_t dstXInBytes;
|
||||
size_t dstY;
|
||||
hipMemoryType dstMemoryType;
|
||||
void* dstHost;
|
||||
hipDeviceptr_t dstDevice;
|
||||
hipArray* dstArray;
|
||||
size_t dstPitch;
|
||||
size_t WidthInBytes;
|
||||
size_t Height;
|
||||
} hip_Memcpy2D;
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
|
||||
typedef struct hipArray* hipArray_t;
|
||||
typedef hipArray_t hiparray;
|
||||
typedef const struct hipArray* hipArray_const_t;
|
||||
|
||||
typedef struct hipMipmappedArray {
|
||||
void* data;
|
||||
struct hipChannelFormatDesc desc;
|
||||
unsigned int type;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int depth;
|
||||
unsigned int min_mipmap_level;
|
||||
unsigned int max_mipmap_level;
|
||||
unsigned int flags;
|
||||
enum hipArray_Format format;
|
||||
} hipMipmappedArray;
|
||||
|
||||
typedef struct hipMipmappedArray* hipMipmappedArray_t;
|
||||
|
||||
typedef const struct hipMipmappedArray* hipMipmappedArray_const_t;
|
||||
|
||||
/**
|
||||
* hip resource types
|
||||
*/
|
||||
typedef enum hipResourceType {
|
||||
hipResourceTypeArray = 0x00,
|
||||
hipResourceTypeMipmappedArray = 0x01,
|
||||
hipResourceTypeLinear = 0x02,
|
||||
hipResourceTypePitch2D = 0x03
|
||||
}hipResourceType;
|
||||
|
||||
typedef enum HIPresourcetype_enum {
|
||||
HIP_RESOURCE_TYPE_ARRAY = 0x00, /**< Array resoure */
|
||||
HIP_RESOURCE_TYPE_MIPMAPPED_ARRAY = 0x01, /**< Mipmapped array resource */
|
||||
HIP_RESOURCE_TYPE_LINEAR = 0x02, /**< Linear resource */
|
||||
HIP_RESOURCE_TYPE_PITCH2D = 0x03 /**< Pitch 2D resource */
|
||||
} HIPresourcetype;
|
||||
|
||||
/**
|
||||
* hip address modes
|
||||
*/
|
||||
typedef enum HIPaddress_mode_enum {
|
||||
HIP_TR_ADDRESS_MODE_WRAP = 0,
|
||||
HIP_TR_ADDRESS_MODE_CLAMP = 1,
|
||||
HIP_TR_ADDRESS_MODE_MIRROR = 2,
|
||||
HIP_TR_ADDRESS_MODE_BORDER = 3
|
||||
} HIPaddress_mode;
|
||||
|
||||
/**
|
||||
* hip filter modes
|
||||
*/
|
||||
typedef enum HIPfilter_mode_enum {
|
||||
HIP_TR_FILTER_MODE_POINT = 0,
|
||||
HIP_TR_FILTER_MODE_LINEAR = 1
|
||||
} HIPfilter_mode;
|
||||
|
||||
/**
|
||||
* Texture descriptor
|
||||
*/
|
||||
typedef struct HIP_TEXTURE_DESC_st {
|
||||
HIPaddress_mode addressMode[3]; /**< Address modes */
|
||||
HIPfilter_mode filterMode; /**< Filter mode */
|
||||
unsigned int flags; /**< Flags */
|
||||
unsigned int maxAnisotropy; /**< Maximum anisotropy ratio */
|
||||
HIPfilter_mode mipmapFilterMode; /**< Mipmap filter mode */
|
||||
float mipmapLevelBias; /**< Mipmap level bias */
|
||||
float minMipmapLevelClamp; /**< Mipmap minimum level clamp */
|
||||
float maxMipmapLevelClamp; /**< Mipmap maximum level clamp */
|
||||
float borderColor[4]; /**< Border Color */
|
||||
int reserved[12];
|
||||
} HIP_TEXTURE_DESC;
|
||||
|
||||
/**
|
||||
* hip texture resource view formats
|
||||
*/
|
||||
typedef enum hipResourceViewFormat {
|
||||
hipResViewFormatNone = 0x00,
|
||||
hipResViewFormatUnsignedChar1 = 0x01,
|
||||
hipResViewFormatUnsignedChar2 = 0x02,
|
||||
hipResViewFormatUnsignedChar4 = 0x03,
|
||||
hipResViewFormatSignedChar1 = 0x04,
|
||||
hipResViewFormatSignedChar2 = 0x05,
|
||||
hipResViewFormatSignedChar4 = 0x06,
|
||||
hipResViewFormatUnsignedShort1 = 0x07,
|
||||
hipResViewFormatUnsignedShort2 = 0x08,
|
||||
hipResViewFormatUnsignedShort4 = 0x09,
|
||||
hipResViewFormatSignedShort1 = 0x0a,
|
||||
hipResViewFormatSignedShort2 = 0x0b,
|
||||
hipResViewFormatSignedShort4 = 0x0c,
|
||||
hipResViewFormatUnsignedInt1 = 0x0d,
|
||||
hipResViewFormatUnsignedInt2 = 0x0e,
|
||||
hipResViewFormatUnsignedInt4 = 0x0f,
|
||||
hipResViewFormatSignedInt1 = 0x10,
|
||||
hipResViewFormatSignedInt2 = 0x11,
|
||||
hipResViewFormatSignedInt4 = 0x12,
|
||||
hipResViewFormatHalf1 = 0x13,
|
||||
hipResViewFormatHalf2 = 0x14,
|
||||
hipResViewFormatHalf4 = 0x15,
|
||||
hipResViewFormatFloat1 = 0x16,
|
||||
hipResViewFormatFloat2 = 0x17,
|
||||
hipResViewFormatFloat4 = 0x18,
|
||||
hipResViewFormatUnsignedBlockCompressed1 = 0x19,
|
||||
hipResViewFormatUnsignedBlockCompressed2 = 0x1a,
|
||||
hipResViewFormatUnsignedBlockCompressed3 = 0x1b,
|
||||
hipResViewFormatUnsignedBlockCompressed4 = 0x1c,
|
||||
hipResViewFormatSignedBlockCompressed4 = 0x1d,
|
||||
hipResViewFormatUnsignedBlockCompressed5 = 0x1e,
|
||||
hipResViewFormatSignedBlockCompressed5 = 0x1f,
|
||||
hipResViewFormatUnsignedBlockCompressed6H = 0x20,
|
||||
hipResViewFormatSignedBlockCompressed6H = 0x21,
|
||||
hipResViewFormatUnsignedBlockCompressed7 = 0x22
|
||||
}hipResourceViewFormat;
|
||||
|
||||
typedef enum HIPresourceViewFormat_enum
|
||||
{
|
||||
HIP_RES_VIEW_FORMAT_NONE = 0x00, /**< No resource view format (use underlying resource format) */
|
||||
HIP_RES_VIEW_FORMAT_UINT_1X8 = 0x01, /**< 1 channel unsigned 8-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_UINT_2X8 = 0x02, /**< 2 channel unsigned 8-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_UINT_4X8 = 0x03, /**< 4 channel unsigned 8-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_SINT_1X8 = 0x04, /**< 1 channel signed 8-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_SINT_2X8 = 0x05, /**< 2 channel signed 8-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_SINT_4X8 = 0x06, /**< 4 channel signed 8-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_UINT_1X16 = 0x07, /**< 1 channel unsigned 16-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_UINT_2X16 = 0x08, /**< 2 channel unsigned 16-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_UINT_4X16 = 0x09, /**< 4 channel unsigned 16-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_SINT_1X16 = 0x0a, /**< 1 channel signed 16-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_SINT_2X16 = 0x0b, /**< 2 channel signed 16-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_SINT_4X16 = 0x0c, /**< 4 channel signed 16-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_UINT_1X32 = 0x0d, /**< 1 channel unsigned 32-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_UINT_2X32 = 0x0e, /**< 2 channel unsigned 32-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_UINT_4X32 = 0x0f, /**< 4 channel unsigned 32-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_SINT_1X32 = 0x10, /**< 1 channel signed 32-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_SINT_2X32 = 0x11, /**< 2 channel signed 32-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_SINT_4X32 = 0x12, /**< 4 channel signed 32-bit integers */
|
||||
HIP_RES_VIEW_FORMAT_FLOAT_1X16 = 0x13, /**< 1 channel 16-bit floating point */
|
||||
HIP_RES_VIEW_FORMAT_FLOAT_2X16 = 0x14, /**< 2 channel 16-bit floating point */
|
||||
HIP_RES_VIEW_FORMAT_FLOAT_4X16 = 0x15, /**< 4 channel 16-bit floating point */
|
||||
HIP_RES_VIEW_FORMAT_FLOAT_1X32 = 0x16, /**< 1 channel 32-bit floating point */
|
||||
HIP_RES_VIEW_FORMAT_FLOAT_2X32 = 0x17, /**< 2 channel 32-bit floating point */
|
||||
HIP_RES_VIEW_FORMAT_FLOAT_4X32 = 0x18, /**< 4 channel 32-bit floating point */
|
||||
HIP_RES_VIEW_FORMAT_UNSIGNED_BC1 = 0x19, /**< Block compressed 1 */
|
||||
HIP_RES_VIEW_FORMAT_UNSIGNED_BC2 = 0x1a, /**< Block compressed 2 */
|
||||
HIP_RES_VIEW_FORMAT_UNSIGNED_BC3 = 0x1b, /**< Block compressed 3 */
|
||||
HIP_RES_VIEW_FORMAT_UNSIGNED_BC4 = 0x1c, /**< Block compressed 4 unsigned */
|
||||
HIP_RES_VIEW_FORMAT_SIGNED_BC4 = 0x1d, /**< Block compressed 4 signed */
|
||||
HIP_RES_VIEW_FORMAT_UNSIGNED_BC5 = 0x1e, /**< Block compressed 5 unsigned */
|
||||
HIP_RES_VIEW_FORMAT_SIGNED_BC5 = 0x1f, /**< Block compressed 5 signed */
|
||||
HIP_RES_VIEW_FORMAT_UNSIGNED_BC6H = 0x20, /**< Block compressed 6 unsigned half-float */
|
||||
HIP_RES_VIEW_FORMAT_SIGNED_BC6H = 0x21, /**< Block compressed 6 signed half-float */
|
||||
HIP_RES_VIEW_FORMAT_UNSIGNED_BC7 = 0x22 /**< Block compressed 7 */
|
||||
} HIPresourceViewFormat;
|
||||
|
||||
/**
|
||||
* HIP resource descriptor
|
||||
*/
|
||||
typedef struct hipResourceDesc {
|
||||
enum hipResourceType resType;
|
||||
|
||||
union {
|
||||
struct {
|
||||
hipArray_t array;
|
||||
} array;
|
||||
struct {
|
||||
hipMipmappedArray_t mipmap;
|
||||
} mipmap;
|
||||
struct {
|
||||
void* devPtr;
|
||||
struct hipChannelFormatDesc desc;
|
||||
size_t sizeInBytes;
|
||||
} linear;
|
||||
struct {
|
||||
void* devPtr;
|
||||
struct hipChannelFormatDesc desc;
|
||||
size_t width;
|
||||
size_t height;
|
||||
size_t pitchInBytes;
|
||||
} pitch2D;
|
||||
} res;
|
||||
}hipResourceDesc;
|
||||
|
||||
typedef struct HIP_RESOURCE_DESC_st
|
||||
{
|
||||
HIPresourcetype resType; /**< Resource type */
|
||||
|
||||
union {
|
||||
struct {
|
||||
hipArray_t hArray; /**< HIP array */
|
||||
} array;
|
||||
struct {
|
||||
hipMipmappedArray_t hMipmappedArray; /**< HIP mipmapped array */
|
||||
} mipmap;
|
||||
struct {
|
||||
hipDeviceptr_t devPtr; /**< Device pointer */
|
||||
hipArray_Format format; /**< Array format */
|
||||
unsigned int numChannels; /**< Channels per array element */
|
||||
size_t sizeInBytes; /**< Size in bytes */
|
||||
} linear;
|
||||
struct {
|
||||
hipDeviceptr_t devPtr; /**< Device pointer */
|
||||
hipArray_Format format; /**< Array format */
|
||||
unsigned int numChannels; /**< Channels per array element */
|
||||
size_t width; /**< Width of the array in elements */
|
||||
size_t height; /**< Height of the array in elements */
|
||||
size_t pitchInBytes; /**< Pitch between two rows in bytes */
|
||||
} pitch2D;
|
||||
struct {
|
||||
int reserved[32];
|
||||
} reserved;
|
||||
} res;
|
||||
|
||||
unsigned int flags; /**< Flags (must be zero) */
|
||||
} HIP_RESOURCE_DESC;
|
||||
|
||||
/**
|
||||
* hip resource view descriptor
|
||||
*/
|
||||
struct hipResourceViewDesc {
|
||||
enum hipResourceViewFormat format;
|
||||
size_t width;
|
||||
size_t height;
|
||||
size_t depth;
|
||||
unsigned int firstMipmapLevel;
|
||||
unsigned int lastMipmapLevel;
|
||||
unsigned int firstLayer;
|
||||
unsigned int lastLayer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resource view descriptor
|
||||
*/
|
||||
typedef struct HIP_RESOURCE_VIEW_DESC_st
|
||||
{
|
||||
HIPresourceViewFormat format; /**< Resource view format */
|
||||
size_t width; /**< Width of the resource view */
|
||||
size_t height; /**< Height of the resource view */
|
||||
size_t depth; /**< Depth of the resource view */
|
||||
unsigned int firstMipmapLevel; /**< First defined mipmap level */
|
||||
unsigned int lastMipmapLevel; /**< Last defined mipmap level */
|
||||
unsigned int firstLayer; /**< First layer index */
|
||||
unsigned int lastLayer; /**< Last layer index */
|
||||
unsigned int reserved[16];
|
||||
} HIP_RESOURCE_VIEW_DESC;
|
||||
|
||||
/**
|
||||
* Memory copy types
|
||||
*
|
||||
*/
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
typedef enum hipMemcpyKind {
|
||||
hipMemcpyHostToHost = 0, ///< Host-to-Host Copy
|
||||
hipMemcpyHostToDevice = 1, ///< Host-to-Device Copy
|
||||
hipMemcpyDeviceToHost = 2, ///< Device-to-Host Copy
|
||||
hipMemcpyDeviceToDevice = 3, ///< Device-to-Device Copy
|
||||
hipMemcpyDefault =
|
||||
4 ///< Runtime will automatically determine copy-kind based on virtual addresses.
|
||||
} hipMemcpyKind;
|
||||
|
||||
typedef struct hipPitchedPtr {
|
||||
void* ptr;
|
||||
size_t pitch;
|
||||
size_t xsize;
|
||||
size_t ysize;
|
||||
}hipPitchedPtr;
|
||||
|
||||
typedef struct hipExtent {
|
||||
size_t width; // Width in elements when referring to array memory, in bytes when referring to
|
||||
// linear memory
|
||||
size_t height;
|
||||
size_t depth;
|
||||
}hipExtent;
|
||||
|
||||
typedef struct hipPos {
|
||||
size_t x;
|
||||
size_t y;
|
||||
size_t z;
|
||||
}hipPos;
|
||||
|
||||
typedef struct hipMemcpy3DParms {
|
||||
hipArray_t srcArray;
|
||||
struct hipPos srcPos;
|
||||
struct hipPitchedPtr srcPtr;
|
||||
hipArray_t dstArray;
|
||||
struct hipPos dstPos;
|
||||
struct hipPitchedPtr dstPtr;
|
||||
struct hipExtent extent;
|
||||
enum hipMemcpyKind kind;
|
||||
} hipMemcpy3DParms;
|
||||
|
||||
typedef struct HIP_MEMCPY3D {
|
||||
unsigned int srcXInBytes;
|
||||
unsigned int srcY;
|
||||
unsigned int srcZ;
|
||||
unsigned int srcLOD;
|
||||
hipMemoryType srcMemoryType;
|
||||
const void* srcHost;
|
||||
hipDeviceptr_t srcDevice;
|
||||
hipArray_t srcArray;
|
||||
unsigned int srcPitch;
|
||||
unsigned int srcHeight;
|
||||
unsigned int dstXInBytes;
|
||||
unsigned int dstY;
|
||||
unsigned int dstZ;
|
||||
unsigned int dstLOD;
|
||||
hipMemoryType dstMemoryType;
|
||||
void* dstHost;
|
||||
hipDeviceptr_t dstDevice;
|
||||
hipArray_t dstArray;
|
||||
unsigned int dstPitch;
|
||||
unsigned int dstHeight;
|
||||
unsigned int WidthInBytes;
|
||||
unsigned int Height;
|
||||
unsigned int Depth;
|
||||
} HIP_MEMCPY3D;
|
||||
|
||||
static inline struct hipPitchedPtr make_hipPitchedPtr(void* d, size_t p, size_t xsz,
|
||||
size_t ysz) {
|
||||
struct hipPitchedPtr s;
|
||||
|
||||
s.ptr = d;
|
||||
s.pitch = p;
|
||||
s.xsize = xsz;
|
||||
s.ysize = ysz;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline struct hipPos make_hipPos(size_t x, size_t y, size_t z) {
|
||||
struct hipPos p;
|
||||
|
||||
p.x = x;
|
||||
p.y = y;
|
||||
p.z = z;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline struct hipExtent make_hipExtent(size_t w, size_t h, size_t d) {
|
||||
struct hipExtent e;
|
||||
|
||||
e.width = w;
|
||||
e.height = h;
|
||||
e.depth = d;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
typedef enum hipFunction_attribute {
|
||||
HIP_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK,
|
||||
HIP_FUNC_ATTRIBUTE_SHARED_SIZE_BYTES,
|
||||
HIP_FUNC_ATTRIBUTE_CONST_SIZE_BYTES,
|
||||
HIP_FUNC_ATTRIBUTE_LOCAL_SIZE_BYTES,
|
||||
HIP_FUNC_ATTRIBUTE_NUM_REGS,
|
||||
HIP_FUNC_ATTRIBUTE_PTX_VERSION,
|
||||
HIP_FUNC_ATTRIBUTE_BINARY_VERSION,
|
||||
HIP_FUNC_ATTRIBUTE_CACHE_MODE_CA,
|
||||
HIP_FUNC_ATTRIBUTE_MAX_DYNAMIC_SHARED_SIZE_BYTES,
|
||||
HIP_FUNC_ATTRIBUTE_PREFERRED_SHARED_MEMORY_CARVEOUT,
|
||||
HIP_FUNC_ATTRIBUTE_MAX
|
||||
}hipFunction_attribute;
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
#endif
|
||||
@@ -0,0 +1,691 @@
|
||||
|
||||
|
||||
#include "amd_device_functions.h"
|
||||
|
||||
#if __has_builtin(__hip_atomic_compare_exchange_strong)
|
||||
|
||||
#if !__HIP_DEVICE_COMPILE__
|
||||
//TODO: Remove this after compiler pre-defines the following Macros.
|
||||
#define __HIP_MEMORY_SCOPE_SINGLETHREAD 1
|
||||
#define __HIP_MEMORY_SCOPE_WAVEFRONT 2
|
||||
#define __HIP_MEMORY_SCOPE_WORKGROUP 3
|
||||
#define __HIP_MEMORY_SCOPE_AGENT 4
|
||||
#define __HIP_MEMORY_SCOPE_SYSTEM 5
|
||||
#endif
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicCAS(int* address, int compare, int val) {
|
||||
__hip_atomic_compare_exchange_strong(address, &compare, val, __ATOMIC_RELAXED, __ATOMIC_RELAXED,
|
||||
__HIP_MEMORY_SCOPE_AGENT);
|
||||
return compare;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicCAS_system(int* address, int compare, int val) {
|
||||
__hip_atomic_compare_exchange_strong(address, &compare, val, __ATOMIC_RELAXED, __ATOMIC_RELAXED,
|
||||
__HIP_MEMORY_SCOPE_SYSTEM);
|
||||
return compare;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicCAS(unsigned int* address, unsigned int compare, unsigned int val) {
|
||||
__hip_atomic_compare_exchange_strong(address, &compare, val, __ATOMIC_RELAXED, __ATOMIC_RELAXED,
|
||||
__HIP_MEMORY_SCOPE_AGENT);
|
||||
return compare;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicCAS_system(unsigned int* address, unsigned int compare, unsigned int val) {
|
||||
__hip_atomic_compare_exchange_strong(address, &compare, val, __ATOMIC_RELAXED, __ATOMIC_RELAXED,
|
||||
__HIP_MEMORY_SCOPE_SYSTEM);
|
||||
return compare;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicCAS(unsigned long long* address, unsigned long long compare,
|
||||
unsigned long long val) {
|
||||
__hip_atomic_compare_exchange_strong(address, &compare, val, __ATOMIC_RELAXED, __ATOMIC_RELAXED,
|
||||
__HIP_MEMORY_SCOPE_AGENT);
|
||||
return compare;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicCAS_system(unsigned long long* address, unsigned long long compare,
|
||||
unsigned long long val) {
|
||||
__hip_atomic_compare_exchange_strong(address, &compare, val, __ATOMIC_RELAXED, __ATOMIC_RELAXED,
|
||||
__HIP_MEMORY_SCOPE_SYSTEM);
|
||||
return compare;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicAdd(int* address, int val) {
|
||||
return __hip_atomic_fetch_add(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicAdd_system(int* address, int val) {
|
||||
return __hip_atomic_fetch_add(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicAdd(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_add(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicAdd_system(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_add(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicAdd(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_fetch_add(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicAdd_system(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_fetch_add(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
float atomicAdd(float* address, float val) {
|
||||
return __hip_atomic_fetch_add(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
float atomicAdd_system(float* address, float val) {
|
||||
return __hip_atomic_fetch_add(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
DEPRECATED("use atomicAdd instead")
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
__device__
|
||||
inline
|
||||
void atomicAddNoRet(float* address, float val)
|
||||
{
|
||||
__ockl_atomic_add_noret_f32(address, val);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
double atomicAdd(double* address, double val) {
|
||||
return __hip_atomic_fetch_add(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
double atomicAdd_system(double* address, double val) {
|
||||
return __hip_atomic_fetch_add(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicSub(int* address, int val) {
|
||||
return __hip_atomic_fetch_add(address, -val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicSub_system(int* address, int val) {
|
||||
return __hip_atomic_fetch_add(address, -val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicSub(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_add(address, -val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicSub_system(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_add(address, -val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicExch(int* address, int val) {
|
||||
return __hip_atomic_exchange(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicExch_system(int* address, int val) {
|
||||
return __hip_atomic_exchange(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicExch(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_exchange(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicExch_system(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_exchange(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicExch(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_exchange(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicExch_system(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_exchange(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
float atomicExch(float* address, float val) {
|
||||
return __hip_atomic_exchange(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
float atomicExch_system(float* address, float val) {
|
||||
return __hip_atomic_exchange(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicMin(int* address, int val) {
|
||||
return __hip_atomic_fetch_min(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicMin_system(int* address, int val) {
|
||||
return __hip_atomic_fetch_min(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicMin(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_min(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicMin_system(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_min(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicMin(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_fetch_min(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicMin_system(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_fetch_min(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicMax(int* address, int val) {
|
||||
return __hip_atomic_fetch_max(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicMax_system(int* address, int val) {
|
||||
return __hip_atomic_fetch_max(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicMax(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_max(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicMax_system(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_max(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicMax(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_fetch_max(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicMax_system(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_fetch_max(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicInc(unsigned int* address, unsigned int val)
|
||||
{
|
||||
__device__
|
||||
extern
|
||||
unsigned int __builtin_amdgcn_atomic_inc(
|
||||
unsigned int*,
|
||||
unsigned int,
|
||||
unsigned int,
|
||||
unsigned int,
|
||||
bool) __asm("llvm.amdgcn.atomic.inc.i32.p0i32");
|
||||
|
||||
return __builtin_amdgcn_atomic_inc(
|
||||
address, val, __ATOMIC_RELAXED, 1 /* Device scope */, false);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicDec(unsigned int* address, unsigned int val)
|
||||
{
|
||||
__device__
|
||||
extern
|
||||
unsigned int __builtin_amdgcn_atomic_dec(
|
||||
unsigned int*,
|
||||
unsigned int,
|
||||
unsigned int,
|
||||
unsigned int,
|
||||
bool) __asm("llvm.amdgcn.atomic.dec.i32.p0i32");
|
||||
|
||||
return __builtin_amdgcn_atomic_dec(
|
||||
address, val, __ATOMIC_RELAXED, 1 /* Device scope */, false);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicAnd(int* address, int val) {
|
||||
return __hip_atomic_fetch_and(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicAnd_system(int* address, int val) {
|
||||
return __hip_atomic_fetch_and(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicAnd(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_and(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicAnd_system(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_and(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicAnd(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_fetch_and(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicAnd_system(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_fetch_and(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicOr(int* address, int val) {
|
||||
return __hip_atomic_fetch_or(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicOr_system(int* address, int val) {
|
||||
return __hip_atomic_fetch_or(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicOr(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_or(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicOr_system(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_or(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicOr(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_fetch_or(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicOr_system(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_fetch_or(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicXor(int* address, int val) {
|
||||
return __hip_atomic_fetch_xor(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicXor_system(int* address, int val) {
|
||||
return __hip_atomic_fetch_xor(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicXor(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_xor(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicXor_system(unsigned int* address, unsigned int val) {
|
||||
return __hip_atomic_fetch_xor(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicXor(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_fetch_xor(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_AGENT);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicXor_system(unsigned long long* address, unsigned long long val) {
|
||||
return __hip_atomic_fetch_xor(address, val, __ATOMIC_RELAXED, __HIP_MEMORY_SCOPE_SYSTEM);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicCAS(int* address, int compare, int val)
|
||||
{
|
||||
__atomic_compare_exchange_n(
|
||||
address, &compare, val, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
|
||||
|
||||
return compare;
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicCAS(
|
||||
unsigned int* address, unsigned int compare, unsigned int val)
|
||||
{
|
||||
__atomic_compare_exchange_n(
|
||||
address, &compare, val, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
|
||||
|
||||
return compare;
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicCAS(
|
||||
unsigned long long* address,
|
||||
unsigned long long compare,
|
||||
unsigned long long val)
|
||||
{
|
||||
__atomic_compare_exchange_n(
|
||||
address, &compare, val, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
|
||||
|
||||
return compare;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicAdd(int* address, int val)
|
||||
{
|
||||
return __atomic_fetch_add(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicAdd(unsigned int* address, unsigned int val)
|
||||
{
|
||||
return __atomic_fetch_add(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicAdd(
|
||||
unsigned long long* address, unsigned long long val)
|
||||
{
|
||||
return __atomic_fetch_add(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
float atomicAdd(float* address, float val)
|
||||
{
|
||||
return __atomic_fetch_add(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
DEPRECATED("use atomicAdd instead")
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
__device__
|
||||
inline
|
||||
void atomicAddNoRet(float* address, float val)
|
||||
{
|
||||
__ockl_atomic_add_noret_f32(address, val);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
double atomicAdd(double* address, double val)
|
||||
{
|
||||
return __atomic_fetch_add(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicSub(int* address, int val)
|
||||
{
|
||||
return __atomic_fetch_sub(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicSub(unsigned int* address, unsigned int val)
|
||||
{
|
||||
return __atomic_fetch_sub(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicExch(int* address, int val)
|
||||
{
|
||||
return __atomic_exchange_n(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicExch(unsigned int* address, unsigned int val)
|
||||
{
|
||||
return __atomic_exchange_n(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicExch(unsigned long long* address, unsigned long long val)
|
||||
{
|
||||
return __atomic_exchange_n(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
float atomicExch(float* address, float val)
|
||||
{
|
||||
return __uint_as_float(__atomic_exchange_n(
|
||||
reinterpret_cast<unsigned int*>(address),
|
||||
__float_as_uint(val),
|
||||
__ATOMIC_RELAXED));
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicMin(int* address, int val)
|
||||
{
|
||||
return __atomic_fetch_min(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicMin(unsigned int* address, unsigned int val)
|
||||
{
|
||||
return __atomic_fetch_min(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicMin(
|
||||
unsigned long long* address, unsigned long long val)
|
||||
{
|
||||
unsigned long long tmp{__atomic_load_n(address, __ATOMIC_RELAXED)};
|
||||
while (val < tmp) {
|
||||
const auto tmp1 = __atomic_load_n(address, __ATOMIC_RELAXED);
|
||||
|
||||
if (tmp1 != tmp) { tmp = tmp1; continue; }
|
||||
|
||||
tmp = atomicCAS(address, tmp, val);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicMax(int* address, int val)
|
||||
{
|
||||
return __atomic_fetch_max(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicMax(unsigned int* address, unsigned int val)
|
||||
{
|
||||
return __atomic_fetch_max(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicMax(
|
||||
unsigned long long* address, unsigned long long val)
|
||||
{
|
||||
unsigned long long tmp{__atomic_load_n(address, __ATOMIC_RELAXED)};
|
||||
while (tmp < val) {
|
||||
const auto tmp1 = __atomic_load_n(address, __ATOMIC_RELAXED);
|
||||
|
||||
if (tmp1 != tmp) { tmp = tmp1; continue; }
|
||||
|
||||
tmp = atomicCAS(address, tmp, val);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicInc(unsigned int* address, unsigned int val)
|
||||
{
|
||||
__device__
|
||||
extern
|
||||
unsigned int __builtin_amdgcn_atomic_inc(
|
||||
unsigned int*,
|
||||
unsigned int,
|
||||
unsigned int,
|
||||
unsigned int,
|
||||
bool) __asm("llvm.amdgcn.atomic.inc.i32.p0i32");
|
||||
|
||||
return __builtin_amdgcn_atomic_inc(
|
||||
address, val, __ATOMIC_RELAXED, 1 /* Device scope */, false);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicDec(unsigned int* address, unsigned int val)
|
||||
{
|
||||
__device__
|
||||
extern
|
||||
unsigned int __builtin_amdgcn_atomic_dec(
|
||||
unsigned int*,
|
||||
unsigned int,
|
||||
unsigned int,
|
||||
unsigned int,
|
||||
bool) __asm("llvm.amdgcn.atomic.dec.i32.p0i32");
|
||||
|
||||
return __builtin_amdgcn_atomic_dec(
|
||||
address, val, __ATOMIC_RELAXED, 1 /* Device scope */, false);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicAnd(int* address, int val)
|
||||
{
|
||||
return __atomic_fetch_and(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicAnd(unsigned int* address, unsigned int val)
|
||||
{
|
||||
return __atomic_fetch_and(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicAnd(
|
||||
unsigned long long* address, unsigned long long val)
|
||||
{
|
||||
return __atomic_fetch_and(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicOr(int* address, int val)
|
||||
{
|
||||
return __atomic_fetch_or(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicOr(unsigned int* address, unsigned int val)
|
||||
{
|
||||
return __atomic_fetch_or(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicOr(
|
||||
unsigned long long* address, unsigned long long val)
|
||||
{
|
||||
return __atomic_fetch_or(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
__device__
|
||||
inline
|
||||
int atomicXor(int* address, int val)
|
||||
{
|
||||
return __atomic_fetch_xor(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned int atomicXor(unsigned int* address, unsigned int val)
|
||||
{
|
||||
return __atomic_fetch_xor(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
__device__
|
||||
inline
|
||||
unsigned long long atomicXor(
|
||||
unsigned long long* address, unsigned long long val)
|
||||
{
|
||||
return __atomic_fetch_xor(address, val, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright (c) 2019 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COMMON_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COMMON_H
|
||||
|
||||
#if defined(__clang__) && defined(__HIP__)
|
||||
#define __HIP_CLANG_ONLY__ 1
|
||||
#else
|
||||
#define __HIP_CLANG_ONLY__ 0
|
||||
#endif
|
||||
|
||||
#endif // HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COMMON_H
|
||||
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COMPLEX_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COMPLEX_H
|
||||
|
||||
#include "hip/amd_detail/amd_hip_vector_types.h"
|
||||
|
||||
#if defined(__HIPCC_RTC__)
|
||||
#define __HOST_DEVICE__ __device__
|
||||
#else
|
||||
#define __HOST_DEVICE__ __host__ __device__
|
||||
// TODO: Clang has a bug which allows device functions to call std functions
|
||||
// when std functions are introduced into default namespace by using statement.
|
||||
// math.h may be included after this bug is fixed.
|
||||
#if __cplusplus
|
||||
#include <cmath>
|
||||
#else
|
||||
#include "math.h"
|
||||
#endif
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
|
||||
#if __cplusplus
|
||||
#define COMPLEX_NEG_OP_OVERLOAD(type) \
|
||||
__HOST_DEVICE__ static inline type operator-(const type& op) { \
|
||||
type ret; \
|
||||
ret.x = -op.x; \
|
||||
ret.y = -op.y; \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define COMPLEX_EQ_OP_OVERLOAD(type) \
|
||||
__HOST_DEVICE__ static inline bool operator==(const type& lhs, const type& rhs) { \
|
||||
return lhs.x == rhs.x && lhs.y == rhs.y; \
|
||||
}
|
||||
|
||||
#define COMPLEX_NE_OP_OVERLOAD(type) \
|
||||
__HOST_DEVICE__ static inline bool operator!=(const type& lhs, const type& rhs) { \
|
||||
return !(lhs == rhs); \
|
||||
}
|
||||
|
||||
#define COMPLEX_ADD_OP_OVERLOAD(type) \
|
||||
__HOST_DEVICE__ static inline type operator+(const type& lhs, const type& rhs) { \
|
||||
type ret; \
|
||||
ret.x = lhs.x + rhs.x; \
|
||||
ret.y = lhs.y + rhs.y; \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define COMPLEX_SUB_OP_OVERLOAD(type) \
|
||||
__HOST_DEVICE__ static inline type operator-(const type& lhs, const type& rhs) { \
|
||||
type ret; \
|
||||
ret.x = lhs.x - rhs.x; \
|
||||
ret.y = lhs.y - rhs.y; \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define COMPLEX_MUL_OP_OVERLOAD(type) \
|
||||
__HOST_DEVICE__ static inline type operator*(const type& lhs, const type& rhs) { \
|
||||
type ret; \
|
||||
ret.x = lhs.x * rhs.x - lhs.y * rhs.y; \
|
||||
ret.y = lhs.x * rhs.y + lhs.y * rhs.x; \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define COMPLEX_DIV_OP_OVERLOAD(type) \
|
||||
__HOST_DEVICE__ static inline type operator/(const type& lhs, const type& rhs) { \
|
||||
type ret; \
|
||||
ret.x = (lhs.x * rhs.x + lhs.y * rhs.y); \
|
||||
ret.y = (rhs.x * lhs.y - lhs.x * rhs.y); \
|
||||
ret.x = ret.x / (rhs.x * rhs.x + rhs.y * rhs.y); \
|
||||
ret.y = ret.y / (rhs.x * rhs.x + rhs.y * rhs.y); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define COMPLEX_ADD_PREOP_OVERLOAD(type) \
|
||||
__HOST_DEVICE__ static inline type& operator+=(type& lhs, const type& rhs) { \
|
||||
lhs.x += rhs.x; \
|
||||
lhs.y += rhs.y; \
|
||||
return lhs; \
|
||||
}
|
||||
|
||||
#define COMPLEX_SUB_PREOP_OVERLOAD(type) \
|
||||
__HOST_DEVICE__ static inline type& operator-=(type& lhs, const type& rhs) { \
|
||||
lhs.x -= rhs.x; \
|
||||
lhs.y -= rhs.y; \
|
||||
return lhs; \
|
||||
}
|
||||
|
||||
#define COMPLEX_MUL_PREOP_OVERLOAD(type) \
|
||||
__HOST_DEVICE__ static inline type& operator*=(type& lhs, const type& rhs) { \
|
||||
lhs = lhs * rhs; \
|
||||
return lhs; \
|
||||
}
|
||||
|
||||
#define COMPLEX_DIV_PREOP_OVERLOAD(type) \
|
||||
__HOST_DEVICE__ static inline type& operator/=(type& lhs, const type& rhs) { \
|
||||
lhs = lhs / rhs; \
|
||||
return lhs; \
|
||||
}
|
||||
|
||||
#define COMPLEX_SCALAR_PRODUCT(type, type1) \
|
||||
__HOST_DEVICE__ static inline type operator*(const type& lhs, type1 rhs) { \
|
||||
type ret; \
|
||||
ret.x = lhs.x * rhs; \
|
||||
ret.y = lhs.y * rhs; \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
typedef float2 hipFloatComplex;
|
||||
|
||||
__HOST_DEVICE__ static inline float hipCrealf(hipFloatComplex z) { return z.x; }
|
||||
|
||||
__HOST_DEVICE__ static inline float hipCimagf(hipFloatComplex z) { return z.y; }
|
||||
|
||||
__HOST_DEVICE__ static inline hipFloatComplex make_hipFloatComplex(float a, float b) {
|
||||
hipFloatComplex z;
|
||||
z.x = a;
|
||||
z.y = b;
|
||||
return z;
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipFloatComplex hipConjf(hipFloatComplex z) {
|
||||
hipFloatComplex ret;
|
||||
ret.x = z.x;
|
||||
ret.y = -z.y;
|
||||
return ret;
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline float hipCsqabsf(hipFloatComplex z) {
|
||||
return z.x * z.x + z.y * z.y;
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipFloatComplex hipCaddf(hipFloatComplex p, hipFloatComplex q) {
|
||||
return make_hipFloatComplex(p.x + q.x, p.y + q.y);
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipFloatComplex hipCsubf(hipFloatComplex p, hipFloatComplex q) {
|
||||
return make_hipFloatComplex(p.x - q.x, p.y - q.y);
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipFloatComplex hipCmulf(hipFloatComplex p, hipFloatComplex q) {
|
||||
return make_hipFloatComplex(p.x * q.x - p.y * q.y, p.y * q.x + p.x * q.y);
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipFloatComplex hipCdivf(hipFloatComplex p, hipFloatComplex q) {
|
||||
float sqabs = hipCsqabsf(q);
|
||||
hipFloatComplex ret;
|
||||
ret.x = (p.x * q.x + p.y * q.y) / sqabs;
|
||||
ret.y = (p.y * q.x - p.x * q.y) / sqabs;
|
||||
return ret;
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline float hipCabsf(hipFloatComplex z) { return sqrtf(hipCsqabsf(z)); }
|
||||
|
||||
|
||||
typedef double2 hipDoubleComplex;
|
||||
|
||||
__HOST_DEVICE__ static inline double hipCreal(hipDoubleComplex z) { return z.x; }
|
||||
|
||||
__HOST_DEVICE__ static inline double hipCimag(hipDoubleComplex z) { return z.y; }
|
||||
|
||||
__HOST_DEVICE__ static inline hipDoubleComplex make_hipDoubleComplex(double a, double b) {
|
||||
hipDoubleComplex z;
|
||||
z.x = a;
|
||||
z.y = b;
|
||||
return z;
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipDoubleComplex hipConj(hipDoubleComplex z) {
|
||||
hipDoubleComplex ret;
|
||||
ret.x = z.x;
|
||||
ret.y = -z.y;
|
||||
return ret;
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline double hipCsqabs(hipDoubleComplex z) {
|
||||
return z.x * z.x + z.y * z.y;
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipDoubleComplex hipCadd(hipDoubleComplex p, hipDoubleComplex q) {
|
||||
return make_hipDoubleComplex(p.x + q.x, p.y + q.y);
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipDoubleComplex hipCsub(hipDoubleComplex p, hipDoubleComplex q) {
|
||||
return make_hipDoubleComplex(p.x - q.x, p.y - q.y);
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipDoubleComplex hipCmul(hipDoubleComplex p, hipDoubleComplex q) {
|
||||
return make_hipDoubleComplex(p.x * q.x - p.y * q.y, p.y * q.x + p.x * q.y);
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipDoubleComplex hipCdiv(hipDoubleComplex p, hipDoubleComplex q) {
|
||||
double sqabs = hipCsqabs(q);
|
||||
hipDoubleComplex ret;
|
||||
ret.x = (p.x * q.x + p.y * q.y) / sqabs;
|
||||
ret.y = (p.y * q.x - p.x * q.y) / sqabs;
|
||||
return ret;
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline double hipCabs(hipDoubleComplex z) { return sqrt(hipCsqabs(z)); }
|
||||
|
||||
|
||||
#if __cplusplus
|
||||
|
||||
COMPLEX_NEG_OP_OVERLOAD(hipFloatComplex)
|
||||
COMPLEX_EQ_OP_OVERLOAD(hipFloatComplex)
|
||||
COMPLEX_NE_OP_OVERLOAD(hipFloatComplex)
|
||||
COMPLEX_ADD_OP_OVERLOAD(hipFloatComplex)
|
||||
COMPLEX_SUB_OP_OVERLOAD(hipFloatComplex)
|
||||
COMPLEX_MUL_OP_OVERLOAD(hipFloatComplex)
|
||||
COMPLEX_DIV_OP_OVERLOAD(hipFloatComplex)
|
||||
COMPLEX_ADD_PREOP_OVERLOAD(hipFloatComplex)
|
||||
COMPLEX_SUB_PREOP_OVERLOAD(hipFloatComplex)
|
||||
COMPLEX_MUL_PREOP_OVERLOAD(hipFloatComplex)
|
||||
COMPLEX_DIV_PREOP_OVERLOAD(hipFloatComplex)
|
||||
COMPLEX_SCALAR_PRODUCT(hipFloatComplex, unsigned short)
|
||||
COMPLEX_SCALAR_PRODUCT(hipFloatComplex, signed short)
|
||||
COMPLEX_SCALAR_PRODUCT(hipFloatComplex, unsigned int)
|
||||
COMPLEX_SCALAR_PRODUCT(hipFloatComplex, signed int)
|
||||
COMPLEX_SCALAR_PRODUCT(hipFloatComplex, float)
|
||||
COMPLEX_SCALAR_PRODUCT(hipFloatComplex, unsigned long)
|
||||
COMPLEX_SCALAR_PRODUCT(hipFloatComplex, signed long)
|
||||
COMPLEX_SCALAR_PRODUCT(hipFloatComplex, double)
|
||||
COMPLEX_SCALAR_PRODUCT(hipFloatComplex, signed long long)
|
||||
COMPLEX_SCALAR_PRODUCT(hipFloatComplex, unsigned long long)
|
||||
|
||||
COMPLEX_NEG_OP_OVERLOAD(hipDoubleComplex)
|
||||
COMPLEX_EQ_OP_OVERLOAD(hipDoubleComplex)
|
||||
COMPLEX_NE_OP_OVERLOAD(hipDoubleComplex)
|
||||
COMPLEX_ADD_OP_OVERLOAD(hipDoubleComplex)
|
||||
COMPLEX_SUB_OP_OVERLOAD(hipDoubleComplex)
|
||||
COMPLEX_MUL_OP_OVERLOAD(hipDoubleComplex)
|
||||
COMPLEX_DIV_OP_OVERLOAD(hipDoubleComplex)
|
||||
COMPLEX_ADD_PREOP_OVERLOAD(hipDoubleComplex)
|
||||
COMPLEX_SUB_PREOP_OVERLOAD(hipDoubleComplex)
|
||||
COMPLEX_MUL_PREOP_OVERLOAD(hipDoubleComplex)
|
||||
COMPLEX_DIV_PREOP_OVERLOAD(hipDoubleComplex)
|
||||
COMPLEX_SCALAR_PRODUCT(hipDoubleComplex, unsigned short)
|
||||
COMPLEX_SCALAR_PRODUCT(hipDoubleComplex, signed short)
|
||||
COMPLEX_SCALAR_PRODUCT(hipDoubleComplex, unsigned int)
|
||||
COMPLEX_SCALAR_PRODUCT(hipDoubleComplex, signed int)
|
||||
COMPLEX_SCALAR_PRODUCT(hipDoubleComplex, float)
|
||||
COMPLEX_SCALAR_PRODUCT(hipDoubleComplex, unsigned long)
|
||||
COMPLEX_SCALAR_PRODUCT(hipDoubleComplex, signed long)
|
||||
COMPLEX_SCALAR_PRODUCT(hipDoubleComplex, double)
|
||||
COMPLEX_SCALAR_PRODUCT(hipDoubleComplex, signed long long)
|
||||
COMPLEX_SCALAR_PRODUCT(hipDoubleComplex, unsigned long long)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef hipFloatComplex hipComplex;
|
||||
|
||||
__HOST_DEVICE__ static inline hipComplex make_hipComplex(float x, float y) {
|
||||
return make_hipFloatComplex(x, y);
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipFloatComplex hipComplexDoubleToFloat(hipDoubleComplex z) {
|
||||
return make_hipFloatComplex((float)z.x, (float)z.y);
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipDoubleComplex hipComplexFloatToDouble(hipFloatComplex z) {
|
||||
return make_hipDoubleComplex((double)z.x, (double)z.y);
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipComplex hipCfmaf(hipComplex p, hipComplex q, hipComplex r) {
|
||||
float real = (p.x * q.x) + r.x;
|
||||
float imag = (q.x * p.y) + r.y;
|
||||
|
||||
real = -(p.y * q.y) + real;
|
||||
imag = (p.x * q.y) + imag;
|
||||
|
||||
return make_hipComplex(real, imag);
|
||||
}
|
||||
|
||||
__HOST_DEVICE__ static inline hipDoubleComplex hipCfma(hipDoubleComplex p, hipDoubleComplex q,
|
||||
hipDoubleComplex r) {
|
||||
double real = (p.x * q.x) + r.x;
|
||||
double imag = (q.x * p.y) + r.y;
|
||||
|
||||
real = -(p.y * q.y) + real;
|
||||
imag = (p.x * q.y) + imag;
|
||||
|
||||
return make_hipDoubleComplex(real, imag);
|
||||
}
|
||||
|
||||
#endif //HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COMPLEX_H
|
||||
@@ -0,0 +1,510 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 amd_detail/hip_cooperative_groups.h
|
||||
*
|
||||
* @brief Device side implementation of `Cooperative Group` feature.
|
||||
*
|
||||
* Defines new types and device API wrappers related to `Cooperative Group`
|
||||
* feature, which the programmer can directly use in his kernel(s) in order to
|
||||
* make use of this feature.
|
||||
*/
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COOPERATIVE_GROUPS_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COOPERATIVE_GROUPS_H
|
||||
|
||||
#if __cplusplus
|
||||
#include <hip/amd_detail/hip_cooperative_groups_helper.h>
|
||||
|
||||
namespace cooperative_groups {
|
||||
|
||||
/** \brief The base type of all cooperative group types
|
||||
*
|
||||
* \details Holds the key properties of a constructed cooperative group types
|
||||
* object, like the group type, its size, etc
|
||||
*/
|
||||
class thread_group {
|
||||
protected:
|
||||
uint32_t _type; // thread_group type
|
||||
uint32_t _size; // total number of threads in the tread_group
|
||||
uint64_t _mask; // Lanemask for coalesced and tiled partitioned group types,
|
||||
// LSB represents lane 0, and MSB represents lane 63
|
||||
|
||||
// Construct a thread group, and set thread group type and other essential
|
||||
// thread group properties. This generic thread group is directly constructed
|
||||
// only when the group is supposed to contain only the calling the thread
|
||||
// (throurh the API - `this_thread()`), and in all other cases, this thread
|
||||
// group object is a sub-object of some other derived thread group object
|
||||
__CG_QUALIFIER__ thread_group(internal::group_type type, uint32_t size,
|
||||
uint64_t mask = (uint64_t)0) {
|
||||
_type = type;
|
||||
_size = size;
|
||||
_mask = mask;
|
||||
}
|
||||
|
||||
struct _tiled_info {
|
||||
bool is_tiled;
|
||||
unsigned int size;
|
||||
} tiled_info;
|
||||
|
||||
friend __CG_QUALIFIER__ thread_group tiled_partition(const thread_group& parent,
|
||||
unsigned int tile_size);
|
||||
friend class thread_block;
|
||||
|
||||
public:
|
||||
// Total number of threads in the thread group, and this serves the purpose
|
||||
// for all derived cooperative group types since their `size` is directly
|
||||
// saved during the construction
|
||||
__CG_QUALIFIER__ uint32_t size() const { return _size; }
|
||||
__CG_QUALIFIER__ unsigned int cg_type() const { return _type; }
|
||||
// Rank of the calling thread within [0, size())
|
||||
__CG_QUALIFIER__ uint32_t thread_rank() const;
|
||||
// Is this cooperative group type valid?
|
||||
__CG_QUALIFIER__ bool is_valid() const;
|
||||
// synchronize the threads in the thread group
|
||||
__CG_QUALIFIER__ void sync() const;
|
||||
};
|
||||
|
||||
/** \brief The multi-grid cooperative group type
|
||||
*
|
||||
* \details Represents an inter-device cooperative group type where the
|
||||
* participating threads within the group spans across multple
|
||||
* devices, running the (same) kernel on these devices
|
||||
*/
|
||||
class multi_grid_group : public thread_group {
|
||||
// Only these friend functions are allowed to construct an object of this class
|
||||
// and access its resources
|
||||
friend __CG_QUALIFIER__ multi_grid_group this_multi_grid();
|
||||
|
||||
protected:
|
||||
// Construct mutli-grid thread group (through the API this_multi_grid())
|
||||
explicit __CG_QUALIFIER__ multi_grid_group(uint32_t size)
|
||||
: thread_group(internal::cg_multi_grid, size) {}
|
||||
|
||||
public:
|
||||
// Number of invocations participating in this multi-grid group. In other
|
||||
// words, the number of GPUs
|
||||
__CG_QUALIFIER__ uint32_t num_grids() { return internal::multi_grid::num_grids(); }
|
||||
// Rank of this invocation. In other words, an ID number within the range
|
||||
// [0, num_grids()) of the GPU, this kernel is running on
|
||||
__CG_QUALIFIER__ uint32_t grid_rank() { return internal::multi_grid::grid_rank(); }
|
||||
__CG_QUALIFIER__ uint32_t thread_rank() const { return internal::multi_grid::thread_rank(); }
|
||||
__CG_QUALIFIER__ bool is_valid() const { return internal::multi_grid::is_valid(); }
|
||||
__CG_QUALIFIER__ void sync() const { internal::multi_grid::sync(); }
|
||||
};
|
||||
|
||||
/** \brief User exposed API interface to construct multi-grid cooperative
|
||||
* group type object - `multi_grid_group`
|
||||
*
|
||||
* \details User is not allowed to directly construct an object of type
|
||||
* `multi_grid_group`. Instead, he should construct it through this
|
||||
* API function
|
||||
*/
|
||||
__CG_QUALIFIER__ multi_grid_group this_multi_grid() {
|
||||
return multi_grid_group(internal::multi_grid::size());
|
||||
}
|
||||
|
||||
/** \brief The grid cooperative group type
|
||||
*
|
||||
* \details Represents an inter-workgroup cooperative group type where the
|
||||
* participating threads within the group spans across multiple
|
||||
* workgroups running the (same) kernel on the same device
|
||||
*/
|
||||
class grid_group : public thread_group {
|
||||
// Only these friend functions are allowed to construct an object of this class
|
||||
// and access its resources
|
||||
friend __CG_QUALIFIER__ grid_group this_grid();
|
||||
|
||||
protected:
|
||||
// Construct grid thread group (through the API this_grid())
|
||||
explicit __CG_QUALIFIER__ grid_group(uint32_t size) : thread_group(internal::cg_grid, size) {}
|
||||
|
||||
public:
|
||||
__CG_QUALIFIER__ uint32_t thread_rank() const { return internal::grid::thread_rank(); }
|
||||
__CG_QUALIFIER__ bool is_valid() const { return internal::grid::is_valid(); }
|
||||
__CG_QUALIFIER__ void sync() const { internal::grid::sync(); }
|
||||
};
|
||||
|
||||
/** \brief User exposed API interface to construct grid cooperative group type
|
||||
* object - `grid_group`
|
||||
*
|
||||
* \details User is not allowed to directly construct an object of type
|
||||
* `multi_grid_group`. Instead, he should construct it through this
|
||||
* API function
|
||||
*/
|
||||
__CG_QUALIFIER__ grid_group this_grid() { return grid_group(internal::grid::size()); }
|
||||
|
||||
/** \brief The workgroup (thread-block in CUDA terminology) cooperative group
|
||||
* type
|
||||
*
|
||||
* \details Represents an intra-workgroup cooperative group type where the
|
||||
* participating threads within the group are exactly the same threads
|
||||
* which are participated in the currently executing `workgroup`
|
||||
*/
|
||||
class thread_block : public thread_group {
|
||||
// Only these friend functions are allowed to construct an object of thi
|
||||
// class and access its resources
|
||||
friend __CG_QUALIFIER__ thread_block this_thread_block();
|
||||
friend __CG_QUALIFIER__ thread_group tiled_partition(const thread_group& parent,
|
||||
unsigned int tile_size);
|
||||
friend __CG_QUALIFIER__ thread_group tiled_partition(const thread_block& parent,
|
||||
unsigned int tile_size);
|
||||
|
||||
protected:
|
||||
// Construct a workgroup thread group (through the API this_thread_block())
|
||||
explicit __CG_QUALIFIER__ thread_block(uint32_t size)
|
||||
: thread_group(internal::cg_workgroup, size) {}
|
||||
|
||||
__CG_QUALIFIER__ thread_group new_tiled_group(unsigned int tile_size) const {
|
||||
const bool pow2 = ((tile_size & (tile_size - 1)) == 0);
|
||||
// Invalid tile size, assert
|
||||
if (!tile_size || (tile_size > WAVEFRONT_SIZE) || !pow2) {
|
||||
assert(false && "invalid tile size");
|
||||
}
|
||||
|
||||
thread_group tiledGroup = thread_group(internal::cg_tiled_group, tile_size);
|
||||
tiledGroup.tiled_info.size = tile_size;
|
||||
tiledGroup.tiled_info.is_tiled = true;
|
||||
return tiledGroup;
|
||||
}
|
||||
|
||||
public:
|
||||
// 3-dimensional block index within the grid
|
||||
__CG_QUALIFIER__ dim3 group_index() { return internal::workgroup::group_index(); }
|
||||
// 3-dimensional thread index within the block
|
||||
__CG_QUALIFIER__ dim3 thread_index() { return internal::workgroup::thread_index(); }
|
||||
__CG_QUALIFIER__ uint32_t thread_rank() const { return internal::workgroup::thread_rank(); }
|
||||
__CG_QUALIFIER__ bool is_valid() const { return internal::workgroup::is_valid(); }
|
||||
__CG_QUALIFIER__ void sync() const { internal::workgroup::sync(); }
|
||||
};
|
||||
|
||||
/** \brief User exposed API interface to construct workgroup cooperative
|
||||
* group type object - `thread_block`.
|
||||
*
|
||||
* \details User is not allowed to directly construct an object of type
|
||||
* `thread_block`. Instead, he should construct it through this API
|
||||
* function.
|
||||
*/
|
||||
__CG_QUALIFIER__ thread_block this_thread_block() {
|
||||
return thread_block(internal::workgroup::size());
|
||||
}
|
||||
|
||||
/** \brief The tiled_group cooperative group type
|
||||
*
|
||||
* \details Represents one tiled thread group in a wavefront.
|
||||
* This group type also supports sub-wave level intrinsics.
|
||||
*/
|
||||
|
||||
class tiled_group : public thread_group {
|
||||
private:
|
||||
friend __CG_QUALIFIER__ thread_group tiled_partition(const thread_group& parent,
|
||||
unsigned int tile_size);
|
||||
friend __CG_QUALIFIER__ tiled_group tiled_partition(const tiled_group& parent,
|
||||
unsigned int tile_size);
|
||||
|
||||
__CG_QUALIFIER__ tiled_group new_tiled_group(unsigned int tile_size) const {
|
||||
const bool pow2 = ((tile_size & (tile_size - 1)) == 0);
|
||||
|
||||
if (!tile_size || (tile_size > WAVEFRONT_SIZE) || !pow2) {
|
||||
assert(false && "invalid tile size");
|
||||
}
|
||||
|
||||
if (size() <= tile_size) {
|
||||
return (*this);
|
||||
}
|
||||
|
||||
tiled_group tiledGroup = tiled_group(tile_size);
|
||||
tiledGroup.tiled_info.is_tiled = true;
|
||||
return tiledGroup;
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit __CG_QUALIFIER__ tiled_group(unsigned int tileSize)
|
||||
: thread_group(internal::cg_tiled_group, tileSize) {
|
||||
tiled_info.size = tileSize;
|
||||
tiled_info.is_tiled = true;
|
||||
}
|
||||
|
||||
public:
|
||||
__CG_QUALIFIER__ unsigned int size() const { return (tiled_info.size); }
|
||||
|
||||
__CG_QUALIFIER__ unsigned int thread_rank() const {
|
||||
return (internal::workgroup::thread_rank() & (tiled_info.size - 1));
|
||||
}
|
||||
|
||||
__CG_QUALIFIER__ void sync() const {
|
||||
// enforce memory ordering for memory instructions.
|
||||
__builtin_amdgcn_fence(__ATOMIC_ACQ_REL, "agent");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implemenation of all publicly exposed base class APIs
|
||||
*/
|
||||
__CG_QUALIFIER__ uint32_t thread_group::thread_rank() const {
|
||||
switch (this->_type) {
|
||||
case internal::cg_multi_grid: {
|
||||
return (static_cast<const multi_grid_group*>(this)->thread_rank());
|
||||
}
|
||||
case internal::cg_grid: {
|
||||
return (static_cast<const grid_group*>(this)->thread_rank());
|
||||
}
|
||||
case internal::cg_workgroup: {
|
||||
return (static_cast<const thread_block*>(this)->thread_rank());
|
||||
}
|
||||
case internal::cg_tiled_group: {
|
||||
return (static_cast<const tiled_group*>(this)->thread_rank());
|
||||
}
|
||||
default: {
|
||||
assert(false && "invalid cooperative group type");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__CG_QUALIFIER__ bool thread_group::is_valid() const {
|
||||
switch (this->_type) {
|
||||
case internal::cg_multi_grid: {
|
||||
return (static_cast<const multi_grid_group*>(this)->is_valid());
|
||||
}
|
||||
case internal::cg_grid: {
|
||||
return (static_cast<const grid_group*>(this)->is_valid());
|
||||
}
|
||||
case internal::cg_workgroup: {
|
||||
return (static_cast<const thread_block*>(this)->is_valid());
|
||||
}
|
||||
case internal::cg_tiled_group: {
|
||||
return (static_cast<const tiled_group*>(this)->is_valid());
|
||||
}
|
||||
default: {
|
||||
assert(false && "invalid cooperative group type");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__CG_QUALIFIER__ void thread_group::sync() const {
|
||||
switch (this->_type) {
|
||||
case internal::cg_multi_grid: {
|
||||
static_cast<const multi_grid_group*>(this)->sync();
|
||||
break;
|
||||
}
|
||||
case internal::cg_grid: {
|
||||
static_cast<const grid_group*>(this)->sync();
|
||||
break;
|
||||
}
|
||||
case internal::cg_workgroup: {
|
||||
static_cast<const thread_block*>(this)->sync();
|
||||
break;
|
||||
}
|
||||
case internal::cg_tiled_group: {
|
||||
static_cast<const tiled_group*>(this)->sync();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert(false && "invalid cooperative group type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implemenation of publicly exposed `wrapper` APIs on top of basic cooperative
|
||||
* group type APIs
|
||||
*/
|
||||
template <class CGTy> __CG_QUALIFIER__ uint32_t group_size(CGTy const& g) { return g.size(); }
|
||||
|
||||
template <class CGTy> __CG_QUALIFIER__ uint32_t thread_rank(CGTy const& g) {
|
||||
return g.thread_rank();
|
||||
}
|
||||
|
||||
template <class CGTy> __CG_QUALIFIER__ bool is_valid(CGTy const& g) { return g.is_valid(); }
|
||||
|
||||
template <class CGTy> __CG_QUALIFIER__ void sync(CGTy const& g) { g.sync(); }
|
||||
|
||||
template <unsigned int tileSize> class tile_base {
|
||||
protected:
|
||||
_CG_STATIC_CONST_DECL_ unsigned int numThreads = tileSize;
|
||||
|
||||
public:
|
||||
// Rank of the thread within this tile
|
||||
_CG_STATIC_CONST_DECL_ unsigned int thread_rank() {
|
||||
return (internal::workgroup::thread_rank() & (numThreads - 1));
|
||||
}
|
||||
|
||||
// Number of threads within this tile
|
||||
__CG_STATIC_QUALIFIER__ unsigned int size() { return numThreads; }
|
||||
};
|
||||
|
||||
template <unsigned int size> class thread_block_tile_base : public tile_base<size> {
|
||||
static_assert(is_valid_tile_size<size>::value,
|
||||
"Tile size is either not a power of 2 or greater than the wavefront size");
|
||||
using tile_base<size>::numThreads;
|
||||
|
||||
public:
|
||||
__CG_STATIC_QUALIFIER__ void sync() {
|
||||
// enforce ordering for memory instructions
|
||||
__builtin_amdgcn_fence(__ATOMIC_ACQ_REL, "agent");
|
||||
}
|
||||
|
||||
template <class T> __CG_QUALIFIER__ T shfl(T var, int srcRank) const {
|
||||
static_assert(is_valid_type<T>::value, "Neither an integer or float type.");
|
||||
return (__shfl(var, srcRank, numThreads));
|
||||
}
|
||||
|
||||
template <class T> __CG_QUALIFIER__ T shfl_down(T var, unsigned int lane_delta) const {
|
||||
static_assert(is_valid_type<T>::value, "Neither an integer or float type.");
|
||||
return (__shfl_down(var, lane_delta, numThreads));
|
||||
}
|
||||
|
||||
template <class T> __CG_QUALIFIER__ T shfl_up(T var, unsigned int lane_delta) const {
|
||||
static_assert(is_valid_type<T>::value, "Neither an integer or float type.");
|
||||
return (__shfl_up(var, lane_delta, numThreads));
|
||||
}
|
||||
|
||||
template <class T> __CG_QUALIFIER__ T shfl_xor(T var, unsigned int laneMask) const {
|
||||
static_assert(is_valid_type<T>::value, "Neither an integer or float type.");
|
||||
return (__shfl_xor(var, laneMask, numThreads));
|
||||
}
|
||||
};
|
||||
|
||||
/** \brief Group type - thread_block_tile
|
||||
*
|
||||
* \details Represents one tile of thread group.
|
||||
*/
|
||||
|
||||
template <unsigned int tileSize, class ParentCGTy = void>
|
||||
class thread_block_tile_type : public thread_block_tile_base<tileSize>, public tiled_group {
|
||||
_CG_STATIC_CONST_DECL_ unsigned int numThreads = tileSize;
|
||||
|
||||
friend class thread_block_tile_type<tileSize, ParentCGTy>;
|
||||
|
||||
typedef thread_block_tile_base<numThreads> tbtBase;
|
||||
|
||||
protected:
|
||||
__CG_QUALIFIER__ thread_block_tile_type() : tiled_group(numThreads) {
|
||||
tiled_info.size = numThreads;
|
||||
tiled_info.is_tiled = true;
|
||||
}
|
||||
|
||||
public:
|
||||
using tbtBase::size;
|
||||
using tbtBase::sync;
|
||||
using tbtBase::thread_rank;
|
||||
};
|
||||
|
||||
|
||||
/** \brief User exposed API to partition groups.
|
||||
*
|
||||
* \details A collective operation that partitions the parent group into a one-dimensional,
|
||||
* row-major, tiling of subgroups.
|
||||
*/
|
||||
|
||||
__CG_QUALIFIER__ thread_group tiled_partition(const thread_group& parent, unsigned int tile_size) {
|
||||
if (parent.cg_type() == internal::cg_tiled_group) {
|
||||
const tiled_group* cg = static_cast<const tiled_group*>(&parent);
|
||||
return cg->new_tiled_group(tile_size);
|
||||
} else {
|
||||
const thread_block* tb = static_cast<const thread_block*>(&parent);
|
||||
return tb->new_tiled_group(tile_size);
|
||||
}
|
||||
}
|
||||
|
||||
// Thread block type overload
|
||||
__CG_QUALIFIER__ thread_group tiled_partition(const thread_block& parent, unsigned int tile_size) {
|
||||
return (parent.new_tiled_group(tile_size));
|
||||
}
|
||||
|
||||
// Coalesced group type overload
|
||||
__CG_QUALIFIER__ tiled_group tiled_partition(const tiled_group& parent, unsigned int tile_size) {
|
||||
return (parent.new_tiled_group(tile_size));
|
||||
}
|
||||
|
||||
template <unsigned int size, class ParentCGTy> class thread_block_tile;
|
||||
|
||||
namespace impl {
|
||||
template <unsigned int size, class ParentCGTy> class thread_block_tile_internal;
|
||||
|
||||
template <unsigned int size, class ParentCGTy>
|
||||
class thread_block_tile_internal : public thread_block_tile_type<size, ParentCGTy> {
|
||||
protected:
|
||||
template <unsigned int tbtSize, class tbtParentT>
|
||||
__CG_QUALIFIER__ thread_block_tile_internal(
|
||||
const thread_block_tile_internal<tbtSize, tbtParentT>& g)
|
||||
: thread_block_tile_type<size, ParentCGTy>() {}
|
||||
|
||||
__CG_QUALIFIER__ thread_block_tile_internal(const thread_block& g)
|
||||
: thread_block_tile_type<size, ParentCGTy>() {}
|
||||
};
|
||||
} // namespace impl
|
||||
|
||||
template <unsigned int size, class ParentCGTy>
|
||||
class thread_block_tile : public impl::thread_block_tile_internal<size, ParentCGTy> {
|
||||
protected:
|
||||
__CG_QUALIFIER__ thread_block_tile(const ParentCGTy& g)
|
||||
: impl::thread_block_tile_internal<size, ParentCGTy>(g) {}
|
||||
|
||||
public:
|
||||
__CG_QUALIFIER__ operator thread_block_tile<size, void>() const {
|
||||
return thread_block_tile<size, void>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <unsigned int size>
|
||||
class thread_block_tile<size, void> : public impl::thread_block_tile_internal<size, void> {
|
||||
template <unsigned int, class ParentCGTy> friend class thread_block_tile;
|
||||
|
||||
protected:
|
||||
public:
|
||||
template <class ParentCGTy>
|
||||
__CG_QUALIFIER__ thread_block_tile(const thread_block_tile<size, ParentCGTy>& g)
|
||||
: impl::thread_block_tile_internal<size, void>(g) {}
|
||||
};
|
||||
|
||||
template <unsigned int size, class ParentCGTy = void> class thread_block_tile;
|
||||
|
||||
namespace impl {
|
||||
template <unsigned int size, class ParentCGTy = void> struct tiled_partition_internal;
|
||||
|
||||
template <unsigned int size>
|
||||
struct tiled_partition_internal<size, thread_block> : public thread_block_tile<size, thread_block> {
|
||||
__CG_QUALIFIER__ tiled_partition_internal(const thread_block& g)
|
||||
: thread_block_tile<size, thread_block>(g) {}
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
/** \brief User exposed API to partition groups.
|
||||
*
|
||||
* \details This constructs a templated class derieved from thread_group.
|
||||
* The template defines tile size of the new thread group at compile time.
|
||||
*/
|
||||
template <unsigned int size, class ParentCGTy>
|
||||
__CG_QUALIFIER__ thread_block_tile<size, ParentCGTy> tiled_partition(const ParentCGTy& g) {
|
||||
static_assert(is_valid_tile_size<size>::value,
|
||||
"Tiled partition with size > wavefront size. Currently not supported ");
|
||||
return impl::tiled_partition_internal<size, ParentCGTy>(g);
|
||||
}
|
||||
} // namespace cooperative_groups
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COOPERATIVE_GROUPS_H
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 amd_detail/hip_runtime.h
|
||||
* @brief Contains definitions of APIs for HIP runtime.
|
||||
*/
|
||||
|
||||
//#pragma once
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_HIP_RUNTIME_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_HIP_RUNTIME_H
|
||||
|
||||
#include <hip/amd_detail/amd_hip_common.h>
|
||||
|
||||
//---
|
||||
// Top part of file can be compiled with any compiler
|
||||
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
//#include <cstring>
|
||||
#if __cplusplus
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#endif // __cplusplus
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
|
||||
// __hip_malloc is not working. Disable it by default.
|
||||
#ifndef __HIP_ENABLE_DEVICE_MALLOC__
|
||||
#define __HIP_ENABLE_DEVICE_MALLOC__ 0
|
||||
#endif
|
||||
|
||||
#if __HIP_CLANG_ONLY__
|
||||
|
||||
#if !defined(__align__)
|
||||
#define __align__(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
|
||||
#define CUDA_SUCCESS hipSuccess
|
||||
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
#include <hip/hip_runtime_api.h>
|
||||
extern int HIP_TRACE_API;
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <hip/amd_detail/hip_ldg.h>
|
||||
#endif
|
||||
#include <hip/amd_detail/amd_hip_atomic.h>
|
||||
#include <hip/amd_detail/host_defines.h>
|
||||
#include <hip/amd_detail/amd_device_functions.h>
|
||||
#include <hip/amd_detail/amd_surface_functions.h>
|
||||
#include <hip/amd_detail/texture_fetch_functions.h>
|
||||
#include <hip/amd_detail/texture_indirect_functions.h>
|
||||
|
||||
// TODO-HCC remove old definitions ; ~1602 hcc supports __HCC_ACCELERATOR__ define.
|
||||
#if defined(__KALMAR_ACCELERATOR__) && !defined(__HCC_ACCELERATOR__)
|
||||
#define __HCC_ACCELERATOR__ __KALMAR_ACCELERATOR__
|
||||
#endif
|
||||
|
||||
// Feature tests:
|
||||
#if (defined(__HCC_ACCELERATOR__) && (__HCC_ACCELERATOR__ != 0)) || __HIP_DEVICE_COMPILE__
|
||||
// Device compile and not host compile:
|
||||
|
||||
// 32-bit Atomics:
|
||||
#define __HIP_ARCH_HAS_GLOBAL_INT32_ATOMICS__ (1)
|
||||
#define __HIP_ARCH_HAS_GLOBAL_FLOAT_ATOMIC_EXCH__ (1)
|
||||
#define __HIP_ARCH_HAS_SHARED_INT32_ATOMICS__ (1)
|
||||
#define __HIP_ARCH_HAS_SHARED_FLOAT_ATOMIC_EXCH__ (1)
|
||||
#define __HIP_ARCH_HAS_FLOAT_ATOMIC_ADD__ (1)
|
||||
|
||||
// 64-bit Atomics:
|
||||
#define __HIP_ARCH_HAS_GLOBAL_INT64_ATOMICS__ (1)
|
||||
#define __HIP_ARCH_HAS_SHARED_INT64_ATOMICS__ (1)
|
||||
|
||||
// Doubles
|
||||
#define __HIP_ARCH_HAS_DOUBLES__ (1)
|
||||
|
||||
// warp cross-lane operations:
|
||||
#define __HIP_ARCH_HAS_WARP_VOTE__ (1)
|
||||
#define __HIP_ARCH_HAS_WARP_BALLOT__ (1)
|
||||
#define __HIP_ARCH_HAS_WARP_SHUFFLE__ (1)
|
||||
#define __HIP_ARCH_HAS_WARP_FUNNEL_SHIFT__ (0)
|
||||
|
||||
// sync
|
||||
#define __HIP_ARCH_HAS_THREAD_FENCE_SYSTEM__ (1)
|
||||
#define __HIP_ARCH_HAS_SYNC_THREAD_EXT__ (0)
|
||||
|
||||
// misc
|
||||
#define __HIP_ARCH_HAS_SURFACE_FUNCS__ (0)
|
||||
#define __HIP_ARCH_HAS_3DGRID__ (1)
|
||||
#define __HIP_ARCH_HAS_DYNAMIC_PARALLEL__ (0)
|
||||
|
||||
#endif /* Device feature flags */
|
||||
|
||||
|
||||
#define launch_bounds_impl0(requiredMaxThreadsPerBlock) \
|
||||
__attribute__((amdgpu_flat_work_group_size(1, requiredMaxThreadsPerBlock)))
|
||||
#define launch_bounds_impl1(requiredMaxThreadsPerBlock, minBlocksPerMultiprocessor) \
|
||||
__attribute__((amdgpu_flat_work_group_size(1, requiredMaxThreadsPerBlock), \
|
||||
amdgpu_waves_per_eu(minBlocksPerMultiprocessor)))
|
||||
#define select_impl_(_1, _2, impl_, ...) impl_
|
||||
#define __launch_bounds__(...) \
|
||||
select_impl_(__VA_ARGS__, launch_bounds_impl1, launch_bounds_impl0)(__VA_ARGS__)
|
||||
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
__host__ inline void* __get_dynamicgroupbaseptr() { return nullptr; }
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
|
||||
#if __HIP_ARCH_GFX701__ == 0
|
||||
|
||||
__device__ unsigned __hip_ds_bpermute(int index, unsigned src);
|
||||
__device__ float __hip_ds_bpermutef(int index, float src);
|
||||
__device__ unsigned __hip_ds_permute(int index, unsigned src);
|
||||
__device__ float __hip_ds_permutef(int index, float src);
|
||||
|
||||
template <int pattern>
|
||||
__device__ unsigned __hip_ds_swizzle_N(unsigned int src);
|
||||
template <int pattern>
|
||||
__device__ float __hip_ds_swizzlef_N(float src);
|
||||
|
||||
template <int dpp_ctrl, int row_mask, int bank_mask, bool bound_ctrl>
|
||||
__device__ int __hip_move_dpp_N(int src);
|
||||
|
||||
#endif //__HIP_ARCH_GFX803__ == 1
|
||||
|
||||
#ifndef __OPENMP_AMDGCN__
|
||||
#if !__CLANG_HIP_RUNTIME_WRAPPER_INCLUDED__
|
||||
#if __HIP_ENABLE_DEVICE_MALLOC__
|
||||
extern "C" __device__ void* __hip_malloc(size_t);
|
||||
extern "C" __device__ void* __hip_free(void* ptr);
|
||||
static inline __device__ void* malloc(size_t size) { return __hip_malloc(size); }
|
||||
static inline __device__ void* free(void* ptr) { return __hip_free(ptr); }
|
||||
#else
|
||||
static inline __device__ void* malloc(size_t size) { __builtin_trap(); return nullptr; }
|
||||
static inline __device__ void* free(void* ptr) { __builtin_trap(); return nullptr; }
|
||||
#endif
|
||||
#endif // !__CLANG_HIP_RUNTIME_WRAPPER_INCLUDED__
|
||||
#endif // !__OPENMP_AMDGCN__
|
||||
|
||||
// End doxygen API:
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
//
|
||||
// hip-clang functions
|
||||
//
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
#define HIP_KERNEL_NAME(...) __VA_ARGS__
|
||||
#define HIP_SYMBOL(X) X
|
||||
|
||||
typedef int hipLaunchParm;
|
||||
|
||||
template <std::size_t n, typename... Ts,
|
||||
typename std::enable_if<n == sizeof...(Ts)>::type* = nullptr>
|
||||
void pArgs(const std::tuple<Ts...>&, void*) {}
|
||||
|
||||
template <std::size_t n, typename... Ts,
|
||||
typename std::enable_if<n != sizeof...(Ts)>::type* = nullptr>
|
||||
void pArgs(const std::tuple<Ts...>& formals, void** _vargs) {
|
||||
using T = typename std::tuple_element<n, std::tuple<Ts...> >::type;
|
||||
|
||||
static_assert(!std::is_reference<T>{},
|
||||
"A __global__ function cannot have a reference as one of its "
|
||||
"arguments.");
|
||||
#if defined(HIP_STRICT)
|
||||
static_assert(std::is_trivially_copyable<T>{},
|
||||
"Only TriviallyCopyable types can be arguments to a __global__ "
|
||||
"function");
|
||||
#endif
|
||||
_vargs[n] = const_cast<void*>(reinterpret_cast<const void*>(&std::get<n>(formals)));
|
||||
return pArgs<n + 1>(formals, _vargs);
|
||||
}
|
||||
|
||||
template <typename... Formals, typename... Actuals>
|
||||
std::tuple<Formals...> validateArgsCountType(void (*kernel)(Formals...), std::tuple<Actuals...>(actuals)) {
|
||||
static_assert(sizeof...(Formals) == sizeof...(Actuals), "Argument Count Mismatch");
|
||||
std::tuple<Formals...> to_formals{std::move(actuals)};
|
||||
return to_formals;
|
||||
}
|
||||
|
||||
#if defined(HIP_TEMPLATE_KERNEL_LAUNCH)
|
||||
template <typename... Args, typename F = void (*)(Args...)>
|
||||
void hipLaunchKernelGGL(F kernel, const dim3& numBlocks, const dim3& dimBlocks,
|
||||
std::uint32_t sharedMemBytes, hipStream_t stream, Args... args) {
|
||||
constexpr size_t count = sizeof...(Args);
|
||||
auto tup_ = std::tuple<Args...>{args...};
|
||||
auto tup = validateArgsCountType(kernel, tup_);
|
||||
void* _Args[count];
|
||||
pArgs<0>(tup, _Args);
|
||||
|
||||
auto k = reinterpret_cast<void*>(kernel);
|
||||
hipLaunchKernel(k, numBlocks, dimBlocks, _Args, sharedMemBytes, stream);
|
||||
}
|
||||
#else
|
||||
#define hipLaunchKernelGGLInternal(kernelName, numBlocks, numThreads, memPerBlock, streamId, ...) \
|
||||
do { \
|
||||
kernelName<<<(numBlocks), (numThreads), (memPerBlock), (streamId)>>>(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define hipLaunchKernelGGL(kernelName, ...) hipLaunchKernelGGLInternal((kernelName), __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#include <hip/hip_runtime_api.h>
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
|
||||
extern "C" __device__ __attribute__((const)) size_t __ockl_get_local_id(uint);
|
||||
extern "C" __device__ __attribute__((const)) size_t __ockl_get_group_id(uint);
|
||||
extern "C" __device__ __attribute__((const)) size_t __ockl_get_local_size(uint);
|
||||
extern "C" __device__ __attribute__((const)) size_t __ockl_get_num_groups(uint);
|
||||
struct __HIP_BlockIdx {
|
||||
__device__
|
||||
std::uint32_t operator()(std::uint32_t x) const noexcept { return __ockl_get_group_id(x); }
|
||||
};
|
||||
struct __HIP_BlockDim {
|
||||
__device__
|
||||
std::uint32_t operator()(std::uint32_t x) const noexcept {
|
||||
return __ockl_get_local_size(x);
|
||||
}
|
||||
};
|
||||
struct __HIP_GridDim {
|
||||
__device__
|
||||
std::uint32_t operator()(std::uint32_t x) const noexcept {
|
||||
return __ockl_get_num_groups(x);
|
||||
}
|
||||
};
|
||||
struct __HIP_ThreadIdx {
|
||||
__device__
|
||||
std::uint32_t operator()(std::uint32_t x) const noexcept {
|
||||
return __ockl_get_local_id(x);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__HIPCC_RTC__)
|
||||
typedef struct dim3 {
|
||||
uint32_t x; ///< x
|
||||
uint32_t y; ///< y
|
||||
uint32_t z; ///< z
|
||||
#ifdef __cplusplus
|
||||
constexpr __device__ dim3(uint32_t _x = 1, uint32_t _y = 1, uint32_t _z = 1) : x(_x), y(_y), z(_z){};
|
||||
#endif
|
||||
} dim3;
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
|
||||
template <typename F>
|
||||
struct __HIP_Coordinates {
|
||||
using R = decltype(F{}(0));
|
||||
|
||||
struct __X { __device__ operator R() const noexcept { return F{}(0); } };
|
||||
struct __Y { __device__ operator R() const noexcept { return F{}(1); } };
|
||||
struct __Z { __device__ operator R() const noexcept { return F{}(2); } };
|
||||
|
||||
static constexpr __X x{};
|
||||
static constexpr __Y y{};
|
||||
static constexpr __Z z{};
|
||||
#ifdef __cplusplus
|
||||
__device__ operator dim3() const { return dim3(x, y, z); }
|
||||
#endif
|
||||
|
||||
};
|
||||
template <typename F>
|
||||
#if !defined(_MSC_VER)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
constexpr typename __HIP_Coordinates<F>::__X __HIP_Coordinates<F>::x;
|
||||
template <typename F>
|
||||
#if !defined(_MSC_VER)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
constexpr typename __HIP_Coordinates<F>::__Y __HIP_Coordinates<F>::y;
|
||||
template <typename F>
|
||||
#if !defined(_MSC_VER)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
constexpr typename __HIP_Coordinates<F>::__Z __HIP_Coordinates<F>::z;
|
||||
|
||||
extern "C" __device__ __attribute__((const)) size_t __ockl_get_global_size(uint);
|
||||
inline
|
||||
__device__
|
||||
std::uint32_t operator*(__HIP_Coordinates<__HIP_GridDim>::__X,
|
||||
__HIP_Coordinates<__HIP_BlockDim>::__X) noexcept {
|
||||
return __ockl_get_global_size(0);
|
||||
}
|
||||
inline
|
||||
__device__
|
||||
std::uint32_t operator*(__HIP_Coordinates<__HIP_BlockDim>::__X,
|
||||
__HIP_Coordinates<__HIP_GridDim>::__X) noexcept {
|
||||
return __ockl_get_global_size(0);
|
||||
}
|
||||
inline
|
||||
__device__
|
||||
std::uint32_t operator*(__HIP_Coordinates<__HIP_GridDim>::__Y,
|
||||
__HIP_Coordinates<__HIP_BlockDim>::__Y) noexcept {
|
||||
return __ockl_get_global_size(1);
|
||||
}
|
||||
inline
|
||||
__device__
|
||||
std::uint32_t operator*(__HIP_Coordinates<__HIP_BlockDim>::__Y,
|
||||
__HIP_Coordinates<__HIP_GridDim>::__Y) noexcept {
|
||||
return __ockl_get_global_size(1);
|
||||
}
|
||||
inline
|
||||
__device__
|
||||
std::uint32_t operator*(__HIP_Coordinates<__HIP_GridDim>::__Z,
|
||||
__HIP_Coordinates<__HIP_BlockDim>::__Z) noexcept {
|
||||
return __ockl_get_global_size(2);
|
||||
}
|
||||
inline
|
||||
__device__
|
||||
std::uint32_t operator*(__HIP_Coordinates<__HIP_BlockDim>::__Z,
|
||||
__HIP_Coordinates<__HIP_GridDim>::__Z) noexcept {
|
||||
return __ockl_get_global_size(2);
|
||||
}
|
||||
|
||||
static constexpr __HIP_Coordinates<__HIP_BlockDim> blockDim{};
|
||||
static constexpr __HIP_Coordinates<__HIP_BlockIdx> blockIdx{};
|
||||
static constexpr __HIP_Coordinates<__HIP_GridDim> gridDim{};
|
||||
static constexpr __HIP_Coordinates<__HIP_ThreadIdx> threadIdx{};
|
||||
|
||||
extern "C" __device__ __attribute__((const)) size_t __ockl_get_local_id(uint);
|
||||
#define hipThreadIdx_x (__ockl_get_local_id(0))
|
||||
#define hipThreadIdx_y (__ockl_get_local_id(1))
|
||||
#define hipThreadIdx_z (__ockl_get_local_id(2))
|
||||
|
||||
extern "C" __device__ __attribute__((const)) size_t __ockl_get_group_id(uint);
|
||||
#define hipBlockIdx_x (__ockl_get_group_id(0))
|
||||
#define hipBlockIdx_y (__ockl_get_group_id(1))
|
||||
#define hipBlockIdx_z (__ockl_get_group_id(2))
|
||||
|
||||
extern "C" __device__ __attribute__((const)) size_t __ockl_get_local_size(uint);
|
||||
#define hipBlockDim_x (__ockl_get_local_size(0))
|
||||
#define hipBlockDim_y (__ockl_get_local_size(1))
|
||||
#define hipBlockDim_z (__ockl_get_local_size(2))
|
||||
|
||||
extern "C" __device__ __attribute__((const)) size_t __ockl_get_num_groups(uint);
|
||||
#define hipGridDim_x (__ockl_get_num_groups(0))
|
||||
#define hipGridDim_y (__ockl_get_num_groups(1))
|
||||
#define hipGridDim_z (__ockl_get_num_groups(2))
|
||||
|
||||
#include <hip/amd_detail/amd_math_functions.h>
|
||||
|
||||
#if __HIP_HCC_COMPAT_MODE__
|
||||
// Define HCC work item functions in terms of HIP builtin variables.
|
||||
#pragma push_macro("__DEFINE_HCC_FUNC")
|
||||
#define __DEFINE_HCC_FUNC(hc_fun,hip_var) \
|
||||
inline __device__ __attribute__((always_inline)) uint hc_get_##hc_fun(uint i) { \
|
||||
if (i==0) \
|
||||
return hip_var.x; \
|
||||
else if(i==1) \
|
||||
return hip_var.y; \
|
||||
else \
|
||||
return hip_var.z; \
|
||||
}
|
||||
|
||||
__DEFINE_HCC_FUNC(workitem_id, threadIdx)
|
||||
__DEFINE_HCC_FUNC(group_id, blockIdx)
|
||||
__DEFINE_HCC_FUNC(group_size, blockDim)
|
||||
__DEFINE_HCC_FUNC(num_groups, gridDim)
|
||||
#pragma pop_macro("__DEFINE_HCC_FUNC")
|
||||
|
||||
extern "C" __device__ __attribute__((const)) size_t __ockl_get_global_id(uint);
|
||||
inline __device__ __attribute__((always_inline)) uint
|
||||
hc_get_workitem_absolute_id(int dim)
|
||||
{
|
||||
return (uint)__ockl_get_global_id(dim);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !__CLANG_HIP_RUNTIME_WRAPPER_INCLUDED__
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
// Support std::complex.
|
||||
#if !_OPENMP || __HIP_ENABLE_CUDA_WRAPPER_FOR_OPENMP__
|
||||
#pragma push_macro("__CUDA__")
|
||||
#define __CUDA__
|
||||
#include <__clang_cuda_math_forward_declares.h>
|
||||
#include <__clang_cuda_complex_builtins.h>
|
||||
// Workaround for using libc++ with HIP-Clang.
|
||||
// The following headers requires clang include path before standard C++ include path.
|
||||
// However libc++ include path requires to be before clang include path.
|
||||
// To workaround this, we pass -isystem with the parent directory of clang include
|
||||
// path instead of the clang include path itself.
|
||||
#include <include/cuda_wrappers/algorithm>
|
||||
#include <include/cuda_wrappers/complex>
|
||||
#include <include/cuda_wrappers/new>
|
||||
#undef __CUDA__
|
||||
#pragma pop_macro("__CUDA__")
|
||||
#endif // !_OPENMP || __HIP_ENABLE_CUDA_WRAPPER_FOR_OPENMP__
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
#endif // !__CLANG_HIP_RUNTIME_WRAPPER_INCLUDED__
|
||||
#endif // __HIP_CLANG_ONLY__
|
||||
|
||||
#include <hip/amd_detail/hip_memory.h>
|
||||
|
||||
#endif // HIP_AMD_DETAIL_RUNTIME_H
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright (c) 2015- present 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 amd_detail/hip_surface_types.h
|
||||
* @brief Defines surface types for HIP runtime.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_HIP_SURFACE_TYPES_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_HIP_SURFACE_TYPES_H
|
||||
|
||||
#include <hip/amd_detail/amd_driver_types.h>
|
||||
|
||||
/**
|
||||
* An opaque value that represents a hip surface object
|
||||
*/
|
||||
typedef unsigned long long hipSurfaceObject_t;
|
||||
|
||||
/**
|
||||
* hip surface reference
|
||||
*/
|
||||
struct surfaceReference {
|
||||
hipSurfaceObject_t surfaceObject;
|
||||
};
|
||||
|
||||
/**
|
||||
* hip surface boundary modes
|
||||
*/
|
||||
enum hipSurfaceBoundaryMode {
|
||||
hipBoundaryModeZero = 0,
|
||||
hipBoundaryModeTrap = 1,
|
||||
hipBoundaryModeClamp = 2
|
||||
};
|
||||
|
||||
#endif /* !HIP_INCLUDE_HIP_AMD_DETAIL_HIP_SURFACE_TYPES_H */
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright (c) 2015-2016 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 amd_detail/hip_texture_types.h
|
||||
* @brief Defines the different newt vector types for HIP runtime.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_HIP_TEXTURE_TYPES_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_HIP_TEXTURE_TYPES_H
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
#include <limits.h>
|
||||
#include <hip/amd_detail/amd_channel_descriptor.h>
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
#include <hip/amd_detail/amd_texture_types.h>
|
||||
|
||||
#if __cplusplus
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#if __HIP__
|
||||
#define __HIP_TEXTURE_ATTRIB __attribute__((device_builtin_texture_type))
|
||||
#else
|
||||
#define __HIP_TEXTURE_ATTRIB
|
||||
#endif
|
||||
|
||||
typedef textureReference* hipTexRef;
|
||||
|
||||
template <class T, int texType = hipTextureType1D,
|
||||
enum hipTextureReadMode mode = hipReadModeElementType>
|
||||
struct __HIP_TEXTURE_ATTRIB texture : public textureReference {
|
||||
texture(int norm = 0, enum hipTextureFilterMode fMode = hipFilterModePoint,
|
||||
enum hipTextureAddressMode aMode = hipAddressModeClamp) {
|
||||
normalized = norm;
|
||||
readMode = mode;
|
||||
filterMode = fMode;
|
||||
addressMode[0] = aMode;
|
||||
addressMode[1] = aMode;
|
||||
addressMode[2] = aMode;
|
||||
channelDesc = hipCreateChannelDesc<T>();
|
||||
sRGB = 0;
|
||||
textureObject = nullptr;
|
||||
maxAnisotropy = 0;
|
||||
mipmapLevelBias = 0;
|
||||
minMipmapLevelClamp = 0;
|
||||
maxMipmapLevelClamp = 0;
|
||||
}
|
||||
|
||||
texture(int norm, enum hipTextureFilterMode fMode, enum hipTextureAddressMode aMode,
|
||||
struct hipChannelFormatDesc desc) {
|
||||
normalized = norm;
|
||||
readMode = mode;
|
||||
filterMode = fMode;
|
||||
addressMode[0] = aMode;
|
||||
addressMode[1] = aMode;
|
||||
addressMode[2] = aMode;
|
||||
channelDesc = desc;
|
||||
sRGB = 0;
|
||||
textureObject = nullptr;
|
||||
maxAnisotropy = 0;
|
||||
mipmapLevelBias = 0;
|
||||
minMipmapLevelClamp = 0;
|
||||
maxMipmapLevelClamp = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* !HIP_INCLUDE_HIP_AMD_DETAIL_HIP_TEXTURE_TYPES_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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.
|
||||
*/
|
||||
#ifndef HIPRTC_H
|
||||
#define HIPRTC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#pragma GCC visibility push (default)
|
||||
#endif
|
||||
|
||||
enum hiprtcResult {
|
||||
HIPRTC_SUCCESS = 0,
|
||||
HIPRTC_ERROR_OUT_OF_MEMORY = 1,
|
||||
HIPRTC_ERROR_PROGRAM_CREATION_FAILURE = 2,
|
||||
HIPRTC_ERROR_INVALID_INPUT = 3,
|
||||
HIPRTC_ERROR_INVALID_PROGRAM = 4,
|
||||
HIPRTC_ERROR_INVALID_OPTION = 5,
|
||||
HIPRTC_ERROR_COMPILATION = 6,
|
||||
HIPRTC_ERROR_BUILTIN_OPERATION_FAILURE = 7,
|
||||
HIPRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION = 8,
|
||||
HIPRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION = 9,
|
||||
HIPRTC_ERROR_NAME_EXPRESSION_NOT_VALID = 10,
|
||||
HIPRTC_ERROR_INTERNAL_ERROR = 11
|
||||
};
|
||||
|
||||
const char* hiprtcGetErrorString(hiprtcResult result);
|
||||
|
||||
|
||||
hiprtcResult hiprtcVersion(int* major, int* minor);
|
||||
|
||||
typedef struct _hiprtcProgram* hiprtcProgram;
|
||||
|
||||
hiprtcResult hiprtcAddNameExpression(hiprtcProgram prog,
|
||||
const char* name_expression);
|
||||
|
||||
hiprtcResult hiprtcCompileProgram(hiprtcProgram prog,
|
||||
int numOptions,
|
||||
const char** options);
|
||||
|
||||
hiprtcResult hiprtcCreateProgram(hiprtcProgram* prog,
|
||||
const char* src,
|
||||
const char* name,
|
||||
int numHeaders,
|
||||
const char** headers,
|
||||
const char** includeNames);
|
||||
|
||||
hiprtcResult hiprtcDestroyProgram(hiprtcProgram* prog);
|
||||
|
||||
hiprtcResult hiprtcGetLoweredName(hiprtcProgram prog,
|
||||
const char* name_expression,
|
||||
const char** lowered_name);
|
||||
|
||||
hiprtcResult hiprtcGetProgramLog(hiprtcProgram prog, char* log);
|
||||
|
||||
hiprtcResult hiprtcGetProgramLogSize(hiprtcProgram prog,
|
||||
size_t* logSizeRet);
|
||||
|
||||
hiprtcResult hiprtcGetCode(hiprtcProgram prog, char* code);
|
||||
|
||||
hiprtcResult hiprtcGetCodeSize(hiprtcProgram prog, size_t* codeSizeRet);
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#pragma GCC visibility pop
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif //HIPRTC_H
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_LIBRARY_TYPES_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_LIBRARY_TYPES_H
|
||||
|
||||
typedef enum hipDataType {
|
||||
HIP_R_16F = 2,
|
||||
HIP_R_32F = 0,
|
||||
HIP_R_64F = 1,
|
||||
HIP_C_16F = 6,
|
||||
HIP_C_32F = 4,
|
||||
HIP_C_64F = 5
|
||||
} hipDataType;
|
||||
|
||||
typedef enum hipLibraryPropertyType {
|
||||
HIP_LIBRARY_MAJOR_VERSION,
|
||||
HIP_LIBRARY_MINOR_VERSION,
|
||||
HIP_LIBRARY_PATCH_LEVEL
|
||||
} hipLibraryPropertyType;
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright (c) 2018 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_SURFACE_FUNCTIONS_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_SURFACE_FUNCTIONS_H
|
||||
|
||||
#include <hip/amd_detail/amd_hip_surface_types.h>
|
||||
|
||||
#define __SURFACE_FUNCTIONS_DECL__ static inline __device__
|
||||
template <class T>
|
||||
__SURFACE_FUNCTIONS_DECL__ void surf2Dread(T* data, hipSurfaceObject_t surfObj, int x, int y,
|
||||
int boundaryMode = hipBoundaryModeZero) {
|
||||
hipArray* arrayPtr = (hipArray*)surfObj;
|
||||
size_t width = arrayPtr->width;
|
||||
size_t height = arrayPtr->height;
|
||||
int32_t xOffset = x / sizeof(T);
|
||||
T* dataPtr = (T*)arrayPtr->data;
|
||||
if ((xOffset > width) || (xOffset < 0) || (y > height) || (y < 0)) {
|
||||
if (boundaryMode == hipBoundaryModeZero) {
|
||||
*data = 0;
|
||||
}
|
||||
} else {
|
||||
*data = *(dataPtr + y * width + xOffset);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__SURFACE_FUNCTIONS_DECL__ void surf2Dwrite(T data, hipSurfaceObject_t surfObj, int x, int y,
|
||||
int boundaryMode = hipBoundaryModeZero) {
|
||||
hipArray* arrayPtr = (hipArray*)surfObj;
|
||||
size_t width = arrayPtr->width;
|
||||
size_t height = arrayPtr->height;
|
||||
int32_t xOffset = x / sizeof(T);
|
||||
T* dataPtr = (T*)arrayPtr->data;
|
||||
if (!((xOffset > width) || (xOffset < 0) || (y > height) || (y < 0))) {
|
||||
*(dataPtr + y * width + xOffset) = data;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_TEXTURE_TYPES_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_TEXTURE_TYPES_H
|
||||
|
||||
#include <hip/amd_detail/amd_driver_types.h>
|
||||
|
||||
#define hipTextureType1D 0x01
|
||||
#define hipTextureType2D 0x02
|
||||
#define hipTextureType3D 0x03
|
||||
#define hipTextureTypeCubemap 0x0C
|
||||
#define hipTextureType1DLayered 0xF1
|
||||
#define hipTextureType2DLayered 0xF2
|
||||
#define hipTextureTypeCubemapLayered 0xFC
|
||||
|
||||
/**
|
||||
* Should be same as HSA_IMAGE_OBJECT_SIZE_DWORD/HSA_SAMPLER_OBJECT_SIZE_DWORD
|
||||
*/
|
||||
#define HIP_IMAGE_OBJECT_SIZE_DWORD 12
|
||||
#define HIP_SAMPLER_OBJECT_SIZE_DWORD 8
|
||||
#define HIP_SAMPLER_OBJECT_OFFSET_DWORD HIP_IMAGE_OBJECT_SIZE_DWORD
|
||||
#define HIP_TEXTURE_OBJECT_SIZE_DWORD (HIP_IMAGE_OBJECT_SIZE_DWORD + HIP_SAMPLER_OBJECT_SIZE_DWORD)
|
||||
|
||||
/**
|
||||
* An opaque value that represents a hip texture object
|
||||
*/
|
||||
struct __hip_texture;
|
||||
typedef struct __hip_texture* hipTextureObject_t;
|
||||
|
||||
/**
|
||||
* hip texture address modes
|
||||
*/
|
||||
enum hipTextureAddressMode {
|
||||
hipAddressModeWrap = 0,
|
||||
hipAddressModeClamp = 1,
|
||||
hipAddressModeMirror = 2,
|
||||
hipAddressModeBorder = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* hip texture filter modes
|
||||
*/
|
||||
enum hipTextureFilterMode { hipFilterModePoint = 0, hipFilterModeLinear = 1 };
|
||||
|
||||
/**
|
||||
* hip texture read modes
|
||||
*/
|
||||
enum hipTextureReadMode { hipReadModeElementType = 0, hipReadModeNormalizedFloat = 1 };
|
||||
|
||||
/**
|
||||
* hip texture reference
|
||||
*/
|
||||
typedef struct textureReference {
|
||||
int normalized;
|
||||
enum hipTextureReadMode readMode;// used only for driver API's
|
||||
enum hipTextureFilterMode filterMode;
|
||||
enum hipTextureAddressMode addressMode[3]; // Texture address mode for up to 3 dimensions
|
||||
struct hipChannelFormatDesc channelDesc;
|
||||
int sRGB; // Perform sRGB->linear conversion during texture read
|
||||
unsigned int maxAnisotropy; // Limit to the anisotropy ratio
|
||||
enum hipTextureFilterMode mipmapFilterMode;
|
||||
float mipmapLevelBias;
|
||||
float minMipmapLevelClamp;
|
||||
float maxMipmapLevelClamp;
|
||||
|
||||
hipTextureObject_t textureObject;
|
||||
int numChannels;
|
||||
enum hipArray_Format format;
|
||||
}textureReference;
|
||||
|
||||
/**
|
||||
* hip texture descriptor
|
||||
*/
|
||||
typedef struct hipTextureDesc {
|
||||
enum hipTextureAddressMode addressMode[3]; // Texture address mode for up to 3 dimensions
|
||||
enum hipTextureFilterMode filterMode;
|
||||
enum hipTextureReadMode readMode;
|
||||
int sRGB; // Perform sRGB->linear conversion during texture read
|
||||
float borderColor[4];
|
||||
int normalizedCoords;
|
||||
unsigned int maxAnisotropy;
|
||||
enum hipTextureFilterMode mipmapFilterMode;
|
||||
float mipmapLevelBias;
|
||||
float minMipmapLevelClamp;
|
||||
float maxMipmapLevelClamp;
|
||||
}hipTextureDesc;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright (c) 2015-present 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
|
||||
|
||||
namespace hip_impl // Documentation only.
|
||||
{
|
||||
#define requires(...)
|
||||
|
||||
#define FunctionalProcedure typename
|
||||
} // namespace hip_impl
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 amd_detail/device_library_decls.h
|
||||
* @brief Contains declarations for types and functions in device library.
|
||||
* Uses int64_t and uint64_t instead of long, long long, unsigned
|
||||
* long and unsigned long long types for device library API
|
||||
* declarations.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_DEVICE_LIBRARY_DECLS_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_DEVICE_LIBRARY_DECLS_H
|
||||
|
||||
#include "hip/amd_detail/host_defines.h"
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned long long ullong;
|
||||
|
||||
extern "C" __device__ __attribute__((const)) bool __ockl_wfany_i32(int);
|
||||
extern "C" __device__ __attribute__((const)) bool __ockl_wfall_i32(int);
|
||||
extern "C" __device__ uint __ockl_activelane_u32(void);
|
||||
|
||||
extern "C" __device__ __attribute__((const)) uint __ockl_mul24_u32(uint, uint);
|
||||
extern "C" __device__ __attribute__((const)) int __ockl_mul24_i32(int, int);
|
||||
extern "C" __device__ __attribute__((const)) uint __ockl_mul_hi_u32(uint, uint);
|
||||
extern "C" __device__ __attribute__((const)) int __ockl_mul_hi_i32(int, int);
|
||||
extern "C" __device__ __attribute__((const)) uint __ockl_sadd_u32(uint, uint, uint);
|
||||
|
||||
extern "C" __device__ __attribute__((const)) uchar __ockl_clz_u8(uchar);
|
||||
extern "C" __device__ __attribute__((const)) ushort __ockl_clz_u16(ushort);
|
||||
extern "C" __device__ __attribute__((const)) uint __ockl_clz_u32(uint);
|
||||
extern "C" __device__ __attribute__((const)) uint64_t __ockl_clz_u64(uint64_t);
|
||||
|
||||
extern "C" __device__ __attribute__((const)) float __ocml_floor_f32(float);
|
||||
extern "C" __device__ __attribute__((const)) float __ocml_rint_f32(float);
|
||||
extern "C" __device__ __attribute__((const)) float __ocml_ceil_f32(float);
|
||||
extern "C" __device__ __attribute__((const)) float __ocml_trunc_f32(float);
|
||||
|
||||
extern "C" __device__ __attribute__((const)) float __ocml_fmin_f32(float, float);
|
||||
extern "C" __device__ __attribute__((const)) float __ocml_fmax_f32(float, float);
|
||||
|
||||
extern "C" __device__ __attribute__((convergent)) void __ockl_gws_init(uint nwm1, uint rid);
|
||||
extern "C" __device__ __attribute__((convergent)) void __ockl_gws_barrier(uint nwm1, uint rid);
|
||||
|
||||
extern "C" __device__ __attribute__((const)) uint32_t __ockl_lane_u32();
|
||||
extern "C" __device__ __attribute__((const)) int __ockl_grid_is_valid(void);
|
||||
extern "C" __device__ __attribute__((convergent)) void __ockl_grid_sync(void);
|
||||
extern "C" __device__ __attribute__((const)) uint __ockl_multi_grid_num_grids(void);
|
||||
extern "C" __device__ __attribute__((const)) uint __ockl_multi_grid_grid_rank(void);
|
||||
extern "C" __device__ __attribute__((const)) uint __ockl_multi_grid_size(void);
|
||||
extern "C" __device__ __attribute__((const)) uint __ockl_multi_grid_thread_rank(void);
|
||||
extern "C" __device__ __attribute__((const)) int __ockl_multi_grid_is_valid(void);
|
||||
extern "C" __device__ __attribute__((convergent)) void __ockl_multi_grid_sync(void);
|
||||
|
||||
extern "C" __device__ void __ockl_atomic_add_noret_f32(float*, float);
|
||||
|
||||
extern "C" __device__ __attribute__((convergent)) int __ockl_wgred_add_i32(int a);
|
||||
extern "C" __device__ __attribute__((convergent)) int __ockl_wgred_and_i32(int a);
|
||||
extern "C" __device__ __attribute__((convergent)) int __ockl_wgred_or_i32(int a);
|
||||
|
||||
|
||||
// Introduce local address space
|
||||
#define __local __attribute__((address_space(3)))
|
||||
|
||||
#ifdef __HIP_DEVICE_COMPILE__
|
||||
__device__ inline static __local void* __to_local(unsigned x) { return (__local void*)x; }
|
||||
#endif //__HIP_DEVICE_COMPILE__
|
||||
|
||||
// Using hip.amdgcn.bc - sync threads
|
||||
#define __CLK_LOCAL_MEM_FENCE 0x01
|
||||
typedef unsigned __cl_mem_fence_flags;
|
||||
|
||||
typedef enum __memory_scope {
|
||||
__memory_scope_work_item = __OPENCL_MEMORY_SCOPE_WORK_ITEM,
|
||||
__memory_scope_work_group = __OPENCL_MEMORY_SCOPE_WORK_GROUP,
|
||||
__memory_scope_device = __OPENCL_MEMORY_SCOPE_DEVICE,
|
||||
__memory_scope_all_svm_devices = __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES,
|
||||
__memory_scope_sub_group = __OPENCL_MEMORY_SCOPE_SUB_GROUP
|
||||
} __memory_scope;
|
||||
|
||||
// enum values aligned with what clang uses in EmitAtomicExpr()
|
||||
typedef enum __memory_order
|
||||
{
|
||||
__memory_order_relaxed = __ATOMIC_RELAXED,
|
||||
__memory_order_acquire = __ATOMIC_ACQUIRE,
|
||||
__memory_order_release = __ATOMIC_RELEASE,
|
||||
__memory_order_acq_rel = __ATOMIC_ACQ_REL,
|
||||
__memory_order_seq_cst = __ATOMIC_SEQ_CST
|
||||
} __memory_order;
|
||||
|
||||
// Linked from hip.amdgcn.bc
|
||||
extern "C" __device__ void
|
||||
__atomic_work_item_fence(__cl_mem_fence_flags, __memory_order, __memory_scope);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 "concepts.hpp"
|
||||
#include "helpers.hpp"
|
||||
#include "program_state.hpp"
|
||||
#include "hip_runtime_api.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
hipError_t ihipExtLaunchMultiKernelMultiDevice(hipLaunchParams* launchParamsList, int numDevices,
|
||||
unsigned int flags, hip_impl::program_state& ps);
|
||||
|
||||
hipError_t hipLaunchCooperativeKernel(const void* f, dim3 gridDim,
|
||||
dim3 blockDim, void** args,
|
||||
size_t sharedMem, hipStream_t stream,
|
||||
hip_impl::program_state& ps);
|
||||
|
||||
hipError_t hipLaunchCooperativeKernelMultiDevice(hipLaunchParams* launchParamsList,
|
||||
int numDevices,
|
||||
unsigned int flags,
|
||||
hip_impl::program_state& ps);
|
||||
|
||||
#pragma GCC visibility push(hidden)
|
||||
|
||||
namespace hip_impl {
|
||||
template <typename T, typename std::enable_if<std::is_integral<T>{}>::type* = nullptr>
|
||||
inline T round_up_to_next_multiple_nonnegative(T x, T y) {
|
||||
T tmp = x + y - 1;
|
||||
return tmp - tmp % y;
|
||||
}
|
||||
|
||||
template <
|
||||
std::size_t n,
|
||||
typename... Ts,
|
||||
typename std::enable_if<n == sizeof...(Ts)>::type* = nullptr>
|
||||
inline hip_impl::kernarg make_kernarg(
|
||||
const std::tuple<Ts...>&,
|
||||
const kernargs_size_align&,
|
||||
hip_impl::kernarg kernarg) {
|
||||
return kernarg;
|
||||
}
|
||||
|
||||
template <
|
||||
std::size_t n,
|
||||
typename... Ts,
|
||||
typename std::enable_if<n != sizeof...(Ts)>::type* = nullptr>
|
||||
inline hip_impl::kernarg make_kernarg(
|
||||
const std::tuple<Ts...>& formals,
|
||||
const kernargs_size_align& size_align,
|
||||
hip_impl::kernarg kernarg) {
|
||||
using T = typename std::tuple_element<n, std::tuple<Ts...>>::type;
|
||||
|
||||
static_assert(
|
||||
!std::is_reference<T>{},
|
||||
"A __global__ function cannot have a reference as one of its "
|
||||
"arguments.");
|
||||
#if defined(HIP_STRICT)
|
||||
static_assert(
|
||||
std::is_trivially_copyable<T>{},
|
||||
"Only TriviallyCopyable types can be arguments to a __global__ "
|
||||
"function");
|
||||
#endif
|
||||
|
||||
kernarg.resize(round_up_to_next_multiple_nonnegative(
|
||||
kernarg.size(), size_align.alignment(n)) + size_align.size(n));
|
||||
|
||||
std::memcpy(
|
||||
kernarg.data() + kernarg.size() - size_align.size(n),
|
||||
&std::get<n>(formals),
|
||||
size_align.size(n));
|
||||
return make_kernarg<n + 1>(formals, size_align, std::move(kernarg));
|
||||
}
|
||||
|
||||
template <typename... Formals, typename... Actuals>
|
||||
inline hip_impl::kernarg make_kernarg(
|
||||
void (*kernel)(Formals...), std::tuple<Actuals...> actuals) {
|
||||
static_assert(sizeof...(Formals) == sizeof...(Actuals),
|
||||
"The count of formal arguments must match the count of actuals.");
|
||||
|
||||
if (sizeof...(Formals) == 0) return {};
|
||||
|
||||
std::tuple<Formals...> to_formals{std::move(actuals)};
|
||||
hip_impl::kernarg kernarg;
|
||||
kernarg.reserve(sizeof(to_formals));
|
||||
|
||||
auto& ps = hip_impl::get_program_state();
|
||||
return make_kernarg<0>(to_formals,
|
||||
ps.get_kernargs_size_align(
|
||||
reinterpret_cast<std::uintptr_t>(kernel)),
|
||||
std::move(kernarg));
|
||||
}
|
||||
|
||||
|
||||
HIP_INTERNAL_EXPORTED_API hsa_agent_t target_agent(hipStream_t stream);
|
||||
|
||||
inline
|
||||
__attribute__((visibility("hidden")))
|
||||
void hipLaunchKernelGGLImpl(
|
||||
std::uintptr_t function_address,
|
||||
const dim3& numBlocks,
|
||||
const dim3& dimBlocks,
|
||||
std::uint32_t sharedMemBytes,
|
||||
hipStream_t stream,
|
||||
void** kernarg) {
|
||||
|
||||
const auto& kd = hip_impl::get_program_state().kernel_descriptor(function_address,
|
||||
target_agent(stream));
|
||||
|
||||
hipModuleLaunchKernel(kd, numBlocks.x, numBlocks.y, numBlocks.z,
|
||||
dimBlocks.x, dimBlocks.y, dimBlocks.z, sharedMemBytes,
|
||||
stream, nullptr, kernarg);
|
||||
}
|
||||
} // Namespace hip_impl.
|
||||
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
hipError_t hipOccupancyMaxPotentialBlockSize(int* gridSize, int* blockSize,
|
||||
T kernel, size_t dynSharedMemPerBlk = 0, int blockSizeLimit = 0) {
|
||||
|
||||
using namespace hip_impl;
|
||||
|
||||
hip_impl::hip_init();
|
||||
auto f = get_program_state().kernel_descriptor(reinterpret_cast<std::uintptr_t>(kernel),
|
||||
target_agent(0));
|
||||
|
||||
return hipModuleOccupancyMaxPotentialBlockSize(gridSize, blockSize, f,
|
||||
dynSharedMemPerBlk, blockSizeLimit);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
hipError_t hipOccupancyMaxPotentialBlockSizeWithFlags(int* gridSize, int* blockSize,
|
||||
T kernel, size_t dynSharedMemPerBlk = 0, int blockSizeLimit = 0, unsigned int flags = 0 ) {
|
||||
|
||||
using namespace hip_impl;
|
||||
|
||||
hip_impl::hip_init();
|
||||
if(flags != hipOccupancyDefault) return hipErrorNotSupported;
|
||||
auto f = get_program_state().kernel_descriptor(reinterpret_cast<std::uintptr_t>(kernel),
|
||||
target_agent(0));
|
||||
|
||||
return hipModuleOccupancyMaxPotentialBlockSize(gridSize, blockSize, f,
|
||||
dynSharedMemPerBlk, blockSizeLimit);
|
||||
}
|
||||
|
||||
template <typename... Args, typename F = void (*)(Args...)>
|
||||
inline
|
||||
void hipLaunchKernelGGL(F kernel, const dim3& numBlocks, const dim3& dimBlocks,
|
||||
std::uint32_t sharedMemBytes, hipStream_t stream,
|
||||
Args... args) {
|
||||
hip_impl::hip_init();
|
||||
auto kernarg = hip_impl::make_kernarg(kernel, std::tuple<Args...>{std::move(args)...});
|
||||
std::size_t kernarg_size = kernarg.size();
|
||||
|
||||
void* config[]{
|
||||
HIP_LAUNCH_PARAM_BUFFER_POINTER,
|
||||
kernarg.data(),
|
||||
HIP_LAUNCH_PARAM_BUFFER_SIZE,
|
||||
&kernarg_size,
|
||||
HIP_LAUNCH_PARAM_END};
|
||||
|
||||
hip_impl::hipLaunchKernelGGLImpl(reinterpret_cast<std::uintptr_t>(kernel),
|
||||
numBlocks, dimBlocks, sharedMemBytes,
|
||||
stream, &config[0]);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline
|
||||
__attribute__((visibility("hidden")))
|
||||
hipError_t hipLaunchCooperativeKernel(F f, dim3 gridDim, dim3 blockDim,
|
||||
void** args, size_t sharedMem,
|
||||
hipStream_t stream) {
|
||||
hip_impl::hip_init();
|
||||
auto& ps = hip_impl::get_program_state();
|
||||
return hipLaunchCooperativeKernel(reinterpret_cast<void*>(f), gridDim,
|
||||
blockDim, args, sharedMem, stream, ps);
|
||||
}
|
||||
|
||||
inline
|
||||
__attribute__((visibility("hidden")))
|
||||
hipError_t hipLaunchCooperativeKernelMultiDevice(hipLaunchParams* launchParamsList,
|
||||
int numDevices,
|
||||
unsigned int flags) {
|
||||
|
||||
hip_impl::hip_init();
|
||||
auto& ps = hip_impl::get_program_state();
|
||||
return hipLaunchCooperativeKernelMultiDevice(launchParamsList, numDevices, flags, ps);
|
||||
}
|
||||
|
||||
#pragma GCC visibility pop
|
||||
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <hc_defines.h>
|
||||
|
||||
#define GRID_LAUNCH_VERSION 20
|
||||
|
||||
// Extern definitions
|
||||
namespace hc{
|
||||
class completion_future;
|
||||
class accelerator_view;
|
||||
}
|
||||
|
||||
|
||||
// 3 dim structure for groups and grids.
|
||||
typedef struct gl_dim3
|
||||
{
|
||||
int x,y,z;
|
||||
gl_dim3(uint32_t _x=1, uint32_t _y=1, uint32_t _z=1) : x(_x), y(_y), z(_z) {};
|
||||
} gl_dim3;
|
||||
|
||||
typedef enum gl_barrier_bit {
|
||||
barrier_bit_queue_default,
|
||||
barrier_bit_none,
|
||||
barrier_bit_wait,
|
||||
} gl_barrier_bit;
|
||||
|
||||
|
||||
// grid_launch_parm contains information used to launch the kernel.
|
||||
typedef struct grid_launch_parm
|
||||
{
|
||||
//! Grid dimensions
|
||||
gl_dim3 grid_dim;
|
||||
|
||||
//! Group dimensions
|
||||
gl_dim3 group_dim;
|
||||
|
||||
//! Amount of dynamic group memory to use with the kernel launch.
|
||||
//! This memory is in addition to the amount used statically in the kernel.
|
||||
unsigned int dynamic_group_mem_bytes;
|
||||
|
||||
//! Control setting of barrier bit on per-packet basis:
|
||||
//! See gl_barrier_bit description.
|
||||
//! Placeholder, is not used to control packet dispatch yet
|
||||
enum gl_barrier_bit barrier_bit;
|
||||
|
||||
//! Value of packet fences to apply to launch.
|
||||
//! The correspond to the value of bits 9:14 in the AQL packet,
|
||||
//! see HSA_PACKET_HEADER_ACQUIRE_FENCE_SCOPE and hsa_fence_scope_t.
|
||||
unsigned int launch_fence;
|
||||
|
||||
//! Pointer to the accelerator_view where the kernel should execute.
|
||||
//! If NULL, the default view on the default accelerator is used.
|
||||
hc::accelerator_view *av;
|
||||
|
||||
//! Pointer to the completion_future used to track the status of the command.
|
||||
//! If NULL, the command does not write status. In this case,
|
||||
//! synchronization can be enforced with queue-level waits or
|
||||
//! waiting on younger commands.
|
||||
hc::completion_future *cf;
|
||||
|
||||
grid_launch_parm() = default;
|
||||
} grid_launch_parm;
|
||||
|
||||
|
||||
extern void init_grid_launch(grid_launch_parm *gl);
|
||||
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "grid_launch.h"
|
||||
#include "hc.hpp"
|
||||
|
||||
class grid_launch_parm_cxx : public grid_launch_parm
|
||||
{
|
||||
public:
|
||||
grid_launch_parm_cxx() = default;
|
||||
|
||||
// customized serialization: don't need av and cf in kernel
|
||||
__attribute__((annotate("serialize")))
|
||||
void __cxxamp_serialize(Kalmar::Serialize& s) const {
|
||||
s.Append(sizeof(int), &grid_dim.x);
|
||||
s.Append(sizeof(int), &grid_dim.y);
|
||||
s.Append(sizeof(int), &grid_dim.z);
|
||||
s.Append(sizeof(int), &group_dim.x);
|
||||
s.Append(sizeof(int), &group_dim.y);
|
||||
s.Append(sizeof(int), &group_dim.z);
|
||||
}
|
||||
|
||||
__attribute__((annotate("user_deserialize")))
|
||||
grid_launch_parm_cxx(int grid_dim_x, int grid_dim_y, int grid_dim_z,
|
||||
int group_dim_x, int group_dim_y, int group_dim_z) {
|
||||
grid_dim.x = grid_dim_x;
|
||||
grid_dim.y = grid_dim_y;
|
||||
grid_dim.z = grid_dim_z;
|
||||
group_dim.x = group_dim_x;
|
||||
group_dim.y = group_dim_y;
|
||||
group_dim.z = group_dim_z;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
extern inline void grid_launch_init(grid_launch_parm *lp) {
|
||||
lp->grid_dim.x = lp->grid_dim.y = lp->grid_dim.z = 1;
|
||||
|
||||
lp->group_dim.x = lp->group_dim.y = lp->group_dim.z = 1;
|
||||
|
||||
lp->dynamic_group_mem_bytes = 0;
|
||||
|
||||
lp->barrier_bit = barrier_bit_queue_default;
|
||||
lp->launch_fence = -1;
|
||||
|
||||
// TODO - set to NULL?
|
||||
static hc::accelerator_view av = hc::accelerator().get_default_view();
|
||||
lp->av = &av;
|
||||
lp->cf = NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 GENERIC_GRID_LAUNCH == 1
|
||||
#include "macro_based_grid_launch.hpp"
|
||||
#endif // GENERIC_GRID_LAUNCH
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 "concepts.hpp"
|
||||
|
||||
#include <type_traits> // For std::conditional, std::decay, std::enable_if,
|
||||
// std::false_type, std result_of and std::true_type.
|
||||
#include <utility> // For std::declval.
|
||||
|
||||
#ifdef __has_include // Check if __has_include is present
|
||||
# if __has_include(<version>) // Check for version header
|
||||
# include <version>
|
||||
# if defined(__cpp_lib_is_invocable) && !defined(HIP_HAS_INVOCABLE)
|
||||
# define HIP_HAS_INVOCABLE __cpp_lib_is_invocable
|
||||
# endif
|
||||
# if defined(__cpp_lib_result_of_sfinae) && !defined(HIP_HAS_RESULT_OF_SFINAE)
|
||||
# define HIP_HAS_RESULT_OF_SFINAE __cpp_lib_result_of_sfinae
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HIP_HAS_INVOCABLE
|
||||
#define HIP_HAS_INVOCABLE 0
|
||||
#endif
|
||||
|
||||
#ifndef HIP_HAS_RESULT_OF_SFINAE
|
||||
#define HIP_HAS_RESULT_OF_SFINAE 0
|
||||
#endif
|
||||
|
||||
namespace std { // TODO: these should be removed as soon as possible.
|
||||
#if (__cplusplus < 201406L)
|
||||
#if (__cplusplus < 201402L)
|
||||
template <bool cond, typename T = void>
|
||||
using enable_if_t = typename enable_if<cond, T>::type;
|
||||
template <bool cond, typename T, typename U>
|
||||
using conditional_t = typename conditional<cond, T, U>::type;
|
||||
template <typename T>
|
||||
using decay_t = typename decay<T>::type;
|
||||
template <FunctionalProcedure F, typename... Ts>
|
||||
using result_of_t = typename result_of<F(Ts...)>::type;
|
||||
template <typename T>
|
||||
using remove_reference_t = typename remove_reference<T>::type;
|
||||
#endif
|
||||
#endif
|
||||
} // namespace std
|
||||
|
||||
namespace hip_impl {
|
||||
template <typename...>
|
||||
using void_t_ = void;
|
||||
|
||||
#if HIP_HAS_INVOCABLE
|
||||
template <typename, typename = void>
|
||||
struct is_callable_impl;
|
||||
|
||||
template <FunctionalProcedure F, typename... Ts>
|
||||
struct is_callable_impl<F(Ts...)> : std::is_invocable<F, Ts...> {};
|
||||
#elif HIP_HAS_RESULT_OF_SFINAE
|
||||
template <typename, typename = void>
|
||||
struct is_callable_impl : std::false_type {};
|
||||
|
||||
template <FunctionalProcedure F, typename... Ts>
|
||||
struct is_callable_impl<F(Ts...), void_t_<typename std::result_of<F(Ts...)>::type > > : std::true_type {};
|
||||
#else
|
||||
template <class Base, class T, class Derived>
|
||||
auto simple_invoke(T Base::*pmd, Derived&& ref)
|
||||
-> decltype(static_cast<Derived&&>(ref).*pmd);
|
||||
|
||||
template <class PMD, class Pointer>
|
||||
auto simple_invoke(PMD&& pmd, Pointer&& ptr)
|
||||
-> decltype((*static_cast<Pointer&&>(ptr)).*static_cast<PMD&&>(pmd));
|
||||
|
||||
template <class Base, class T, class Derived>
|
||||
auto simple_invoke(T Base::*pmd, const std::reference_wrapper<Derived>& ref)
|
||||
-> decltype(ref.get().*pmd);
|
||||
|
||||
template <class Base, class T, class Derived, class... Args>
|
||||
auto simple_invoke(T Base::*pmf, Derived&& ref, Args&&... args)
|
||||
-> decltype((static_cast<Derived&&>(ref).*pmf)(static_cast<Args&&>(args)...));
|
||||
|
||||
template <class PMF, class Pointer, class... Args>
|
||||
auto simple_invoke(PMF&& pmf, Pointer&& ptr, Args&&... args)
|
||||
-> decltype(((*static_cast<Pointer&&>(ptr)).*static_cast<PMF&&>(pmf))(static_cast<Args&&>(args)...));
|
||||
|
||||
template <class Base, class T, class Derived, class... Args>
|
||||
auto simple_invoke(T Base::*pmf, const std::reference_wrapper<Derived>& ref, Args&&... args)
|
||||
-> decltype((ref.get().*pmf)(static_cast<Args&&>(args)...));
|
||||
|
||||
template<class F, class... Ts>
|
||||
auto simple_invoke(F&& f, Ts&&... xs)
|
||||
-> decltype(f(static_cast<Ts&&>(xs)...));
|
||||
|
||||
template <typename, typename = void>
|
||||
struct is_callable_impl : std::false_type {};
|
||||
|
||||
template <FunctionalProcedure F, typename... Ts>
|
||||
struct is_callable_impl<F(Ts...), void_t_<decltype(simple_invoke(std::declval<F>(), std::declval<Ts>()...))> >
|
||||
: std::true_type {};
|
||||
|
||||
#endif
|
||||
|
||||
template <typename Call>
|
||||
struct is_callable : is_callable_impl<Call> {};
|
||||
|
||||
#define count_macro_args_impl_hip_(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \
|
||||
_14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, \
|
||||
_26, _27, _28, _29, _30, _31, _n, ...) \
|
||||
_n
|
||||
#define count_macro_args_hip_(...) \
|
||||
count_macro_args_impl_hip_(, ##__VA_ARGS__, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
|
||||
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, \
|
||||
0)
|
||||
|
||||
#define overloaded_macro_expand_hip_(macro, arg_cnt) macro##arg_cnt
|
||||
#define overload_macro_impl_hip_(macro, arg_cnt) overloaded_macro_expand_hip_(macro, arg_cnt)
|
||||
#define overload_macro_hip_(macro, ...) \
|
||||
overload_macro_impl_hip_(macro, count_macro_args_hip_(__VA_ARGS__))(__VA_ARGS__)
|
||||
} // namespace hip_impl
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 amd_detail/hip_cooperative_groups_helper.h
|
||||
*
|
||||
* @brief Device side implementation of cooperative group feature.
|
||||
*
|
||||
* Defines helper constructs and APIs which aid the types and device API
|
||||
* wrappers defined within `amd_detail/hip_cooperative_groups.h`.
|
||||
*/
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COOPERATIVE_GROUPS_HELPER_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COOPERATIVE_GROUPS_HELPER_H
|
||||
|
||||
#if __cplusplus
|
||||
#include <hip/amd_detail/amd_device_functions.h>
|
||||
|
||||
#if !defined(__align__)
|
||||
#define __align__(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
|
||||
#if !defined(__CG_QUALIFIER__)
|
||||
#define __CG_QUALIFIER__ __device__ __forceinline__
|
||||
#endif
|
||||
|
||||
#if !defined(__CG_STATIC_QUALIFIER__)
|
||||
#define __CG_STATIC_QUALIFIER__ __device__ static __forceinline__
|
||||
#endif
|
||||
|
||||
#if !defined(_CG_STATIC_CONST_DECL_)
|
||||
#define _CG_STATIC_CONST_DECL_ static constexpr
|
||||
#endif
|
||||
|
||||
#if !defined(WAVEFRONT_SIZE)
|
||||
#if __gfx1010__ || __gfx1011__ || __gfx1012__ || __gfx1030__ || __gfx1031__
|
||||
#define WAVEFRONT_SIZE 32
|
||||
#else
|
||||
#define WAVEFRONT_SIZE 64
|
||||
#endif
|
||||
|
||||
namespace cooperative_groups {
|
||||
|
||||
/* Global scope */
|
||||
template <unsigned int size>
|
||||
using is_power_of_2 = std::integral_constant<bool, (size & (size - 1)) == 0>;
|
||||
|
||||
template <unsigned int size>
|
||||
using is_valid_wavefront = std::integral_constant<bool, (size <= WAVEFRONT_SIZE)>;
|
||||
|
||||
template <unsigned int size>
|
||||
using is_valid_tile_size =
|
||||
std::integral_constant<bool, is_power_of_2<size>::value && is_valid_wavefront<size>::value>;
|
||||
|
||||
template <typename T>
|
||||
using is_valid_type =
|
||||
std::integral_constant<bool, std::is_integral<T>::value || std::is_floating_point<T>::value>;
|
||||
|
||||
namespace internal {
|
||||
|
||||
/** \brief Enums representing different cooperative group types
|
||||
*/
|
||||
typedef enum {
|
||||
cg_invalid,
|
||||
cg_multi_grid,
|
||||
cg_grid,
|
||||
cg_workgroup,
|
||||
cg_tiled_group
|
||||
} group_type;
|
||||
|
||||
/**
|
||||
* Functionalities related to multi-grid cooperative group type
|
||||
*/
|
||||
namespace multi_grid {
|
||||
|
||||
__CG_STATIC_QUALIFIER__ uint32_t num_grids() { return (uint32_t)__ockl_multi_grid_num_grids(); }
|
||||
|
||||
__CG_STATIC_QUALIFIER__ uint32_t grid_rank() { return (uint32_t)__ockl_multi_grid_grid_rank(); }
|
||||
|
||||
__CG_STATIC_QUALIFIER__ uint32_t size() { return (uint32_t)__ockl_multi_grid_size(); }
|
||||
|
||||
__CG_STATIC_QUALIFIER__ uint32_t thread_rank() { return (uint32_t)__ockl_multi_grid_thread_rank(); }
|
||||
|
||||
__CG_STATIC_QUALIFIER__ bool is_valid() { return (bool)__ockl_multi_grid_is_valid(); }
|
||||
|
||||
__CG_STATIC_QUALIFIER__ void sync() { __ockl_multi_grid_sync(); }
|
||||
|
||||
} // namespace multi_grid
|
||||
|
||||
/**
|
||||
* Functionalities related to grid cooperative group type
|
||||
*/
|
||||
namespace grid {
|
||||
|
||||
__CG_STATIC_QUALIFIER__ uint32_t size() {
|
||||
return (uint32_t)((hipBlockDim_z * hipGridDim_z) * (hipBlockDim_y * hipGridDim_y) *
|
||||
(hipBlockDim_x * hipGridDim_x));
|
||||
}
|
||||
|
||||
__CG_STATIC_QUALIFIER__ uint32_t thread_rank() {
|
||||
// Compute global id of the workgroup to which the current thread belongs to
|
||||
uint32_t blkIdx = (uint32_t)((hipBlockIdx_z * hipGridDim_y * hipGridDim_x) +
|
||||
(hipBlockIdx_y * hipGridDim_x) + (hipBlockIdx_x));
|
||||
|
||||
// Compute total number of threads being passed to reach current workgroup
|
||||
// within grid
|
||||
uint32_t num_threads_till_current_workgroup =
|
||||
(uint32_t)(blkIdx * (hipBlockDim_x * hipBlockDim_y * hipBlockDim_z));
|
||||
|
||||
// Compute thread local rank within current workgroup
|
||||
uint32_t local_thread_rank = (uint32_t)((hipThreadIdx_z * hipBlockDim_y * hipBlockDim_x) +
|
||||
(hipThreadIdx_y * hipBlockDim_x) + (hipThreadIdx_x));
|
||||
|
||||
return (num_threads_till_current_workgroup + local_thread_rank);
|
||||
}
|
||||
|
||||
__CG_STATIC_QUALIFIER__ bool is_valid() { return (bool)__ockl_grid_is_valid(); }
|
||||
|
||||
__CG_STATIC_QUALIFIER__ void sync() { __ockl_grid_sync(); }
|
||||
|
||||
} // namespace grid
|
||||
|
||||
/**
|
||||
* Functionalities related to `workgroup` (thread_block in CUDA terminology)
|
||||
* cooperative group type
|
||||
*/
|
||||
namespace workgroup {
|
||||
|
||||
__CG_STATIC_QUALIFIER__ dim3 group_index() {
|
||||
return (dim3((uint32_t)hipBlockIdx_x, (uint32_t)hipBlockIdx_y, (uint32_t)hipBlockIdx_z));
|
||||
}
|
||||
|
||||
__CG_STATIC_QUALIFIER__ dim3 thread_index() {
|
||||
return (dim3((uint32_t)hipThreadIdx_x, (uint32_t)hipThreadIdx_y, (uint32_t)hipThreadIdx_z));
|
||||
}
|
||||
|
||||
__CG_STATIC_QUALIFIER__ uint32_t size() {
|
||||
return ((uint32_t)(hipBlockDim_x * hipBlockDim_y * hipBlockDim_z));
|
||||
}
|
||||
|
||||
__CG_STATIC_QUALIFIER__ uint32_t thread_rank() {
|
||||
return ((uint32_t)((hipThreadIdx_z * hipBlockDim_y * hipBlockDim_x) +
|
||||
(hipThreadIdx_y * hipBlockDim_x) + (hipThreadIdx_x)));
|
||||
}
|
||||
|
||||
__CG_STATIC_QUALIFIER__ bool is_valid() {
|
||||
// TODO(mahesha) any functionality need to be added here? I believe not
|
||||
return true;
|
||||
}
|
||||
|
||||
__CG_STATIC_QUALIFIER__ void sync() { __syncthreads(); }
|
||||
|
||||
} // namespace workgroup
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace cooperative_groups
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // HIP_INCLUDE_HIP_AMD_DETAIL_HIP_COOPERATIVE_GROUPS_HELPER_H
|
||||
#endif
|
||||
@@ -0,0 +1,254 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
struct __half_raw {
|
||||
unsigned short x;
|
||||
};
|
||||
|
||||
struct __half2_raw {
|
||||
unsigned short x;
|
||||
unsigned short y;
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
struct __half;
|
||||
|
||||
__half __float2half(float);
|
||||
float __half2float(__half);
|
||||
|
||||
// BEGIN STRUCT __HALF
|
||||
struct __half {
|
||||
protected:
|
||||
unsigned short __x;
|
||||
public:
|
||||
// CREATORS
|
||||
__half() = default;
|
||||
__half(const __half_raw& x) : __x{x.x} {}
|
||||
#if !defined(__HIP_NO_HALF_CONVERSIONS__)
|
||||
__half(float x) : __x{__float2half(x).__x} {}
|
||||
__half(double x) : __x{__float2half(x).__x} {}
|
||||
#endif
|
||||
__half(const __half&) = default;
|
||||
__half(__half&&) = default;
|
||||
~__half() = default;
|
||||
|
||||
// MANIPULATORS
|
||||
__half& operator=(const __half&) = default;
|
||||
__half& operator=(__half&&) = default;
|
||||
__half& operator=(const __half_raw& x) { __x = x.x; return *this; }
|
||||
#if !defined(__HIP_NO_HALF_CONVERSIONS__)
|
||||
__half& operator=(float x)
|
||||
{
|
||||
__x = __float2half(x).__x;
|
||||
return *this;
|
||||
}
|
||||
__half& operator=(double x)
|
||||
{
|
||||
return *this = static_cast<float>(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
// ACCESSORS
|
||||
operator float() const { return __half2float(*this); }
|
||||
operator __half_raw() const { return __half_raw{__x}; }
|
||||
};
|
||||
// END STRUCT __HALF
|
||||
|
||||
// BEGIN STRUCT __HALF2
|
||||
struct __half2 {
|
||||
public:
|
||||
__half x;
|
||||
__half y;
|
||||
|
||||
// CREATORS
|
||||
__half2() = default;
|
||||
__half2(const __half2_raw& ix)
|
||||
:
|
||||
x{reinterpret_cast<const __half&>(ix.x)},
|
||||
y{reinterpret_cast<const __half&>(ix.y)}
|
||||
{}
|
||||
__half2(const __half& ix, const __half& iy) : x{ix}, y{iy} {}
|
||||
__half2(const __half2&) = default;
|
||||
__half2(__half2&&) = default;
|
||||
~__half2() = default;
|
||||
|
||||
// MANIPULATORS
|
||||
__half2& operator=(const __half2&) = default;
|
||||
__half2& operator=(__half2&&) = default;
|
||||
__half2& operator=(const __half2_raw& ix)
|
||||
{
|
||||
x = reinterpret_cast<const __half_raw&>(ix.x);
|
||||
y = reinterpret_cast<const __half_raw&>(ix.y);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ACCESSORS
|
||||
operator __half2_raw() const
|
||||
{
|
||||
return __half2_raw{
|
||||
reinterpret_cast<const unsigned short&>(x),
|
||||
reinterpret_cast<const unsigned short&>(y)};
|
||||
}
|
||||
};
|
||||
// END STRUCT __HALF2
|
||||
|
||||
inline
|
||||
unsigned short __internal_float2half(
|
||||
float flt, unsigned int& sgn, unsigned int& rem)
|
||||
{
|
||||
unsigned int x{};
|
||||
std::memcpy(&x, &flt, sizeof(flt));
|
||||
|
||||
unsigned int u = (x & 0x7fffffffU);
|
||||
sgn = ((x >> 16) & 0x8000U);
|
||||
|
||||
// NaN/+Inf/-Inf
|
||||
if (u >= 0x7f800000U) {
|
||||
rem = 0;
|
||||
return static_cast<unsigned short>(
|
||||
(u == 0x7f800000U) ? (sgn | 0x7c00U) : 0x7fffU);
|
||||
}
|
||||
// Overflows
|
||||
if (u > 0x477fefffU) {
|
||||
rem = 0x80000000U;
|
||||
return static_cast<unsigned short>(sgn | 0x7bffU);
|
||||
}
|
||||
// Normal numbers
|
||||
if (u >= 0x38800000U) {
|
||||
rem = u << 19;
|
||||
u -= 0x38000000U;
|
||||
return static_cast<unsigned short>(sgn | (u >> 13));
|
||||
}
|
||||
// +0/-0
|
||||
if (u < 0x33000001U) {
|
||||
rem = u;
|
||||
return static_cast<unsigned short>(sgn);
|
||||
}
|
||||
// Denormal numbers
|
||||
unsigned int exponent = u >> 23;
|
||||
unsigned int mantissa = (u & 0x7fffffU);
|
||||
unsigned int shift = 0x7eU - exponent;
|
||||
mantissa |= 0x800000U;
|
||||
rem = mantissa << (32 - shift);
|
||||
return static_cast<unsigned short>(sgn | (mantissa >> shift));
|
||||
}
|
||||
|
||||
inline
|
||||
__half __float2half(float x)
|
||||
{
|
||||
__half_raw r;
|
||||
unsigned int sgn{};
|
||||
unsigned int rem{};
|
||||
r.x = __internal_float2half(x, sgn, rem);
|
||||
if (rem > 0x80000000U || (rem == 0x80000000U && (r.x & 0x1))) ++r.x;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline
|
||||
__half __float2half_rn(float x) { return __float2half(x); }
|
||||
|
||||
inline
|
||||
__half __float2half_rz(float x)
|
||||
{
|
||||
__half_raw r;
|
||||
unsigned int sgn{};
|
||||
unsigned int rem{};
|
||||
r.x = __internal_float2half(x, sgn, rem);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline
|
||||
__half __float2half_rd(float x)
|
||||
{
|
||||
__half_raw r;
|
||||
unsigned int sgn{};
|
||||
unsigned int rem{};
|
||||
r.x = __internal_float2half(x, sgn, rem);
|
||||
if (rem && sgn) ++r.x;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline
|
||||
__half __float2half_ru(float x)
|
||||
{
|
||||
__half_raw r;
|
||||
unsigned int sgn{};
|
||||
unsigned int rem{};
|
||||
r.x = __internal_float2half(x, sgn, rem);
|
||||
if (rem && !sgn) ++r.x;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline
|
||||
__half2 __float2half2_rn(float x)
|
||||
{
|
||||
return __half2{__float2half_rn(x), __float2half_rn(x)};
|
||||
}
|
||||
|
||||
inline
|
||||
__half2 __floats2half2_rn(float x, float y)
|
||||
{
|
||||
return __half2{__float2half_rn(x), __float2half_rn(y)};
|
||||
}
|
||||
|
||||
inline
|
||||
float __internal_half2float(unsigned short x)
|
||||
{
|
||||
unsigned int sign = ((x >> 15) & 1);
|
||||
unsigned int exponent = ((x >> 10) & 0x1f);
|
||||
unsigned int mantissa = ((x & 0x3ff) << 13);
|
||||
|
||||
if (exponent == 0x1fU) { /* NaN or Inf */
|
||||
mantissa = (mantissa ? (sign = 0, 0x7fffffU) : 0);
|
||||
exponent = 0xffU;
|
||||
} else if (!exponent) { /* Denorm or Zero */
|
||||
if (mantissa) {
|
||||
unsigned int msb;
|
||||
exponent = 0x71U;
|
||||
do {
|
||||
msb = (mantissa & 0x400000U);
|
||||
mantissa <<= 1; /* normalize */
|
||||
--exponent;
|
||||
} while (!msb);
|
||||
mantissa &= 0x7fffffU; /* 1.mantissa is implicit */
|
||||
}
|
||||
} else {
|
||||
exponent += 0x70U;
|
||||
}
|
||||
unsigned int u = ((sign << 31) | (exponent << 23) | mantissa);
|
||||
float f;
|
||||
memcpy(&f, &u, sizeof(u));
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
inline
|
||||
float __half2float(__half x)
|
||||
{
|
||||
return __internal_half2float(static_cast<__half_raw>(x).x);
|
||||
}
|
||||
|
||||
inline
|
||||
float __low2float(__half2 x)
|
||||
{
|
||||
return __internal_half2float(static_cast<__half2_raw>(x).x);
|
||||
}
|
||||
|
||||
inline
|
||||
float __high2float(__half2 x)
|
||||
{
|
||||
return __internal_half2float(static_cast<__half2_raw>(x).y);
|
||||
}
|
||||
|
||||
#if !defined(HIP_NO_HALF)
|
||||
using half = __half;
|
||||
using half2 = __half2;
|
||||
#endif
|
||||
#endif // defined(__cplusplus)
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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
|
||||
|
||||
// /*
|
||||
// Half Math Functions
|
||||
// */
|
||||
|
||||
#include "host_defines.h"
|
||||
#if !__CLANG_HIP_RUNTIME_WRAPPER_INCLUDED__
|
||||
extern "C"
|
||||
{
|
||||
__device__ __attribute__((const)) _Float16 __ocml_ceil_f16(_Float16);
|
||||
__device__ _Float16 __ocml_cos_f16(_Float16);
|
||||
__device__ __attribute__((pure)) _Float16 __ocml_exp_f16(_Float16);
|
||||
__device__ __attribute__((pure)) _Float16 __ocml_exp10_f16(_Float16);
|
||||
__device__ __attribute__((pure)) _Float16 __ocml_exp2_f16(_Float16);
|
||||
__device__ __attribute__((const)) _Float16 __ocml_floor_f16(_Float16);
|
||||
__device__ __attribute__((const))
|
||||
_Float16 __ocml_fma_f16(_Float16, _Float16, _Float16);
|
||||
__device__ __attribute__((const)) _Float16 __ocml_fabs_f16(_Float16);
|
||||
__device__ __attribute__((const)) int __ocml_isinf_f16(_Float16);
|
||||
__device__ __attribute__((const)) int __ocml_isnan_f16(_Float16);
|
||||
__device__ __attribute__((pure)) _Float16 __ocml_log_f16(_Float16);
|
||||
__device__ __attribute__((pure)) _Float16 __ocml_log10_f16(_Float16);
|
||||
__device__ __attribute__((pure)) _Float16 __ocml_log2_f16(_Float16);
|
||||
__device__ __attribute__((pure)) _Float16 __ocml_pown_f16(_Float16, int);
|
||||
__device__ __attribute__((const)) _Float16 __llvm_amdgcn_rcp_f16(_Float16);
|
||||
__device__ __attribute__((const)) _Float16 __ocml_rint_f16(_Float16);
|
||||
__device__ __attribute__((const)) _Float16 __ocml_rsqrt_f16(_Float16);
|
||||
__device__ _Float16 __ocml_sin_f16(_Float16);
|
||||
__device__ __attribute__((const)) _Float16 __ocml_sqrt_f16(_Float16);
|
||||
__device__ __attribute__((const)) _Float16 __ocml_trunc_f16(_Float16);
|
||||
|
||||
typedef _Float16 __2f16 __attribute__((ext_vector_type(2)));
|
||||
typedef short __2i16 __attribute__((ext_vector_type(2)));
|
||||
|
||||
#if __HIP_CLANG_ONLY__
|
||||
__device__ __attribute__((const)) float __ockl_fdot2(__2f16 a, __2f16 b, float c, bool s);
|
||||
#endif
|
||||
|
||||
__device__ __attribute__((const)) __2f16 __ocml_ceil_2f16(__2f16);
|
||||
__device__ __attribute__((const)) __2f16 __ocml_fabs_2f16(__2f16);
|
||||
__device__ __2f16 __ocml_cos_2f16(__2f16);
|
||||
__device__ __attribute__((pure)) __2f16 __ocml_exp_2f16(__2f16);
|
||||
__device__ __attribute__((pure)) __2f16 __ocml_exp10_2f16(__2f16);
|
||||
__device__ __attribute__((pure)) __2f16 __ocml_exp2_2f16(__2f16);
|
||||
__device__ __attribute__((const)) __2f16 __ocml_floor_2f16(__2f16);
|
||||
__device__ __attribute__((const)) __2f16 __ocml_fma_2f16(__2f16, __2f16, __2f16);
|
||||
__device__ __attribute__((const)) __2i16 __ocml_isinf_2f16(__2f16);
|
||||
__device__ __attribute__((const)) __2i16 __ocml_isnan_2f16(__2f16);
|
||||
__device__ __attribute__((pure)) __2f16 __ocml_log_2f16(__2f16);
|
||||
__device__ __attribute__((pure)) __2f16 __ocml_log10_2f16(__2f16);
|
||||
__device__ __attribute__((pure)) __2f16 __ocml_log2_2f16(__2f16);
|
||||
__device__ inline
|
||||
__2f16 __llvm_amdgcn_rcp_2f16(__2f16 x) // Not currently exposed by ROCDL.
|
||||
{
|
||||
return __2f16{__llvm_amdgcn_rcp_f16(x.x), __llvm_amdgcn_rcp_f16(x.y)};
|
||||
}
|
||||
__device__ __attribute__((const)) __2f16 __ocml_rint_2f16(__2f16);
|
||||
__device__ __attribute__((const)) __2f16 __ocml_rsqrt_2f16(__2f16);
|
||||
__device__ __2f16 __ocml_sin_2f16(__2f16);
|
||||
__device__ __attribute__((const)) __2f16 __ocml_sqrt_2f16(__2f16);
|
||||
__device__ __attribute__((const)) __2f16 __ocml_trunc_2f16(__2f16);
|
||||
}
|
||||
#endif // !__CLANG_HIP_RUNTIME_WRAPPER_INCLUDED__
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_HIP_LDG_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_HIP_LDG_H
|
||||
|
||||
#if __HIP_CLANG_ONLY__
|
||||
#include "amd_hip_vector_types.h"
|
||||
#include "host_defines.h"
|
||||
|
||||
__device__ inline static char __ldg(const char* ptr) { return *ptr; }
|
||||
|
||||
__device__ inline static char2 __ldg(const char2* ptr) { return *ptr; }
|
||||
|
||||
__device__ inline static char4 __ldg(const char4* ptr) { return *ptr; }
|
||||
|
||||
__device__ inline static signed char __ldg(const signed char* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static unsigned char __ldg(const unsigned char* ptr) { return ptr[0]; }
|
||||
|
||||
|
||||
__device__ inline static short __ldg(const short* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static short2 __ldg(const short2* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static short4 __ldg(const short4* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static unsigned short __ldg(const unsigned short* ptr) { return ptr[0]; }
|
||||
|
||||
|
||||
__device__ inline static int __ldg(const int* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static int2 __ldg(const int2* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static int4 __ldg(const int4* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static unsigned int __ldg(const unsigned int* ptr) { return ptr[0]; }
|
||||
|
||||
|
||||
__device__ inline static long __ldg(const long* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static unsigned long __ldg(const unsigned long* ptr) { return ptr[0]; }
|
||||
|
||||
|
||||
__device__ inline static long long __ldg(const long long* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static longlong2 __ldg(const longlong2* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static unsigned long long __ldg(const unsigned long long* ptr) { return ptr[0]; }
|
||||
|
||||
|
||||
__device__ inline static uchar2 __ldg(const uchar2* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static uchar4 __ldg(const uchar4* ptr) { return ptr[0]; }
|
||||
|
||||
|
||||
__device__ inline static ushort2 __ldg(const ushort2* ptr) { return ptr[0]; }
|
||||
|
||||
|
||||
__device__ inline static uint2 __ldg(const uint2* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static uint4 __ldg(const uint4* ptr) { return ptr[0]; }
|
||||
|
||||
|
||||
__device__ inline static ulonglong2 __ldg(const ulonglong2* ptr) { return ptr[0]; }
|
||||
|
||||
|
||||
__device__ inline static float __ldg(const float* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static float2 __ldg(const float2* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static float4 __ldg(const float4* ptr) { return ptr[0]; }
|
||||
|
||||
|
||||
__device__ inline static double __ldg(const double* ptr) { return ptr[0]; }
|
||||
|
||||
__device__ inline static double2 __ldg(const double2* ptr) { return ptr[0]; }
|
||||
|
||||
#endif // __HIP_CLANG_ONLY__
|
||||
|
||||
#endif // HIP_LDG_H
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_HIP_MEMORY_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_HIP_MEMORY_H
|
||||
|
||||
// Implementation of malloc and free device functions.
|
||||
// HIP heap is implemented as a global array with fixed size. Users may define
|
||||
// __HIP_SIZE_OF_PAGE and __HIP_NUM_PAGES to have a larger heap.
|
||||
|
||||
#if __HIP__ && __HIP_ENABLE_DEVICE_MALLOC__
|
||||
|
||||
// Size of page in bytes.
|
||||
#ifndef __HIP_SIZE_OF_PAGE
|
||||
#define __HIP_SIZE_OF_PAGE 64
|
||||
#endif
|
||||
|
||||
// Total number of pages
|
||||
#ifndef __HIP_NUM_PAGES
|
||||
#define __HIP_NUM_PAGES (16 * 64 * 64)
|
||||
#endif
|
||||
|
||||
#define __HIP_SIZE_OF_HEAP (__HIP_NUM_PAGES * __HIP_SIZE_OF_PAGE)
|
||||
|
||||
#if __HIP_DEVICE_COMPILE__
|
||||
__attribute__((weak)) __device__ char __hip_device_heap[__HIP_SIZE_OF_HEAP];
|
||||
__attribute__((weak)) __device__
|
||||
uint32_t __hip_device_page_flag[__HIP_NUM_PAGES];
|
||||
#else
|
||||
extern __device__ char __hip_device_heap[];
|
||||
extern __device__ uint32_t __hip_device_page_flag[];
|
||||
#endif
|
||||
|
||||
extern "C" inline __device__ void* __hip_malloc(size_t size) {
|
||||
char* heap = (char*)__hip_device_heap;
|
||||
if (size > __HIP_SIZE_OF_HEAP) {
|
||||
return (void*)nullptr;
|
||||
}
|
||||
uint32_t totalThreads =
|
||||
hipBlockDim_x * hipGridDim_x * hipBlockDim_y
|
||||
* hipGridDim_y * hipBlockDim_z * hipGridDim_z;
|
||||
uint32_t currentWorkItem = hipThreadIdx_x + hipBlockDim_x * hipBlockIdx_x
|
||||
+ (hipThreadIdx_y + hipBlockDim_y * hipBlockIdx_y) * hipBlockDim_x
|
||||
+ (hipThreadIdx_z + hipBlockDim_z * hipBlockIdx_z) * hipBlockDim_x
|
||||
* hipBlockDim_y;
|
||||
|
||||
uint32_t numHeapsPerWorkItem = __HIP_NUM_PAGES / totalThreads;
|
||||
uint32_t heapSizePerWorkItem = __HIP_SIZE_OF_HEAP / totalThreads;
|
||||
|
||||
uint32_t stride = size / __HIP_SIZE_OF_PAGE;
|
||||
uint32_t start = numHeapsPerWorkItem * currentWorkItem;
|
||||
|
||||
uint32_t k = 0;
|
||||
|
||||
while (__hip_device_page_flag[k] > 0) {
|
||||
k++;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < stride - 1; i++) {
|
||||
__hip_device_page_flag[i + start + k] = 1;
|
||||
}
|
||||
|
||||
__hip_device_page_flag[start + stride - 1 + k] = 2;
|
||||
|
||||
void* ptr = (void*)(heap
|
||||
+ heapSizePerWorkItem * currentWorkItem + k * __HIP_SIZE_OF_PAGE);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
extern "C" inline __device__ void* __hip_free(void* ptr) {
|
||||
if (ptr == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t offsetByte = (uint64_t)ptr - (uint64_t)__hip_device_heap;
|
||||
uint32_t offsetPage = offsetByte / __HIP_SIZE_OF_PAGE;
|
||||
|
||||
while (__hip_device_page_flag[offsetPage] != 0) {
|
||||
if (__hip_device_page_flag[offsetPage] == 2) {
|
||||
__hip_device_page_flag[offsetPage] = 0;
|
||||
offsetPage++;
|
||||
break;
|
||||
} else {
|
||||
__hip_device_page_flag[offsetPage] = 0;
|
||||
offsetPage++;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // HIP_INCLUDE_HIP_AMD_DETAIL_HIP_MEMORY_H
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Copyright (c) 2019 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_HIP_RUNTIME_PROF_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_HIP_RUNTIME_PROF_H
|
||||
|
||||
// HIP ROCclr Op IDs enumeration
|
||||
enum HipVdiOpId {
|
||||
kHipVdiOpIdDispatch = 0,
|
||||
kHipVdiOpIdCopy = 1,
|
||||
kHipVdiOpIdBarrier = 2,
|
||||
kHipVdiOpIdNumber = 3
|
||||
};
|
||||
|
||||
// Types of ROCclr commands
|
||||
enum HipVdiCommandKind {
|
||||
kHipVdiCommandKernel = 0x11F0,
|
||||
kHipVdiMemcpyDeviceToHost = 0x11F3,
|
||||
kHipHipVdiMemcpyHostToDevice = 0x11F4,
|
||||
kHipVdiMemcpyDeviceToDevice = 0x11F5,
|
||||
kHipVidMemcpyDeviceToHostRect = 0x1201,
|
||||
kHipVdiMemcpyHostToDeviceRect = 0x1202,
|
||||
kHipVdiMemcpyDeviceToDeviceRect = 0x1203,
|
||||
kHipVdiFillMemory = 0x1207,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initializes activity callback
|
||||
*
|
||||
* @param [input] id_callback Event ID callback function
|
||||
* @param [input] op_callback Event operation callback function
|
||||
* @param [input] arg Arguments passed into callback
|
||||
*
|
||||
* @returns None
|
||||
*/
|
||||
void hipInitActivityCallback(void* id_callback, void* op_callback, void* arg);
|
||||
|
||||
/**
|
||||
* @brief Enables activity callback
|
||||
*
|
||||
* @param [input] op Operation, which will trigger a callback (@see HipVdiOpId)
|
||||
* @param [input] enable Enable state for the callback
|
||||
*
|
||||
* @returns True if successful
|
||||
*/
|
||||
bool hipEnableActivityCallback(uint32_t op, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Returns the description string for the operation kind
|
||||
*
|
||||
* @param [input] id Command kind id (@see HipVdiCommandKind)
|
||||
*
|
||||
* @returns A pointer to a const string with the command description
|
||||
*/
|
||||
const char* hipGetCmdName(uint32_t id);
|
||||
|
||||
#endif // HIP_INCLUDE_HIP_AMD_DETAIL_HIP_RUNTIME_PROF_H
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 amd_detail/host_defines.h
|
||||
* @brief TODO-doc
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_HOST_DEFINES_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_HOST_DEFINES_H
|
||||
|
||||
// The follow macro should be removed after upstream updation.
|
||||
// It's defined here for workarround of rocThrust building failure.
|
||||
#define HIP_INCLUDE_HIP_HCC_DETAIL_HOST_DEFINES_H
|
||||
|
||||
// Add guard to Generic Grid Launch method
|
||||
#ifndef GENERIC_GRID_LAUNCH
|
||||
#define GENERIC_GRID_LAUNCH 1
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) && defined(__HIP__)
|
||||
|
||||
#if !__CLANG_HIP_RUNTIME_WRAPPER_INCLUDED__
|
||||
#define __host__ __attribute__((host))
|
||||
#define __device__ __attribute__((device))
|
||||
#define __global__ __attribute__((global))
|
||||
#define __shared__ __attribute__((shared))
|
||||
#define __constant__ __attribute__((constant))
|
||||
#endif // !__CLANG_HIP_RUNTIME_WRAPPER_INCLUDED__
|
||||
|
||||
#define __noinline__ __attribute__((noinline))
|
||||
#define __forceinline__ inline __attribute__((always_inline))
|
||||
|
||||
#else
|
||||
|
||||
// Non-HCC compiler
|
||||
/**
|
||||
* Function and kernel markers
|
||||
*/
|
||||
#define __host__
|
||||
#define __device__
|
||||
|
||||
#define __global__
|
||||
|
||||
#define __noinline__
|
||||
#define __forceinline__ inline
|
||||
|
||||
#define __shared__
|
||||
#define __constant__
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 <hsa/hsa.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace hip_impl {
|
||||
inline void* address(hsa_executable_symbol_t x) {
|
||||
void* r = nullptr;
|
||||
hsa_executable_symbol_get_info(x, HSA_EXECUTABLE_SYMBOL_INFO_VARIABLE_ADDRESS, &r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline hsa_agent_t agent(hsa_executable_symbol_t x) {
|
||||
hsa_agent_t r = {};
|
||||
hsa_executable_symbol_get_info(x, HSA_EXECUTABLE_SYMBOL_INFO_AGENT, &r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline std::uint32_t group_size(hsa_executable_symbol_t x) {
|
||||
std::uint32_t r = 0u;
|
||||
hsa_executable_symbol_get_info(x, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_GROUP_SEGMENT_SIZE, &r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline hsa_isa_t isa(hsa_agent_t x) {
|
||||
hsa_isa_t r = {};
|
||||
hsa_agent_iterate_isas(x,
|
||||
[](hsa_isa_t i, void* o) {
|
||||
*static_cast<hsa_isa_t*>(o) = i; // Pick the first.
|
||||
|
||||
return HSA_STATUS_INFO_BREAK;
|
||||
},
|
||||
&r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline std::uint64_t kernel_object(hsa_executable_symbol_t x) {
|
||||
std::uint64_t r = 0u;
|
||||
hsa_executable_symbol_get_info(x, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline std::string name(hsa_executable_symbol_t x) {
|
||||
std::uint32_t sz = 0u;
|
||||
hsa_executable_symbol_get_info(x, HSA_EXECUTABLE_SYMBOL_INFO_NAME_LENGTH, &sz);
|
||||
|
||||
std::string r(sz, '\0');
|
||||
hsa_executable_symbol_get_info(x, HSA_EXECUTABLE_SYMBOL_INFO_NAME, &r.front());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline std::uint32_t private_size(hsa_executable_symbol_t x) {
|
||||
std::uint32_t r = 0u;
|
||||
hsa_executable_symbol_get_info(x, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_PRIVATE_SEGMENT_SIZE, &r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline std::uint32_t size(hsa_executable_symbol_t x) {
|
||||
std::uint32_t r = 0;
|
||||
hsa_executable_symbol_get_info(x, HSA_EXECUTABLE_SYMBOL_INFO_VARIABLE_SIZE, &r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline hsa_symbol_kind_t type(hsa_executable_symbol_t x) {
|
||||
hsa_symbol_kind_t r = {};
|
||||
hsa_executable_symbol_get_info(x, HSA_EXECUTABLE_SYMBOL_INFO_TYPE, &r);
|
||||
|
||||
return r;
|
||||
}
|
||||
} // namespace hip_impl
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 amd_detail/llvm_intrinsics.h
|
||||
* @brief Contains declarations for wrapper functions for llvm intrinsics
|
||||
* like llvm.amdgcn.s.barrier.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_AMD_DETAIL_LLVM_INTRINSICS_H
|
||||
#define HIP_INCLUDE_HIP_AMD_DETAIL_LLVM_INTRINSICS_H
|
||||
|
||||
#include "hip/amd_detail/host_defines.h"
|
||||
|
||||
// FIXME: These should all be removed and proper builtins used.
|
||||
__device__
|
||||
unsigned __llvm_amdgcn_groupstaticsize() __asm("llvm.amdgcn.groupstaticsize");
|
||||
|
||||
__device__
|
||||
int __llvm_amdgcn_ds_swizzle(int index, int pattern) __asm("llvm.amdgcn.ds.swizzle");
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,798 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 "concepts.hpp"
|
||||
#include "helpers.hpp"
|
||||
|
||||
#include "hc.hpp"
|
||||
#include "hip/hip_ext.h"
|
||||
#include "hip_runtime.h"
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace hip_impl {
|
||||
namespace {
|
||||
struct New_grid_launch_tag {};
|
||||
struct Old_grid_launch_tag {};
|
||||
|
||||
template <typename C, typename D>
|
||||
class RAII_guard {
|
||||
D dtor_;
|
||||
|
||||
public:
|
||||
RAII_guard() = default;
|
||||
|
||||
RAII_guard(const C& ctor, D dtor) : dtor_{std::move(dtor)} { ctor(); }
|
||||
|
||||
RAII_guard(const RAII_guard&) = default;
|
||||
RAII_guard(RAII_guard&&) = default;
|
||||
|
||||
RAII_guard& operator=(const RAII_guard&) = default;
|
||||
RAII_guard& operator=(RAII_guard&&) = default;
|
||||
|
||||
~RAII_guard() { dtor_(); }
|
||||
};
|
||||
|
||||
template <typename C, typename D>
|
||||
RAII_guard<C, D> make_RAII_guard(const C& ctor, D dtor) {
|
||||
return RAII_guard<C, D>{ctor, std::move(dtor)};
|
||||
}
|
||||
|
||||
template <FunctionalProcedure F, typename... Ts>
|
||||
using is_new_grid_launch_t = typename std::conditional<is_callable<F(Ts...)>{}, New_grid_launch_tag,
|
||||
Old_grid_launch_tag>::type;
|
||||
} // namespace
|
||||
|
||||
// TODO: - dispatch rank should be derived from the domain dimensions passed
|
||||
// in, and not always assumed to be 3;
|
||||
|
||||
template <FunctionalProcedure K, typename... Ts>
|
||||
requires(Domain<K> ==
|
||||
{Ts...}) inline void grid_launch_hip_impl_(New_grid_launch_tag, dim3 num_blocks,
|
||||
dim3 dim_blocks, int group_mem_bytes,
|
||||
const hc::accelerator_view& acc_v, K k) {
|
||||
const auto d =
|
||||
hc::extent<3>{num_blocks.z * dim_blocks.z, num_blocks.y * dim_blocks.y,
|
||||
num_blocks.x * dim_blocks.x}
|
||||
.tile_with_dynamic(dim_blocks.z, dim_blocks.y, dim_blocks.x, group_mem_bytes);
|
||||
|
||||
try {
|
||||
hc::parallel_for_each(acc_v, d, k);
|
||||
} catch (std::exception& ex) {
|
||||
std::cerr << "Failed in " << __func__ << ", with exception: " << ex.what() << std::endl;
|
||||
hip_throw(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: these are workarounds, they should be removed.
|
||||
|
||||
hc::accelerator_view lock_stream_hip_(hipStream_t&, void*&);
|
||||
void print_prelaunch_trace_(const char*, dim3, dim3, int, hipStream_t);
|
||||
void unlock_stream_hip_(hipStream_t, void*, const char*, hc::accelerator_view*);
|
||||
|
||||
template <FunctionalProcedure K, typename... Ts>
|
||||
requires(Domain<K> == {Ts...}) inline void grid_launch_hip_impl_(New_grid_launch_tag,
|
||||
dim3 num_blocks, dim3 dim_blocks,
|
||||
int group_mem_bytes,
|
||||
hipStream_t stream,
|
||||
const char* kernel_name, K k) {
|
||||
void* lck_stream = nullptr;
|
||||
auto acc_v = lock_stream_hip_(stream, lck_stream);
|
||||
auto stream_guard =
|
||||
make_RAII_guard(std::bind(print_prelaunch_trace_, kernel_name, num_blocks, dim_blocks,
|
||||
group_mem_bytes, stream),
|
||||
std::bind(unlock_stream_hip_, stream, lck_stream, kernel_name, &acc_v));
|
||||
|
||||
try {
|
||||
grid_launch_hip_impl_(New_grid_launch_tag{}, std::move(num_blocks), std::move(dim_blocks),
|
||||
group_mem_bytes, acc_v, std::move(k));
|
||||
} catch (std::exception& ex) {
|
||||
std::cerr << "Failed in " << __func__ << ", with exception: " << ex.what() << std::endl;
|
||||
hip_throw(ex);
|
||||
}
|
||||
}
|
||||
|
||||
template <FunctionalProcedure K, typename... Ts>
|
||||
requires(Domain<K> ==
|
||||
{hipLaunchParm, Ts...}) inline void grid_launch_hip_impl_(Old_grid_launch_tag,
|
||||
dim3 num_blocks, dim3 dim_blocks,
|
||||
int group_mem_bytes,
|
||||
hipStream_t stream, K k) {
|
||||
grid_launch_hip_impl_(New_grid_launch_tag{}, std::move(num_blocks), std::move(dim_blocks),
|
||||
group_mem_bytes, std::move(stream), std::move(k));
|
||||
}
|
||||
|
||||
template <FunctionalProcedure K, typename... Ts>
|
||||
requires(Domain<K> == {hipLaunchParm, Ts...}) inline void grid_launch_hip_impl_(
|
||||
Old_grid_launch_tag, dim3 num_blocks, dim3 dim_blocks, int group_mem_bytes, hipStream_t stream,
|
||||
const char* kernel_name, K k) {
|
||||
grid_launch_hip_impl_(New_grid_launch_tag{}, std::move(num_blocks), std::move(dim_blocks),
|
||||
group_mem_bytes, std::move(stream), kernel_name, std::move(k));
|
||||
}
|
||||
|
||||
template <FunctionalProcedure K, typename... Ts>
|
||||
requires(Domain<K> == {Ts...}) inline std::enable_if_t<
|
||||
!std::is_function<K>::value> grid_launch_hip_(dim3 num_blocks, dim3 dim_blocks,
|
||||
int group_mem_bytes, hipStream_t stream,
|
||||
const char* kernel_name, K k) {
|
||||
grid_launch_hip_impl_(is_new_grid_launch_t<K, Ts...>{}, std::move(num_blocks),
|
||||
std::move(dim_blocks), group_mem_bytes, std::move(stream), kernel_name,
|
||||
std::move(k));
|
||||
}
|
||||
|
||||
template <FunctionalProcedure K, typename... Ts>
|
||||
requires(Domain<K> == {Ts...}) inline std::enable_if_t<
|
||||
!std::is_function<K>::value> grid_launch_hip_(dim3 num_blocks, dim3 dim_blocks,
|
||||
int group_mem_bytes, hipStream_t stream, K k) {
|
||||
grid_launch_hip_impl_(is_new_grid_launch_t<K, Ts...>{}, std::move(num_blocks),
|
||||
std::move(dim_blocks), group_mem_bytes, std::move(stream), std::move(k));
|
||||
}
|
||||
|
||||
// TODO: these are temporary and purposefully noisy and disruptive.
|
||||
#define make_kernel_name_hip(k, n) \
|
||||
HIP_kernel_functor_name_begin##_##k##_##HIP_kernel_functor_name_end##_##n
|
||||
|
||||
#define make_kernel_functor_hip_30(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, \
|
||||
p22, p23, p24, p25, p26, p27) \
|
||||
struct make_kernel_name_hip(function_name, 28) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
std::decay_t<decltype(p16)> _p16_; \
|
||||
std::decay_t<decltype(p17)> _p17_; \
|
||||
std::decay_t<decltype(p18)> _p18_; \
|
||||
std::decay_t<decltype(p19)> _p19_; \
|
||||
std::decay_t<decltype(p20)> _p20_; \
|
||||
std::decay_t<decltype(p21)> _p21_; \
|
||||
std::decay_t<decltype(p22)> _p22_; \
|
||||
std::decay_t<decltype(p23)> _p23_; \
|
||||
std::decay_t<decltype(p24)> _p24_; \
|
||||
std::decay_t<decltype(p25)> _p25_; \
|
||||
std::decay_t<decltype(p26)> _p26_; \
|
||||
std::decay_t<decltype(p27)> _p27_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_, _p16_, _p17_, _p18_, _p19_, _p20_, _p21_, \
|
||||
_p22_, _p23_, _p24_, _p25_, _p26_, _p27_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_29(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, \
|
||||
p22, p23, p24, p25, p26) \
|
||||
struct make_kernel_name_hip(function_name, 27) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
std::decay_t<decltype(p16)> _p16_; \
|
||||
std::decay_t<decltype(p17)> _p17_; \
|
||||
std::decay_t<decltype(p18)> _p18_; \
|
||||
std::decay_t<decltype(p19)> _p19_; \
|
||||
std::decay_t<decltype(p20)> _p20_; \
|
||||
std::decay_t<decltype(p21)> _p21_; \
|
||||
std::decay_t<decltype(p22)> _p22_; \
|
||||
std::decay_t<decltype(p23)> _p23_; \
|
||||
std::decay_t<decltype(p24)> _p24_; \
|
||||
std::decay_t<decltype(p25)> _p25_; \
|
||||
std::decay_t<decltype(p26)> _p26_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_, _p16_, _p17_, _p18_, _p19_, _p20_, _p21_, \
|
||||
_p22_, _p23_, _p24_, _p25_, _p26_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_28(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, \
|
||||
p22, p23, p24, p25) \
|
||||
struct make_kernel_name_hip(function_name, 26) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
std::decay_t<decltype(p16)> _p16_; \
|
||||
std::decay_t<decltype(p17)> _p17_; \
|
||||
std::decay_t<decltype(p18)> _p18_; \
|
||||
std::decay_t<decltype(p19)> _p19_; \
|
||||
std::decay_t<decltype(p20)> _p20_; \
|
||||
std::decay_t<decltype(p21)> _p21_; \
|
||||
std::decay_t<decltype(p22)> _p22_; \
|
||||
std::decay_t<decltype(p23)> _p23_; \
|
||||
std::decay_t<decltype(p24)> _p24_; \
|
||||
std::decay_t<decltype(p25)> _p25_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_, _p16_, _p17_, _p18_, _p19_, _p20_, _p21_, \
|
||||
_p22_, _p23_, _p24_, _p25_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_27(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, \
|
||||
p22, p23, p24) \
|
||||
struct make_kernel_name_hip(function_name, 25) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
std::decay_t<decltype(p16)> _p16_; \
|
||||
std::decay_t<decltype(p17)> _p17_; \
|
||||
std::decay_t<decltype(p18)> _p18_; \
|
||||
std::decay_t<decltype(p19)> _p19_; \
|
||||
std::decay_t<decltype(p20)> _p20_; \
|
||||
std::decay_t<decltype(p21)> _p21_; \
|
||||
std::decay_t<decltype(p22)> _p22_; \
|
||||
std::decay_t<decltype(p23)> _p23_; \
|
||||
std::decay_t<decltype(p24)> _p24_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_, _p16_, _p17_, _p18_, _p19_, _p20_, _p21_, \
|
||||
_p22_, _p23_, _p24_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_26(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, \
|
||||
p22, p23) \
|
||||
struct make_kernel_name_hip(function_name, 24) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
std::decay_t<decltype(p16)> _p16_; \
|
||||
std::decay_t<decltype(p17)> _p17_; \
|
||||
std::decay_t<decltype(p18)> _p18_; \
|
||||
std::decay_t<decltype(p19)> _p19_; \
|
||||
std::decay_t<decltype(p20)> _p20_; \
|
||||
std::decay_t<decltype(p21)> _p21_; \
|
||||
std::decay_t<decltype(p22)> _p22_; \
|
||||
std::decay_t<decltype(p23)> _p23_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_, _p16_, _p17_, _p18_, _p19_, _p20_, _p21_, \
|
||||
_p22_, _p23_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_25(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, \
|
||||
p22) \
|
||||
struct make_kernel_name_hip(function_name, 23) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
std::decay_t<decltype(p16)> _p16_; \
|
||||
std::decay_t<decltype(p17)> _p17_; \
|
||||
std::decay_t<decltype(p18)> _p18_; \
|
||||
std::decay_t<decltype(p19)> _p19_; \
|
||||
std::decay_t<decltype(p20)> _p20_; \
|
||||
std::decay_t<decltype(p21)> _p21_; \
|
||||
std::decay_t<decltype(p22)> _p22_; \
|
||||
__attribute__((used, flatten)) void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_, _p16_, _p17_, _p18_, _p19_, _p20_, _p21_, \
|
||||
_p22_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_24(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21) \
|
||||
struct make_kernel_name_hip(function_name, 22) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
std::decay_t<decltype(p16)> _p16_; \
|
||||
std::decay_t<decltype(p17)> _p17_; \
|
||||
std::decay_t<decltype(p18)> _p18_; \
|
||||
std::decay_t<decltype(p19)> _p19_; \
|
||||
std::decay_t<decltype(p20)> _p20_; \
|
||||
std::decay_t<decltype(p21)> _p21_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_, _p16_, _p17_, _p18_, _p19_, _p20_, _p21_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_23(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20) \
|
||||
struct make_kernel_name_hip(function_name, 21) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
std::decay_t<decltype(p16)> _p16_; \
|
||||
std::decay_t<decltype(p17)> _p17_; \
|
||||
std::decay_t<decltype(p18)> _p18_; \
|
||||
std::decay_t<decltype(p19)> _p19_; \
|
||||
std::decay_t<decltype(p20)> _p20_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_, _p16_, _p17_, _p18_, _p19_, _p20_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_22(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19) \
|
||||
struct make_kernel_name_hip(function_name, 20) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
std::decay_t<decltype(p16)> _p16_; \
|
||||
std::decay_t<decltype(p17)> _p17_; \
|
||||
std::decay_t<decltype(p18)> _p18_; \
|
||||
std::decay_t<decltype(p19)> _p19_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_, _p16_, _p17_, _p18_, _p19_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_21(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15, p16, p17, p18) \
|
||||
struct make_kernel_name_hip(function_name, 19) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
std::decay_t<decltype(p16)> _p16_; \
|
||||
std::decay_t<decltype(p17)> _p17_; \
|
||||
std::decay_t<decltype(p18)> _p18_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_, _p16_, _p17_, _p18_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_20(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15, p16, p17) \
|
||||
struct make_kernel_name_hip(function_name, 18) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
std::decay_t<decltype(p16)> _p16_; \
|
||||
std::decay_t<decltype(p17)> _p17_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_, _p16_, _p17_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_19(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15, p16) \
|
||||
struct make_kernel_name_hip(function_name, 17) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
std::decay_t<decltype(p16)> _p16_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_, _p16_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_18(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14, p15) \
|
||||
struct make_kernel_name_hip(function_name, 16) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
std::decay_t<decltype(p15)> _p15_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_, _p15_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_17(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13, p14) \
|
||||
struct make_kernel_name_hip(function_name, 15) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
std::decay_t<decltype(p14)> _p14_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_, _p14_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_16(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12, p13) \
|
||||
struct make_kernel_name_hip(function_name, 14) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
std::decay_t<decltype(p13)> _p13_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_, _p13_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_15(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11, p12) \
|
||||
struct make_kernel_name_hip(function_name, 13) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
std::decay_t<decltype(p12)> _p12_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_, \
|
||||
_p12_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_14(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10, p11) \
|
||||
struct make_kernel_name_hip(function_name, 12) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
std::decay_t<decltype(p11)> _p11_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_, _p11_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_13(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9, p10) \
|
||||
struct make_kernel_name_hip(function_name, 11) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
std::decay_t<decltype(p10)> _p10_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { \
|
||||
kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_, _p10_); \
|
||||
} \
|
||||
}
|
||||
#define make_kernel_functor_hip_12(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8, \
|
||||
p9) \
|
||||
struct make_kernel_name_hip(function_name, 10) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
std::decay_t<decltype(p9)> _p9_; \
|
||||
void operator()(const hc::tiled_index<3>&) const \
|
||||
[[hc]] { kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_, _p9_); } \
|
||||
}
|
||||
#define make_kernel_functor_hip_11(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
|
||||
struct make_kernel_name_hip(function_name, 9) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
std::decay_t<decltype(p8)> _p8_; \
|
||||
void operator()(const hc::tiled_index<3>&) const \
|
||||
[[hc]] { kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_, _p8_); } \
|
||||
}
|
||||
#define make_kernel_functor_hip_10(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6, p7) \
|
||||
struct make_kernel_name_hip(function_name, 8) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
std::decay_t<decltype(p7)> _p7_; \
|
||||
void operator()(const hc::tiled_index<3>&) const \
|
||||
[[hc]] { kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_, _p7_); } \
|
||||
}
|
||||
#define make_kernel_functor_hip_9(function_name, kernel_name, p0, p1, p2, p3, p4, p5, p6) \
|
||||
struct make_kernel_name_hip(function_name, 7) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
std::decay_t<decltype(p6)> _p6_; \
|
||||
void operator()(const hc::tiled_index<3>&) const \
|
||||
[[hc]] { kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_, _p6_); } \
|
||||
}
|
||||
#define make_kernel_functor_hip_8(function_name, kernel_name, p0, p1, p2, p3, p4, p5) \
|
||||
struct make_kernel_name_hip(function_name, 6) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
std::decay_t<decltype(p5)> _p5_; \
|
||||
void operator()(const hc::tiled_index<3>&) const \
|
||||
[[hc]] { kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_, _p5_); } \
|
||||
}
|
||||
#define make_kernel_functor_hip_7(function_name, kernel_name, p0, p1, p2, p3, p4) \
|
||||
struct make_kernel_name_hip(function_name, 5) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
std::decay_t<decltype(p4)> _p4_; \
|
||||
void operator()(const hc::tiled_index<3>&) const \
|
||||
[[hc]] { kernel_name(_p0_, _p1_, _p2_, _p3_, _p4_); } \
|
||||
}
|
||||
#define make_kernel_functor_hip_6(function_name, kernel_name, p0, p1, p2, p3) \
|
||||
struct make_kernel_name_hip(function_name, 4) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
std::decay_t<decltype(p3)> _p3_; \
|
||||
void operator()(const hc::tiled_index<3>&) const \
|
||||
[[hc]] { kernel_name(_p0_, _p1_, _p2_, _p3_); } \
|
||||
}
|
||||
#define make_kernel_functor_hip_5(function_name, kernel_name, p0, p1, p2) \
|
||||
struct make_kernel_name_hip(function_name, 3) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
std::decay_t<decltype(p2)> _p2_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { kernel_name(_p0_, _p1_, _p2_); } \
|
||||
}
|
||||
#define make_kernel_functor_hip_4(function_name, kernel_name, p0, p1) \
|
||||
struct make_kernel_name_hip(function_name, 2) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
std::decay_t<decltype(p1)> _p1_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { kernel_name(_p0_, _p1_); } \
|
||||
}
|
||||
#define fofo(f, n) kernel_prefix_hip##f##kernel_suffix_hip##n
|
||||
#define make_kernel_functor_hip_3(function_name, kernel_name, p0) \
|
||||
struct make_kernel_name_hip(function_name, 1) { \
|
||||
std::decay_t<decltype(p0)> _p0_; \
|
||||
void operator()(const hc::tiled_index<3>&) const [[hc]] { kernel_name(_p0_); } \
|
||||
}
|
||||
#define make_kernel_functor_hip_2(function_name, kernel_name) \
|
||||
struct make_kernel_name_hip(function_name, 0) { \
|
||||
void operator()(const hc::tiled_index<3>&)[[hc]] { return kernel_name(hipLaunchParm{}); } \
|
||||
}
|
||||
#define make_kernel_functor_hip_1(...)
|
||||
#define make_kernel_functor_hip_0(...)
|
||||
#define make_kernel_functor_hip_(...) overload_macro_hip_(make_kernel_functor_hip_, __VA_ARGS__)
|
||||
|
||||
|
||||
#define hipLaunchNamedKernelGGL(function_name, kernel_name, num_blocks, dim_blocks, \
|
||||
group_mem_bytes, stream, ...) \
|
||||
do { \
|
||||
make_kernel_functor_hip_(function_name, kernel_name, __VA_ARGS__) \
|
||||
hip_kernel_functor_impl_{__VA_ARGS__}; \
|
||||
hip_impl::grid_launch_hip_(num_blocks, dim_blocks, group_mem_bytes, stream, #kernel_name, \
|
||||
hip_kernel_functor_impl_); \
|
||||
} while (0)
|
||||
|
||||
#define hipLaunchKernelGGL(kernel_name, num_blocks, dim_blocks, group_mem_bytes, stream, ...) \
|
||||
do { \
|
||||
hipLaunchNamedKernelGGL(unnamed, kernel_name, num_blocks, dim_blocks, group_mem_bytes, \
|
||||
stream, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define hipLaunchKernel(kernel_name, num_blocks, dim_blocks, group_mem_bytes, stream, ...) \
|
||||
do { \
|
||||
hipLaunchKernelGGL(kernel_name, num_blocks, dim_blocks, group_mem_bytes, stream, \
|
||||
hipLaunchParm{}, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
} // namespace hip_impl
|
||||
@@ -0,0 +1,714 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 "host_defines.h"
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// DOT FUNCTIONS
|
||||
#if __HIP_CLANG_ONLY__
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ockl_sdot2(
|
||||
HIP_vector_base<short, 2>::Native_vec_,
|
||||
HIP_vector_base<short, 2>::Native_vec_,
|
||||
int, bool);
|
||||
|
||||
__device__
|
||||
__attribute__((const))
|
||||
unsigned int __ockl_udot2(
|
||||
HIP_vector_base<unsigned short, 2>::Native_vec_,
|
||||
HIP_vector_base<unsigned short, 2>::Native_vec_,
|
||||
unsigned int, bool);
|
||||
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ockl_sdot4(
|
||||
HIP_vector_base<char, 4>::Native_vec_,
|
||||
HIP_vector_base<char, 4>::Native_vec_,
|
||||
int, bool);
|
||||
|
||||
__device__
|
||||
__attribute__((const))
|
||||
unsigned int __ockl_udot4(
|
||||
HIP_vector_base<unsigned char, 4>::Native_vec_,
|
||||
HIP_vector_base<unsigned char, 4>::Native_vec_,
|
||||
unsigned int, bool);
|
||||
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ockl_sdot8(int, int, int, bool);
|
||||
|
||||
__device__
|
||||
__attribute__((const))
|
||||
unsigned int __ockl_udot8(unsigned int, unsigned int, unsigned int, bool);
|
||||
#endif
|
||||
|
||||
#if !__CLANG_HIP_RUNTIME_WRAPPER_INCLUDED__
|
||||
// BEGIN FLOAT
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_acos_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_acosh_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_asin_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_asinh_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_atan2_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_atan_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_atanh_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_cbrt_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_ceil_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
__device__
|
||||
float __ocml_copysign_f32(float, float);
|
||||
__device__
|
||||
float __ocml_cos_f32(float);
|
||||
__device__
|
||||
float __ocml_native_cos_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
__device__
|
||||
float __ocml_cosh_f32(float);
|
||||
__device__
|
||||
float __ocml_cospi_f32(float);
|
||||
__device__
|
||||
float __ocml_i0_f32(float);
|
||||
__device__
|
||||
float __ocml_i1_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_erfc_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_erfcinv_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_erfcx_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_erf_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_erfinv_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_exp10_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_native_exp10_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_exp2_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_exp_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_native_exp_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_expm1_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_fabs_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_fdim_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_floor_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_fma_f32(float, float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_fmax_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_fmin_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
__device__
|
||||
float __ocml_fmod_f32(float, float);
|
||||
__device__
|
||||
float __ocml_frexp_f32(float, __attribute__((address_space(5))) int*);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_hypot_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ocml_ilogb_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ocml_isfinite_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ocml_isinf_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ocml_isnan_f32(float);
|
||||
__device__
|
||||
float __ocml_j0_f32(float);
|
||||
__device__
|
||||
float __ocml_j1_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_ldexp_f32(float, int);
|
||||
__device__
|
||||
float __ocml_lgamma_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_log10_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_native_log10_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_log1p_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_log2_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_native_log2_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_logb_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_log_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_native_log_f32(float);
|
||||
__device__
|
||||
float __ocml_modf_f32(float, __attribute__((address_space(5))) float*);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_nearbyint_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_nextafter_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_len3_f32(float, float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_len4_f32(float, float, float, float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_ncdf_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_ncdfinv_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_pow_f32(float, float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_pown_f32(float, int);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_rcbrt_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_remainder_f32(float, float);
|
||||
__device__
|
||||
float __ocml_remquo_f32(float, float, __attribute__((address_space(5))) int*);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_rhypot_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_rint_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_rlen3_f32(float, float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_rlen4_f32(float, float, float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_round_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_rsqrt_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_scalb_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_scalbn_f32(float, int);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ocml_signbit_f32(float);
|
||||
__device__
|
||||
float __ocml_sincos_f32(float, __attribute__((address_space(5))) float*);
|
||||
__device__
|
||||
float __ocml_sincospi_f32(float, __attribute__((address_space(5))) float*);
|
||||
__device__
|
||||
float __ocml_sin_f32(float);
|
||||
__device__
|
||||
float __ocml_native_sin_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_sinh_f32(float);
|
||||
__device__
|
||||
float __ocml_sinpi_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_sqrt_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_native_sqrt_f32(float);
|
||||
__device__
|
||||
float __ocml_tan_f32(float);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
float __ocml_tanh_f32(float);
|
||||
__device__
|
||||
float __ocml_tgamma_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_trunc_f32(float);
|
||||
__device__
|
||||
float __ocml_y0_f32(float);
|
||||
__device__
|
||||
float __ocml_y1_f32(float);
|
||||
|
||||
// BEGIN INTRINSICS
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_add_rte_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_add_rtn_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_add_rtp_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_add_rtz_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_sub_rte_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_sub_rtn_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_sub_rtp_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_sub_rtz_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_mul_rte_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_mul_rtn_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_mul_rtp_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_mul_rtz_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_div_rte_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_div_rtn_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_div_rtp_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_div_rtz_f32(float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_sqrt_rte_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_sqrt_rtn_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_sqrt_rtp_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_sqrt_rtz_f32(float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_fma_rte_f32(float, float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_fma_rtn_f32(float, float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_fma_rtp_f32(float, float, float);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __ocml_fma_rtz_f32(float, float, float);
|
||||
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __llvm_amdgcn_cos_f32(float) __asm("llvm.amdgcn.cos.f32");
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __llvm_amdgcn_rcp_f32(float) __asm("llvm.amdgcn.rcp.f32");
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __llvm_amdgcn_rsq_f32(float) __asm("llvm.amdgcn.rsq.f32");
|
||||
__device__
|
||||
__attribute__((const))
|
||||
float __llvm_amdgcn_sin_f32(float) __asm("llvm.amdgcn.sin.f32");
|
||||
// END INTRINSICS
|
||||
// END FLOAT
|
||||
|
||||
// BEGIN DOUBLE
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_acos_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_acosh_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_asin_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_asinh_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_atan2_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_atan_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_atanh_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_cbrt_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_ceil_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_copysign_f64(double, double);
|
||||
__device__
|
||||
double __ocml_cos_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_cosh_f64(double);
|
||||
__device__
|
||||
double __ocml_cospi_f64(double);
|
||||
__device__
|
||||
double __ocml_i0_f64(double);
|
||||
__device__
|
||||
double __ocml_i1_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_erfc_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_erfcinv_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_erfcx_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_erf_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_erfinv_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_exp10_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_exp2_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_exp_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_expm1_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_fabs_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_fdim_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_floor_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_fma_f64(double, double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_fmax_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_fmin_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_fmod_f64(double, double);
|
||||
__device__
|
||||
double __ocml_frexp_f64(double, __attribute__((address_space(5))) int*);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_hypot_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ocml_ilogb_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ocml_isfinite_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ocml_isinf_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ocml_isnan_f64(double);
|
||||
__device__
|
||||
double __ocml_j0_f64(double);
|
||||
__device__
|
||||
double __ocml_j1_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_ldexp_f64(double, int);
|
||||
__device__
|
||||
double __ocml_lgamma_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_log10_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_log1p_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_log2_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_logb_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_log_f64(double);
|
||||
__device__
|
||||
double __ocml_modf_f64(double, __attribute__((address_space(5))) double*);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_nearbyint_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_nextafter_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_len3_f64(double, double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_len4_f64(double, double, double, double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_ncdf_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_ncdfinv_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_pow_f64(double, double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_pown_f64(double, int);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_rcbrt_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_remainder_f64(double, double);
|
||||
__device__
|
||||
double __ocml_remquo_f64(
|
||||
double, double, __attribute__((address_space(5))) int*);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_rhypot_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_rint_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_rlen3_f64(double, double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_rlen4_f64(double, double, double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_round_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_rsqrt_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_scalb_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_scalbn_f64(double, int);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
int __ocml_signbit_f64(double);
|
||||
__device__
|
||||
double __ocml_sincos_f64(double, __attribute__((address_space(5))) double*);
|
||||
__device__
|
||||
double __ocml_sincospi_f64(double, __attribute__((address_space(5))) double*);
|
||||
__device__
|
||||
double __ocml_sin_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_sinh_f64(double);
|
||||
__device__
|
||||
double __ocml_sinpi_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_sqrt_f64(double);
|
||||
__device__
|
||||
double __ocml_tan_f64(double);
|
||||
__device__
|
||||
__attribute__((pure))
|
||||
double __ocml_tanh_f64(double);
|
||||
__device__
|
||||
double __ocml_tgamma_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_trunc_f64(double);
|
||||
__device__
|
||||
double __ocml_y0_f64(double);
|
||||
__device__
|
||||
double __ocml_y1_f64(double);
|
||||
|
||||
// BEGIN INTRINSICS
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_add_rte_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_add_rtn_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_add_rtp_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_add_rtz_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_sub_rte_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_sub_rtn_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_sub_rtp_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_sub_rtz_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_mul_rte_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_mul_rtn_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_mul_rtp_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_mul_rtz_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_div_rte_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_div_rtn_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_div_rtp_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_div_rtz_f64(double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_sqrt_rte_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_sqrt_rtn_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_sqrt_rtp_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_sqrt_rtz_f64(double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_fma_rte_f64(double, double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_fma_rtn_f64(double, double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_fma_rtp_f64(double, double, double);
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __ocml_fma_rtz_f64(double, double, double);
|
||||
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __llvm_amdgcn_rcp_f64(double) __asm("llvm.amdgcn.rcp.f64");
|
||||
__device__
|
||||
__attribute__((const))
|
||||
double __llvm_amdgcn_rsq_f64(double) __asm("llvm.amdgcn.rsq.f64");
|
||||
// END INTRINSICS
|
||||
// END DOUBLE
|
||||
|
||||
#endif // !__CLANG_HIP_RUNTIME_WRAPPER_INCLUDED__
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 <hip/hip_vector_types.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
#define ADDRESS_SPACE_CONSTANT __attribute__((address_space(4)))
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_1D(unsigned int ADDRESS_SPACE_CONSTANT*i, int c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_1Db(unsigned int ADDRESS_SPACE_CONSTANT*i, int c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_1Da(unsigned int ADDRESS_SPACE_CONSTANT*i, int2::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_2D(unsigned int ADDRESS_SPACE_CONSTANT*i, int2::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_2Da(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_3D(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_CM(unsigned int ADDRESS_SPACE_CONSTANT*i, int2::Native_vec_ c, int f);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_CMa(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c, int f);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_lod_1D(unsigned int ADDRESS_SPACE_CONSTANT*i, int c, int l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_lod_1Da(unsigned int ADDRESS_SPACE_CONSTANT*i, int2::Native_vec_ c, int l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_lod_2D(unsigned int ADDRESS_SPACE_CONSTANT*i, int2::Native_vec_ c, int l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_lod_2Da(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c, int l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_lod_3D(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c, int l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_lod_CM(unsigned int ADDRESS_SPACE_CONSTANT*i, int2::Native_vec_ c, int f, int l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_load_lod_CMa(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c, int f, int l);
|
||||
|
||||
__device__ void __ockl_image_store_1D(unsigned int ADDRESS_SPACE_CONSTANT*i, int c, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_1Da(unsigned int ADDRESS_SPACE_CONSTANT*i, int2::Native_vec_ c, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_2D(unsigned int ADDRESS_SPACE_CONSTANT*i, int2::Native_vec_ c, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_2Da(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_3D(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_CM(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_CMa(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_lod_1D(unsigned int ADDRESS_SPACE_CONSTANT*i, int c, int l, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_lod_1Da(unsigned int ADDRESS_SPACE_CONSTANT*i, int2::Native_vec_ c, int l, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_lod_2D(unsigned int ADDRESS_SPACE_CONSTANT*i, int2::Native_vec_ c, int l, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_lod_2Da(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c, int l, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_lod_3D(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c, int l, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_lod_CM(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c, int l, float4::Native_vec_ p);
|
||||
|
||||
__device__ void __ockl_image_store_lod_CMa(unsigned int ADDRESS_SPACE_CONSTANT*i, int4::Native_vec_ c, int l, float4::Native_vec_ p);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_1D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_1Da(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float2::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_2D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float2::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_2Da(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float4::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_3D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float4::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_CM(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float4::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_CMa(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float4::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_grad_1D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float c, float dx, float dy);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_grad_1Da(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float2::Native_vec_ c, float dx, float dy);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_grad_2D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float2::Native_vec_ c, float2::Native_vec_ dx, float2::Native_vec_ dy);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_grad_2Da(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float4::Native_vec_ c, float2::Native_vec_ dx, float2::Native_vec_ dy);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_grad_3D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float4::Native_vec_ c, float4::Native_vec_ dx, float4::Native_vec_ dy);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_lod_1D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float c, float l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_lod_1Da(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float2::Native_vec_ c, float l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_lod_2D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float2::Native_vec_ c, float l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_lod_2Da(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float4::Native_vec_ c, float l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_lod_3D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float4::Native_vec_ c, float l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_lod_CM(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float4::Native_vec_ c, float l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_sample_lod_CMa(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float4::Native_vec_ c, float l);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_gather4r_2D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float2::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_gather4g_2D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float2::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_gather4b_2D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float2::Native_vec_ c);
|
||||
|
||||
__device__ float4::Native_vec_ __ockl_image_gather4a_2D(unsigned int ADDRESS_SPACE_CONSTANT*i, unsigned int ADDRESS_SPACE_CONSTANT*s, float2::Native_vec_ c);
|
||||
|
||||
};
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 <hsa/amd_hsa_kernel_code.h>
|
||||
#include <hsa/hsa.h>
|
||||
#include <hsa/hsa_ext_amd.h>
|
||||
#include <hsa/hsa_ven_amd_loader.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <hip/hip_common.h>
|
||||
|
||||
struct ihipModuleSymbol_t;
|
||||
using hipFunction_t = ihipModuleSymbol_t*;
|
||||
|
||||
namespace hip_impl {
|
||||
|
||||
// This section contains internal APIs that
|
||||
// needs to be exported
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC visibility push (default)
|
||||
#endif
|
||||
|
||||
struct kernarg_impl;
|
||||
class kernarg {
|
||||
public:
|
||||
kernarg();
|
||||
kernarg(kernarg&&);
|
||||
~kernarg();
|
||||
std::uint8_t* data();
|
||||
std::size_t size();
|
||||
void reserve(std::size_t);
|
||||
void resize(std::size_t);
|
||||
private:
|
||||
kernarg_impl* impl;
|
||||
};
|
||||
|
||||
class kernargs_size_align;
|
||||
class program_state_impl;
|
||||
class program_state {
|
||||
public:
|
||||
program_state();
|
||||
~program_state();
|
||||
program_state(const program_state&) = delete;
|
||||
|
||||
hipFunction_t kernel_descriptor(std::uintptr_t,
|
||||
hsa_agent_t);
|
||||
|
||||
kernargs_size_align get_kernargs_size_align(std::uintptr_t);
|
||||
hsa_executable_t load_executable(const char*, const size_t,
|
||||
hsa_executable_t,
|
||||
hsa_agent_t);
|
||||
hsa_executable_t load_executable_no_copy(const char*, const size_t,
|
||||
hsa_executable_t,
|
||||
hsa_agent_t);
|
||||
|
||||
void* global_addr_by_name(const char* name);
|
||||
|
||||
private:
|
||||
friend class agent_globals_impl;
|
||||
program_state_impl* impl;
|
||||
};
|
||||
|
||||
class kernargs_size_align {
|
||||
public:
|
||||
std::size_t size(std::size_t n) const;
|
||||
std::size_t alignment(std::size_t n) const;
|
||||
const void* getHandle() const {return handle;};
|
||||
private:
|
||||
const void* handle;
|
||||
friend kernargs_size_align program_state::get_kernargs_size_align(std::uintptr_t);
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC visibility pop
|
||||
#endif
|
||||
|
||||
inline
|
||||
__attribute__((visibility("hidden")))
|
||||
program_state& get_program_state() {
|
||||
static program_state ps;
|
||||
return ps;
|
||||
}
|
||||
} // Namespace hip_impl.
|
||||
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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(__cplusplus)
|
||||
|
||||
#include <hip/hip_vector_types.h>
|
||||
#include <hip/hip_texture_types.h>
|
||||
#include <hip/amd_detail/ockl_image.h>
|
||||
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
#include <type_traits>
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
|
||||
#define TEXTURE_PARAMETERS_INIT \
|
||||
unsigned int ADDRESS_SPACE_CONSTANT* i = (unsigned int ADDRESS_SPACE_CONSTANT*)t.textureObject; \
|
||||
unsigned int ADDRESS_SPACE_CONSTANT* s = i + HIP_SAMPLER_OBJECT_OFFSET_DWORD;
|
||||
|
||||
template<typename T>
|
||||
struct __hip_is_tex_channel_type
|
||||
{
|
||||
static constexpr bool value =
|
||||
std::is_same<T, char>::value ||
|
||||
std::is_same<T, unsigned char>::value ||
|
||||
std::is_same<T, short>::value ||
|
||||
std::is_same<T, unsigned short>::value ||
|
||||
std::is_same<T, int>::value ||
|
||||
std::is_same<T, unsigned int>::value ||
|
||||
std::is_same<T, float>::value;
|
||||
};
|
||||
|
||||
template<
|
||||
typename T,
|
||||
unsigned int rank>
|
||||
struct __hip_is_tex_channel_type<HIP_vector_type<T, rank>>
|
||||
{
|
||||
static constexpr bool value =
|
||||
__hip_is_tex_channel_type<T>::value &&
|
||||
((rank == 1) ||
|
||||
(rank == 2) ||
|
||||
(rank == 4));
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct __hip_is_tex_normalized_channel_type
|
||||
{
|
||||
static constexpr bool value =
|
||||
std::is_same<T, char>::value ||
|
||||
std::is_same<T, unsigned char>::value ||
|
||||
std::is_same<T, short>::value ||
|
||||
std::is_same<T, unsigned short>::value;
|
||||
};
|
||||
|
||||
template<
|
||||
typename T,
|
||||
unsigned int rank>
|
||||
struct __hip_is_tex_normalized_channel_type<HIP_vector_type<T, rank>>
|
||||
{
|
||||
static constexpr bool value =
|
||||
__hip_is_tex_normalized_channel_type<T>::value &&
|
||||
((rank == 1) ||
|
||||
(rank == 2) ||
|
||||
(rank == 4));
|
||||
};
|
||||
|
||||
template <
|
||||
typename T,
|
||||
hipTextureReadMode readMode,
|
||||
typename Enable = void>
|
||||
struct __hip_tex_ret
|
||||
{
|
||||
static_assert(std::is_same<Enable, void>::value, "Invalid channel type!");
|
||||
};
|
||||
|
||||
template <
|
||||
typename T,
|
||||
hipTextureReadMode readMode>
|
||||
using __hip_tex_ret_t = typename __hip_tex_ret<T, readMode, bool>::type;
|
||||
|
||||
template <typename T>
|
||||
struct __hip_tex_ret<
|
||||
T,
|
||||
hipReadModeElementType,
|
||||
typename std::enable_if<__hip_is_tex_channel_type<T>::value, bool>::type>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<
|
||||
typename T,
|
||||
unsigned int rank>
|
||||
struct __hip_tex_ret<
|
||||
HIP_vector_type<T, rank>,
|
||||
hipReadModeElementType,
|
||||
typename std::enable_if<__hip_is_tex_channel_type<HIP_vector_type<T, rank>>::value, bool>::type>
|
||||
{
|
||||
using type = HIP_vector_type<__hip_tex_ret_t<T, hipReadModeElementType>, rank>;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct __hip_tex_ret<
|
||||
T,
|
||||
hipReadModeNormalizedFloat,
|
||||
typename std::enable_if<__hip_is_tex_normalized_channel_type<T>::value, bool>::type>
|
||||
{
|
||||
using type = float;
|
||||
};
|
||||
|
||||
template<
|
||||
typename T,
|
||||
unsigned int rank>
|
||||
struct __hip_tex_ret<
|
||||
HIP_vector_type<T, rank>,
|
||||
hipReadModeNormalizedFloat,
|
||||
typename std::enable_if<__hip_is_tex_normalized_channel_type<HIP_vector_type<T, rank>>::value, bool>::type>
|
||||
{
|
||||
using type = HIP_vector_type<__hip_tex_ret_t<T, hipReadModeNormalizedFloat>, rank>;
|
||||
};
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex1Dfetch(texture<T, hipTextureType1D, readMode> t, int x)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_load_1Db(i, x);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex1D(texture<T, hipTextureType1D, readMode> t, float x)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_1D(i, s, x);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex2D(texture<T, hipTextureType2D, readMode> t, float x, float y)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_2D(i, s, float2(x, y).data);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex1DLayered(texture<T, hipTextureType1DLayered, readMode> t, float x, int layer)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_1Da(i, s, float2(x, layer).data);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex2DLayered(texture<T, hipTextureType2DLayered, readMode> t, float x, float y, int layer)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_2Da(i, s, float4(x, y, layer, 0.0f).data);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex3D(texture<T, hipTextureType3D, readMode> t, float x, float y, float z)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_3D(i, s, float4(x, y, z, 0.0f).data);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> texCubemap(texture<T, hipTextureTypeCubemap, readMode> t, float x, float y, float z)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_CM(i, s, float4(x, y, z, 0.0f).data);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex1DLod(texture<T, hipTextureType1D, readMode> t, float x, float level)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_lod_1D(i, s, x, level);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex2DLod(texture<T, hipTextureType2D, readMode> t, float x, float y, float level)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_lod_2D(i, s, float2(x, y).data, level);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex1DLayeredLod(texture<T, hipTextureType1DLayered, readMode> t, float x, int layer, float level)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_lod_1Da(i, s, float2(x, layer).data, level);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex2DLayeredLod(texture<T, hipTextureType2DLayered, readMode> t, float x, float y, int layer, float level)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_lod_2Da(i, s, float4(x, y, layer, 0.0f).data, level);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex3DLod(texture<T, hipTextureType3D, readMode> t, float x, float y, float z, float level)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_lod_3D(i, s, float4(x, y, z, 0.0f).data, level);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> texCubemapLod(texture<T, hipTextureTypeCubemap, readMode> t, float x, float y, float z, float level)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_lod_CM(i, s, float4(x, y, z, 0.0f).data, level);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> texCubemapLayered(texture<T, hipTextureTypeCubemapLayered, readMode> t, float x, float y, float z, int layer)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_CMa(i, s, float4(x, y, z, layer).data);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> texCubemapLayeredLod(texture<T, hipTextureTypeCubemapLayered, readMode> t, float x, float y, float z, int layer, float level)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_lod_CMa(i, s, float4(x, y, z, layer).data, level);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> texCubemapGrad(texture<T, hipTextureTypeCubemap, readMode> t, float x, float y, float z, float4 dPdx, float4 dPdy)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
// TODO missing in device libs.
|
||||
// auto tmp = __ockl_image_sample_grad_CM(i, s, float4(x, y, z, 0.0f).data, float4(dPdx.x, dPdx.y, dPdx.z, 0.0f).data, float4(dPdy.x, dPdy.y, dPdy.z, 0.0f).data);
|
||||
// return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> texCubemapLayeredGrad(texture<T, hipTextureTypeCubemapLayered, readMode> t, float x, float y, float z, int layer, float4 dPdx, float4 dPdy)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
// TODO missing in device libs.
|
||||
// auto tmp = __ockl_image_sample_grad_CMa(i, s, float4(x, y, z, layer).data, float4(dPdx.x, dPdx.y, dPdx.z, 0.0f).data, float4(dPdy.x, dPdy.y, dPdy.z, 0.0f).data);
|
||||
// return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex1DGrad(texture<T, hipTextureType1D, readMode> t, float x, float dPdx, float dPdy)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_grad_1D(i, s, x, dPdx, dPdy);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex2DGrad(texture<T, hipTextureType2D, readMode> t, float x, float y, float2 dPdx, float2 dPdy)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_grad_2D(i, s, float2(x, y).data, float2(dPdx.x, dPdx.y).data, float2(dPdy.x, dPdy.y).data);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex1DLayeredGrad(texture<T, hipTextureType1DLayered, readMode> t, float x, int layer, float dPdx, float dPdy)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_grad_1Da(i, s, float2(x, layer).data, dPdx, dPdy);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex2DLayeredGrad(texture<T, hipTextureType2DLayered, readMode> t, float x, float y, int layer, float2 dPdx, float2 dPdy)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_grad_2Da(i, s, float4(x, y, layer, 0.0f).data, float2(dPdx.x, dPdx.y).data, float2(dPdy.x, dPdy.y).data);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex_ret_t<T, readMode> tex3DGrad(texture<T, hipTextureType3D, readMode> t, float x, float y, float z, float4 dPdx, float4 dPdy)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
auto tmp = __ockl_image_sample_grad_3D(i, s, float4(x, y, z, 0.0f).data, float4(dPdx.x, dPdx.y, dPdx.z, 0.0f).data, float4(dPdy.x, dPdy.y, dPdy.z, 0.0f).data);
|
||||
return *reinterpret_cast<__hip_tex_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
hipTextureReadMode readMode,
|
||||
typename Enable = void>
|
||||
struct __hip_tex2dgather_ret
|
||||
{
|
||||
static_assert(std::is_same<Enable, void>::value, "Invalid channel type!");
|
||||
};
|
||||
|
||||
template <
|
||||
typename T,
|
||||
hipTextureReadMode readMode>
|
||||
using __hip_tex2dgather_ret_t = typename __hip_tex2dgather_ret<T, readMode, bool>::type;
|
||||
|
||||
template <typename T>
|
||||
struct __hip_tex2dgather_ret<
|
||||
T,
|
||||
hipReadModeElementType,
|
||||
typename std::enable_if<__hip_is_tex_channel_type<T>::value, bool>::type>
|
||||
{
|
||||
using type = HIP_vector_type<T, 4>;
|
||||
};
|
||||
|
||||
template<
|
||||
typename T,
|
||||
unsigned int rank>
|
||||
struct __hip_tex2dgather_ret<
|
||||
HIP_vector_type<T, rank>,
|
||||
hipReadModeElementType,
|
||||
typename std::enable_if<__hip_is_tex_channel_type<HIP_vector_type<T, rank>>::value, bool>::type>
|
||||
{
|
||||
using type = HIP_vector_type<T, 4>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct __hip_tex2dgather_ret<
|
||||
T,
|
||||
hipReadModeNormalizedFloat,
|
||||
typename std::enable_if<__hip_is_tex_normalized_channel_type<T>::value, bool>::type>
|
||||
{
|
||||
using type = float4;
|
||||
};
|
||||
|
||||
template <typename T, hipTextureReadMode readMode>
|
||||
static __forceinline__ __device__ __hip_tex2dgather_ret_t<T, readMode> tex2Dgather(texture<T, hipTextureType2D, readMode> t, float x, float y, int comp=0)
|
||||
{
|
||||
TEXTURE_PARAMETERS_INIT;
|
||||
switch (comp) {
|
||||
case 1: {
|
||||
auto tmp = __ockl_image_gather4g_2D(i, s, float2(x, y).data);
|
||||
return *reinterpret_cast<__hip_tex2dgather_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
case 2: {
|
||||
auto tmp = __ockl_image_gather4b_2D(i, s, float2(x, y).data);
|
||||
return *reinterpret_cast<__hip_tex2dgather_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
case 3: {
|
||||
auto tmp = __ockl_image_gather4a_2D(i, s, float2(x, y).data);
|
||||
return *reinterpret_cast<__hip_tex2dgather_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
default: {
|
||||
auto tmp = __ockl_image_gather4r_2D(i, s, float2(x, y).data);
|
||||
return *reinterpret_cast<__hip_tex2dgather_ret_t<T, readMode>*>(&tmp);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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(__cplusplus)
|
||||
|
||||
#include <hip/hip_vector_types.h>
|
||||
#include <hip/hip_texture_types.h>
|
||||
#include <hip/amd_detail/ockl_image.h>
|
||||
|
||||
#if !defined(__HIPCC_RTC__)
|
||||
#include <type_traits>
|
||||
#endif // !defined(__HIPCC_RTC__)
|
||||
|
||||
#define TEXTURE_OBJECT_PARAMETERS_INIT \
|
||||
unsigned int ADDRESS_SPACE_CONSTANT* i = (unsigned int ADDRESS_SPACE_CONSTANT*)textureObject; \
|
||||
unsigned int ADDRESS_SPACE_CONSTANT* s = i + HIP_SAMPLER_OBJECT_OFFSET_DWORD;
|
||||
|
||||
template<typename T>
|
||||
struct __hip_is_itex_channel_type
|
||||
{
|
||||
static constexpr bool value =
|
||||
std::is_same<T, char>::value ||
|
||||
std::is_same<T, unsigned char>::value ||
|
||||
std::is_same<T, short>::value ||
|
||||
std::is_same<T, unsigned short>::value ||
|
||||
std::is_same<T, int>::value ||
|
||||
std::is_same<T, unsigned int>::value ||
|
||||
std::is_same<T, float>::value;
|
||||
};
|
||||
|
||||
template<
|
||||
typename T,
|
||||
unsigned int rank>
|
||||
struct __hip_is_itex_channel_type<HIP_vector_type<T, rank>>
|
||||
{
|
||||
static constexpr bool value =
|
||||
__hip_is_itex_channel_type<T>::value &&
|
||||
((rank == 1) ||
|
||||
(rank == 2) ||
|
||||
(rank == 4));
|
||||
};
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex1Dfetch(hipTextureObject_t textureObject, int x)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_load_1Db(i, x);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex1Dfetch(T *ptr, hipTextureObject_t textureObject, int x)
|
||||
{
|
||||
*ptr = tex1Dfetch<T>(textureObject, x);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex1D(hipTextureObject_t textureObject, float x)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_1D(i, s, x);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex1D(T *ptr, hipTextureObject_t textureObject, float x)
|
||||
{
|
||||
*ptr = tex1D<T>(textureObject, x);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex2D(hipTextureObject_t textureObject, float x, float y)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_2D(i, s, float2(x, y).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex2D(T *ptr, hipTextureObject_t textureObject, float x, float y)
|
||||
{
|
||||
*ptr = tex2D<T>(textureObject, x, y);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex3D(hipTextureObject_t textureObject, float x, float y, float z)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_3D(i, s, float4(x, y, z, 0.0f).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex3D(T *ptr, hipTextureObject_t textureObject, float x, float y, float z)
|
||||
{
|
||||
*ptr = tex3D<T>(textureObject, x, y, z);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex1DLayered(hipTextureObject_t textureObject, float x, int layer)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_1Da(i, s, float2(x, layer).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex1DLayered(T *ptr, hipTextureObject_t textureObject, float x, int layer)
|
||||
{
|
||||
*ptr = tex1DLayered<T>(textureObject, x, layer);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex2DLayered(hipTextureObject_t textureObject, float x, float y, int layer)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_2Da(i, s, float4(x, y, layer, 0.0f).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex2DLayered(T *ptr, hipTextureObject_t textureObject, float x, float y, int layer)
|
||||
{
|
||||
*ptr = tex1DLayered<T>(textureObject, x, y, layer);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T texCubemap(hipTextureObject_t textureObject, float x, float y, float z)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_CM(i, s, float4(x, y, z, 0.0f).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void texCubemap(T *ptr, hipTextureObject_t textureObject, float x, float y, float z)
|
||||
{
|
||||
*ptr = texCubemap<T>(textureObject, x, y, z);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T texCubemapLayered(hipTextureObject_t textureObject, float x, float y, float z, int layer)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_CMa(i, s, float4(x, y, z, layer).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void texCubemapLayered(T *ptr, hipTextureObject_t textureObject, float x, float y, float z, int layer)
|
||||
{
|
||||
*ptr = texCubemapLayered<T>(textureObject, x, y, z, layer);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex2Dgather(hipTextureObject_t textureObject, float x, float y, int comp = 0)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
switch (comp) {
|
||||
case 1: {
|
||||
auto tmp = __ockl_image_gather4r_2D(i, s, float2(x, y).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
auto tmp = __ockl_image_gather4g_2D(i, s, float2(x, y).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
auto tmp = __ockl_image_gather4b_2D(i, s, float2(x, y).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
auto tmp = __ockl_image_gather4a_2D(i, s, float2(x, y).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
break;
|
||||
}
|
||||
};
|
||||
return {};
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex2Dgather(T *ptr, hipTextureObject_t textureObject, float x, float y, int comp = 0)
|
||||
{
|
||||
*ptr = texCubemapLayered<T>(textureObject, x, y, comp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex1DLod(hipTextureObject_t textureObject, float x, float level)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_lod_1D(i, s, x, level);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex1DLod(T *ptr, hipTextureObject_t textureObject, float x, float level)
|
||||
{
|
||||
*ptr = tex1DLod<T>(textureObject, x, level);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex2DLod(hipTextureObject_t textureObject, float x, float y, float level)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_lod_2D(i, s, float2(x, y).data, level);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex2DLod(T *ptr, hipTextureObject_t textureObject, float x, float y, float level)
|
||||
{
|
||||
*ptr = tex2DLod<T>(textureObject, x, y, level);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex3DLod(hipTextureObject_t textureObject, float x, float y, float z, float level)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_lod_3D(i, s, float4(x, y, z, 0.0f).data, level);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex3DLod(T *ptr, hipTextureObject_t textureObject, float x, float y, float z, float level)
|
||||
{
|
||||
*ptr = tex3DLod<T>(textureObject, x, y, z, level);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex1DLayeredLod(hipTextureObject_t textureObject, float x, int layer, float level)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_1Da(i, s, float2(x, layer).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex1DLayeredLod(T *ptr, hipTextureObject_t textureObject, float x, int layer, float level)
|
||||
{
|
||||
*ptr = tex1DLayeredLod<T>(textureObject, x, layer, level);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex2DLayeredLod(hipTextureObject_t textureObject, float x, float y, int layer, float level)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_2Da(i, s, float4(x, y, layer, 0.0f).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex2DLayeredLod(T *ptr, hipTextureObject_t textureObject, float x, float y, int layer, float level)
|
||||
{
|
||||
*ptr = tex2DLayeredLod<T>(textureObject, x, y, layer, level);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T texCubemapLod(hipTextureObject_t textureObject, float x, float y, float z, float level)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_lod_CM(i, s, float4(x, y, z, 0.0f).data, level);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void texCubemapLod(T *ptr, hipTextureObject_t textureObject, float x, float y, float z, float level)
|
||||
{
|
||||
*ptr = texCubemapLod<T>(textureObject, x, y, z, level);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T texCubemapGrad(hipTextureObject_t textureObject, float x, float y, float z, float4 dPdx, float4 dPdy)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
// TODO missing in device libs.
|
||||
// auto tmp = __ockl_image_sample_grad_CM(i, s, float4(x, y, z, 0.0f).data, float4(dPdx.x, dPdx.y, dPdx.z, 0.0f).data, float4(dPdy.x, dPdy.y, dPdy.z, 0.0f).data);
|
||||
// return *reinterpret_cast<T*>(&tmp);
|
||||
return {};
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void texCubemapGrad(T *ptr, hipTextureObject_t textureObject, float x, float y, float z, float4 dPdx, float4 dPdy)
|
||||
{
|
||||
*ptr = texCubemapGrad<T>(textureObject, x, y, z, dPdx, dPdy);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T texCubemapLayeredLod(hipTextureObject_t textureObject, float x, float y, float z, int layer, float level)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_lod_CMa(i, s, float4(x, y, z, layer).data, level);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void texCubemapLayeredLod(T *ptr, hipTextureObject_t textureObject, float x, float y, float z, int layer, float level)
|
||||
{
|
||||
*ptr = texCubemapLayeredLod<T>(textureObject, x, y, z, layer, level);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex1DGrad(hipTextureObject_t textureObject, float x, float dPdx, float dPdy)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_grad_1D(i, s, x, dPdx, dPdy);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex1DGrad(T *ptr, hipTextureObject_t textureObject, float x, float dPdx, float dPdy)
|
||||
{
|
||||
*ptr = tex1DGrad<T>(textureObject, x, dPdx, dPdy);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex2DGrad(hipTextureObject_t textureObject, float x, float y, float2 dPdx, float2 dPdy)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_grad_2D(i, s, float2(x, y).data, float2(dPdx.x, dPdx.y).data, float2(dPdy.x, dPdy.y).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex2DGrad(T *ptr, hipTextureObject_t textureObject, float x, float y, float2 dPdx, float2 dPdy)
|
||||
{
|
||||
*ptr = tex2DGrad<T>(textureObject, x, y, dPdx, dPdy);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex3DGrad(hipTextureObject_t textureObject, float x, float y, float z, float4 dPdx, float4 dPdy)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_grad_3D(i, s, float4(x, y, z, 0.0f).data, float4(dPdx.x, dPdx.y, dPdx.z, 0.0f).data, float4(dPdy.x, dPdy.y, dPdy.z, 0.0f).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex3DGrad(T *ptr, hipTextureObject_t textureObject, float x, float y, float z, float4 dPdx, float4 dPdy)
|
||||
{
|
||||
*ptr = tex3DGrad<T>(textureObject, x, y, z, dPdx, dPdy);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex1DLayeredGrad(hipTextureObject_t textureObject, float x, int layer, float dPdx, float dPdy)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_grad_1Da(i, s, float2(x, layer).data, dPdx, dPdy);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex1DLayeredGrad(T *ptr, hipTextureObject_t textureObject, float x, int layer, float dPdx, float dPdy)
|
||||
{
|
||||
*ptr = tex1DLayeredGrad<T>(textureObject, x, layer, dPdx, dPdy);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T tex2DLayeredGrad(hipTextureObject_t textureObject, float x, float y, int layer, float2 dPdx, float2 dPdy)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
auto tmp = __ockl_image_sample_grad_2Da(i, s, float4(x, y, layer, 0.0f).data, float2(dPdx.x, dPdx.y).data, float2(dPdy.x, dPdy.y).data);
|
||||
return *reinterpret_cast<T*>(&tmp);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void tex2DLayeredGrad(T *ptr, hipTextureObject_t textureObject, float x, float y, int layer, float2 dPdx, float2 dPdy)
|
||||
{
|
||||
*ptr = tex2DLayeredGrad<T>(textureObject, x, y, layer, dPdx, dPdy);
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ T texCubemapLayeredGrad(hipTextureObject_t textureObject, float x, float y, float z, int layer, float4 dPdx, float4 dPdy)
|
||||
{
|
||||
TEXTURE_OBJECT_PARAMETERS_INIT
|
||||
// TODO missing in device libs.
|
||||
// auto tmp = __ockl_image_sample_grad_CMa(i, s, float4(x, y, z, layer).data, float4(dPdx.x, dPdx.y, dPdx.z, 0.0f).data, float4(dPdy.x, dPdy.y, dPdy.z, 0.0f).data);
|
||||
// return *reinterpret_cast<T*>(&tmp);
|
||||
return {};
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<__hip_is_itex_channel_type<T>::value>::type* = nullptr>
|
||||
static __device__ void texCubemapLayeredGrad(T *ptr, hipTextureObject_t textureObject, float x, float y, float z, int layer, float4 dPdx, float4 dPdy)
|
||||
{
|
||||
*ptr = texCubemapLayeredGrad<T>(textureObject, x, y, z, layer, dPdx, dPdy);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
amd_detail
|
||||
@@ -0,0 +1 @@
|
||||
nvidia_detail
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_NVIDIA_DETAIL_CHANNEL_DESCRIPTOR_H
|
||||
#define HIP_INCLUDE_HIP_NVIDIA_DETAIL_CHANNEL_DESCRIPTOR_H
|
||||
|
||||
#include "channel_descriptor.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_NVIDIA_DETAIL_HIP_COMPLEX_H
|
||||
#define HIP_INCLUDE_HIP_NVIDIA_DETAIL_HIP_COMPLEX_H
|
||||
|
||||
#include "cuComplex.h"
|
||||
|
||||
typedef cuFloatComplex hipFloatComplex;
|
||||
|
||||
__device__ __host__ static inline float hipCrealf(hipFloatComplex z) { return cuCrealf(z); }
|
||||
|
||||
__device__ __host__ static inline float hipCimagf(hipFloatComplex z) { return cuCimagf(z); }
|
||||
|
||||
__device__ __host__ static inline hipFloatComplex make_hipFloatComplex(float a, float b) {
|
||||
return make_cuFloatComplex(a, b);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipFloatComplex hipConjf(hipFloatComplex z) { return cuConjf(z); }
|
||||
|
||||
__device__ __host__ static inline float hipCsqabsf(hipFloatComplex z) {
|
||||
return cuCabsf(z) * cuCabsf(z);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipFloatComplex hipCaddf(hipFloatComplex p, hipFloatComplex q) {
|
||||
return cuCaddf(p, q);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipFloatComplex hipCsubf(hipFloatComplex p, hipFloatComplex q) {
|
||||
return cuCsubf(p, q);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipFloatComplex hipCmulf(hipFloatComplex p, hipFloatComplex q) {
|
||||
return cuCmulf(p, q);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipFloatComplex hipCdivf(hipFloatComplex p, hipFloatComplex q) {
|
||||
return cuCdivf(p, q);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline float hipCabsf(hipFloatComplex z) { return cuCabsf(z); }
|
||||
|
||||
typedef cuDoubleComplex hipDoubleComplex;
|
||||
|
||||
__device__ __host__ static inline double hipCreal(hipDoubleComplex z) { return cuCreal(z); }
|
||||
|
||||
__device__ __host__ static inline double hipCimag(hipDoubleComplex z) { return cuCimag(z); }
|
||||
|
||||
__device__ __host__ static inline hipDoubleComplex make_hipDoubleComplex(double a, double b) {
|
||||
return make_cuDoubleComplex(a, b);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipDoubleComplex hipConj(hipDoubleComplex z) { return cuConj(z); }
|
||||
|
||||
__device__ __host__ static inline double hipCsqabs(hipDoubleComplex z) {
|
||||
return cuCabs(z) * cuCabs(z);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipDoubleComplex hipCadd(hipDoubleComplex p, hipDoubleComplex q) {
|
||||
return cuCadd(p, q);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipDoubleComplex hipCsub(hipDoubleComplex p, hipDoubleComplex q) {
|
||||
return cuCsub(p, q);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipDoubleComplex hipCmul(hipDoubleComplex p, hipDoubleComplex q) {
|
||||
return cuCmul(p, q);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipDoubleComplex hipCdiv(hipDoubleComplex p, hipDoubleComplex q) {
|
||||
return cuCdiv(p, q);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline double hipCabs(hipDoubleComplex z) { return cuCabs(z); }
|
||||
|
||||
typedef cuFloatComplex hipComplex;
|
||||
|
||||
__device__ __host__ static inline hipComplex make_Complex(float x, float y) {
|
||||
return make_cuComplex(x, y);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipFloatComplex hipComplexDoubleToFloat(hipDoubleComplex z) {
|
||||
return cuComplexDoubleToFloat(z);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipDoubleComplex hipComplexFloatToDouble(hipFloatComplex z) {
|
||||
return cuComplexFloatToDouble(z);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipComplex hipCfmaf(hipComplex p, hipComplex q, hipComplex r) {
|
||||
return cuCfmaf(p, q, r);
|
||||
}
|
||||
|
||||
__device__ __host__ static inline hipDoubleComplex hipCfma(hipDoubleComplex p, hipDoubleComplex q,
|
||||
hipDoubleComplex r) {
|
||||
return cuCfma(p, q, r);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef HIP_INCLUDE_HIP_NVIDIA_DETAIL_HIP_COOPERATIVE_GROUPS_H
|
||||
#define HIP_INCLUDE_HIP_NVIDIA_DETAIL_HIP_COOPERATIVE_GROUPS_H
|
||||
|
||||
// Include CUDA headers
|
||||
#include <cuda_runtime.h>
|
||||
#include <cooperative_groups.h>
|
||||
|
||||
// Include HIP wrapper headers around CUDA
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <hip/hip_runtime_api.h>
|
||||
|
||||
#endif // HIP_INCLUDE_HIP_NVIDIA_DETAIL_HIP_COOPERATIVE_GROUPS_H
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_INCLUDE_HIP_NVIDIA_DETAIL_HIP_RUNTIME_H
|
||||
#define HIP_INCLUDE_HIP_NVIDIA_DETAIL_HIP_RUNTIME_H
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
#include <hip/hip_runtime_api.h>
|
||||
|
||||
#define HIP_KERNEL_NAME(...) __VA_ARGS__
|
||||
|
||||
typedef int hipLaunchParm;
|
||||
|
||||
#define hipLaunchKernelGGLInternal(kernelName, numBlocks, numThreads, memPerBlock, streamId, ...) \
|
||||
do { \
|
||||
kernelName<<<numBlocks, numThreads, memPerBlock, streamId>>>(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define hipLaunchKernelGGL(kernelName, ...) hipLaunchKernelGGLInternal((kernelName), __VA_ARGS__)
|
||||
|
||||
#define hipReadModeElementType cudaReadModeElementType
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
|
||||
|
||||
// 32-bit Atomics:
|
||||
#define __HIP_ARCH_HAS_GLOBAL_INT32_ATOMICS__ (__CUDA_ARCH__ >= 110)
|
||||
#define __HIP_ARCH_HAS_GLOBAL_FLOAT_ATOMIC_EXCH__ (__CUDA_ARCH__ >= 110)
|
||||
#define __HIP_ARCH_HAS_SHARED_INT32_ATOMICS__ (__CUDA_ARCH__ >= 120)
|
||||
#define __HIP_ARCH_HAS_SHARED_FLOAT_ATOMIC_EXCH__ (__CUDA_ARCH__ >= 120)
|
||||
#define __HIP_ARCH_HAS_FLOAT_ATOMIC_ADD__ (__CUDA_ARCH__ >= 200)
|
||||
|
||||
// 64-bit Atomics:
|
||||
#define __HIP_ARCH_HAS_GLOBAL_INT64_ATOMICS__ (__CUDA_ARCH__ >= 200)
|
||||
#define __HIP_ARCH_HAS_SHARED_INT64_ATOMICS__ (__CUDA_ARCH__ >= 120)
|
||||
|
||||
// Doubles
|
||||
#define __HIP_ARCH_HAS_DOUBLES__ (__CUDA_ARCH__ >= 120)
|
||||
|
||||
// warp cross-lane operations:
|
||||
#define __HIP_ARCH_HAS_WARP_VOTE__ (__CUDA_ARCH__ >= 120)
|
||||
#define __HIP_ARCH_HAS_WARP_BALLOT__ (__CUDA_ARCH__ >= 200)
|
||||
#define __HIP_ARCH_HAS_WARP_SHUFFLE__ (__CUDA_ARCH__ >= 300)
|
||||
#define __HIP_ARCH_HAS_WARP_FUNNEL_SHIFT__ (__CUDA_ARCH__ >= 350)
|
||||
|
||||
// sync
|
||||
#define __HIP_ARCH_HAS_THREAD_FENCE_SYSTEM__ (__CUDA_ARCH__ >= 200)
|
||||
#define __HIP_ARCH_HAS_SYNC_THREAD_EXT__ (__CUDA_ARCH__ >= 200)
|
||||
|
||||
// misc
|
||||
#define __HIP_ARCH_HAS_SURFACE_FUNCS__ (__CUDA_ARCH__ >= 200)
|
||||
#define __HIP_ARCH_HAS_3DGRID__ (__CUDA_ARCH__ >= 200)
|
||||
#define __HIP_ARCH_HAS_DYNAMIC_PARALLEL__ (__CUDA_ARCH__ >= 350)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __CUDACC__
|
||||
|
||||
|
||||
#define hipThreadIdx_x threadIdx.x
|
||||
#define hipThreadIdx_y threadIdx.y
|
||||
#define hipThreadIdx_z threadIdx.z
|
||||
|
||||
#define hipBlockIdx_x blockIdx.x
|
||||
#define hipBlockIdx_y blockIdx.y
|
||||
#define hipBlockIdx_z blockIdx.z
|
||||
|
||||
#define hipBlockDim_x blockDim.x
|
||||
#define hipBlockDim_y blockDim.y
|
||||
#define hipBlockDim_z blockDim.z
|
||||
|
||||
#define hipGridDim_x gridDim.x
|
||||
#define hipGridDim_y gridDim.y
|
||||
#define hipGridDim_z gridDim.z
|
||||
|
||||
#define HIP_SYMBOL(X) &X
|
||||
|
||||
/**
|
||||
* Map HIP_DYNAMIC_SHARED to "extern __shared__" for compatibility with old HIP applications
|
||||
* To be removed in a future release.
|
||||
*/
|
||||
#define HIP_DYNAMIC_SHARED(type, var) extern __shared__ type var[];
|
||||
#define HIP_DYNAMIC_SHARED_ATTRIBUTE
|
||||
|
||||
#ifdef __HIP_DEVICE_COMPILE__
|
||||
#define abort_() \
|
||||
{ asm("trap;"); }
|
||||
#undef assert
|
||||
#define assert(COND) \
|
||||
{ \
|
||||
if (!COND) { \
|
||||
abort_(); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define __clock() clock()
|
||||
#define __clock64() clock64()
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,6 @@
|
||||
#ifndef HIP_INCLUDE_HIP_NVIDIA_DETAIL_HIP_TEXTURE_TYPES_H
|
||||
#define HIP_INCLUDE_HIP_NVIDIA_DETAIL_HIP_TEXTURE_TYPES_H
|
||||
|
||||
#include <texture_types.h>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
Copyright (c) 2021 - present 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.
|
||||
*/
|
||||
#ifndef HIPRTC_H
|
||||
#define HIPRTC_H
|
||||
|
||||
#include <cuda.h>
|
||||
#include <nvrtc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#pragma GCC visibility push(default)
|
||||
#endif
|
||||
|
||||
typedef enum hiprtcResult {
|
||||
HIPRTC_SUCCESS = 0,
|
||||
HIPRTC_ERROR_OUT_OF_MEMORY = 1,
|
||||
HIPRTC_ERROR_PROGRAM_CREATION_FAILURE = 2,
|
||||
HIPRTC_ERROR_INVALID_INPUT = 3,
|
||||
HIPRTC_ERROR_INVALID_PROGRAM = 4,
|
||||
HIPRTC_ERROR_INVALID_OPTION = 5,
|
||||
HIPRTC_ERROR_COMPILATION = 6,
|
||||
HIPRTC_ERROR_BUILTIN_OPERATION_FAILURE = 7,
|
||||
HIPRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION = 8,
|
||||
HIPRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION = 9,
|
||||
HIPRTC_ERROR_NAME_EXPRESSION_NOT_VALID = 10,
|
||||
HIPRTC_ERROR_INTERNAL_ERROR = 11
|
||||
} hiprtcResult;
|
||||
|
||||
inline static nvrtcResult hiprtcResultTonvrtcResult(hiprtcResult result) {
|
||||
switch (result) {
|
||||
case HIPRTC_SUCCESS:
|
||||
return NVRTC_SUCCESS;
|
||||
case HIPRTC_ERROR_OUT_OF_MEMORY:
|
||||
return NVRTC_ERROR_OUT_OF_MEMORY;
|
||||
case HIPRTC_ERROR_PROGRAM_CREATION_FAILURE:
|
||||
return NVRTC_ERROR_PROGRAM_CREATION_FAILURE;
|
||||
case HIPRTC_ERROR_INVALID_INPUT:
|
||||
return NVRTC_ERROR_INVALID_INPUT;
|
||||
case HIPRTC_ERROR_INVALID_PROGRAM:
|
||||
return NVRTC_ERROR_INVALID_PROGRAM;
|
||||
case HIPRTC_ERROR_INVALID_OPTION:
|
||||
return NVRTC_ERROR_INVALID_OPTION;
|
||||
case HIPRTC_ERROR_COMPILATION:
|
||||
return NVRTC_ERROR_COMPILATION;
|
||||
case HIPRTC_ERROR_BUILTIN_OPERATION_FAILURE:
|
||||
return NVRTC_ERROR_BUILTIN_OPERATION_FAILURE;
|
||||
case HIPRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION:
|
||||
return NVRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION;
|
||||
case HIPRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION:
|
||||
return NVRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION;
|
||||
case HIPRTC_ERROR_NAME_EXPRESSION_NOT_VALID:
|
||||
return NVRTC_ERROR_NAME_EXPRESSION_NOT_VALID;
|
||||
case HIPRTC_ERROR_INTERNAL_ERROR:
|
||||
return NVRTC_ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
inline static hiprtcResult nvrtcResultTohiprtcResult(nvrtcResult result) {
|
||||
switch (result) {
|
||||
case NVRTC_SUCCESS:
|
||||
return HIPRTC_SUCCESS;
|
||||
case NVRTC_ERROR_OUT_OF_MEMORY:
|
||||
return HIPRTC_ERROR_OUT_OF_MEMORY;
|
||||
case NVRTC_ERROR_PROGRAM_CREATION_FAILURE:
|
||||
return HIPRTC_ERROR_PROGRAM_CREATION_FAILURE;
|
||||
case NVRTC_ERROR_INVALID_INPUT:
|
||||
return HIPRTC_ERROR_INVALID_INPUT;
|
||||
case NVRTC_ERROR_INVALID_PROGRAM:
|
||||
return HIPRTC_ERROR_INVALID_PROGRAM;
|
||||
case NVRTC_ERROR_INVALID_OPTION:
|
||||
return HIPRTC_ERROR_INVALID_OPTION;
|
||||
case NVRTC_ERROR_COMPILATION:
|
||||
return HIPRTC_ERROR_COMPILATION;
|
||||
case NVRTC_ERROR_BUILTIN_OPERATION_FAILURE:
|
||||
return HIPRTC_ERROR_BUILTIN_OPERATION_FAILURE;
|
||||
case NVRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION:
|
||||
return HIPRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION;
|
||||
case NVRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION:
|
||||
return HIPRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION;
|
||||
case NVRTC_ERROR_NAME_EXPRESSION_NOT_VALID:
|
||||
return HIPRTC_ERROR_NAME_EXPRESSION_NOT_VALID;
|
||||
case NVRTC_ERROR_INTERNAL_ERROR:
|
||||
return HIPRTC_ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
const char* hiprtcGetErrorString(hiprtcResult result) {
|
||||
return nvrtcGetErrorString(hiprtcResultTonvrtcResult(result));
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcVersion(int* major, int* minor) {
|
||||
return nvrtcResultTohiprtcResult(nvrtcVersion(major, minor));
|
||||
}
|
||||
|
||||
typedef nvrtcProgram hiprtcProgram;
|
||||
|
||||
hiprtcResult hiprtcAddNameExpression(hiprtcProgram prog, const char* name_expression) {
|
||||
return nvrtcResultTohiprtcResult(nvrtcAddNameExpression(prog, name_expression));
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcCompileProgram(hiprtcProgram prog, int numOptions, const char** options) {
|
||||
return nvrtcResultTohiprtcResult(nvrtcCompileProgram(prog, numOptions, options));
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcCreateProgram(hiprtcProgram* prog, const char* src, const char* name,
|
||||
int numHeaders, const char** headers, const char** includeNames) {
|
||||
return nvrtcResultTohiprtcResult(
|
||||
nvrtcCreateProgram(prog, src, name, numHeaders, headers, includeNames));
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcDestroyProgram(hiprtcProgram* prog) {
|
||||
return nvrtcResultTohiprtcResult(nvrtcDestroyProgram(prog));
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcGetLoweredName(hiprtcProgram prog, const char* name_expression,
|
||||
const char** lowered_name) {
|
||||
return nvrtcResultTohiprtcResult(nvrtcGetLoweredName(prog, name_expression, lowered_name));
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcGetProgramLog(hiprtcProgram prog, char* log) {
|
||||
return nvrtcResultTohiprtcResult(nvrtcGetProgramLog(prog, log));
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcGetProgramLogSize(hiprtcProgram prog, size_t* logSizeRet) {
|
||||
return nvrtcResultTohiprtcResult(nvrtcGetProgramLogSize(prog, logSizeRet));
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcGetCode(hiprtcProgram prog, char* code) {
|
||||
return nvrtcResultTohiprtcResult(nvrtcGetPTX(prog, code));
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcGetCodeSize(hiprtcProgram prog, size_t* codeSizeRet) {
|
||||
return nvrtcResultTohiprtcResult(nvrtcGetPTXSize(prog, codeSizeRet));
|
||||
}
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#pragma GCC visibility pop
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif // HIPRTC_H
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright (c) 2015-2020 - present 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
|
||||
|
||||
// AMDGPU OS for HSA compatible compute kernels.
|
||||
enum { ELFOSABI_AMDGPU_HSA = 64, ELFOSABI_AMDGPU_PAL = 65, ELFOSABI_AMDGPU_MESA3D = 66 };
|
||||
|
||||
enum {
|
||||
ELFABIVERSION_AMDGPU_HSA_V2 = 0,
|
||||
ELFABIVERSION_AMDGPU_HSA_V3 = 1,
|
||||
ELFABIVERSION_AMDGPU_HSA_V4 = 2
|
||||
};
|
||||
|
||||
// AMDGPU specific e_flags
|
||||
enum : unsigned {
|
||||
EF_AMDGPU_MACH = 0x0ff,
|
||||
// AMDGPU processors
|
||||
EF_AMDGPU_MACH_NONE = 0x000,
|
||||
EF_AMDGPU_MACH_R600_R600 = 0x001,
|
||||
EF_AMDGPU_MACH_R600_R630 = 0x002,
|
||||
EF_AMDGPU_MACH_R600_RS880 = 0x003,
|
||||
EF_AMDGPU_MACH_R600_RV670 = 0x004,
|
||||
EF_AMDGPU_MACH_R600_RV710 = 0x005,
|
||||
EF_AMDGPU_MACH_R600_RV730 = 0x006,
|
||||
EF_AMDGPU_MACH_R600_RV770 = 0x007,
|
||||
EF_AMDGPU_MACH_R600_CEDAR = 0x008,
|
||||
EF_AMDGPU_MACH_R600_CYPRESS = 0x009,
|
||||
EF_AMDGPU_MACH_R600_JUNIPER = 0x00a,
|
||||
EF_AMDGPU_MACH_R600_REDWOOD = 0x00b,
|
||||
EF_AMDGPU_MACH_R600_SUMO = 0x00c,
|
||||
EF_AMDGPU_MACH_R600_BARTS = 0x00d,
|
||||
EF_AMDGPU_MACH_R600_CAICOS = 0x00e,
|
||||
EF_AMDGPU_MACH_R600_CAYMAN = 0x00f,
|
||||
EF_AMDGPU_MACH_R600_TURKS = 0x010,
|
||||
EF_AMDGPU_MACH_R600_RESERVED_FIRST = 0x011,
|
||||
EF_AMDGPU_MACH_R600_RESERVED_LAST = 0x01f,
|
||||
EF_AMDGPU_MACH_R600_FIRST = EF_AMDGPU_MACH_R600_R600,
|
||||
EF_AMDGPU_MACH_R600_LAST = EF_AMDGPU_MACH_R600_TURKS,
|
||||
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX601 = 0x021,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX701 = 0x023,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX702 = 0x024,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX703 = 0x025,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX704 = 0x026,
|
||||
EF_AMDGPU_MACH_AMDGCN_RESERVED_0X027 = 0x027,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX802 = 0x029,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX803 = 0x02a,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX810 = 0x02b,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX908 = 0x030,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX909 = 0x031,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX90C = 0x032,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX1011 = 0x034,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX1012 = 0x035,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX1031 = 0x037,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX1032 = 0x038,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX1033 = 0x039,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX602 = 0x03a,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX705 = 0x03b,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX805 = 0x03c,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX90A = 0x03f,
|
||||
EF_AMDGPU_MACH_AMDGCN_FIRST = EF_AMDGPU_MACH_AMDGCN_GFX600,
|
||||
EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX90A,
|
||||
|
||||
// Indicates if the "xnack" target feature is enabled for all code contained
|
||||
// in the object.
|
||||
//
|
||||
// Only valid for ELFOSABI_AMDGPU_HSA and ELFABIVERSION_AMDGPU_HSA_V3.
|
||||
EF_AMDGPU_FEATURE_XNACK_V3 = 0x100,
|
||||
// Indicates if the "sramecc" target feature is enabled for all code
|
||||
// contained in the object.
|
||||
//
|
||||
// Only valid for ELFOSABI_AMDGPU_HSA and ELFABIVERSION_AMDGPU_HSA_V3.
|
||||
EF_AMDGPU_FEATURE_SRAMECC_V3 = 0x200,
|
||||
|
||||
// Only valid for ELFOSABI_AMDGPU_HSA and ELFABIVERSION_AMDGPU_HSA_V4.
|
||||
EF_AMDGPU_FEATURE_XNACK_V4 = 0x300,
|
||||
EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4 = 0x000,
|
||||
EF_AMDGPU_FEATURE_XNACK_ANY_V4 = 0x100,
|
||||
EF_AMDGPU_FEATURE_XNACK_OFF_V4 = 0x200,
|
||||
EF_AMDGPU_FEATURE_XNACK_ON_V4 = 0x300,
|
||||
|
||||
// SRAMECC selection mask for EF_AMDGPU_FEATURE_SRAMECC_* values.
|
||||
// Only valid for ELFOSABI_AMDGPU_HSA and ELFABIVERSION_AMDGPU_HSA_V4.
|
||||
EF_AMDGPU_FEATURE_SRAMECC_V4 = 0xc00,
|
||||
EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4 = 0x000,
|
||||
EF_AMDGPU_FEATURE_SRAMECC_ANY_V4 = 0x400,
|
||||
EF_AMDGPU_FEATURE_SRAMECC_OFF_V4 = 0x800,
|
||||
EF_AMDGPU_FEATURE_SRAMECC_ON_V4 = 0xc00,
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,855 @@
|
||||
/* Copyright (c) 2012-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "top.hpp"
|
||||
|
||||
#include "cl_d3d9_amd.hpp"
|
||||
#include "platform/command.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#define D3DFMT_NV_12 static_cast<D3DFORMAT>(MAKEFOURCC('N', 'V', '1', '2'))
|
||||
#define D3DFMT_P010 static_cast<D3DFORMAT>(MAKEFOURCC('P', '0', '1', '0'))
|
||||
#define D3DFMT_YV_12 static_cast<D3DFORMAT>(MAKEFOURCC('Y', 'V', '1', '2'))
|
||||
#define D3DFMT_YUY2 static_cast<D3DFORMAT>(MAKEFOURCC('Y', 'U', 'Y', '2'))
|
||||
|
||||
|
||||
RUNTIME_ENTRY(cl_int, clGetDeviceIDsFromDX9MediaAdapterKHR,
|
||||
(cl_platform_id platform, cl_uint num_media_adapters,
|
||||
cl_dx9_media_adapter_type_khr* media_adapters_type, void* media_adapters,
|
||||
cl_dx9_media_adapter_set_khr media_adapter_set, cl_uint num_entries,
|
||||
cl_device_id* devices, cl_uint* num_devices)) {
|
||||
cl_int errcode;
|
||||
// Accept an array of DX9 devices here as the spec mention of array of num_media_adapters size.
|
||||
IDirect3DDevice9Ex** d3d9_device = static_cast<IDirect3DDevice9Ex**>(media_adapters);
|
||||
cl_device_id* gpu_devices = NULL;
|
||||
cl_uint num_gpu_devices = 0;
|
||||
static const bool VALIDATE_ONLY = true;
|
||||
|
||||
if (platform != NULL && platform != AMD_PLATFORM) {
|
||||
LogWarning("\"platrform\" is not a valid AMD platform");
|
||||
return CL_INVALID_PLATFORM;
|
||||
}
|
||||
// check if input parameter are correct
|
||||
if ((num_media_adapters == 0) || (media_adapters_type == NULL) || (media_adapters == NULL) ||
|
||||
(media_adapter_set != CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR &&
|
||||
media_adapter_set != CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR) ||
|
||||
(num_entries == 0 && devices != NULL)) {
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
// Get GPU devices
|
||||
errcode = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, 0, NULL, &num_gpu_devices);
|
||||
if (errcode != CL_SUCCESS && errcode != CL_DEVICE_NOT_FOUND) {
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (!num_gpu_devices) {
|
||||
*not_null(num_devices) = 0;
|
||||
return CL_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
switch (media_adapter_set) {
|
||||
case CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR:
|
||||
case CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR: {
|
||||
gpu_devices = new cl_device_id[num_gpu_devices];
|
||||
errcode = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, num_gpu_devices, gpu_devices, NULL);
|
||||
if (errcode != CL_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<amd::Device*> compatible_devices;
|
||||
for (cl_uint i = 0; i < num_gpu_devices; ++i) {
|
||||
cl_device_id device = gpu_devices[i];
|
||||
amd::Context::Flags context_flag;
|
||||
amd::Context::DeviceFlagIdx devIdx;
|
||||
switch (media_adapters_type[i]) {
|
||||
case CL_ADAPTER_D3D9_KHR:
|
||||
context_flag = amd::Context::Flags::D3D9DeviceKhr;
|
||||
devIdx = amd::Context::DeviceFlagIdx::D3D9DeviceKhrIdx;
|
||||
break;
|
||||
case CL_ADAPTER_D3D9EX_KHR:
|
||||
context_flag = amd::Context::Flags::D3D9DeviceEXKhr;
|
||||
devIdx = amd::Context::DeviceFlagIdx::D3D9DeviceEXKhrIdx;
|
||||
break;
|
||||
case CL_ADAPTER_DXVA_KHR:
|
||||
context_flag = amd::Context::Flags::D3D9DeviceVAKhr;
|
||||
devIdx = amd::Context::DeviceFlagIdx::D3D9DeviceVAKhrIdx;
|
||||
break;
|
||||
}
|
||||
|
||||
for (cl_uint j = 0; j < num_media_adapters; ++j) {
|
||||
// Since there can be multiple DX9 adapters passed in the array we need to validate
|
||||
// interopability with each.
|
||||
void* external_device[amd::Context::DeviceFlagIdx::LastDeviceFlagIdx] = {};
|
||||
external_device[devIdx] = d3d9_device[j];
|
||||
|
||||
if (is_valid(device) && (media_adapters_type[j] == CL_ADAPTER_D3D9EX_KHR) &&
|
||||
as_amd(device)->bindExternalDevice(context_flag, external_device, NULL,
|
||||
VALIDATE_ONLY)) {
|
||||
compatible_devices.push_back(as_amd(device));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (compatible_devices.size() == 0) {
|
||||
*not_null(num_devices) = 0;
|
||||
errcode = CL_DEVICE_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
auto it = compatible_devices.cbegin();
|
||||
cl_uint compatible_count = std::min(num_entries, (cl_uint)compatible_devices.size());
|
||||
|
||||
while (compatible_count--) {
|
||||
*devices++ = as_cl(*it++);
|
||||
--num_entries;
|
||||
}
|
||||
while (num_entries--) {
|
||||
*devices++ = (cl_device_id)0;
|
||||
}
|
||||
|
||||
*not_null(num_devices) = (cl_uint)compatible_devices.size();
|
||||
} break;
|
||||
|
||||
default:
|
||||
LogWarning("\"d3d9_device_set\" is invalid");
|
||||
errcode = CL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
delete[] gpu_devices;
|
||||
return errcode;
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
RUNTIME_ENTRY_RET(cl_mem, clCreateFromDX9MediaSurfaceKHR,
|
||||
(cl_context context, cl_mem_flags flags,
|
||||
cl_dx9_media_adapter_type_khr adapter_type, void* surface_info, cl_uint plane,
|
||||
cl_int* errcode_ret)) {
|
||||
cl_mem clMemObj = NULL;
|
||||
|
||||
cl_dx9_surface_info_khr* cl_surf_info = NULL;
|
||||
|
||||
if (!is_valid(context)) {
|
||||
*not_null(errcode_ret) = CL_INVALID_CONTEXT;
|
||||
LogWarning("invalid parameter \"context\"");
|
||||
return clMemObj;
|
||||
}
|
||||
|
||||
if (!flags) flags = CL_MEM_READ_WRITE;
|
||||
if (!(((flags & CL_MEM_READ_ONLY) == CL_MEM_READ_ONLY) ||
|
||||
((flags & CL_MEM_WRITE_ONLY) == CL_MEM_WRITE_ONLY) ||
|
||||
((flags & CL_MEM_READ_WRITE) == CL_MEM_READ_WRITE))) {
|
||||
*not_null(errcode_ret) = CL_INVALID_VALUE;
|
||||
LogWarning("invalid parameter \"flags\"");
|
||||
return clMemObj;
|
||||
}
|
||||
|
||||
if ((adapter_type != CL_ADAPTER_D3D9_KHR) && (adapter_type != CL_ADAPTER_D3D9EX_KHR) &&
|
||||
(adapter_type != CL_ADAPTER_DXVA_KHR)) {
|
||||
*not_null(errcode_ret) = CL_INVALID_VALUE;
|
||||
return clMemObj;
|
||||
}
|
||||
|
||||
if (!surface_info) {
|
||||
*not_null(errcode_ret) = CL_INVALID_VALUE;
|
||||
LogWarning("parameter \"pD3DResource\" is a NULL pointer");
|
||||
return clMemObj;
|
||||
}
|
||||
|
||||
cl_surf_info = (cl_dx9_surface_info_khr*)surface_info;
|
||||
IDirect3DSurface9* pD3D9Resource = cl_surf_info->resource;
|
||||
HANDLE shared_handle = cl_surf_info->shared_handle;
|
||||
|
||||
if (!pD3D9Resource) {
|
||||
*not_null(errcode_ret) = CL_INVALID_VALUE;
|
||||
LogWarning("parameter \"surface_info\" is a NULL pointer");
|
||||
return clMemObj;
|
||||
}
|
||||
|
||||
D3DSURFACE_DESC Desc;
|
||||
pD3D9Resource->GetDesc(&Desc);
|
||||
|
||||
if ((Desc.Format != D3DFMT_NV_12) &&
|
||||
(Desc.Format != D3DFMT_P010) &&
|
||||
(Desc.Format != D3DFMT_YV_12) && (plane != 0)) {
|
||||
*not_null(errcode_ret) = CL_INVALID_VALUE;
|
||||
LogWarning("The plane has to be Zero if the surface format is non-planar !");
|
||||
return clMemObj;
|
||||
}
|
||||
|
||||
// Check for image support
|
||||
const std::vector<amd::Device*>& devices = as_amd(context)->devices();
|
||||
bool supportPass = false;
|
||||
bool sizePass = false;
|
||||
for (const auto& it : devices) {
|
||||
if (it->info().imageSupport_) {
|
||||
supportPass = true;
|
||||
}
|
||||
}
|
||||
if (!supportPass) {
|
||||
*not_null(errcode_ret) = CL_INVALID_OPERATION;
|
||||
LogWarning("there are no devices in context to support images");
|
||||
return (cl_mem)0;
|
||||
}
|
||||
// Verify the resource is a 2D image
|
||||
return amd::clCreateImage2DFromD3D9ResourceAMD(*as_amd(context), flags, adapter_type,
|
||||
cl_surf_info, plane, errcode_ret);
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
RUNTIME_ENTRY(cl_int, clEnqueueAcquireDX9MediaSurfacesKHR,
|
||||
(cl_command_queue command_queue, cl_uint num_objects, const cl_mem* mem_objects,
|
||||
cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event)) {
|
||||
return amd::clEnqueueAcquireExtObjectsAMD(command_queue, num_objects, mem_objects,
|
||||
num_events_in_wait_list, event_wait_list, event,
|
||||
CL_COMMAND_ACQUIRE_DX9_MEDIA_SURFACES_KHR);
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
RUNTIME_ENTRY(cl_int, clEnqueueReleaseDX9MediaSurfacesKHR,
|
||||
(cl_command_queue command_queue, cl_uint num_objects, const cl_mem* mem_objects,
|
||||
cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event)) {
|
||||
return amd::clEnqueueReleaseExtObjectsAMD(command_queue, num_objects, mem_objects,
|
||||
num_events_in_wait_list, event_wait_list, event,
|
||||
CL_COMMAND_RELEASE_DX9_MEDIA_SURFACES_KHR);
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
//
|
||||
//
|
||||
// namespace amd
|
||||
//
|
||||
//
|
||||
namespace amd {
|
||||
/*! @}
|
||||
* \addtogroup CL-D3D9 interop helper functions
|
||||
* @{
|
||||
*/
|
||||
//
|
||||
// Class D3D9Object implementation
|
||||
//
|
||||
std::vector<std::pair<TD3D9RESINFO, TD3D9RESINFO>> D3D9Object::resources_;
|
||||
Monitor D3D9Object::resLock_;
|
||||
|
||||
//
|
||||
// clCreateImage2DFromD3D9ResourceAMD
|
||||
//
|
||||
cl_mem clCreateImage2DFromD3D9ResourceAMD(Context& amdContext, cl_mem_flags flags,
|
||||
cl_dx9_media_adapter_type_khr adapter_type,
|
||||
cl_dx9_surface_info_khr* surface_info, cl_uint plane,
|
||||
int* errcode_ret) {
|
||||
cl_dx9_surface_info_khr* cl_surf_info = reinterpret_cast<cl_dx9_surface_info_khr*>(surface_info);
|
||||
IDirect3DSurface9* pD3D9Resource = cl_surf_info->resource;
|
||||
HANDLE shared_handle = cl_surf_info->shared_handle;
|
||||
|
||||
D3D9Object obj;
|
||||
cl_int errcode = D3D9Object::initD3D9Object(amdContext, adapter_type, surface_info, plane, obj);
|
||||
if (CL_SUCCESS != errcode) {
|
||||
*not_null(errcode_ret) = errcode;
|
||||
return (cl_mem)0;
|
||||
}
|
||||
|
||||
Image2DD3D9* pImage2DD3D9 = new (amdContext) Image2DD3D9(amdContext, flags, obj);
|
||||
if (!pImage2DD3D9) {
|
||||
*not_null(errcode_ret) = CL_OUT_OF_HOST_MEMORY;
|
||||
return (cl_mem)0;
|
||||
}
|
||||
if (!pImage2DD3D9->create()) {
|
||||
*not_null(errcode_ret) = CL_MEM_OBJECT_ALLOCATION_FAILURE;
|
||||
pImage2DD3D9->release();
|
||||
return (cl_mem)0;
|
||||
}
|
||||
|
||||
*not_null(errcode_ret) = CL_SUCCESS;
|
||||
return as_cl<Memory>(pImage2DD3D9);
|
||||
}
|
||||
|
||||
//
|
||||
// Helper function SyncD3D9Objects
|
||||
//
|
||||
void SyncD3D9Objects(std::vector<amd::Memory*>& memObjects) {
|
||||
Memory*& mem = memObjects.front();
|
||||
if (!mem) {
|
||||
LogWarning("\nNULL memory object\n");
|
||||
return;
|
||||
}
|
||||
InteropObject* interop = mem->getInteropObj();
|
||||
if (!interop) {
|
||||
LogWarning("\nNULL interop object\n");
|
||||
return;
|
||||
}
|
||||
D3D9Object* d3d9Obj = interop->asD3D9Object();
|
||||
if (!d3d9Obj) {
|
||||
LogWarning("\nNULL D3D9 object\n");
|
||||
return;
|
||||
}
|
||||
IDirect3DQuery9* query = d3d9Obj->getQuery();
|
||||
if (!query) {
|
||||
LogWarning("\nNULL IDirect3DQuery9\n");
|
||||
return;
|
||||
}
|
||||
ScopedLock sl(d3d9Obj->getResLock());
|
||||
query->Issue(D3DISSUE_END);
|
||||
BOOL data = FALSE;
|
||||
while (S_OK != query->GetData(&data, sizeof(BOOL), D3DGETDATA_FLUSH)) {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Class D3D10Object implementation
|
||||
//
|
||||
size_t D3D9Object::getElementBytes(D3DFORMAT d3d9Format, cl_uint plane) {
|
||||
size_t bytesPerPixel;
|
||||
|
||||
switch (d3d9Format) {
|
||||
case D3DFMT_UNKNOWN:
|
||||
case D3DFMT_UYVY:
|
||||
case D3DFMT_DXT1:
|
||||
case D3DFMT_DXT2:
|
||||
case D3DFMT_DXT3:
|
||||
case D3DFMT_DXT4:
|
||||
case D3DFMT_DXT5:
|
||||
case D3DFMT_VERTEXDATA:
|
||||
case D3DFMT_D32:
|
||||
case D3DFMT_D15S1:
|
||||
case D3DFMT_D24S8:
|
||||
case D3DFMT_D24X8:
|
||||
case D3DFMT_D24X4S4:
|
||||
case D3DFMT_D16:
|
||||
case D3DFMT_INDEX16:
|
||||
case D3DFMT_INDEX32:
|
||||
case D3DFMT_MULTI2_ARGB8:
|
||||
case D3DFMT_CxV8U8:
|
||||
// Less than 1 byte per pixel - needs special consideration
|
||||
bytesPerPixel = 0;
|
||||
break;
|
||||
|
||||
case D3DFMT_R3G3B2:
|
||||
case D3DFMT_P8:
|
||||
case D3DFMT_A8:
|
||||
case D3DFMT_L8:
|
||||
case D3DFMT_A4L4:
|
||||
bytesPerPixel = 1;
|
||||
break;
|
||||
|
||||
case D3DFMT_R16F:
|
||||
case D3DFMT_R5G6B5:
|
||||
case D3DFMT_X1R5G5B5:
|
||||
case D3DFMT_A1R5G5B5:
|
||||
case D3DFMT_A4R4G4B4:
|
||||
case D3DFMT_A8R3G3B2:
|
||||
case D3DFMT_X4R4G4B4:
|
||||
case D3DFMT_A8P8:
|
||||
case D3DFMT_A8L8:
|
||||
case D3DFMT_V8U8:
|
||||
case D3DFMT_L6V5U5:
|
||||
case D3DFMT_D16_LOCKABLE:
|
||||
case D3DFMT_L16:
|
||||
bytesPerPixel = 2;
|
||||
break;
|
||||
|
||||
case D3DFMT_R8G8B8:
|
||||
case D3DFMT_D24FS8:
|
||||
bytesPerPixel = 3;
|
||||
break;
|
||||
|
||||
case D3DFMT_D32F_LOCKABLE:
|
||||
case D3DFMT_A8R8G8B8:
|
||||
case D3DFMT_R32F:
|
||||
case D3DFMT_X8R8G8B8:
|
||||
case D3DFMT_A2B10G10R10:
|
||||
case D3DFMT_A8B8G8R8:
|
||||
case D3DFMT_X8B8G8R8:
|
||||
case D3DFMT_G16R16:
|
||||
case D3DFMT_A2R10G10B10:
|
||||
case D3DFMT_Q8W8V8U8:
|
||||
case D3DFMT_X8L8V8U8:
|
||||
case D3DFMT_V16U16:
|
||||
case D3DFMT_A2W10V10U10:
|
||||
case D3DFMT_R8G8_B8G8:
|
||||
case D3DFMT_G8R8_G8B8:
|
||||
case D3DFMT_G16R16F:
|
||||
case D3DFMT_YUY2:
|
||||
bytesPerPixel = 4;
|
||||
break;
|
||||
|
||||
case D3DFMT_G32R32F:
|
||||
case D3DFMT_A16B16G16R16:
|
||||
case D3DFMT_A16B16G16R16F:
|
||||
case D3DFMT_Q16W16V16U16:
|
||||
bytesPerPixel = 8;
|
||||
break;
|
||||
case D3DFMT_A32B32G32R32F:
|
||||
bytesPerPixel = 16;
|
||||
break;
|
||||
//#if !defined(D3D_DISABLE_9EX)
|
||||
// case D3DFMT_D32_LOCKABLE:
|
||||
// case D3DFMT_S8_LOCKABLE:
|
||||
//#endif // !D3D_DISABLE_9EX
|
||||
case D3DFMT_NV_12:
|
||||
if (plane == 0) {
|
||||
bytesPerPixel = 1;
|
||||
} else if (plane == 1) {
|
||||
bytesPerPixel = 2;
|
||||
} // plane != 0 or != 1 shouldn't happen here
|
||||
break;
|
||||
case D3DFMT_P010:
|
||||
if (plane == 0) {
|
||||
bytesPerPixel = 2;
|
||||
} else if (plane == 1) {
|
||||
bytesPerPixel = 4;
|
||||
} // plane != 0 or != 1 shouldn't happen here
|
||||
break;
|
||||
case D3DFMT_YV_12:
|
||||
bytesPerPixel = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
bytesPerPixel = 0;
|
||||
_ASSERT(FALSE);
|
||||
break;
|
||||
}
|
||||
return bytesPerPixel;
|
||||
}
|
||||
|
||||
void setObjDesc(amd::D3D9ObjDesc_t& objDesc, D3DSURFACE_DESC& resDesc, cl_uint plane) {
|
||||
objDesc.d3dPool_ = resDesc.Pool;
|
||||
objDesc.resType_ = resDesc.Type;
|
||||
objDesc.usage_ = resDesc.Usage;
|
||||
objDesc.d3dFormat_ = resDesc.Format;
|
||||
switch (resDesc.Format) {
|
||||
case D3DFMT_NV_12:
|
||||
case D3DFMT_P010:
|
||||
objDesc.surfRect_.left = 0;
|
||||
objDesc.surfRect_.top = 0;
|
||||
if (plane == 0) {
|
||||
objDesc.objSize_.Height = resDesc.Height;
|
||||
objDesc.objSize_.Width = resDesc.Width;
|
||||
objDesc.surfRect_.right = resDesc.Width; // resDesc.Width/2-1;
|
||||
objDesc.surfRect_.bottom = 3 * resDesc.Height / 2;
|
||||
; // 3*resDesc.Height/2-1;
|
||||
} else if (plane == 1) {
|
||||
objDesc.objSize_.Height = resDesc.Height / 2;
|
||||
objDesc.objSize_.Width = resDesc.Width / 2;
|
||||
objDesc.surfRect_.right = resDesc.Width; // resDesc.Width/2-1;
|
||||
objDesc.surfRect_.bottom = 3 * resDesc.Height / 2;
|
||||
; // 3*resDesc.Height/2-1;
|
||||
} // plane != 0 or != 1 shouldn't happen here
|
||||
break;
|
||||
case D3DFMT_YV_12:
|
||||
objDesc.surfRect_.left = 0;
|
||||
if (plane == 0) {
|
||||
objDesc.objSize_.Height = resDesc.Height;
|
||||
objDesc.objSize_.Width = resDesc.Width;
|
||||
objDesc.surfRect_.top = 0;
|
||||
objDesc.surfRect_.right = resDesc.Width - 1;
|
||||
objDesc.surfRect_.bottom = resDesc.Height - 1;
|
||||
} else if (plane == 1) {
|
||||
objDesc.objSize_.Height = resDesc.Height / 2;
|
||||
objDesc.objSize_.Width = resDesc.Width / 2;
|
||||
objDesc.surfRect_.top = resDesc.Height;
|
||||
objDesc.surfRect_.right = resDesc.Width / 2 - 1;
|
||||
objDesc.surfRect_.bottom = 3 * resDesc.Height / 2 - 1;
|
||||
} else if (plane == 2) {
|
||||
objDesc.objSize_.Height = resDesc.Height / 2;
|
||||
objDesc.objSize_.Width = resDesc.Width / 2;
|
||||
objDesc.surfRect_.top = 3 * resDesc.Height / 2;
|
||||
objDesc.surfRect_.right = resDesc.Width / 2 - 1;
|
||||
objDesc.surfRect_.bottom = 2 * resDesc.Height - 1;
|
||||
} // plane > 0 or > 2 shouldn't happen here
|
||||
break;
|
||||
default:
|
||||
objDesc.objSize_.Height = resDesc.Height;
|
||||
objDesc.objSize_.Width = resDesc.Width;
|
||||
objDesc.surfRect_.left = 0;
|
||||
objDesc.surfRect_.top = 0;
|
||||
objDesc.surfRect_.right = resDesc.Width - 1;
|
||||
objDesc.surfRect_.bottom = resDesc.Height - 1;
|
||||
if (resDesc.Format == D3DFMT_YUY2) {
|
||||
objDesc.objSize_.Width >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int D3D9Object::initD3D9Object(const Context& amdContext,
|
||||
cl_dx9_media_adapter_type_khr adapter_type,
|
||||
cl_dx9_surface_info_khr* cl_surf_info, cl_uint plane,
|
||||
D3D9Object& obj) {
|
||||
ScopedLock sl(resLock_);
|
||||
|
||||
IDirect3DDevice9Ex* pDev9Ex = NULL;
|
||||
cl_int errcode = CL_SUCCESS;
|
||||
|
||||
// Check if this ressource has already been used for interop
|
||||
IDirect3DSurface9* pD3D9res = cl_surf_info->resource;
|
||||
HANDLE shared_handle = cl_surf_info->shared_handle;
|
||||
|
||||
if ((adapter_type == CL_ADAPTER_D3D9_KHR) || (adapter_type == CL_ADAPTER_DXVA_KHR)) {
|
||||
return CL_INVALID_DX9_MEDIA_ADAPTER_KHR; // Not supported yet
|
||||
}
|
||||
|
||||
for (const auto& it : resources_) {
|
||||
if (it.first.surfInfo.resource == cl_surf_info->resource && it.first.surfPlane == plane) {
|
||||
return CL_INVALID_D3D9_RESOURCE_KHR;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
D3DQUERYTYPE desc = D3DQUERYTYPE_EVENT;
|
||||
|
||||
D3DSURFACE_DESC resDesc;
|
||||
if (D3D_OK != pD3D9res->GetDesc(&resDesc)) {
|
||||
return CL_INVALID_D3D9_RESOURCE_KHR;
|
||||
}
|
||||
|
||||
hr = pD3D9res->GetContainer(IID_IDirect3DDevice9Ex, (void**)&pDev9Ex);
|
||||
if (hr == D3D_OK) {
|
||||
pDev9Ex->CreateQuery(desc, &(obj.pQuery_));
|
||||
} else {
|
||||
return CL_INVALID_D3D9_RESOURCE_KHR; // d3d9ex should be supported
|
||||
}
|
||||
|
||||
obj.handleShared_ = shared_handle;
|
||||
obj.surfPlane_ = plane;
|
||||
obj.surfInfo_ = *cl_surf_info;
|
||||
obj.adapterType_ = adapter_type;
|
||||
|
||||
// Init defaults
|
||||
setObjDesc(obj.objDescOrig_, resDesc, plane);
|
||||
obj.objDesc_ = obj.objDescOrig_;
|
||||
|
||||
// shared handle cases if the shared_handle is NULL
|
||||
// first check if the format is NV12 or YV12, which we need special handling
|
||||
if (NULL == shared_handle) {
|
||||
bool found = false;
|
||||
for (const auto& it : resources_) {
|
||||
if (it.first.surfInfo.resource == cl_surf_info->resource &&
|
||||
it.first.surfPlane != plane) {
|
||||
obj.handleShared_ = it.second.surfInfo.shared_handle;
|
||||
obj.pD3D9Res_ = it.second.surfInfo.resource;
|
||||
obj.pD3D9Res_->AddRef();
|
||||
obj.objDesc_ = obj.objDescOrig_;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
obj.handleShared_ = 0;
|
||||
hr = pDev9Ex->CreateOffscreenPlainSurface(resDesc.Width, resDesc.Height, resDesc.Format,
|
||||
resDesc.Pool, &obj.pD3D9Res_, &obj.handleShared_);
|
||||
|
||||
if (D3D_OK != hr) {
|
||||
errcode = CL_INVALID_D3D9_RESOURCE_KHR;
|
||||
}
|
||||
}
|
||||
|
||||
// put the original info into the obj
|
||||
obj.pD3D9ResOrig_ = pD3D9res;
|
||||
obj.pD3D9ResOrig_->AddRef(); // addRef in case lost the resource
|
||||
} else {
|
||||
// Share the original resource
|
||||
obj.pD3D9ResOrig_ = NULL;
|
||||
obj.pD3D9Res_ = pD3D9res;
|
||||
obj.pD3D9Res_->AddRef();
|
||||
}
|
||||
|
||||
// Release the Ex interface
|
||||
if (pDev9Ex) pDev9Ex->Release();
|
||||
|
||||
// Check for CL format compatibilty
|
||||
if (obj.objDesc_.resType_ == D3DRTYPE_SURFACE) {
|
||||
cl_image_format clFmt = obj.getCLFormatFromD3D9(obj.objDesc_.d3dFormat_, plane);
|
||||
amd::Image::Format imageFormat(clFmt);
|
||||
if (!imageFormat.isSupported(amdContext)) {
|
||||
return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
|
||||
}
|
||||
}
|
||||
|
||||
TD3D9RESINFO d3d9ObjOri = {*cl_surf_info, plane};
|
||||
TD3D9RESINFO d3d9ObjShared = {{obj.pD3D9Res_, obj.handleShared_}, plane};
|
||||
|
||||
if (errcode == CL_SUCCESS) {
|
||||
resources_.push_back({d3d9ObjOri, d3d9ObjShared});
|
||||
}
|
||||
|
||||
return errcode;
|
||||
}
|
||||
cl_uint D3D9Object::getMiscFlag() {
|
||||
switch (objDescOrig_.d3dFormat_) {
|
||||
case D3DFMT_NV_12:
|
||||
case D3DFMT_P010:
|
||||
return 1;
|
||||
break;
|
||||
case D3DFMT_YV_12:
|
||||
return 2;
|
||||
break;
|
||||
case D3DFMT_YUY2:
|
||||
return 3;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cl_image_format D3D9Object::getCLFormatFromD3D9() {
|
||||
return getCLFormatFromD3D9(objDesc_.d3dFormat_, surfPlane_);
|
||||
}
|
||||
|
||||
cl_image_format D3D9Object::getCLFormatFromD3D9(D3DFORMAT d3d9Fmt, cl_uint plane) {
|
||||
cl_image_format fmt;
|
||||
|
||||
fmt.image_channel_order = 0; // CL_RGBA;
|
||||
fmt.image_channel_data_type = 0; // CL_UNSIGNED_INT8;
|
||||
|
||||
switch (d3d9Fmt) {
|
||||
case D3DFMT_R32F:
|
||||
fmt.image_channel_order = CL_R;
|
||||
fmt.image_channel_data_type = CL_FLOAT;
|
||||
break;
|
||||
|
||||
case D3DFMT_R16F:
|
||||
fmt.image_channel_order = CL_R;
|
||||
fmt.image_channel_data_type = CL_HALF_FLOAT;
|
||||
break;
|
||||
|
||||
case D3DFMT_L16:
|
||||
fmt.image_channel_order = CL_R;
|
||||
fmt.image_channel_data_type = CL_UNORM_INT16;
|
||||
break;
|
||||
|
||||
case D3DFMT_A8:
|
||||
fmt.image_channel_order = CL_A;
|
||||
fmt.image_channel_data_type = CL_UNORM_INT8;
|
||||
break;
|
||||
|
||||
case D3DFMT_L8:
|
||||
fmt.image_channel_order = CL_R;
|
||||
fmt.image_channel_data_type = CL_UNORM_INT8;
|
||||
break;
|
||||
|
||||
case D3DFMT_G32R32F:
|
||||
fmt.image_channel_order = CL_RG;
|
||||
fmt.image_channel_data_type = CL_FLOAT;
|
||||
break;
|
||||
|
||||
case D3DFMT_G16R16F:
|
||||
fmt.image_channel_order = CL_RG;
|
||||
fmt.image_channel_data_type = CL_HALF_FLOAT;
|
||||
break;
|
||||
|
||||
case D3DFMT_G16R16:
|
||||
fmt.image_channel_order = CL_RG;
|
||||
fmt.image_channel_data_type = CL_UNORM_INT16;
|
||||
break;
|
||||
|
||||
case D3DFMT_A8L8:
|
||||
fmt.image_channel_order = CL_RG;
|
||||
fmt.image_channel_data_type = CL_UNORM_INT8;
|
||||
break;
|
||||
|
||||
case D3DFMT_A32B32G32R32F:
|
||||
fmt.image_channel_order = CL_RGBA;
|
||||
fmt.image_channel_data_type = CL_FLOAT;
|
||||
break;
|
||||
|
||||
case D3DFMT_A16B16G16R16F:
|
||||
fmt.image_channel_order = CL_RGBA;
|
||||
fmt.image_channel_data_type = CL_HALF_FLOAT;
|
||||
break;
|
||||
|
||||
case D3DFMT_A16B16G16R16:
|
||||
fmt.image_channel_order = CL_RGBA;
|
||||
fmt.image_channel_data_type = CL_UNORM_INT16;
|
||||
break;
|
||||
|
||||
case D3DFMT_A8B8G8R8:
|
||||
fmt.image_channel_order = CL_RGBA;
|
||||
fmt.image_channel_data_type = CL_UNORM_INT8;
|
||||
break;
|
||||
|
||||
case D3DFMT_X8B8G8R8:
|
||||
fmt.image_channel_order = CL_RGBA;
|
||||
fmt.image_channel_data_type = CL_UNORM_INT8;
|
||||
break;
|
||||
|
||||
case D3DFMT_A8R8G8B8:
|
||||
fmt.image_channel_order = CL_BGRA;
|
||||
fmt.image_channel_data_type = CL_UNORM_INT8;
|
||||
break;
|
||||
|
||||
case D3DFMT_X8R8G8B8:
|
||||
fmt.image_channel_order = CL_BGRA;
|
||||
fmt.image_channel_data_type = CL_UNORM_INT8;
|
||||
break;
|
||||
case D3DFMT_NV_12:
|
||||
fmt.image_channel_data_type = CL_UNORM_INT8;
|
||||
if (plane == 0) {
|
||||
fmt.image_channel_order = CL_R;
|
||||
} else if (plane == 1) {
|
||||
fmt.image_channel_order = CL_RG;
|
||||
}
|
||||
break;
|
||||
case D3DFMT_P010:
|
||||
fmt.image_channel_data_type = CL_UNORM_INT16;
|
||||
if (plane == 0) {
|
||||
fmt.image_channel_order = CL_R;
|
||||
} else if (plane == 1) {
|
||||
fmt.image_channel_order = CL_RG;
|
||||
}
|
||||
break;
|
||||
case D3DFMT_YV_12:
|
||||
fmt.image_channel_order = CL_R;
|
||||
fmt.image_channel_data_type = CL_UNORM_INT8;
|
||||
break;
|
||||
case D3DFMT_YUY2:
|
||||
fmt.image_channel_order = CL_RGBA;
|
||||
fmt.image_channel_data_type = CL_UNSIGNED_INT8;
|
||||
break;
|
||||
case D3DFMT_UNKNOWN:
|
||||
case D3DFMT_R8G8B8:
|
||||
case D3DFMT_R5G6B5:
|
||||
case D3DFMT_X1R5G5B5:
|
||||
case D3DFMT_A1R5G5B5:
|
||||
case D3DFMT_A4R4G4B4:
|
||||
case D3DFMT_R3G3B2:
|
||||
case D3DFMT_A8R3G3B2:
|
||||
case D3DFMT_X4R4G4B4:
|
||||
case D3DFMT_A2B10G10R10:
|
||||
case D3DFMT_A2R10G10B10:
|
||||
case D3DFMT_A8P8:
|
||||
case D3DFMT_P8:
|
||||
case D3DFMT_A4L4:
|
||||
case D3DFMT_V8U8:
|
||||
case D3DFMT_L6V5U5:
|
||||
case D3DFMT_X8L8V8U8:
|
||||
case D3DFMT_Q8W8V8U8:
|
||||
case D3DFMT_V16U16:
|
||||
case D3DFMT_A2W10V10U10:
|
||||
case D3DFMT_UYVY:
|
||||
case D3DFMT_R8G8_B8G8:
|
||||
case D3DFMT_G8R8_G8B8:
|
||||
case D3DFMT_DXT1:
|
||||
case D3DFMT_DXT2:
|
||||
case D3DFMT_DXT3:
|
||||
case D3DFMT_DXT4:
|
||||
case D3DFMT_DXT5:
|
||||
case D3DFMT_D16_LOCKABLE:
|
||||
case D3DFMT_D32:
|
||||
case D3DFMT_D15S1:
|
||||
case D3DFMT_D24S8:
|
||||
case D3DFMT_D24X8:
|
||||
case D3DFMT_D24X4S4:
|
||||
case D3DFMT_D16:
|
||||
case D3DFMT_D32F_LOCKABLE:
|
||||
case D3DFMT_D24FS8:
|
||||
//#if !defined(D3D_DISABLE_9EX)
|
||||
case D3DFMT_D32_LOCKABLE:
|
||||
case D3DFMT_S8_LOCKABLE:
|
||||
//#endif // !D3D_DISABLE_9EX
|
||||
case D3DFMT_VERTEXDATA:
|
||||
case D3DFMT_INDEX16:
|
||||
case D3DFMT_INDEX32:
|
||||
case D3DFMT_Q16W16V16U16:
|
||||
case D3DFMT_MULTI2_ARGB8:
|
||||
case D3DFMT_CxV8U8:
|
||||
//#if !defined(D3D_DISABLE_9EX)
|
||||
case D3DFMT_A1:
|
||||
case D3DFMT_A2B10G10R10_XR_BIAS:
|
||||
case D3DFMT_BINARYBUFFER:
|
||||
_ASSERT(FALSE); // NOT SURPPORTED
|
||||
break;
|
||||
//#endif // !D3D_DISABLE_9EX
|
||||
default:
|
||||
_ASSERT(FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
return fmt;
|
||||
}
|
||||
|
||||
bool D3D9Object::copyOrigToShared() {
|
||||
// Don't copy if there is no orig
|
||||
if (NULL == getD3D9ResOrig()) return true;
|
||||
|
||||
IDirect3DDevice9Ex* d3dDev;
|
||||
HRESULT hr;
|
||||
ScopedLock sl(getResLock());
|
||||
|
||||
IDirect3DSurface9* srcSurf = getD3D9ResOrig();
|
||||
IDirect3DSurface9* dstSurf = getD3D9Resource();
|
||||
|
||||
hr = getD3D9Resource()->GetContainer(IID_IDirect3DDevice9Ex, (void**)&d3dDev);
|
||||
if (hr != D3D_OK || !d3dDev) {
|
||||
LogError("\nCannot get D3D9 device from D3D9 surface\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = d3dDev->StretchRect(srcSurf, NULL, dstSurf, NULL, D3DTEXF_NONE);
|
||||
if (hr != D3D_OK) {
|
||||
LogError("\ncopy original surface to shared surface failed\n");
|
||||
return false;
|
||||
}
|
||||
// Flush D3D queues and make sure D3D stuff is finished
|
||||
pQuery_->Issue(D3DISSUE_END);
|
||||
BOOL data;
|
||||
while ((D3D_OK != pQuery_->GetData(&data, sizeof(BOOL), D3DGETDATA_FLUSH)) && (data != TRUE)) {
|
||||
}
|
||||
|
||||
if (d3dDev) d3dDev->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool D3D9Object::copySharedToOrig() {
|
||||
// Don't copy if there is no orig
|
||||
if (NULL == getD3D9ResOrig()) return true;
|
||||
|
||||
IDirect3DDevice9Ex* d3dDev;
|
||||
HRESULT hr;
|
||||
ScopedLock sl(getResLock());
|
||||
|
||||
hr = getD3D9Resource()->GetContainer(IID_IDirect3DDevice9Ex, (void**)&d3dDev);
|
||||
if (hr != D3D_OK || !d3dDev) {
|
||||
LogError("\nCannot get D3D9 device from D3D9 surface\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = d3dDev->StretchRect(getD3D9Resource(), NULL, getD3D9ResOrig(), NULL, D3DTEXF_NONE);
|
||||
if (hr != D3D_OK) {
|
||||
LogError("\ncopy shared surface to original surface failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d3dDev) d3dDev->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Image2DD3D9::initDeviceMemory() {
|
||||
deviceMemories_ =
|
||||
reinterpret_cast<DeviceMemory*>(reinterpret_cast<char*>(this) + sizeof(Image2DD3D9));
|
||||
memset(deviceMemories_, 0, context_().devices().size() * sizeof(DeviceMemory));
|
||||
}
|
||||
|
||||
} // namespace amd
|
||||
|
||||
#endif //_WIN32
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,379 @@
|
||||
/* Copyright (c) 2010-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef CL_GL_AMD_HPP_
|
||||
#define CL_GL_AMD_HPP_
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else //!_WIN32
|
||||
#include <dlfcn.h>
|
||||
#endif //!_WIN32
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include "CL/cl_gl.h"
|
||||
#ifndef _WIN32
|
||||
#include <GL/glx.h>
|
||||
#endif //!_WIN32
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <EGL/eglplatform.h>
|
||||
|
||||
#include "platform/context.hpp"
|
||||
#include "platform/command.hpp"
|
||||
|
||||
namespace amd
|
||||
{
|
||||
|
||||
//! Class GLObject keeps all the info about the GL object
|
||||
//! from which the CL object is created
|
||||
class GLObject : public InteropObject
|
||||
{
|
||||
protected:
|
||||
cl_gl_object_type clGLType_; //!< CL GL object type
|
||||
GLenum glTarget_;
|
||||
GLuint gluiName_;
|
||||
GLint gliMipLevel_;
|
||||
GLenum glInternalFormat_;
|
||||
GLint gliWidth_;
|
||||
GLint gliHeight_;
|
||||
GLint gliDepth_;
|
||||
GLenum glCubemapFace_;
|
||||
GLsizei glNumSamples_;
|
||||
|
||||
public:
|
||||
//! GLObject constructor initializes member variables
|
||||
GLObject(
|
||||
GLenum glTarget,
|
||||
GLuint gluiName,
|
||||
GLint gliMipLevel,
|
||||
GLenum glInternalFormat,
|
||||
GLint gliWidth,
|
||||
GLint gliHeight,
|
||||
GLint gliDepth,
|
||||
cl_gl_object_type clGLType,
|
||||
GLenum glCubemapFace,
|
||||
GLsizei glNumSamples
|
||||
): // Initialization of member variables
|
||||
clGLType_(clGLType),
|
||||
glTarget_(glTarget),
|
||||
gluiName_(gluiName),
|
||||
gliMipLevel_(gliMipLevel),
|
||||
glInternalFormat_(glInternalFormat),
|
||||
gliWidth_(gliWidth),
|
||||
gliHeight_(gliHeight),
|
||||
gliDepth_(gliDepth),
|
||||
glCubemapFace_(glCubemapFace),
|
||||
glNumSamples_(glNumSamples)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~GLObject() {}
|
||||
virtual GLObject* asGLObject() {return this;}
|
||||
|
||||
//! GLObject query functions to get GL info from member variables
|
||||
GLenum getGLTarget() const {return glTarget_;}
|
||||
GLuint getGLName() const {return gluiName_;}
|
||||
GLint getGLMipLevel() const {return gliMipLevel_;}
|
||||
GLenum getGLInternalFormat() const {return glInternalFormat_;}
|
||||
GLint getGLSize() const {return gliWidth_;}
|
||||
GLint getGLWidth() const {return gliWidth_;}
|
||||
GLint getGLHeight() const {return gliHeight_;}
|
||||
GLint getGLDepth() const {return gliDepth_;}
|
||||
cl_gl_object_type getCLGLObjectType() const { return clGLType_; }
|
||||
GLenum getCubemapFace() const {return glCubemapFace_;}
|
||||
GLsizei getNumSamples() const { return glNumSamples_;}
|
||||
};
|
||||
|
||||
|
||||
//! Class BufferGL is drived from classes Buffer and GLObject
|
||||
//! where the former keeps all data for CL object and
|
||||
//! the latter keeps all data for GL object
|
||||
class BufferGL : public Buffer, public GLObject
|
||||
{
|
||||
protected:
|
||||
//! Initializes the device memory array which is nested
|
||||
// after'BufferGL' object in memory layout.
|
||||
virtual void initDeviceMemory();
|
||||
public:
|
||||
//! BufferGL constructor just calls constructors of base classes
|
||||
//! to pass down the parameters
|
||||
BufferGL(
|
||||
Context& amdContext,
|
||||
cl_mem_flags clFlags,
|
||||
size_t uiSizeInBytes,
|
||||
GLenum glTarget,
|
||||
GLuint gluiName)
|
||||
: // Call base classes constructors
|
||||
Buffer(
|
||||
amdContext,
|
||||
clFlags,
|
||||
uiSizeInBytes
|
||||
),
|
||||
GLObject(
|
||||
glTarget,
|
||||
gluiName,
|
||||
0, // Mipmap level default
|
||||
GL_ARRAY_BUFFER, // Just init to some value
|
||||
(GLint) uiSizeInBytes,
|
||||
1,
|
||||
1,
|
||||
CL_GL_OBJECT_BUFFER,
|
||||
0,
|
||||
0
|
||||
)
|
||||
{
|
||||
setInteropObj(this);
|
||||
}
|
||||
virtual ~BufferGL() {}
|
||||
|
||||
virtual BufferGL* asBufferGL() { return this; }
|
||||
};
|
||||
|
||||
|
||||
//! Class ImageGL is derived from classes Image and GLObject
|
||||
//! where the former keeps all data for CL object and
|
||||
//! the latter keeps all data for GL object
|
||||
class ImageGL : public Image, public GLObject
|
||||
{
|
||||
public:
|
||||
//! ImageGL constructor just calls constructors of base classes
|
||||
//! to pass down the parameters
|
||||
ImageGL(
|
||||
Context& amdContext,
|
||||
cl_mem_object_type clType,
|
||||
cl_mem_flags clFlags,
|
||||
const Format& format,
|
||||
size_t width,
|
||||
size_t height,
|
||||
size_t depth,
|
||||
GLenum glTarget,
|
||||
GLuint gluiName,
|
||||
GLint gliMipLevel,
|
||||
GLenum glInternalFormat,
|
||||
cl_gl_object_type clGLType,
|
||||
GLsizei numSamples,
|
||||
GLenum glCubemapFace = 0)
|
||||
: Image(amdContext, clType, clFlags, format, width, height, depth,
|
||||
Format(format).getElementSize() * width,
|
||||
Format(format).getElementSize() * width * depth)
|
||||
, GLObject(glTarget, gluiName, gliMipLevel, glInternalFormat,
|
||||
static_cast<GLint>(width), static_cast<GLint>(height),
|
||||
static_cast<GLint>(depth), clGLType, glCubemapFace,numSamples)
|
||||
{
|
||||
setInteropObj(this);
|
||||
}
|
||||
|
||||
virtual ~ImageGL() {}
|
||||
|
||||
protected:
|
||||
//! Initializes the device memory array which is nested
|
||||
// after'BufferGL' object in memory layout.
|
||||
virtual void initDeviceMemory();
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
#define APICALL WINAPI
|
||||
#define GETPROCADDRESS GetProcAddress
|
||||
#define API_GETPROCADDR "wglGetProcAddress"
|
||||
#define FCN_STR_TYPE LPCSTR
|
||||
typedef PROC (WINAPI* PFN_xxxGetProcAddress) (LPCSTR fcnName);
|
||||
typedef HGLRC (APICALL* PFN_wglCreateContext) (HDC hdc);
|
||||
typedef HGLRC (APICALL* PFN_wglGetCurrentContext) (void);
|
||||
typedef HDC (APICALL* PFN_wglGetCurrentDC) (void);
|
||||
typedef BOOL (APICALL* PFN_wglDeleteContext) (HGLRC hglrc);
|
||||
typedef BOOL (APICALL* PFN_wglMakeCurrent) (HDC hdc, HGLRC hglrc);
|
||||
typedef BOOL (APICALL* PFN_wglShareLists) (HGLRC hglrc1, HGLRC hglrc2);
|
||||
#else //!_WIN32
|
||||
#define APICALL // __stdcall //??? todo odintsov
|
||||
#define API_GETPROCADDR "glXGetProcAddress"
|
||||
#define GETPROCADDRESS dlsym
|
||||
#define FCN_STR_TYPE const GLubyte*
|
||||
#define WINAPI
|
||||
#define PROC void*
|
||||
typedef void* (*PFN_xxxGetProcAddress) (const GLubyte* procName);
|
||||
// X11 typedef
|
||||
typedef Display* (*PFNXOpenDisplay)(_Xconst char* display_name );
|
||||
typedef int (*PFNXCloseDisplay)(Display* display );
|
||||
|
||||
//glx typedefs
|
||||
typedef GLXDrawable (*PFNglXGetCurrentDrawable)();
|
||||
typedef Display* (*PFNglXGetCurrentDisplay)();
|
||||
typedef GLXContext (*PFNglXGetCurrentContext)( void );
|
||||
typedef XVisualInfo* (*PFNglXChooseVisual)(Display *dpy, int screen, int *attribList);
|
||||
typedef GLXContext(*PFNglXCreateContext)(Display* dpy,XVisualInfo* vis,GLXContext shareList,Bool direct);
|
||||
typedef void(*PFNglXDestroyContext)(Display* dpy, GLXContext ctx);
|
||||
typedef Bool(*PFNglXMakeCurrent)( Display* dpy, GLXDrawable drawable, GLXContext ctx);
|
||||
typedef void* HMODULE;
|
||||
#endif //!_WIN32
|
||||
|
||||
#define GLPREFIX(rtype, fcn, dclargs) \
|
||||
typedef rtype (APICALL* PFN_##fcn) dclargs;
|
||||
|
||||
// Declare prototypes for GL functions
|
||||
#include "gl_functions.hpp"
|
||||
|
||||
class GLFunctions
|
||||
{
|
||||
public:
|
||||
//! Locks any access to the virtual GPUs
|
||||
class SetIntEnv : public amd::StackObject {
|
||||
public:
|
||||
//! Default constructor
|
||||
SetIntEnv(GLFunctions* env);
|
||||
|
||||
//! Destructor
|
||||
~SetIntEnv();
|
||||
|
||||
//! Checks if the environment setup was successful
|
||||
bool isValid() const { return isValid_; }
|
||||
|
||||
private:
|
||||
GLFunctions* env_; //!< GL environment
|
||||
bool isValid_; //!< If TRUE, then it's a valid setup
|
||||
};
|
||||
|
||||
private:
|
||||
HMODULE libHandle_;
|
||||
int missed_; // Indicates how many GL functions not init'ed, if any
|
||||
|
||||
amd::Monitor lock_;
|
||||
|
||||
EGLDisplay eglDisplay_;
|
||||
EGLContext eglOriginalContext_;
|
||||
EGLContext eglInternalContext_;
|
||||
EGLContext eglTempContext_;
|
||||
bool isEGL_;
|
||||
|
||||
#ifdef _WIN32
|
||||
HGLRC hOrigGLRC_;
|
||||
HDC hDC_;
|
||||
HGLRC hIntGLRC_; // handle for internal GLRC to access shared context
|
||||
HDC tempDC_;
|
||||
HGLRC tempGLRC_;
|
||||
|
||||
PFN_wglCreateContext wglCreateContext_;
|
||||
PFN_wglGetCurrentContext wglGetCurrentContext_;
|
||||
PFN_wglGetCurrentDC wglGetCurrentDC_;
|
||||
PFN_wglDeleteContext wglDeleteContext_;
|
||||
PFN_wglMakeCurrent wglMakeCurrent_;
|
||||
PFN_wglShareLists wglShareLists_;
|
||||
#else
|
||||
public:
|
||||
Display* Dpy_;
|
||||
GLXDrawable Drawable_;
|
||||
GLXContext origCtx_;
|
||||
Display* intDpy_;
|
||||
Window intDrawable_;
|
||||
GLXContext intCtx_;
|
||||
Display* tempDpy_;
|
||||
GLXDrawable tempDrawable_;
|
||||
GLXContext tempCtx_;
|
||||
|
||||
//pointers to X11 functions
|
||||
PFNXOpenDisplay XOpenDisplay_;
|
||||
PFNXCloseDisplay XCloseDisplay_;
|
||||
|
||||
//pointers to GLX functions
|
||||
PFNglXGetCurrentDrawable glXGetCurrentDrawable_;
|
||||
PFNglXGetCurrentDisplay glXGetCurrentDisplay_;
|
||||
PFNglXGetCurrentContext glXGetCurrentContext_;
|
||||
PFNglXChooseVisual glXChooseVisual_;
|
||||
PFNglXCreateContext glXCreateContext_;
|
||||
PFNglXDestroyContext glXDestroyContext_;
|
||||
PFNglXMakeCurrent glXMakeCurrent_;
|
||||
#endif
|
||||
public:
|
||||
|
||||
GLFunctions(HMODULE h, bool isEGL);
|
||||
~GLFunctions();
|
||||
|
||||
// Query CL-GL context association
|
||||
bool isAssociated() const
|
||||
{
|
||||
if (isEGL_ && eglDisplay_ && eglOriginalContext_) return true;
|
||||
#ifdef _WIN32
|
||||
if(hDC_ && hOrigGLRC_) return true;
|
||||
#else //!_WIN32
|
||||
if(Dpy_ && origCtx_) return true;
|
||||
#endif //!_WIN32
|
||||
return false;
|
||||
}
|
||||
bool isEGL() const
|
||||
{
|
||||
return isEGL_;
|
||||
}
|
||||
// Accessor methods
|
||||
#ifdef _WIN32
|
||||
HGLRC getOrigGLRC() const {return hOrigGLRC_;}
|
||||
HDC getDC() const {return hDC_;}
|
||||
HGLRC getIntGLRC() const {return hIntGLRC_;}
|
||||
#else //!_WIN32
|
||||
Display* getDpy() const {return Dpy_;}
|
||||
GLXDrawable getDrawable() const {return Drawable_;}
|
||||
GLXContext getOrigCtx() const {return origCtx_;}
|
||||
|
||||
Display* getIntDpy() const {return intDpy_;}
|
||||
GLXDrawable getIntDrawable() const {return intDrawable_;}
|
||||
GLXContext getIntCtx() const {return intCtx_;}
|
||||
|
||||
EGLDisplay getEglDpy() const { return eglDisplay_; }
|
||||
EGLContext getEglOrigCtx() const { return eglOriginalContext_; }
|
||||
#endif //!_WIN32
|
||||
|
||||
// Initialize GL dynamic library and function pointers
|
||||
bool init(intptr_t hdc, intptr_t hglrc);
|
||||
|
||||
// Return true if successful, false - if error occurred
|
||||
bool setIntEnv();
|
||||
bool restoreEnv();
|
||||
|
||||
amd::Monitor& getLock() { return lock_; }
|
||||
|
||||
PFN_xxxGetProcAddress GetProcAddress_;
|
||||
|
||||
#define GLPREFIX(rtype, fcn, dclargs) \
|
||||
PFN_##fcn fcn##_;
|
||||
// Declare pointers to GL functions
|
||||
#include "gl_functions.hpp"
|
||||
};
|
||||
|
||||
//! Functions for executing the GL related stuff
|
||||
cl_mem clCreateFromGLBufferAMD(Context& amdContext, cl_mem_flags flags,
|
||||
GLuint bufobj, cl_int* errcode_ret);
|
||||
cl_mem clCreateFromGLTextureAMD(Context& amdContext, cl_mem_flags flags,
|
||||
GLenum target, GLint miplevel, GLuint texture, int* errcode_ret);
|
||||
cl_mem clCreateFromGLRenderbufferAMD(Context& amdContext, cl_mem_flags flags,
|
||||
GLuint renderbuffer, int* errcode_ret);
|
||||
|
||||
bool
|
||||
getCLFormatFromGL(
|
||||
const Context& amdContext,
|
||||
GLint gliInternalFormat,
|
||||
cl_image_format* pclImageFormat,
|
||||
int* piBytesPerPixel,
|
||||
cl_mem_flags flags
|
||||
);
|
||||
|
||||
} //namespace amd
|
||||
|
||||
#endif //CL_GL_AMD_HPP_
|
||||
@@ -0,0 +1,312 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include "cl_common.hpp"
|
||||
#include <CL/cl_ext.h>
|
||||
|
||||
#include "platform/object.hpp"
|
||||
|
||||
#include "cl_lqdflash_amd.h"
|
||||
|
||||
#ifndef WITH_LIQUID_FLASH
|
||||
#if (!defined(BUILD_HSA_TARGET) && defined(WITH_HSA_DEVICE) && \
|
||||
defined(WITH_AMDGPU_PRO)) || defined(_WIN32)
|
||||
#define WITH_LIQUID_FLASH 1
|
||||
#endif // _WIN32
|
||||
#endif
|
||||
|
||||
#if WITH_LIQUID_FLASH
|
||||
#include "lf.h"
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#endif // WITH_LIQUID_FLASH
|
||||
|
||||
namespace amd {
|
||||
|
||||
LiquidFlashFile::~LiquidFlashFile() { close(); }
|
||||
|
||||
bool LiquidFlashFile::open() {
|
||||
#if WITH_LIQUID_FLASH
|
||||
lf_status err;
|
||||
lf_file_flags flags = 0;
|
||||
|
||||
switch (flags_) {
|
||||
case CL_FILE_READ_ONLY_AMD:
|
||||
flags = LF_READ;
|
||||
break;
|
||||
case CL_FILE_WRITE_ONLY_AMD:
|
||||
flags = LF_WRITE;
|
||||
break;
|
||||
case CL_FILE_READ_WRITE_AMD:
|
||||
flags = LF_READ | LF_WRITE;
|
||||
break;
|
||||
}
|
||||
#ifdef ATI_OS_LINUX
|
||||
assert(sizeof(wchar_t) != sizeof(lf_char));
|
||||
std::string name_char;
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cv;
|
||||
name_char = cv.to_bytes(name_);
|
||||
handle_ = lfOpenFile(name_char.c_str(), flags, &err);
|
||||
#else
|
||||
handle_ = lfOpenFile(name_.c_str(), flags, &err);
|
||||
#endif
|
||||
|
||||
if (err != lf_success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lfGetFileBlockSize((lf_file)handle_, &blockSize_) != lf_success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lfGetFileSize((lf_file)handle_, &fileSize_) != lf_success) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif // WITH_LIQUID_FLASH
|
||||
}
|
||||
|
||||
void LiquidFlashFile::close() {
|
||||
#if WITH_LIQUID_FLASH
|
||||
if (handle_ != NULL) {
|
||||
lfReleaseFile((lf_file)handle_);
|
||||
handle_ = NULL;
|
||||
}
|
||||
#endif // WITH_LIQUID_FLASH
|
||||
}
|
||||
|
||||
bool LiquidFlashFile::transferBlock(bool writeBuffer, void* srcDst, uint64_t bufferSize,
|
||||
uint64_t fileOffset, uint64_t bufferOffset,
|
||||
uint64_t size) const {
|
||||
#if WITH_LIQUID_FLASH
|
||||
lf_status status;
|
||||
|
||||
lf_region_descriptor region = {fileOffset / blockSize(), bufferOffset / blockSize(),
|
||||
size / blockSize()};
|
||||
if (writeBuffer) {
|
||||
status = lfReadFile(srcDst, bufferSize, (lf_file)handle_, 1, ®ion, NULL);
|
||||
} else {
|
||||
status = lfWriteFile(srcDst, bufferSize, (lf_file)handle_, 1, ®ion, NULL);
|
||||
}
|
||||
if (lf_success == status) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif // WITH_LIQUID_FLASH
|
||||
}
|
||||
|
||||
} // namespace amd
|
||||
|
||||
/*! \addtogroup API
|
||||
* @{
|
||||
*
|
||||
* \addtogroup AMD_Extensions
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
RUNTIME_ENTRY_RET(cl_file_amd, clCreateSsgFileObjectAMD,
|
||||
(cl_context context, cl_file_flags_amd flags, const wchar_t* file_name,
|
||||
cl_int* errcode_ret)) {
|
||||
#if WITH_LIQUID_FLASH && defined ATI_OS_LINUX
|
||||
if (!is_valid(context)) {
|
||||
*not_null(errcode_ret) = CL_INVALID_CONTEXT;
|
||||
LogWarning("invalid parameter \"context\"");
|
||||
return (cl_file_amd)0;
|
||||
}
|
||||
|
||||
const std::vector<amd::Device*>& devices = as_amd(context)->devices();
|
||||
bool supportPass = false;
|
||||
for (auto& dev : devices) {
|
||||
if (lf_success == lfCheckExtensionSupportForDevice(dev->info().pcieDeviceId_,
|
||||
dev->info().pcieRevisionId_)) {
|
||||
supportPass = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!supportPass) {
|
||||
*not_null(errcode_ret) = CL_INVALID_DEVICE;
|
||||
LogWarning("SSG isn't supported");
|
||||
return (cl_file_amd)0;
|
||||
}
|
||||
#endif
|
||||
amd::LiquidFlashFile* file = new amd::LiquidFlashFile(file_name, flags);
|
||||
|
||||
if (file == NULL) {
|
||||
*not_null(errcode_ret) = CL_OUT_OF_HOST_MEMORY;
|
||||
return (cl_file_amd)0;
|
||||
}
|
||||
|
||||
if (!file->open()) {
|
||||
*not_null(errcode_ret) = CL_INVALID_VALUE;
|
||||
delete file;
|
||||
return (cl_file_amd)0;
|
||||
}
|
||||
|
||||
*not_null(errcode_ret) = CL_SUCCESS;
|
||||
return as_cl(file);
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
RUNTIME_ENTRY(cl_int, clGetSsgFileObjectInfoAMD,
|
||||
(cl_file_amd file, cl_file_info_amd param_name, size_t param_value_size,
|
||||
void* param_value, size_t* param_value_size_ret)) {
|
||||
if (!is_valid(file)) {
|
||||
return CL_INVALID_FILE_OBJECT_AMD;
|
||||
}
|
||||
|
||||
switch (param_name) {
|
||||
case CL_FILE_BLOCK_SIZE_AMD: {
|
||||
cl_uint blockSize = as_amd(file)->blockSize();
|
||||
return amd::clGetInfo(blockSize, param_value_size, param_value, param_value_size_ret);
|
||||
}
|
||||
case CL_FILE_SIZE_AMD: {
|
||||
cl_ulong fileSize = as_amd(file)->fileSize();
|
||||
return amd::clGetInfo(fileSize, param_value_size, param_value, param_value_size_ret);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
RUNTIME_ENTRY(cl_int, clRetainSsgFileObjectAMD, (cl_file_amd file)) {
|
||||
if (!is_valid(file)) {
|
||||
return CL_INVALID_FILE_OBJECT_AMD;
|
||||
}
|
||||
as_amd(file)->retain();
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
RUNTIME_ENTRY(cl_int, clReleaseSsgFileObjectAMD, (cl_file_amd file)) {
|
||||
if (!is_valid(file)) {
|
||||
return CL_INVALID_FILE_OBJECT_AMD;
|
||||
}
|
||||
as_amd(file)->release();
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
static cl_int EnqueueTransferBufferFromSsgFileAMD(
|
||||
cl_bool isWrite, cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write,
|
||||
size_t buffer_offset, size_t cb, cl_file_amd file, size_t file_offset,
|
||||
cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event) {
|
||||
if (!is_valid(command_queue)) {
|
||||
return CL_INVALID_COMMAND_QUEUE;
|
||||
}
|
||||
|
||||
if (!is_valid(buffer)) {
|
||||
return CL_INVALID_MEM_OBJECT;
|
||||
}
|
||||
amd::Buffer* pBuffer = as_amd(buffer)->asBuffer();
|
||||
if (pBuffer == NULL) {
|
||||
return CL_INVALID_MEM_OBJECT;
|
||||
}
|
||||
|
||||
if (pBuffer->getMemFlags() & (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS)) {
|
||||
return CL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
amd::HostQueue* queue = as_amd(command_queue)->asHostQueue();
|
||||
if (NULL == queue) {
|
||||
return CL_INVALID_COMMAND_QUEUE;
|
||||
}
|
||||
amd::HostQueue& hostQueue = *queue;
|
||||
|
||||
if (hostQueue.context() != pBuffer->getContext()) {
|
||||
return CL_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
if (!is_valid(file)) {
|
||||
return CL_INVALID_FILE_OBJECT_AMD;
|
||||
}
|
||||
|
||||
amd::LiquidFlashFile* amdFile = as_amd(file);
|
||||
amd::Coord3D bufferOffset(buffer_offset, 0, 0);
|
||||
amd::Coord3D bufferSize(cb, 1, 1);
|
||||
|
||||
if ((!pBuffer->validateRegion(bufferOffset, bufferSize)) ||
|
||||
// LF library supports aligned sizes only
|
||||
((buffer_offset % amdFile->blockSize()) != 0) || ((cb % amdFile->blockSize()) != 0) ||
|
||||
((file_offset % amdFile->blockSize()) != 0)) {
|
||||
return CL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
amd::Command::EventWaitList eventWaitList;
|
||||
cl_int err = amd::clSetEventWaitList(eventWaitList, hostQueue, num_events_in_wait_list,
|
||||
event_wait_list);
|
||||
if (err != CL_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
amd::TransferBufferFileCommand* command;
|
||||
command = new amd::TransferBufferFileCommand(
|
||||
isWrite ? CL_COMMAND_READ_SSG_FILE_AMD : CL_COMMAND_WRITE_SSG_FILE_AMD, hostQueue,
|
||||
eventWaitList, *pBuffer, bufferOffset, bufferSize, amdFile, file_offset);
|
||||
|
||||
if (command == NULL) {
|
||||
return CL_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
// Make sure we have memory for the command execution
|
||||
if (!command->validateMemory()) {
|
||||
delete command;
|
||||
return CL_MEM_OBJECT_ALLOCATION_FAILURE;
|
||||
}
|
||||
|
||||
command->enqueue();
|
||||
if (blocking_write) {
|
||||
command->awaitCompletion();
|
||||
}
|
||||
|
||||
*not_null(event) = as_cl(&command->event());
|
||||
if (event == NULL) {
|
||||
command->release();
|
||||
}
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
RUNTIME_ENTRY(cl_int, clEnqueueReadSsgFileAMD,
|
||||
(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write,
|
||||
size_t buffer_offset, size_t cb, cl_file_amd file, size_t file_offset,
|
||||
cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event)) {
|
||||
return EnqueueTransferBufferFromSsgFileAMD(CL_TRUE, command_queue, buffer, blocking_write,
|
||||
buffer_offset, cb, file, file_offset,
|
||||
num_events_in_wait_list, event_wait_list, event);
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
|
||||
RUNTIME_ENTRY(cl_int, clEnqueueWriteSsgFileAMD,
|
||||
(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write,
|
||||
size_t buffer_offset, size_t cb, cl_file_amd file, size_t file_offset,
|
||||
cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event)) {
|
||||
return EnqueueTransferBufferFromSsgFileAMD(CL_FALSE, command_queue, buffer, blocking_write,
|
||||
buffer_offset, cb, file, file_offset,
|
||||
num_events_in_wait_list, event_wait_list, event);
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
@@ -0,0 +1,58 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef __CL_LQDFLASH_AMD_H
|
||||
#define __CL_LQDFLASH_AMD_H
|
||||
|
||||
#include "CL/cl_ext.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
extern CL_API_ENTRY cl_file_amd CL_API_CALL
|
||||
clCreateSsgFileObjectAMD(cl_context context, cl_file_flags_amd flags, const wchar_t* file_name,
|
||||
cl_int* errcode_ret) CL_EXT_SUFFIX__VERSION_1_2;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL clGetSsgFileObjectInfoAMD(
|
||||
cl_file_amd file, cl_file_info_amd param_name, size_t param_value_size, void* param_value,
|
||||
size_t* param_value_size_ret) CL_EXT_SUFFIX__VERSION_1_2;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL clRetainSsgFileObjectAMD(cl_file_amd file)
|
||||
CL_EXT_SUFFIX__VERSION_1_2;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL clReleaseSsgFileObjectAMD(cl_file_amd file)
|
||||
CL_EXT_SUFFIX__VERSION_1_2;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL clEnqueueReadSsgFileAMD(
|
||||
cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, size_t buffer_offset,
|
||||
size_t cb, cl_file_amd file, size_t file_offset, cl_uint num_events_in_wait_list,
|
||||
const cl_event* event_wait_list, cl_event* event) CL_EXT_SUFFIX__VERSION_1_2;
|
||||
|
||||
extern CL_API_ENTRY cl_int CL_API_CALL clEnqueueWriteSsgFileAMD(
|
||||
cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, size_t buffer_offset,
|
||||
size_t cb, cl_file_amd file, size_t file_offset, cl_uint num_events_in_wait_list,
|
||||
const cl_event* event_wait_list, cl_event* event) CL_EXT_SUFFIX__VERSION_1_2;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include "vdi_common.hpp"
|
||||
#include <icd/loader/icd_dispatch.h>
|
||||
|
||||
cl_icd_dispatch amd::ICDDispatchedObject::icdVendorDispatch_[] = {0};
|
||||
amd::PlatformIDS amd::PlatformID::Platform = {amd::ICDDispatchedObject::icdVendorDispatch_};
|
||||
|
||||
RUNTIME_ENTRY(cl_int, clGetDeviceIDs,
|
||||
(cl_platform_id platform, cl_device_type device_type, cl_uint num_entries,
|
||||
cl_device_id* devices, cl_uint* num_devices)) {
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
RUNTIME_EXIT
|
||||
@@ -0,0 +1,35 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include "platform/activity.hpp"
|
||||
|
||||
extern "C" void hipInitActivityCallback(void* id_callback, void* op_callback, void* arg) {
|
||||
activity_prof::CallbacksTable::init(reinterpret_cast<activity_prof::id_callback_fun_t>(id_callback),
|
||||
reinterpret_cast<activity_prof::callback_fun_t>(op_callback),
|
||||
arg);
|
||||
}
|
||||
|
||||
extern "C" bool hipEnableActivityCallback(unsigned op, bool enable) {
|
||||
return activity_prof::CallbacksTable::SetEnabled(op, enable);
|
||||
}
|
||||
|
||||
extern "C" const char* hipGetCmdName(unsigned op) {
|
||||
return getOclCommandKindString(static_cast<uint32_t>(op));
|
||||
}
|
||||
+850
@@ -0,0 +1,850 @@
|
||||
/*
|
||||
Copyright (c) 2015-2020 - present 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.
|
||||
*/
|
||||
#include "hip_code_object.hpp"
|
||||
#include "amd_hsa_elf.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <hip/amd_detail/amd_driver_types.h>
|
||||
#include "hip/hip_runtime_api.h"
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "hip_internal.hpp"
|
||||
#include "platform/program.hpp"
|
||||
#include <elf/elf.hpp>
|
||||
|
||||
hipError_t ihipMemcpy(void* dst, const void* src, size_t sizeBytes, hipMemcpyKind kind,
|
||||
amd::HostQueue& queue, bool isAsync = false);
|
||||
hipError_t ihipFree(void* ptr);
|
||||
//forward declaration of methods required for managed variables
|
||||
hipError_t ihipMallocManaged(void** ptr, size_t size, unsigned int align = 0);
|
||||
namespace {
|
||||
size_t constexpr strLiteralLength(char const* str) {
|
||||
return *str ? 1 + strLiteralLength(str + 1) : 0;
|
||||
}
|
||||
constexpr char const* CLANG_OFFLOAD_BUNDLER_MAGIC_STR = "__CLANG_OFFLOAD_BUNDLE__";
|
||||
constexpr char const* OFFLOAD_KIND_HIP = "hip";
|
||||
constexpr char const* OFFLOAD_KIND_HIPV4 = "hipv4";
|
||||
constexpr char const* OFFLOAD_KIND_HCC = "hcc";
|
||||
constexpr char const* AMDGCN_TARGET_TRIPLE = "amdgcn-amd-amdhsa-";
|
||||
|
||||
// ClangOFFLOADBundle info.
|
||||
static constexpr size_t bundle_magic_string_size =
|
||||
strLiteralLength(CLANG_OFFLOAD_BUNDLER_MAGIC_STR);
|
||||
|
||||
// Clang Offload bundler description & Header.
|
||||
struct __ClangOffloadBundleInfo {
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
uint64_t bundleEntryIdSize;
|
||||
const char bundleEntryId[1];
|
||||
};
|
||||
|
||||
struct __ClangOffloadBundleHeader {
|
||||
const char magic[bundle_magic_string_size - 1];
|
||||
uint64_t numOfCodeObjects;
|
||||
__ClangOffloadBundleInfo desc[1];
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace hip {
|
||||
|
||||
uint64_t CodeObject::ElfSize(const void *emi) {
|
||||
return amd::Elf::getElfSize(emi);
|
||||
}
|
||||
|
||||
static bool getProcName(uint32_t EFlags, std::string& proc_name, bool& xnackSupported,
|
||||
bool& sramEccSupported) {
|
||||
switch (EFlags & EF_AMDGPU_MACH) {
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX700:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx700";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX701:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx701";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX702:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx702";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX703:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx703";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX704:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx704";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX705:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx705";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX801:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx801";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX802:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx802";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX803:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx803";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX805:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx805";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX810:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx810";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX900:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx900";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX902:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx902";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX904:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx904";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX906:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = true;
|
||||
proc_name = "gfx906";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX908:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = true;
|
||||
proc_name = "gfx908";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX909:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx909";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX90A:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = true;
|
||||
proc_name = "gfx90a";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX90C:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx90c";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX1010:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx1010";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX1011:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx1011";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX1012:
|
||||
xnackSupported = true;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx1012";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX1030:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx1030";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX1031:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx1031";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX1032:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx1032";
|
||||
break;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX1033:
|
||||
xnackSupported = false;
|
||||
sramEccSupported = false;
|
||||
proc_name = "gfx1033";
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool getTripleTargetIDFromCodeObject(const void* code_object, std::string& target_id,
|
||||
unsigned& co_version) {
|
||||
if (!code_object) return false;
|
||||
const Elf64_Ehdr* ehdr = reinterpret_cast<const Elf64_Ehdr*>(code_object);
|
||||
if (ehdr->e_machine != EM_AMDGPU) return false;
|
||||
if (ehdr->e_ident[EI_OSABI] != ELFOSABI_AMDGPU_HSA) return false;
|
||||
|
||||
bool isXnackSupported{false}, isSramEccSupported{false};
|
||||
|
||||
std::string proc_name;
|
||||
if (!getProcName(ehdr->e_flags, proc_name, isXnackSupported, isSramEccSupported)) return false;
|
||||
target_id = std::string(AMDGCN_TARGET_TRIPLE) + '-' + proc_name;
|
||||
|
||||
switch (ehdr->e_ident[EI_ABIVERSION]) {
|
||||
case ELFABIVERSION_AMDGPU_HSA_V2: {
|
||||
co_version = 2;
|
||||
return false;
|
||||
}
|
||||
|
||||
case ELFABIVERSION_AMDGPU_HSA_V3: {
|
||||
co_version = 3;
|
||||
if (isSramEccSupported) {
|
||||
if (ehdr->e_flags & EF_AMDGPU_FEATURE_SRAMECC_V3)
|
||||
target_id += ":sramecc+";
|
||||
else
|
||||
target_id += ":sramecc-";
|
||||
}
|
||||
if (isXnackSupported) {
|
||||
if (ehdr->e_flags & EF_AMDGPU_FEATURE_XNACK_V3)
|
||||
target_id += ":xnack+";
|
||||
else
|
||||
target_id += ":xnack-";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ELFABIVERSION_AMDGPU_HSA_V4: {
|
||||
co_version = 4;
|
||||
unsigned co_sram_value = (ehdr->e_flags) & EF_AMDGPU_FEATURE_SRAMECC_V4;
|
||||
if (co_sram_value == EF_AMDGPU_FEATURE_SRAMECC_OFF_V4)
|
||||
target_id += ":sramecc-";
|
||||
else if (co_sram_value == EF_AMDGPU_FEATURE_SRAMECC_ON_V4)
|
||||
target_id += ":sramecc+";
|
||||
|
||||
unsigned co_xnack_value = (ehdr->e_flags) & EF_AMDGPU_FEATURE_XNACK_V4;
|
||||
if (co_xnack_value == EF_AMDGPU_FEATURE_XNACK_OFF_V4)
|
||||
target_id += ":xnack-";
|
||||
else if (co_xnack_value == EF_AMDGPU_FEATURE_XNACK_ON_V4)
|
||||
target_id += ":xnack+";
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Consumes the string 'consume_' from the starting of the given input
|
||||
// eg: input = amdgcn-amd-amdhsa--gfx908 and consume_ is amdgcn-amd-amdhsa--
|
||||
// input will become gfx908.
|
||||
static bool consume(std::string& input, std::string consume_) {
|
||||
if (input.substr(0, consume_.size()) != consume_) {
|
||||
return false;
|
||||
}
|
||||
input = input.substr(consume_.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Trim String till character, will be used to get gpuname
|
||||
// example: input is gfx908:sram-ecc+ and trim char is :
|
||||
// input will become sram-ecc+.
|
||||
static std::string trimName(std::string& input, char trim) {
|
||||
auto pos_ = input.find(trim);
|
||||
auto res = input;
|
||||
if (pos_ == std::string::npos) {
|
||||
input = "";
|
||||
} else {
|
||||
res = input.substr(0, pos_);
|
||||
input = input.substr(pos_);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static char getFeatureValue(std::string& input, std::string feature) {
|
||||
char res = ' ';
|
||||
if (consume(input, std::move(feature))) {
|
||||
res = input[0];
|
||||
input = input.substr(1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool getTargetIDValue(std::string& input, std::string& processor, char& sramecc_value,
|
||||
char& xnack_value) {
|
||||
processor = trimName(input, ':');
|
||||
sramecc_value = getFeatureValue(input, std::string(":sramecc"));
|
||||
if (sramecc_value != ' ' && sramecc_value != '+' && sramecc_value != '-') return false;
|
||||
xnack_value = getFeatureValue(input, std::string(":xnack"));
|
||||
if (xnack_value != ' ' && xnack_value != '+' && xnack_value != '-') return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool getTripleTargetID(std::string bundled_co_entry_id, const void* code_object,
|
||||
std::string& co_triple_target_id, unsigned& co_version) {
|
||||
std::string offload_kind = trimName(bundled_co_entry_id, '-');
|
||||
if (offload_kind != OFFLOAD_KIND_HIPV4 && offload_kind != OFFLOAD_KIND_HIP &&
|
||||
offload_kind != OFFLOAD_KIND_HCC)
|
||||
return false;
|
||||
|
||||
if (offload_kind != OFFLOAD_KIND_HIPV4)
|
||||
return getTripleTargetIDFromCodeObject(code_object, co_triple_target_id, co_version);
|
||||
|
||||
// For code object V4 onwards the bundled code object entry ID correctly
|
||||
// specifies the target tripple.
|
||||
co_version = 4;
|
||||
co_triple_target_id = bundled_co_entry_id.substr(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isCodeObjectCompatibleWithDevice(std::string co_triple_target_id,
|
||||
std::string agent_triple_target_id) {
|
||||
// Primitive Check
|
||||
if (co_triple_target_id == agent_triple_target_id) return true;
|
||||
|
||||
// Parse code object triple target id
|
||||
if (!consume(co_triple_target_id, std::string(AMDGCN_TARGET_TRIPLE) + '-')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string co_processor;
|
||||
char co_sram_ecc, co_xnack;
|
||||
if (!getTargetIDValue(co_triple_target_id, co_processor, co_sram_ecc, co_xnack)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!co_triple_target_id.empty()) return false;
|
||||
|
||||
// Parse agent isa triple target id
|
||||
if (!consume(agent_triple_target_id, std::string(AMDGCN_TARGET_TRIPLE) + '-')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string agent_isa_processor;
|
||||
char isa_sram_ecc, isa_xnack;
|
||||
if (!getTargetIDValue(agent_triple_target_id, agent_isa_processor, isa_sram_ecc, isa_xnack)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!agent_triple_target_id.empty()) return false;
|
||||
|
||||
// Check for compatibility
|
||||
if (agent_isa_processor != co_processor) return false;
|
||||
if (co_sram_ecc != ' ') {
|
||||
if (co_sram_ecc != isa_sram_ecc) return false;
|
||||
}
|
||||
if (co_xnack != ' ') {
|
||||
if (co_xnack != isa_xnack) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// This will be moved to COMGR eventually
|
||||
hipError_t CodeObject::ExtractCodeObjectFromFile(amd::Os::FileDesc fdesc, size_t fsize,
|
||||
const void ** image, const std::vector<std::string>& device_names,
|
||||
std::vector<std::pair<const void*, size_t>>& code_objs) {
|
||||
|
||||
hipError_t hip_error = hipSuccess;
|
||||
|
||||
if (fdesc < 0) {
|
||||
return hipErrorFileNotFound;
|
||||
}
|
||||
|
||||
// Map the file to memory, with offset 0.
|
||||
//file will be unmapped in ModuleUnload
|
||||
//const void* image = nullptr;
|
||||
if (!amd::Os::MemoryMapFileDesc(fdesc, fsize, 0, image)) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
// retrieve code_objs{binary_image, binary_size} for devices
|
||||
hip_error = extractCodeObjectFromFatBinary(*image, device_names, code_objs);
|
||||
|
||||
return hip_error;
|
||||
}
|
||||
|
||||
// This will be moved to COMGR eventually
|
||||
hipError_t CodeObject::ExtractCodeObjectFromMemory(const void* data,
|
||||
const std::vector<std::string>& device_names,
|
||||
std::vector<std::pair<const void*, size_t>>& code_objs,
|
||||
std::string& uri) {
|
||||
|
||||
// Get the URI from memory
|
||||
if (!amd::Os::GetURIFromMemory(data, 0, uri)) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
return extractCodeObjectFromFatBinary(data, device_names, code_objs);
|
||||
}
|
||||
|
||||
// This will be moved to COMGR eventually
|
||||
hipError_t CodeObject::extractCodeObjectFromFatBinary(const void* data,
|
||||
const std::vector<std::string>& agent_triple_target_ids,
|
||||
std::vector<std::pair<const void*, size_t>>& code_objs) {
|
||||
std::string magic((const char*)data, bundle_magic_string_size);
|
||||
if (magic.compare(CLANG_OFFLOAD_BUNDLER_MAGIC_STR)) {
|
||||
return hipErrorInvalidKernelFile;
|
||||
}
|
||||
|
||||
// Initialize Code objects
|
||||
code_objs.reserve(agent_triple_target_ids.size());
|
||||
for (size_t i = 0; i < agent_triple_target_ids.size(); i++) {
|
||||
code_objs.push_back(std::make_pair(nullptr, 0));
|
||||
}
|
||||
|
||||
const auto obheader = reinterpret_cast<const __ClangOffloadBundleHeader*>(data);
|
||||
const auto* desc = &obheader->desc[0];
|
||||
size_t num_code_objs = code_objs.size();
|
||||
for (uint64_t i = 0; i < obheader->numOfCodeObjects; ++i,
|
||||
desc = reinterpret_cast<const __ClangOffloadBundleInfo*>(
|
||||
reinterpret_cast<uintptr_t>(&desc->bundleEntryId[0]) +
|
||||
desc->bundleEntryIdSize)) {
|
||||
const void* image =
|
||||
reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(obheader) + desc->offset);
|
||||
const size_t image_size = desc->size;
|
||||
|
||||
if (num_code_objs == 0) break;
|
||||
std::string bundleEntryId{desc->bundleEntryId, desc->bundleEntryIdSize};
|
||||
|
||||
unsigned co_version = 0;
|
||||
std::string co_triple_target_id;
|
||||
if (!getTripleTargetID(bundleEntryId, image, co_triple_target_id, co_version)) continue;
|
||||
|
||||
for (size_t dev = 0; dev < agent_triple_target_ids.size(); ++dev) {
|
||||
if (code_objs[dev].first) continue;
|
||||
if (isCodeObjectCompatibleWithDevice(co_triple_target_id, agent_triple_target_ids[dev])) {
|
||||
code_objs[dev] = std::make_pair(image, image_size);
|
||||
--num_code_objs;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num_code_objs == 0) {
|
||||
return hipSuccess;
|
||||
} else {
|
||||
LogPrintfError("%s",
|
||||
"hipErrorNoBinaryForGpu: Unable to find code object for all current devices!");
|
||||
LogPrintfError("%s", " Devices:");
|
||||
for (size_t i = 0; i < agent_triple_target_ids.size(); i++) {
|
||||
LogPrintfError(" %s - [%s]", agent_triple_target_ids[i].c_str(),
|
||||
((code_objs[i].first) ? "Found" : "Not Found"));
|
||||
}
|
||||
const auto obheader = reinterpret_cast<const __ClangOffloadBundleHeader*>(data);
|
||||
const auto* desc = &obheader->desc[0];
|
||||
LogPrintfError("%s", " Bundled Code Objects:");
|
||||
for (uint64_t i = 0; i < obheader->numOfCodeObjects; ++i,
|
||||
desc = reinterpret_cast<const __ClangOffloadBundleInfo*>(
|
||||
reinterpret_cast<uintptr_t>(&desc->bundleEntryId[0]) +
|
||||
desc->bundleEntryIdSize)) {
|
||||
std::string bundleEntryId{desc->bundleEntryId, desc->bundleEntryIdSize};
|
||||
const void* image =
|
||||
reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(obheader) + desc->offset);
|
||||
|
||||
unsigned co_version = 0;
|
||||
std::string co_triple_target_id;
|
||||
bool valid_co = getTripleTargetID(bundleEntryId, image, co_triple_target_id, co_version);
|
||||
|
||||
if (valid_co) {
|
||||
LogPrintfError(" %s - [code object v%u is %s]", bundleEntryId.c_str(), co_version,
|
||||
co_triple_target_id.c_str());
|
||||
} else {
|
||||
LogPrintfError(" %s - [Unsupported]", bundleEntryId.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
guarantee(false, "hipErrorNoBinaryForGpu: Unable to find code object for all current devices!");
|
||||
return hipErrorNoBinaryForGpu;
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t DynCO::loadCodeObject(const char* fname, const void* image) {
|
||||
|
||||
amd::ScopedLock lock(dclock_);
|
||||
|
||||
// Number of devices = 1 in dynamic code object
|
||||
fb_info_ = new FatBinaryInfo(fname, image);
|
||||
std::vector<hip::Device*> devices = { g_devices[ihipGetDevice()] };
|
||||
IHIP_RETURN_ONFAIL(fb_info_->ExtractFatBinary(devices));
|
||||
|
||||
// No Lazy loading for DynCO
|
||||
IHIP_RETURN_ONFAIL(fb_info_->BuildProgram(ihipGetDevice()));
|
||||
|
||||
// Define Global variables
|
||||
IHIP_RETURN_ONFAIL(populateDynGlobalVars());
|
||||
|
||||
// Define Global functions
|
||||
IHIP_RETURN_ONFAIL(populateDynGlobalFuncs());
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
//Dynamic Code Object
|
||||
DynCO::~DynCO() {
|
||||
amd::ScopedLock lock(dclock_);
|
||||
|
||||
for (auto& elem : vars_) {
|
||||
if(elem.second->getVarKind() == Var::DVK_Managed) {
|
||||
ihipFree(elem.second->getManagedVarPtr());
|
||||
}
|
||||
delete elem.second;
|
||||
}
|
||||
vars_.clear();
|
||||
|
||||
for (auto& elem : functions_) {
|
||||
delete elem.second;
|
||||
}
|
||||
functions_.clear();
|
||||
|
||||
delete fb_info_;
|
||||
}
|
||||
|
||||
hipError_t DynCO::getDeviceVar(DeviceVar** dvar, std::string var_name) {
|
||||
amd::ScopedLock lock(dclock_);
|
||||
|
||||
CheckDeviceIdMatch();
|
||||
|
||||
auto it = vars_.find(var_name);
|
||||
if (it == vars_.end()) {
|
||||
LogPrintfError("Cannot find the Var: %s ", var_name.c_str());
|
||||
return hipErrorNotFound;
|
||||
}
|
||||
|
||||
it->second->getDeviceVar(dvar, device_id_, module());
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t DynCO::getDynFunc(hipFunction_t* hfunc, std::string func_name) {
|
||||
amd::ScopedLock lock(dclock_);
|
||||
|
||||
CheckDeviceIdMatch();
|
||||
|
||||
if(hfunc == nullptr) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
auto it = functions_.find(func_name);
|
||||
if (it == functions_.end()) {
|
||||
LogPrintfError("Cannot find the function: %s ", func_name.c_str());
|
||||
return hipErrorNotFound;
|
||||
}
|
||||
|
||||
/* See if this could be solved */
|
||||
return it->second->getDynFunc(hfunc, module());
|
||||
}
|
||||
|
||||
hipError_t DynCO::initDynManagedVars(const std::string& managedVar) {
|
||||
amd::ScopedLock lock(dclock_);
|
||||
DeviceVar* dvar;
|
||||
void* pointer = nullptr;
|
||||
hipError_t status = hipSuccess;
|
||||
// To get size of the managed variable
|
||||
status = getDeviceVar(&dvar, managedVar + ".managed");
|
||||
if (status != hipSuccess) {
|
||||
ClPrint(amd::LOG_ERROR, amd::LOG_API, "Status %d, failed to get .managed device variable:%s",
|
||||
status, managedVar.c_str());
|
||||
return status;
|
||||
}
|
||||
// Allocate managed memory for these symbols
|
||||
status = ihipMallocManaged(&pointer, dvar->size());
|
||||
if (status != hipSuccess) {
|
||||
ClPrint(amd::LOG_ERROR, amd::LOG_API, "Status %d, failed to allocate managed memory", status);
|
||||
guarantee(false, "Error during allocation of managed memory!");
|
||||
}
|
||||
// update as manager variable and set managed memory pointer and size
|
||||
auto it = vars_.find(managedVar);
|
||||
it->second->setManagedVarInfo(pointer, dvar->size());
|
||||
|
||||
// copy initial value to the managed variable to the managed memory allocated
|
||||
amd::HostQueue* queue = hip::getNullStream();
|
||||
if (queue != nullptr) {
|
||||
status = ihipMemcpy(pointer, reinterpret_cast<address>(dvar->device_ptr()), dvar->size(),
|
||||
hipMemcpyDeviceToDevice, *queue);
|
||||
if (status != hipSuccess) {
|
||||
ClPrint(amd::LOG_ERROR, amd::LOG_API, "Status %d, failed to copy device ptr:%s", status,
|
||||
managedVar.c_str());
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
ClPrint(amd::LOG_ERROR, amd::LOG_API, "Host Queue is NULL");
|
||||
return hipErrorInvalidResourceHandle;
|
||||
}
|
||||
|
||||
// Get deivce ptr to initialize with managed memory pointer
|
||||
status = getDeviceVar(&dvar, managedVar);
|
||||
if (status != hipSuccess) {
|
||||
ClPrint(amd::LOG_ERROR, amd::LOG_API, "Status %d, failed to get managed device variable:%s",
|
||||
status, managedVar.c_str());
|
||||
return status;
|
||||
}
|
||||
// copy managed memory pointer to the managed device variable
|
||||
status = ihipMemcpy(reinterpret_cast<address>(dvar->device_ptr()), &pointer, dvar->size(),
|
||||
hipMemcpyHostToDevice, *queue);
|
||||
if (status != hipSuccess) {
|
||||
ClPrint(amd::LOG_ERROR, amd::LOG_API, "Status %d, failed to copy device ptr:%s", status,
|
||||
managedVar.c_str());
|
||||
return status;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
hipError_t DynCO::populateDynGlobalVars() {
|
||||
amd::ScopedLock lock(dclock_);
|
||||
std::vector<std::string> var_names;
|
||||
std::vector<std::string> undef_var_names;
|
||||
std::string managedVarExt = ".managed";
|
||||
// For Dynamic Modules there is only one hipFatBinaryDevInfo_
|
||||
device::Program* dev_program = fb_info_->GetProgram(ihipGetDevice())
|
||||
->getDeviceProgram(*hip::getCurrentDevice()->devices()[0]);
|
||||
|
||||
if (!dev_program->getGlobalVarFromCodeObj(&var_names)) {
|
||||
LogPrintfError("Could not get Global vars from Code Obj for Module: 0x%x \n", module());
|
||||
return hipErrorSharedObjectSymbolNotFound;
|
||||
}
|
||||
|
||||
for (auto& elem : var_names) {
|
||||
vars_.insert(
|
||||
std::make_pair(elem, new Var(elem, Var::DeviceVarKind::DVK_Variable, 0, 0, 0, nullptr)));
|
||||
}
|
||||
|
||||
for (auto& elem : var_names) {
|
||||
if (elem.find(managedVarExt) != std::string::npos) {
|
||||
std::string managedVar = elem;
|
||||
managedVar.erase(managedVar.length() - managedVarExt.length(), managedVarExt.length());
|
||||
initDynManagedVars(managedVar);
|
||||
}
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t DynCO::populateDynGlobalFuncs() {
|
||||
amd::ScopedLock lock(dclock_);
|
||||
|
||||
std::vector<std::string> func_names;
|
||||
device::Program* dev_program
|
||||
= fb_info_->GetProgram(ihipGetDevice())->getDeviceProgram(
|
||||
*hip::getCurrentDevice()->devices()[0]);
|
||||
|
||||
// Get all the global func names from COMGR
|
||||
if (!dev_program->getGlobalFuncFromCodeObj(&func_names)) {
|
||||
LogPrintfError("Could not get Global Funcs from Code Obj for Module: 0x%x \n", module());
|
||||
return hipErrorSharedObjectSymbolNotFound;
|
||||
}
|
||||
|
||||
for (auto& elem : func_names) {
|
||||
functions_.insert(std::make_pair(elem, new Function(elem)));
|
||||
}
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
//Static Code Object
|
||||
StatCO::StatCO() {
|
||||
}
|
||||
|
||||
StatCO::~StatCO() {
|
||||
amd::ScopedLock lock(sclock_);
|
||||
|
||||
for (auto& elem : functions_) {
|
||||
delete elem.second;
|
||||
}
|
||||
functions_.clear();
|
||||
|
||||
for (auto& elem : vars_) {
|
||||
delete elem.second;
|
||||
}
|
||||
vars_.clear();
|
||||
}
|
||||
|
||||
hipError_t StatCO::digestFatBinary(const void* data, FatBinaryInfo*& programs) {
|
||||
amd::ScopedLock lock(sclock_);
|
||||
|
||||
if (programs != nullptr) {
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
// Create a new fat binary object and extract the fat binary for all devices.
|
||||
programs = new FatBinaryInfo(nullptr, data);
|
||||
IHIP_RETURN_ONFAIL(programs->ExtractFatBinary(g_devices));
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
FatBinaryInfo** StatCO::addFatBinary(const void* data, bool initialized) {
|
||||
amd::ScopedLock lock(sclock_);
|
||||
|
||||
if (initialized) {
|
||||
digestFatBinary(data, modules_[data]);
|
||||
}
|
||||
return &modules_[data];
|
||||
}
|
||||
|
||||
hipError_t StatCO::removeFatBinary(FatBinaryInfo** module) {
|
||||
amd::ScopedLock lock(sclock_);
|
||||
|
||||
auto vit = vars_.begin();
|
||||
while (vit != vars_.end()) {
|
||||
if (vit->second->moduleInfo() == module) {
|
||||
delete vit->second;
|
||||
vit = vars_.erase(vit);
|
||||
} else {
|
||||
++vit;
|
||||
}
|
||||
}
|
||||
|
||||
auto it = managedVars_.begin();
|
||||
while (it != managedVars_.end()) {
|
||||
if ((*it)->moduleInfo() == module) {
|
||||
ihipFree((*it)->getManagedVarPtr());
|
||||
delete *it;
|
||||
managedVars_.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
auto fit = functions_.begin();
|
||||
while (fit != functions_.end()) {
|
||||
if (fit->second->moduleInfo() == module) {
|
||||
delete fit->second;
|
||||
fit = functions_.erase(fit);
|
||||
} else {
|
||||
++fit;
|
||||
}
|
||||
}
|
||||
|
||||
auto mit = modules_.begin();
|
||||
while (mit != modules_.end()) {
|
||||
if (&mit->second == module) {
|
||||
delete mit->second;
|
||||
mit = modules_.erase(mit);
|
||||
} else {
|
||||
++mit;
|
||||
}
|
||||
}
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t StatCO::registerStatFunction(const void* hostFunction, Function* func) {
|
||||
amd::ScopedLock lock(sclock_);
|
||||
|
||||
if (functions_.find(hostFunction) != functions_.end()) {
|
||||
DevLogPrintfError("hostFunctionPtr: 0x%x already exists", hostFunction);
|
||||
}
|
||||
functions_.insert(std::make_pair(hostFunction, func));
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t StatCO::getStatFunc(hipFunction_t* hfunc, const void* hostFunction, int deviceId) {
|
||||
amd::ScopedLock lock(sclock_);
|
||||
|
||||
const auto it = functions_.find(hostFunction);
|
||||
if (it == functions_.end()) {
|
||||
return hipErrorInvalidSymbol;
|
||||
}
|
||||
|
||||
return it->second->getStatFunc(hfunc, deviceId);
|
||||
}
|
||||
|
||||
hipError_t StatCO::getStatFuncAttr(hipFuncAttributes* func_attr, const void* hostFunction, int deviceId) {
|
||||
amd::ScopedLock lock(sclock_);
|
||||
|
||||
const auto it = functions_.find(hostFunction);
|
||||
if (it == functions_.end()) {
|
||||
return hipErrorInvalidSymbol;
|
||||
}
|
||||
|
||||
return it->second->getStatFuncAttr(func_attr, deviceId);
|
||||
}
|
||||
|
||||
hipError_t StatCO::registerStatGlobalVar(const void* hostVar, Var* var) {
|
||||
amd::ScopedLock lock(sclock_);
|
||||
|
||||
if (vars_.find(hostVar) != vars_.end()) {
|
||||
return hipErrorInvalidSymbol;
|
||||
}
|
||||
|
||||
vars_.insert(std::make_pair(hostVar, var));
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t StatCO::getStatGlobalVar(const void* hostVar, int deviceId, hipDeviceptr_t* dev_ptr,
|
||||
size_t* size_ptr) {
|
||||
amd::ScopedLock lock(sclock_);
|
||||
|
||||
const auto it = vars_.find(hostVar);
|
||||
if (it == vars_.end()) {
|
||||
return hipErrorInvalidSymbol;
|
||||
}
|
||||
|
||||
DeviceVar* dvar = nullptr;
|
||||
IHIP_RETURN_ONFAIL(it->second->getStatDeviceVar(&dvar, deviceId));
|
||||
|
||||
*dev_ptr = dvar->device_ptr();
|
||||
*size_ptr = dvar->size();
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t StatCO::registerStatManagedVar(Var* var) {
|
||||
managedVars_.emplace_back(var);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t StatCO::initStatManagedVarDevicePtr(int deviceId) {
|
||||
amd::ScopedLock lock(sclock_);
|
||||
|
||||
if (managedVarsDevicePtrInitalized_.find(deviceId) == managedVarsDevicePtrInitalized_.end() ||
|
||||
!managedVarsDevicePtrInitalized_[deviceId]) {
|
||||
for (auto var : managedVars_) {
|
||||
DeviceVar* dvar = nullptr;
|
||||
IHIP_RETURN_ONFAIL(var->getStatDeviceVar(&dvar, deviceId));
|
||||
|
||||
amd::HostQueue* queue = hip::getNullStream();
|
||||
if(queue != nullptr) {
|
||||
ihipMemcpy(reinterpret_cast<address>(dvar->device_ptr()), var->getManagedVarPtr(),
|
||||
dvar->size(), hipMemcpyHostToDevice, *queue);
|
||||
} else {
|
||||
ClPrint(amd::LOG_ERROR, amd::LOG_API, "Host Queue is NULL");
|
||||
return hipErrorInvalidResourceHandle;
|
||||
}
|
||||
}
|
||||
managedVarsDevicePtrInitalized_[deviceId] = true;
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
}; //namespace: hip
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
Copyright (c) 2015-2020 - present 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.
|
||||
*/
|
||||
|
||||
#ifndef HIP_CODE_OBJECT_HPP
|
||||
#define HIP_CODE_OBJECT_HPP
|
||||
|
||||
#include "hip_global.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "hip/hip_runtime_api.h"
|
||||
#include "hip_internal.hpp"
|
||||
#include "device/device.hpp"
|
||||
#include "platform/program.hpp"
|
||||
|
||||
//Forward Declaration for friend usage
|
||||
class PlatformState;
|
||||
|
||||
namespace hip {
|
||||
|
||||
//Code Object base class
|
||||
class CodeObject {
|
||||
public:
|
||||
virtual ~CodeObject() {}
|
||||
|
||||
// Functions to add_dev_prog and build
|
||||
static hipError_t add_program(int deviceId, hipModule_t hmod, const void* binary_ptr,
|
||||
size_t binary_size);
|
||||
static hipError_t build_module(hipModule_t hmod, const std::vector<amd::Device*>& devices);
|
||||
|
||||
// Given an file desc and file size, extracts to code object for corresponding devices,
|
||||
// return code_objs{binary_ptr, binary_size}, which could be used to determine foffset
|
||||
static hipError_t ExtractCodeObjectFromFile(amd::Os::FileDesc fdesc, size_t fsize,
|
||||
const void ** image, const std::vector<std::string>& device_names,
|
||||
std::vector<std::pair<const void*, size_t>>& code_objs);
|
||||
|
||||
// Given an ptr to memory, extracts to code object for corresponding devices,
|
||||
// returns code_objs{binary_ptr, binary_size} and uniform resource indicator
|
||||
static hipError_t ExtractCodeObjectFromMemory(const void* data,
|
||||
const std::vector<std::string>& device_names,
|
||||
std::vector<std::pair<const void*, size_t>>& code_objs,
|
||||
std::string& uri);
|
||||
|
||||
static uint64_t ElfSize(const void* emi);
|
||||
|
||||
protected:
|
||||
//Given an ptr to image or file, extracts to code object
|
||||
//for corresponding devices
|
||||
static hipError_t extractCodeObjectFromFatBinary(const void*,
|
||||
const std::vector<std::string>&,
|
||||
std::vector<std::pair<const void*, size_t>>&);
|
||||
|
||||
CodeObject() {}
|
||||
private:
|
||||
friend const std::vector<hipModule_t>& modules();
|
||||
};
|
||||
|
||||
//Dynamic Code Object
|
||||
class DynCO : public CodeObject {
|
||||
amd::Monitor dclock_{"Guards Dynamic Code object", true};
|
||||
|
||||
public:
|
||||
DynCO() : device_id_(ihipGetDevice()) {}
|
||||
virtual ~DynCO();
|
||||
|
||||
//LoadsCodeObject and its data
|
||||
hipError_t loadCodeObject(const char* fname, const void* image=nullptr);
|
||||
hipModule_t module() { return fb_info_->Module(ihipGetDevice()); };
|
||||
|
||||
//Gets GlobalVar/Functions from a dynamically loaded code object
|
||||
hipError_t getDynFunc(hipFunction_t* hfunc, std::string func_name);
|
||||
hipError_t getDeviceVar(DeviceVar** dvar, std::string var_name);
|
||||
|
||||
hipError_t getManagedVarPointer(std::string name, void** pointer, size_t* size_ptr) const {
|
||||
auto it = vars_.find(name);
|
||||
if (it != vars_.end() && it->second->getVarKind() == Var::DVK_Managed) {
|
||||
*pointer = it->second->getManagedVarPtr();
|
||||
*size_ptr = it->second->getSize();
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
// Device ID Check to check if module is launched in the same device it was loaded.
|
||||
inline void CheckDeviceIdMatch() {
|
||||
if (device_id_ != ihipGetDevice()) {
|
||||
guarantee(false, "Device mismatch from where this module is loaded");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int device_id_;
|
||||
FatBinaryInfo* fb_info_;
|
||||
|
||||
//Maps for vars/funcs, could be keyed in with std::string name
|
||||
std::unordered_map<std::string, Function*> functions_;
|
||||
std::unordered_map<std::string, Var*> vars_;
|
||||
|
||||
//Populate Global Vars/Funcs from an code object(@ module_load)
|
||||
hipError_t populateDynGlobalFuncs();
|
||||
hipError_t populateDynGlobalVars();
|
||||
hipError_t initDynManagedVars(const std::string& managedVar);
|
||||
};
|
||||
|
||||
//Static Code Object
|
||||
class StatCO: public CodeObject {
|
||||
amd::Monitor sclock_{"Guards Static Code object", true};
|
||||
public:
|
||||
StatCO();
|
||||
virtual ~StatCO();
|
||||
|
||||
//Add/Remove/Digest Fat Binaries passed to us from "__hipRegisterFatBinary"
|
||||
FatBinaryInfo** addFatBinary(const void* data, bool initialized);
|
||||
hipError_t removeFatBinary(FatBinaryInfo** module);
|
||||
hipError_t digestFatBinary(const void* data, FatBinaryInfo*& programs);
|
||||
|
||||
//Register vars/funcs given to use from __hipRegister[Var/Func/ManagedVar]
|
||||
hipError_t registerStatFunction(const void* hostFunction, Function* func);
|
||||
hipError_t registerStatGlobalVar(const void* hostVar, Var* var);
|
||||
hipError_t registerStatManagedVar(Var *var);
|
||||
|
||||
//Retrive Vars/Funcs for a given hostSidePtr(const void*), unless stated otherwise.
|
||||
hipError_t getStatFunc(hipFunction_t* hfunc, const void* hostFunction, int deviceId);
|
||||
hipError_t getStatFuncAttr(hipFuncAttributes* func_attr, const void* hostFunction, int deviceId);
|
||||
hipError_t getStatGlobalVar(const void* hostVar, int deviceId, hipDeviceptr_t* dev_ptr,
|
||||
size_t* size_ptr);
|
||||
|
||||
//Managed variable is a defined symbol in code object
|
||||
//pointer to the alocated managed memory has to be copied to the address of symbol
|
||||
hipError_t initStatManagedVarDevicePtr(int deviceId);
|
||||
private:
|
||||
friend class ::PlatformState;
|
||||
//Populated during __hipRegisterFatBinary
|
||||
std::unordered_map<const void*, FatBinaryInfo*> modules_;
|
||||
//Populated during __hipRegisterFuncs
|
||||
std::unordered_map<const void*, Function*> functions_;
|
||||
//Populated during __hipRegisterVars
|
||||
std::unordered_map<const void*, Var*> vars_;
|
||||
//Populated during __hipRegisterManagedVar
|
||||
std::vector<Var*> managedVars_;
|
||||
std::unordered_map<int, bool> managedVarsDevicePtrInitalized_;
|
||||
};
|
||||
|
||||
}; // namespace hip
|
||||
|
||||
#endif /* HIP_CODE_OBJECT_HPP */
|
||||
Executable
+377
@@ -0,0 +1,377 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include "hip_internal.hpp"
|
||||
#include "hip_platform.hpp"
|
||||
#include "platform/runtime.hpp"
|
||||
#include "utils/flags.hpp"
|
||||
#include "utils/versions.hpp"
|
||||
|
||||
std::vector<hip::Device*> g_devices;
|
||||
|
||||
namespace hip {
|
||||
|
||||
thread_local Device* g_device = nullptr;
|
||||
thread_local std::stack<Device*> g_ctxtStack;
|
||||
thread_local hipError_t g_lastError = hipSuccess;
|
||||
std::once_flag g_ihipInitialized;
|
||||
Device* host_device = nullptr;
|
||||
|
||||
void init() {
|
||||
if (!amd::Runtime::initialized()) {
|
||||
amd::IS_HIP = true;
|
||||
GPU_NUM_MEM_DEPENDENCY = 0;
|
||||
AMD_DIRECT_DISPATCH = flagIsDefault(AMD_DIRECT_DISPATCH) ? false : AMD_DIRECT_DISPATCH;
|
||||
amd::Runtime::init();
|
||||
}
|
||||
|
||||
const std::vector<amd::Device*>& devices = amd::Device::getDevices(CL_DEVICE_TYPE_GPU, false);
|
||||
|
||||
for (unsigned int i=0; i<devices.size(); i++) {
|
||||
const std::vector<amd::Device*> device(1, devices[i]);
|
||||
amd::Context* context = new amd::Context(device, amd::Context::Info());
|
||||
if (!context) return;
|
||||
|
||||
// Enable active wait on the device by default
|
||||
devices[i]->SetActiveWait(true);
|
||||
|
||||
if (context && CL_SUCCESS != context->create(nullptr)) {
|
||||
context->release();
|
||||
} else {
|
||||
g_devices.push_back(new Device(context, i));
|
||||
}
|
||||
}
|
||||
|
||||
amd::Context* hContext = new amd::Context(devices, amd::Context::Info());
|
||||
if (!hContext) return;
|
||||
|
||||
if (CL_SUCCESS != hContext->create(nullptr)) {
|
||||
hContext->release();
|
||||
}
|
||||
host_device = new Device(hContext, -1);
|
||||
|
||||
PlatformState::instance().init();
|
||||
}
|
||||
|
||||
Device* getCurrentDevice() {
|
||||
return g_device;
|
||||
}
|
||||
|
||||
void setCurrentDevice(unsigned int index) {
|
||||
assert(index<g_devices.size());
|
||||
g_device = g_devices[index];
|
||||
}
|
||||
|
||||
amd::HostQueue* getQueue(hipStream_t stream) {
|
||||
if (stream == nullptr) {
|
||||
return getNullStream();
|
||||
} else {
|
||||
constexpr bool WaitNullStreamOnly = true;
|
||||
amd::HostQueue* queue = reinterpret_cast<hip::Stream*>(stream)->asHostQueue();
|
||||
if (!(reinterpret_cast<hip::Stream*>(stream)->Flags() & hipStreamNonBlocking)) {
|
||||
iHipWaitActiveStreams(queue, WaitNullStreamOnly);
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
amd::HostQueue* getNullStream(amd::Context& ctx) {
|
||||
for (auto& it : g_devices) {
|
||||
if (it->asContext() == &ctx) {
|
||||
return it->NullStream();
|
||||
}
|
||||
}
|
||||
// If it's a pure SVM allocation with system memory access, then it shouldn't matter which device
|
||||
// runtime selects by default
|
||||
if (hip::host_device->asContext() == &ctx) {
|
||||
// Return current...
|
||||
return getNullStream();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
amd::HostQueue* getNullStream() {
|
||||
Device* device = getCurrentDevice();
|
||||
return device ? device->NullStream() : nullptr;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
using namespace hip;
|
||||
|
||||
hipError_t hipInit(unsigned int flags) {
|
||||
HIP_INIT_API(hipInit, flags);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipCtxCreate(hipCtx_t *ctx, unsigned int flags, hipDevice_t device) {
|
||||
HIP_INIT_API(hipCtxCreate, ctx, flags, device);
|
||||
|
||||
if (static_cast<size_t>(device) >= g_devices.size()) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
*ctx = reinterpret_cast<hipCtx_t>(g_devices[device]);
|
||||
|
||||
// Increment ref count for device primary context
|
||||
g_devices[device]->retain();
|
||||
g_ctxtStack.push(g_devices[device]);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipCtxSetCurrent(hipCtx_t ctx) {
|
||||
HIP_INIT_API(hipCtxSetCurrent, ctx);
|
||||
|
||||
if (ctx == nullptr) {
|
||||
if(!g_ctxtStack.empty()) {
|
||||
g_ctxtStack.pop();
|
||||
}
|
||||
} else {
|
||||
hip::g_device = reinterpret_cast<hip::Device*>(ctx);
|
||||
if(!g_ctxtStack.empty()) {
|
||||
g_ctxtStack.pop();
|
||||
}
|
||||
g_ctxtStack.push(hip::getCurrentDevice());
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipCtxGetCurrent(hipCtx_t* ctx) {
|
||||
HIP_INIT_API(hipCtxGetCurrent, ctx);
|
||||
|
||||
*ctx = reinterpret_cast<hipCtx_t>(hip::getCurrentDevice());
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipCtxGetSharedMemConfig(hipSharedMemConfig* pConfig) {
|
||||
HIP_INIT_API(hipCtxGetSharedMemConfig, pConfig);
|
||||
|
||||
*pConfig = hipSharedMemBankSizeFourByte;
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipRuntimeGetVersion(int *runtimeVersion) {
|
||||
HIP_INIT_API(hipRuntimeGetVersion, runtimeVersion);
|
||||
|
||||
if (!runtimeVersion) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
// HIP_VERSION = HIP_VERSION_MAJOR*100 + HIP_MINOR_VERSION
|
||||
*runtimeVersion = HIP_VERSION;
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipCtxDestroy(hipCtx_t ctx) {
|
||||
HIP_INIT_API(hipCtxDestroy, ctx);
|
||||
|
||||
hip::Device* dev = reinterpret_cast<hip::Device*>(ctx);
|
||||
if (dev == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
// Need to remove the ctx of calling thread if its the top one
|
||||
if (!g_ctxtStack.empty() && g_ctxtStack.top() == dev) {
|
||||
g_ctxtStack.pop();
|
||||
}
|
||||
|
||||
// Remove context from global context list
|
||||
for (unsigned int i = 0; i < g_devices.size(); i++) {
|
||||
if (g_devices[i] == dev) {
|
||||
// Decrement ref count for device primary context
|
||||
dev->release();
|
||||
}
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipCtxPopCurrent(hipCtx_t* ctx) {
|
||||
HIP_INIT_API(hipCtxPopCurrent, ctx);
|
||||
|
||||
hip::Device** dev = reinterpret_cast<hip::Device**>(ctx);
|
||||
if (!g_ctxtStack.empty()) {
|
||||
if (dev != nullptr) {
|
||||
*dev = g_ctxtStack.top();
|
||||
}
|
||||
g_ctxtStack.pop();
|
||||
} else {
|
||||
DevLogError("Context Stack empty \n");
|
||||
HIP_RETURN(hipErrorInvalidContext);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipCtxPushCurrent(hipCtx_t ctx) {
|
||||
HIP_INIT_API(hipCtxPushCurrent, ctx);
|
||||
|
||||
hip::Device* dev = reinterpret_cast<hip::Device*>(ctx);
|
||||
if (dev == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidContext);
|
||||
}
|
||||
|
||||
hip::g_device = dev;
|
||||
g_ctxtStack.push(hip::getCurrentDevice());
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDriverGetVersion(int* driverVersion) {
|
||||
HIP_INIT_API(hipDriverGetVersion, driverVersion);
|
||||
|
||||
if (!driverVersion) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
// HIP_VERSION = HIP_VERSION_MAJOR*100 + HIP_MINOR_VERSION
|
||||
*driverVersion = HIP_VERSION;
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipCtxGetDevice(hipDevice_t* device) {
|
||||
HIP_INIT_API(hipCtxGetDevice, device);
|
||||
|
||||
if (device != nullptr) {
|
||||
*device = hip::getCurrentDevice()->deviceId();
|
||||
HIP_RETURN(hipSuccess);
|
||||
} else {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipErrorInvalidContext);
|
||||
}
|
||||
|
||||
hipError_t hipCtxGetApiVersion(hipCtx_t ctx, int* apiVersion) {
|
||||
HIP_INIT_API(hipCtxGetApiVersion, apiVersion);
|
||||
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
|
||||
hipError_t hipCtxGetCacheConfig(hipFuncCache_t* cacheConfig) {
|
||||
HIP_INIT_API(hipCtxGetCacheConfig, cacheConfig);
|
||||
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
|
||||
hipError_t hipCtxSetCacheConfig(hipFuncCache_t cacheConfig) {
|
||||
HIP_INIT_API(hipCtxSetCacheConfig, cacheConfig);
|
||||
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
|
||||
hipError_t hipCtxSetSharedMemConfig(hipSharedMemConfig config) {
|
||||
HIP_INIT_API(hipCtxSetSharedMemConfig, config);
|
||||
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
|
||||
hipError_t hipCtxSynchronize(void) {
|
||||
HIP_INIT_API(hipCtxSynchronize, 1);
|
||||
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
|
||||
hipError_t hipCtxGetFlags(unsigned int* flags) {
|
||||
HIP_INIT_API(hipCtxGetFlags, flags);
|
||||
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
|
||||
hipError_t hipDevicePrimaryCtxGetState(hipDevice_t dev, unsigned int* flags, int* active) {
|
||||
HIP_INIT_API(hipDevicePrimaryCtxGetState, dev, flags, active);
|
||||
|
||||
if (static_cast<unsigned int>(dev) >= g_devices.size()) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
if (flags != nullptr) {
|
||||
*flags = 0;
|
||||
}
|
||||
|
||||
if (active != nullptr) {
|
||||
*active = (g_devices[dev] == hip::getCurrentDevice())? 1 : 0;
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDevicePrimaryCtxRelease(hipDevice_t dev) {
|
||||
HIP_INIT_API(hipDevicePrimaryCtxRelease, dev);
|
||||
|
||||
if (static_cast<unsigned int>(dev) >= g_devices.size()) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDevicePrimaryCtxRetain(hipCtx_t* pctx, hipDevice_t dev) {
|
||||
HIP_INIT_API(hipDevicePrimaryCtxRetain, pctx, dev);
|
||||
|
||||
if (static_cast<unsigned int>(dev) >= g_devices.size()) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
if (pctx == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
*pctx = reinterpret_cast<hipCtx_t>(g_devices[dev]);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDevicePrimaryCtxReset(hipDevice_t dev) {
|
||||
HIP_INIT_API(hipDevicePrimaryCtxReset, dev);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDevicePrimaryCtxSetFlags(hipDevice_t dev, unsigned int flags) {
|
||||
HIP_INIT_API(hipDevicePrimaryCtxSetFlags, dev, flags);
|
||||
|
||||
if (static_cast<unsigned int>(dev) >= g_devices.size()) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
} else {
|
||||
HIP_RETURN(hipErrorContextAlreadyInUse);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,903 @@
|
||||
/*
|
||||
Copyright (c) 2015 - present 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 <hip/amd_detail/amd_driver_types.h>
|
||||
#include <hip/amd_detail/amd_texture_types.h>
|
||||
|
||||
namespace hip
|
||||
{
|
||||
inline
|
||||
cl_channel_type getCLChannelType(const hipArray_Format hipFormat,
|
||||
const hipTextureReadMode hipReadMode) {
|
||||
if (hipReadMode == hipReadModeElementType) {
|
||||
switch (hipFormat) {
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT8:
|
||||
return CL_UNSIGNED_INT8;
|
||||
case HIP_AD_FORMAT_SIGNED_INT8:
|
||||
return CL_SIGNED_INT8;
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT16:
|
||||
return CL_UNSIGNED_INT16;
|
||||
case HIP_AD_FORMAT_SIGNED_INT16:
|
||||
return CL_SIGNED_INT16;
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT32:
|
||||
return CL_UNSIGNED_INT32;
|
||||
case HIP_AD_FORMAT_SIGNED_INT32:
|
||||
return CL_SIGNED_INT32;
|
||||
case HIP_AD_FORMAT_HALF:
|
||||
return CL_HALF_FLOAT;
|
||||
case HIP_AD_FORMAT_FLOAT:
|
||||
return CL_FLOAT;
|
||||
}
|
||||
} else if (hipReadMode == hipReadModeNormalizedFloat) {
|
||||
switch (hipFormat) {
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT8:
|
||||
return CL_UNORM_INT8;
|
||||
case HIP_AD_FORMAT_SIGNED_INT8:
|
||||
return CL_SNORM_INT8;
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT16:
|
||||
return CL_UNORM_INT16;
|
||||
case HIP_AD_FORMAT_SIGNED_INT16:
|
||||
return CL_SNORM_INT16;
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT32:
|
||||
return CL_UNSIGNED_INT32;
|
||||
case HIP_AD_FORMAT_SIGNED_INT32:
|
||||
return CL_SIGNED_INT32;
|
||||
case HIP_AD_FORMAT_HALF:
|
||||
return CL_HALF_FLOAT;
|
||||
case HIP_AD_FORMAT_FLOAT:
|
||||
return CL_FLOAT;
|
||||
}
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
cl_channel_order getCLChannelOrder(const unsigned int hipNumChannels,
|
||||
const int sRGB) {
|
||||
switch (hipNumChannels) {
|
||||
case 1:
|
||||
return CL_R;
|
||||
case 2:
|
||||
return CL_RG;
|
||||
case 4:
|
||||
return (sRGB == 1) ? CL_sRGBA : CL_RGBA;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
cl_mem_object_type getCLMemObjectType(const unsigned int hipWidth,
|
||||
const unsigned int hipHeight,
|
||||
const unsigned int hipDepth,
|
||||
const unsigned int flags) {
|
||||
if (flags == hipArrayDefault) {
|
||||
if ((hipWidth != 0) && (hipHeight == 0) && (hipDepth == 0)) {
|
||||
return CL_MEM_OBJECT_IMAGE1D;
|
||||
} else if ((hipWidth != 0) && (hipHeight != 0) && (hipDepth == 0)) {
|
||||
return CL_MEM_OBJECT_IMAGE2D;
|
||||
} else if ((hipWidth != 0) && (hipHeight != 0) && (hipDepth != 0)) {
|
||||
return CL_MEM_OBJECT_IMAGE3D;
|
||||
}
|
||||
} else if (flags == hipArrayLayered) {
|
||||
if ((hipWidth != 0) && (hipHeight == 0) && (hipDepth != 0)) {
|
||||
return CL_MEM_OBJECT_IMAGE1D_ARRAY;
|
||||
} else if ((hipWidth != 0) && (hipHeight != 0) && (hipDepth != 0)) {
|
||||
return CL_MEM_OBJECT_IMAGE2D_ARRAY;
|
||||
}
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
cl_addressing_mode getCLAddressingMode(const hipTextureAddressMode hipAddressMode) {
|
||||
switch (hipAddressMode) {
|
||||
case hipAddressModeWrap:
|
||||
return CL_ADDRESS_REPEAT;
|
||||
case hipAddressModeClamp:
|
||||
return CL_ADDRESS_CLAMP_TO_EDGE;
|
||||
case hipAddressModeMirror:
|
||||
return CL_ADDRESS_MIRRORED_REPEAT;
|
||||
case hipAddressModeBorder:
|
||||
return CL_ADDRESS_CLAMP;
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
cl_filter_mode getCLFilterMode(const hipTextureFilterMode hipFilterMode) {
|
||||
switch (hipFilterMode) {
|
||||
case hipFilterModePoint:
|
||||
return CL_FILTER_NEAREST;
|
||||
case hipFilterModeLinear:
|
||||
return CL_FILTER_LINEAR;
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
cl_mem_object_type getCLMemObjectType(const hipResourceType hipResType) {
|
||||
switch (hipResType) {
|
||||
case hipResourceTypeLinear:
|
||||
return CL_MEM_OBJECT_IMAGE1D_BUFFER;
|
||||
case hipResourceTypePitch2D:
|
||||
return CL_MEM_OBJECT_IMAGE2D;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
size_t getElementSize(const hipArray_const_t array) {
|
||||
switch (array->Format) {
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT8:
|
||||
case HIP_AD_FORMAT_SIGNED_INT8:
|
||||
return 1 * array->NumChannels;
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT16:
|
||||
case HIP_AD_FORMAT_SIGNED_INT16:
|
||||
case HIP_AD_FORMAT_HALF:
|
||||
return 2 * array->NumChannels;
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT32:
|
||||
case HIP_AD_FORMAT_SIGNED_INT32:
|
||||
case HIP_AD_FORMAT_FLOAT:
|
||||
return 4 * array->NumChannels;
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
hipChannelFormatDesc getChannelFormatDesc(int numChannels,
|
||||
hipArray_Format arrayFormat) {
|
||||
switch (arrayFormat) {
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT8:
|
||||
switch (numChannels) {
|
||||
case 1:
|
||||
return {8, 0, 0, 0, hipChannelFormatKindUnsigned};
|
||||
case 2:
|
||||
return {8, 8, 0, 0, hipChannelFormatKindUnsigned};
|
||||
case 4:
|
||||
return {8, 8, 8, 8, hipChannelFormatKindUnsigned};
|
||||
}
|
||||
case HIP_AD_FORMAT_SIGNED_INT8:
|
||||
switch (numChannels) {
|
||||
case 1:
|
||||
return {8, 0, 0, 0, hipChannelFormatKindSigned};
|
||||
case 2:
|
||||
return {8, 8, 0, 0, hipChannelFormatKindSigned};
|
||||
case 4:
|
||||
return {8, 8, 8, 8, hipChannelFormatKindSigned};
|
||||
}
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT16:
|
||||
switch (numChannels) {
|
||||
case 1:
|
||||
return {16, 0, 0, 0, hipChannelFormatKindUnsigned};
|
||||
case 2:
|
||||
return {16, 16, 0, 0, hipChannelFormatKindUnsigned};
|
||||
case 4:
|
||||
return {16, 16, 16, 16, hipChannelFormatKindUnsigned};
|
||||
}
|
||||
case HIP_AD_FORMAT_SIGNED_INT16:
|
||||
switch (numChannels) {
|
||||
case 1:
|
||||
return {16, 0, 0, 0, hipChannelFormatKindSigned};
|
||||
case 2:
|
||||
return {16, 16, 0, 0, hipChannelFormatKindSigned};
|
||||
case 4:
|
||||
return {16, 16, 16, 16, hipChannelFormatKindSigned};
|
||||
}
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT32:
|
||||
switch (numChannels) {
|
||||
case 1:
|
||||
return {32, 0, 0, 0, hipChannelFormatKindUnsigned};
|
||||
case 2:
|
||||
return {32, 32, 0, 0, hipChannelFormatKindUnsigned};
|
||||
case 4:
|
||||
return {32, 32, 32, 32, hipChannelFormatKindUnsigned};
|
||||
}
|
||||
case HIP_AD_FORMAT_SIGNED_INT32:
|
||||
switch (numChannels) {
|
||||
case 1:
|
||||
return {32, 0, 0, 0, hipChannelFormatKindSigned};
|
||||
case 2:
|
||||
return {32, 32, 0, 0, hipChannelFormatKindSigned};
|
||||
case 4:
|
||||
return {32, 32, 32, 32, hipChannelFormatKindSigned};
|
||||
}
|
||||
case HIP_AD_FORMAT_HALF:
|
||||
switch (numChannels) {
|
||||
case 1:
|
||||
return {16, 0, 0, 0, hipChannelFormatKindFloat};
|
||||
case 2:
|
||||
return {16, 16, 0, 0, hipChannelFormatKindFloat};
|
||||
case 4:
|
||||
return {16, 16, 16, 16, hipChannelFormatKindFloat};
|
||||
}
|
||||
case HIP_AD_FORMAT_FLOAT:
|
||||
switch (numChannels) {
|
||||
case 1:
|
||||
return {32, 0, 0, 0, hipChannelFormatKindFloat};
|
||||
case 2:
|
||||
return {32, 32, 0, 0, hipChannelFormatKindFloat};
|
||||
case 4:
|
||||
return {32, 32, 32, 32, hipChannelFormatKindFloat};
|
||||
}
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned int getNumChannels(const hipChannelFormatDesc& desc) {
|
||||
return ((desc.x != 0) + (desc.y != 0) + (desc.z != 0) + (desc.w != 0));
|
||||
}
|
||||
|
||||
inline
|
||||
hipArray_Format getArrayFormat(const hipChannelFormatDesc& desc) {
|
||||
switch (desc.f) {
|
||||
case hipChannelFormatKindUnsigned:
|
||||
switch (desc.x) {
|
||||
case 8:
|
||||
return HIP_AD_FORMAT_UNSIGNED_INT8;
|
||||
case 16:
|
||||
return HIP_AD_FORMAT_UNSIGNED_INT16;
|
||||
case 32:
|
||||
return HIP_AD_FORMAT_UNSIGNED_INT32;
|
||||
}
|
||||
case hipChannelFormatKindSigned:
|
||||
switch (desc.x) {
|
||||
case 8:
|
||||
return HIP_AD_FORMAT_SIGNED_INT8;
|
||||
case 16:
|
||||
return HIP_AD_FORMAT_SIGNED_INT16;
|
||||
case 32:
|
||||
return HIP_AD_FORMAT_SIGNED_INT32;
|
||||
}
|
||||
case hipChannelFormatKindFloat:
|
||||
switch (desc.x) {
|
||||
case 16:
|
||||
return HIP_AD_FORMAT_HALF;
|
||||
case 32:
|
||||
return HIP_AD_FORMAT_FLOAT;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
int getNumChannels(const hipResourceViewFormat hipFormat) {
|
||||
switch (hipFormat) {
|
||||
case hipResViewFormatUnsignedChar1:
|
||||
case hipResViewFormatSignedChar1:
|
||||
case hipResViewFormatUnsignedShort1:
|
||||
case hipResViewFormatSignedShort1:
|
||||
case hipResViewFormatUnsignedInt1:
|
||||
case hipResViewFormatSignedInt1:
|
||||
case hipResViewFormatHalf1:
|
||||
case hipResViewFormatFloat1:
|
||||
return 1;
|
||||
case hipResViewFormatUnsignedChar2:
|
||||
case hipResViewFormatSignedChar2:
|
||||
case hipResViewFormatUnsignedShort2:
|
||||
case hipResViewFormatSignedShort2:
|
||||
case hipResViewFormatUnsignedInt2:
|
||||
case hipResViewFormatSignedInt2:
|
||||
case hipResViewFormatHalf2:
|
||||
case hipResViewFormatFloat2:
|
||||
return 2;
|
||||
case hipResViewFormatUnsignedChar4:
|
||||
case hipResViewFormatSignedChar4:
|
||||
case hipResViewFormatUnsignedShort4:
|
||||
case hipResViewFormatSignedShort4:
|
||||
case hipResViewFormatUnsignedInt4:
|
||||
case hipResViewFormatSignedInt4:
|
||||
case hipResViewFormatHalf4:
|
||||
case hipResViewFormatFloat4:
|
||||
return 4;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
hipArray_Format getArrayFormat(const hipResourceViewFormat hipFormat) {
|
||||
switch (hipFormat) {
|
||||
case hipResViewFormatUnsignedChar1:
|
||||
case hipResViewFormatUnsignedChar2:
|
||||
case hipResViewFormatUnsignedChar4:
|
||||
return HIP_AD_FORMAT_UNSIGNED_INT8;
|
||||
case hipResViewFormatSignedChar1:
|
||||
case hipResViewFormatSignedChar2:
|
||||
case hipResViewFormatSignedChar4:
|
||||
return HIP_AD_FORMAT_SIGNED_INT8;
|
||||
case hipResViewFormatUnsignedShort1:
|
||||
case hipResViewFormatUnsignedShort2:
|
||||
case hipResViewFormatUnsignedShort4:
|
||||
return HIP_AD_FORMAT_UNSIGNED_INT16;
|
||||
case hipResViewFormatSignedShort1:
|
||||
case hipResViewFormatSignedShort2:
|
||||
case hipResViewFormatSignedShort4:
|
||||
return HIP_AD_FORMAT_SIGNED_INT16;
|
||||
case hipResViewFormatUnsignedInt1:
|
||||
case hipResViewFormatUnsignedInt2:
|
||||
case hipResViewFormatUnsignedInt4:
|
||||
return HIP_AD_FORMAT_UNSIGNED_INT32;
|
||||
case hipResViewFormatSignedInt1:
|
||||
case hipResViewFormatSignedInt2:
|
||||
case hipResViewFormatSignedInt4:
|
||||
return HIP_AD_FORMAT_SIGNED_INT32;
|
||||
case hipResViewFormatHalf1:
|
||||
case hipResViewFormatHalf2:
|
||||
case hipResViewFormatHalf4:
|
||||
return HIP_AD_FORMAT_HALF;
|
||||
case hipResViewFormatFloat1:
|
||||
case hipResViewFormatFloat2:
|
||||
case hipResViewFormatFloat4:
|
||||
return HIP_AD_FORMAT_FLOAT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
hipResourceViewFormat getResourceViewFormat(const hipChannelFormatDesc& desc) {
|
||||
switch (desc.f) {
|
||||
case hipChannelFormatKindUnsigned:
|
||||
switch (getNumChannels(desc)) {
|
||||
case 1:
|
||||
switch (desc.x) {
|
||||
case 8:
|
||||
return hipResViewFormatUnsignedChar1;
|
||||
case 16:
|
||||
return hipResViewFormatUnsignedShort1;
|
||||
case 32:
|
||||
return hipResViewFormatUnsignedInt1;
|
||||
}
|
||||
case 2:
|
||||
switch (desc.x) {
|
||||
case 8:
|
||||
return hipResViewFormatUnsignedChar2;
|
||||
case 16:
|
||||
return hipResViewFormatUnsignedShort2;
|
||||
case 32:
|
||||
return hipResViewFormatUnsignedInt2;
|
||||
}
|
||||
case 4:
|
||||
switch (desc.x) {
|
||||
case 8:
|
||||
return hipResViewFormatUnsignedChar4;
|
||||
case 16:
|
||||
return hipResViewFormatUnsignedShort4;
|
||||
case 32:
|
||||
return hipResViewFormatUnsignedInt4;
|
||||
}
|
||||
}
|
||||
case hipChannelFormatKindSigned:
|
||||
switch (getNumChannels(desc)) {
|
||||
case 1:
|
||||
switch (desc.x) {
|
||||
case 8:
|
||||
return hipResViewFormatSignedChar1;
|
||||
case 16:
|
||||
return hipResViewFormatSignedShort1;
|
||||
case 32:
|
||||
return hipResViewFormatSignedInt1;
|
||||
}
|
||||
case 2:
|
||||
switch (desc.x) {
|
||||
case 8:
|
||||
return hipResViewFormatSignedChar2;
|
||||
case 16:
|
||||
return hipResViewFormatSignedShort2;
|
||||
case 32:
|
||||
return hipResViewFormatSignedInt2;
|
||||
}
|
||||
case 4:
|
||||
switch (desc.x) {
|
||||
case 8:
|
||||
return hipResViewFormatSignedChar4;
|
||||
case 16:
|
||||
return hipResViewFormatSignedShort4;
|
||||
case 32:
|
||||
return hipResViewFormatSignedInt4;
|
||||
}
|
||||
}
|
||||
case hipChannelFormatKindFloat:
|
||||
switch (getNumChannels(desc)) {
|
||||
case 1:
|
||||
switch (desc.x) {
|
||||
case 16:
|
||||
return hipResViewFormatHalf1;
|
||||
case 32:
|
||||
return hipResViewFormatFloat1;
|
||||
}
|
||||
case 2:
|
||||
switch (desc.x) {
|
||||
case 16:
|
||||
return hipResViewFormatHalf2;
|
||||
case 32:
|
||||
return hipResViewFormatFloat2;
|
||||
}
|
||||
case 4:
|
||||
switch (desc.x) {
|
||||
case 16:
|
||||
return hipResViewFormatHalf4;
|
||||
case 32:
|
||||
return hipResViewFormatFloat4;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
hipTextureDesc getTextureDesc(const textureReference* texRef) {
|
||||
hipTextureDesc texDesc = {};
|
||||
std::memcpy(texDesc.addressMode, texRef->addressMode, sizeof(texDesc.addressMode));
|
||||
texDesc.filterMode = texRef->filterMode;
|
||||
texDesc.readMode = texRef->readMode;
|
||||
texDesc.sRGB = texRef->sRGB;
|
||||
texDesc.normalizedCoords = texRef->normalized;
|
||||
texDesc.maxAnisotropy = texRef->maxAnisotropy;
|
||||
texDesc.mipmapFilterMode = texRef->mipmapFilterMode;
|
||||
texDesc.mipmapLevelBias = texRef->mipmapLevelBias;
|
||||
texDesc.minMipmapLevelClamp = texRef->minMipmapLevelClamp;
|
||||
texDesc.maxMipmapLevelClamp = texRef->maxMipmapLevelClamp;
|
||||
|
||||
return texDesc;
|
||||
}
|
||||
|
||||
inline
|
||||
hipResourceViewDesc getResourceViewDesc(hipArray_const_t array,
|
||||
const hipResourceViewFormat format) {
|
||||
hipResourceViewDesc resViewDesc = {};
|
||||
resViewDesc.format = format;
|
||||
resViewDesc.width = array->width;
|
||||
resViewDesc.height = array->height;
|
||||
resViewDesc.depth = array->depth;
|
||||
resViewDesc.firstMipmapLevel = 0;
|
||||
resViewDesc.lastMipmapLevel = 0;
|
||||
resViewDesc.firstLayer = 0;
|
||||
resViewDesc.lastLayer = 0; /* TODO add hipArray::numLayers */
|
||||
|
||||
return resViewDesc;
|
||||
}
|
||||
|
||||
inline
|
||||
hipResourceViewDesc getResourceViewDesc(hipMipmappedArray_const_t array,
|
||||
const hipResourceViewFormat format) {
|
||||
hipResourceViewDesc resViewDesc = {};
|
||||
resViewDesc.format = format;
|
||||
resViewDesc.width = array->width;
|
||||
resViewDesc.height = array->height;
|
||||
resViewDesc.depth = array->depth;
|
||||
resViewDesc.firstMipmapLevel = 0;
|
||||
resViewDesc.lastMipmapLevel = 0; /* TODO add hipMipmappedArray::numMipLevels */
|
||||
resViewDesc.firstLayer = 0;
|
||||
resViewDesc.lastLayer = 0; /* TODO add hipArray::numLayers */
|
||||
|
||||
return resViewDesc;
|
||||
}
|
||||
|
||||
inline
|
||||
std::pair<hipMemoryType, hipMemoryType> getMemoryType(const hipMemcpyKind kind) {
|
||||
switch (kind) {
|
||||
case hipMemcpyHostToHost:
|
||||
return {hipMemoryTypeHost, hipMemoryTypeHost};
|
||||
case hipMemcpyHostToDevice:
|
||||
return {hipMemoryTypeHost, hipMemoryTypeDevice};
|
||||
case hipMemcpyDeviceToHost:
|
||||
return {hipMemoryTypeDevice, hipMemoryTypeHost};
|
||||
case hipMemcpyDeviceToDevice:
|
||||
return {hipMemoryTypeDevice, hipMemoryTypeDevice};
|
||||
case hipMemcpyDefault:
|
||||
return {hipMemoryTypeUnified, hipMemoryTypeUnified};
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline
|
||||
HIP_MEMCPY3D getDrvMemcpy3DDesc(const hip_Memcpy2D& desc2D) {
|
||||
HIP_MEMCPY3D desc3D = {};
|
||||
|
||||
desc3D.srcXInBytes = desc2D.srcXInBytes;
|
||||
desc3D.srcY = desc2D.srcY;
|
||||
desc3D.srcZ = 0;
|
||||
desc3D.srcLOD = 0;
|
||||
desc3D.srcMemoryType = desc2D.srcMemoryType;
|
||||
desc3D.srcHost = desc2D.srcHost;
|
||||
desc3D.srcDevice = desc2D.srcDevice;
|
||||
desc3D.srcArray = desc2D.srcArray;
|
||||
desc3D.srcPitch = desc2D.srcPitch;
|
||||
desc3D.srcHeight = 0;
|
||||
|
||||
desc3D.dstXInBytes = desc2D.dstXInBytes;
|
||||
desc3D.dstY = desc2D.dstY;
|
||||
desc3D.dstZ = 0;
|
||||
desc3D.dstLOD = 0;
|
||||
desc3D.dstMemoryType = desc2D.dstMemoryType;
|
||||
desc3D.dstHost = desc2D.dstHost;
|
||||
desc3D.dstDevice = desc2D.dstDevice;
|
||||
desc3D.dstArray = desc2D.dstArray;
|
||||
desc3D.dstPitch = desc2D.dstPitch;
|
||||
desc3D.dstHeight = 0;
|
||||
|
||||
desc3D.WidthInBytes = desc2D.WidthInBytes;
|
||||
desc3D.Height = desc2D.Height;
|
||||
desc3D.Depth = 1;
|
||||
|
||||
return desc3D;
|
||||
}
|
||||
|
||||
inline
|
||||
HIP_MEMCPY3D getDrvMemcpy3DDesc(const hipMemcpy3DParms& desc) {
|
||||
HIP_MEMCPY3D descDrv = {};
|
||||
|
||||
descDrv.WidthInBytes = desc.extent.width;
|
||||
descDrv.Height = desc.extent.height;
|
||||
descDrv.Depth = desc.extent.depth;
|
||||
|
||||
descDrv.srcXInBytes = desc.srcPos.x;
|
||||
descDrv.srcY = desc.srcPos.y;
|
||||
descDrv.srcZ = desc.srcPos.z;
|
||||
descDrv.srcLOD = 0;
|
||||
|
||||
descDrv.dstXInBytes = desc.dstPos.x;
|
||||
descDrv.dstY = desc.dstPos.y;
|
||||
descDrv.dstZ = desc.dstPos.z;
|
||||
descDrv.dstLOD = 0;
|
||||
|
||||
if (desc.srcArray != nullptr) {
|
||||
descDrv.srcMemoryType = hipMemoryTypeArray;
|
||||
descDrv.srcArray = desc.srcArray;
|
||||
// When reffering to array memory, hipPos::x is in elements.
|
||||
descDrv.srcXInBytes *= getElementSize(desc.srcArray);
|
||||
}
|
||||
|
||||
if (desc.srcPtr.ptr != nullptr) {
|
||||
descDrv.srcMemoryType = std::get<0>(hip::getMemoryType(desc.kind));
|
||||
descDrv.srcHost = desc.srcPtr.ptr;
|
||||
descDrv.srcDevice = desc.srcPtr.ptr;
|
||||
descDrv.srcPitch = desc.srcPtr.pitch;
|
||||
descDrv.srcHeight = desc.srcPtr.ysize;
|
||||
}
|
||||
|
||||
if (desc.dstArray != nullptr) {
|
||||
descDrv.dstMemoryType = hipMemoryTypeArray;
|
||||
descDrv.dstArray = desc.dstArray;
|
||||
// When reffering to array memory, hipPos::x is in elements.
|
||||
descDrv.dstXInBytes *= getElementSize(desc.dstArray);
|
||||
}
|
||||
|
||||
if (desc.dstPtr.ptr != nullptr) {
|
||||
descDrv.dstMemoryType = std::get<1>(getMemoryType(desc.kind));
|
||||
descDrv.dstHost = desc.dstPtr.ptr;
|
||||
descDrv.dstDevice = desc.dstPtr.ptr;
|
||||
descDrv.dstPitch = desc.dstPtr.pitch;
|
||||
descDrv.dstHeight = desc.dstPtr.ysize;
|
||||
}
|
||||
|
||||
// If a HIP array is participating in the copy, the extent is defined in terms of that array's elements.
|
||||
if ((desc.srcArray != nullptr) && (desc.dstArray == nullptr)) {
|
||||
descDrv.WidthInBytes *= getElementSize(desc.srcArray);
|
||||
} else if ((desc.srcArray == nullptr) && (desc.dstArray != nullptr)) {
|
||||
descDrv.WidthInBytes *= getElementSize(desc.dstArray);
|
||||
} else if ((desc.srcArray != nullptr) && (desc.dstArray != nullptr)) {
|
||||
descDrv.WidthInBytes *= getElementSize(desc.dstArray);
|
||||
}
|
||||
|
||||
return descDrv;
|
||||
}
|
||||
|
||||
inline
|
||||
hipResourceType getResourceType(const HIPresourcetype resType) {
|
||||
// These two enums should be isomorphic.
|
||||
return static_cast<hipResourceType>(resType);
|
||||
}
|
||||
|
||||
inline
|
||||
HIPresourcetype getResourceType(const hipResourceType resType) {
|
||||
// These two enums should be isomorphic.
|
||||
return static_cast<HIPresourcetype>(resType);
|
||||
}
|
||||
|
||||
inline
|
||||
hipResourceDesc getResourceDesc(const HIP_RESOURCE_DESC& resDesc) {
|
||||
hipResourceDesc desc;
|
||||
|
||||
desc.resType = getResourceType(resDesc.resType);
|
||||
switch (desc.resType) {
|
||||
case hipResourceTypeArray:
|
||||
desc.res.array.array = resDesc.res.array.hArray;
|
||||
break;
|
||||
case hipResourceTypeMipmappedArray:
|
||||
desc.res.mipmap.mipmap = resDesc.res.mipmap.hMipmappedArray;
|
||||
break;
|
||||
case hipResourceTypeLinear:
|
||||
desc.res.linear.devPtr = resDesc.res.linear.devPtr;
|
||||
desc.res.linear.desc = getChannelFormatDesc(resDesc.res.linear.numChannels, resDesc.res.linear.format);
|
||||
desc.res.linear.sizeInBytes = resDesc.res.linear.sizeInBytes;
|
||||
break;
|
||||
case hipResourceTypePitch2D:
|
||||
desc.res.pitch2D.devPtr = resDesc.res.pitch2D.devPtr;
|
||||
desc.res.pitch2D.desc = getChannelFormatDesc(resDesc.res.pitch2D.numChannels, resDesc.res.pitch2D.format);
|
||||
desc.res.pitch2D.width = resDesc.res.pitch2D.width;
|
||||
desc.res.pitch2D.height = resDesc.res.pitch2D.height;
|
||||
desc.res.pitch2D.pitchInBytes = resDesc.res.pitch2D.pitchInBytes;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
inline
|
||||
HIP_RESOURCE_DESC getResourceDesc(const hipResourceDesc& resDesc) {
|
||||
HIP_RESOURCE_DESC desc;
|
||||
|
||||
desc.resType = getResourceType(resDesc.resType);
|
||||
switch (desc.resType) {
|
||||
case HIP_RESOURCE_TYPE_ARRAY:
|
||||
desc.res.array.hArray = resDesc.res.array.array;
|
||||
break;
|
||||
case HIP_RESOURCE_TYPE_MIPMAPPED_ARRAY:
|
||||
desc.res.mipmap.hMipmappedArray = resDesc.res.mipmap.mipmap;
|
||||
break;
|
||||
case HIP_RESOURCE_TYPE_LINEAR:
|
||||
desc.res.linear.devPtr = resDesc.res.linear.devPtr;
|
||||
desc.res.linear.numChannels = getNumChannels(resDesc.res.linear.desc);
|
||||
desc.res.linear.format = getArrayFormat(resDesc.res.linear.desc);
|
||||
desc.res.linear.sizeInBytes = resDesc.res.linear.sizeInBytes;
|
||||
break;
|
||||
case HIP_RESOURCE_TYPE_PITCH2D:
|
||||
desc.res.pitch2D.devPtr = resDesc.res.pitch2D.devPtr;
|
||||
desc.res.pitch2D.numChannels = getNumChannels(resDesc.res.pitch2D.desc);
|
||||
desc.res.pitch2D.format = getArrayFormat(resDesc.res.pitch2D.desc);
|
||||
desc.res.pitch2D.width = resDesc.res.pitch2D.width;
|
||||
desc.res.pitch2D.height = resDesc.res.pitch2D.height;
|
||||
desc.res.pitch2D.pitchInBytes = resDesc.res.pitch2D.pitchInBytes;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
inline
|
||||
hipTextureAddressMode getAddressMode(const HIPaddress_mode mode) {
|
||||
// These two enums should be isomorphic.
|
||||
return static_cast<hipTextureAddressMode>(mode);
|
||||
}
|
||||
|
||||
inline
|
||||
HIPaddress_mode getAddressMode(const hipTextureAddressMode mode) {
|
||||
// These two enums should be isomorphic.
|
||||
return static_cast<HIPaddress_mode>(mode);
|
||||
}
|
||||
|
||||
inline
|
||||
hipTextureFilterMode getFilterMode(const HIPfilter_mode mode) {
|
||||
// These two enums should be isomorphic.
|
||||
return static_cast<hipTextureFilterMode>(mode);
|
||||
}
|
||||
|
||||
inline
|
||||
HIPfilter_mode getFilterMode(const hipTextureFilterMode mode) {
|
||||
// These two enums should be isomorphic.
|
||||
return static_cast<HIPfilter_mode>(mode);
|
||||
}
|
||||
|
||||
inline
|
||||
hipTextureReadMode getReadMode(const unsigned int flags) {
|
||||
if (flags & HIP_TRSF_READ_AS_INTEGER) {
|
||||
return hipReadModeElementType;
|
||||
} else {
|
||||
return hipReadModeNormalizedFloat;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned int getReadMode(const hipTextureReadMode mode) {
|
||||
if (mode == hipReadModeElementType) {
|
||||
return HIP_TRSF_READ_AS_INTEGER;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
int getsRGB(const unsigned int flags) {
|
||||
if (flags & HIP_TRSF_SRGB) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned int getsRGB(const int sRGB) {
|
||||
if (sRGB == 1) {
|
||||
return HIP_TRSF_SRGB;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
int getNormalizedCoords(const unsigned int flags) {
|
||||
if (flags & HIP_TRSF_NORMALIZED_COORDINATES) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned int getNormalizedCoords(const int normalizedCoords) {
|
||||
if (normalizedCoords == 1) {
|
||||
return HIP_TRSF_NORMALIZED_COORDINATES;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
hipTextureDesc getTextureDesc(const HIP_TEXTURE_DESC& texDesc) {
|
||||
hipTextureDesc desc;
|
||||
|
||||
desc.addressMode[0] = getAddressMode(texDesc.addressMode[0]);
|
||||
desc.addressMode[1] = getAddressMode(texDesc.addressMode[1]);
|
||||
desc.addressMode[2] = getAddressMode(texDesc.addressMode[2]);
|
||||
desc.filterMode = getFilterMode(texDesc.filterMode);
|
||||
desc.readMode = getReadMode(texDesc.flags);
|
||||
desc.sRGB = getsRGB(texDesc.flags);
|
||||
std::memcpy(desc.borderColor, texDesc.borderColor, sizeof(desc.borderColor));
|
||||
desc.normalizedCoords = getNormalizedCoords(texDesc.flags);
|
||||
desc.maxAnisotropy = texDesc.maxAnisotropy;
|
||||
desc.mipmapFilterMode = getFilterMode(texDesc.mipmapFilterMode);
|
||||
desc.mipmapLevelBias = texDesc.mipmapLevelBias;
|
||||
desc.minMipmapLevelClamp = texDesc.minMipmapLevelClamp;
|
||||
desc.maxMipmapLevelClamp = texDesc.maxMipmapLevelClamp;
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
inline
|
||||
HIP_TEXTURE_DESC getTextureDesc(const hipTextureDesc& texDesc) {
|
||||
HIP_TEXTURE_DESC desc;
|
||||
|
||||
desc.addressMode[0] = getAddressMode(texDesc.addressMode[0]);
|
||||
desc.addressMode[1] = getAddressMode(texDesc.addressMode[1]);
|
||||
desc.addressMode[2] = getAddressMode(texDesc.addressMode[2]);
|
||||
desc.filterMode = getFilterMode(texDesc.filterMode);
|
||||
desc.flags = 0;
|
||||
desc.flags |= getReadMode(texDesc.readMode);
|
||||
desc.flags |= getsRGB(texDesc.sRGB);
|
||||
desc.flags |= getNormalizedCoords(texDesc.normalizedCoords);
|
||||
desc.maxAnisotropy = texDesc.maxAnisotropy;
|
||||
desc.mipmapFilterMode = getFilterMode(texDesc.mipmapFilterMode);
|
||||
desc.mipmapLevelBias = texDesc.mipmapLevelBias;
|
||||
desc.minMipmapLevelClamp = texDesc.minMipmapLevelClamp;
|
||||
desc.maxMipmapLevelClamp = texDesc.maxMipmapLevelClamp;
|
||||
std::memcpy(desc.borderColor, texDesc.borderColor, sizeof(desc.borderColor));
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
inline
|
||||
hipResourceViewFormat getResourceViewFormat(const HIPresourceViewFormat format) {
|
||||
// These two enums should be isomorphic.
|
||||
return static_cast<hipResourceViewFormat>(format);
|
||||
}
|
||||
|
||||
inline
|
||||
HIPresourceViewFormat getResourceViewFormat(const hipResourceViewFormat format) {
|
||||
// These two enums should be isomorphic.
|
||||
return static_cast<HIPresourceViewFormat>(format);
|
||||
}
|
||||
|
||||
inline
|
||||
hipResourceViewDesc getResourceViewDesc(const HIP_RESOURCE_VIEW_DESC& resViewDesc) {
|
||||
hipResourceViewDesc desc;
|
||||
|
||||
desc.format = getResourceViewFormat(resViewDesc.format);
|
||||
desc.width = resViewDesc.width;
|
||||
desc.height = resViewDesc.height;
|
||||
desc.depth = resViewDesc.depth;
|
||||
desc.firstMipmapLevel = resViewDesc.firstMipmapLevel;
|
||||
desc.lastMipmapLevel = resViewDesc.lastMipmapLevel;
|
||||
desc.firstLayer = resViewDesc.firstLayer;
|
||||
desc.lastLayer = resViewDesc.lastLayer;
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
inline
|
||||
HIP_RESOURCE_VIEW_DESC getResourceViewDesc(const hipResourceViewDesc& resViewDesc) {
|
||||
HIP_RESOURCE_VIEW_DESC desc;
|
||||
|
||||
desc.format = getResourceViewFormat(resViewDesc.format);
|
||||
desc.width = resViewDesc.width;
|
||||
desc.height = resViewDesc.height;
|
||||
desc.depth = resViewDesc.depth;
|
||||
desc.firstMipmapLevel = resViewDesc.firstMipmapLevel;
|
||||
desc.lastMipmapLevel = resViewDesc.lastMipmapLevel;
|
||||
desc.firstLayer = resViewDesc.firstLayer;
|
||||
desc.lastLayer = resViewDesc.lastLayer;
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t getElementSize(const hipChannelFormatDesc &desc) {
|
||||
return (desc.x / 8) * getNumChannels(desc);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,240 @@
|
||||
/* Copyright (c) 2018-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
#include "hip_internal.hpp"
|
||||
|
||||
namespace hip {
|
||||
|
||||
// ================================================================================================
|
||||
amd::HostQueue* Device::NullStream(bool skip_alloc) {
|
||||
amd::HostQueue* null_queue = null_stream_.asHostQueue(skip_alloc);
|
||||
if (null_queue == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
// Wait for all active streams before executing commands on the default
|
||||
iHipWaitActiveStreams(null_queue);
|
||||
return null_queue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
hipError_t hipDeviceGet(hipDevice_t *device, int deviceId) {
|
||||
HIP_INIT_API(hipDeviceGet, device, deviceId);
|
||||
|
||||
if (deviceId < 0 ||
|
||||
static_cast<size_t>(deviceId) >= g_devices.size() ||
|
||||
device == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
*device = deviceId;
|
||||
HIP_RETURN(hipSuccess);
|
||||
};
|
||||
|
||||
hipError_t hipDeviceTotalMem (size_t *bytes, hipDevice_t device) {
|
||||
|
||||
HIP_INIT_API(hipDeviceTotalMem, bytes, device);
|
||||
|
||||
if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
if (bytes == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
auto* deviceHandle = g_devices[device]->devices()[0];
|
||||
const auto& info = deviceHandle->info();
|
||||
|
||||
*bytes = info.globalMemSize_;
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceComputeCapability(int *major, int *minor, hipDevice_t device) {
|
||||
|
||||
HIP_INIT_API(hipDeviceComputeCapability, major, minor, device);
|
||||
|
||||
if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
if (major == nullptr || minor == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
auto* deviceHandle = g_devices[device]->devices()[0];
|
||||
const auto& isa = deviceHandle->isa();
|
||||
*major = isa.versionMajor();
|
||||
*minor = isa.versionMinor();
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceGetCount(int* count) {
|
||||
HIP_INIT_API(hipDeviceGetCount, count);
|
||||
|
||||
HIP_RETURN(ihipDeviceGetCount(count));
|
||||
}
|
||||
|
||||
hipError_t ihipDeviceGetCount(int* count) {
|
||||
if (count == nullptr) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
// Get all available devices
|
||||
*count = g_devices.size();
|
||||
|
||||
if (*count < 1) {
|
||||
return hipErrorNoDevice;
|
||||
}
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t hipDeviceGetName(char *name, int len, hipDevice_t device) {
|
||||
|
||||
HIP_INIT_API(hipDeviceGetName, (void*)name, len, device);
|
||||
|
||||
if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
if (name == nullptr || len <= 0) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
auto* deviceHandle = g_devices[device]->devices()[0];
|
||||
const auto& info = deviceHandle->info();
|
||||
const auto nameLen = ::strlen(info.boardName_);
|
||||
|
||||
// Make sure that the size of `dest` is big enough to hold `src` including
|
||||
// trailing zero byte
|
||||
if (nameLen > (cl_uint)(len - 1)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
::strncpy(name, info.boardName_, (nameLen + 1));
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipGetDeviceProperties ( hipDeviceProp_t* props, hipDevice_t device ) {
|
||||
HIP_INIT_API(hipGetDeviceProperties, props, device);
|
||||
|
||||
if (props == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
if (unsigned(device) >= g_devices.size()) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
auto* deviceHandle = g_devices[device]->devices()[0];
|
||||
|
||||
hipDeviceProp_t deviceProps = {0};
|
||||
|
||||
const auto& info = deviceHandle->info();
|
||||
const auto& isa = deviceHandle->isa();
|
||||
::strncpy(deviceProps.name, info.boardName_, 128);
|
||||
deviceProps.totalGlobalMem = info.globalMemSize_;
|
||||
deviceProps.sharedMemPerBlock = info.localMemSizePerCU_;
|
||||
deviceProps.regsPerBlock = info.availableRegistersPerCU_;
|
||||
deviceProps.warpSize = info.wavefrontWidth_;
|
||||
deviceProps.maxThreadsPerBlock = info.maxWorkGroupSize_;
|
||||
deviceProps.maxThreadsDim[0] = info.maxWorkItemSizes_[0];
|
||||
deviceProps.maxThreadsDim[1] = info.maxWorkItemSizes_[1];
|
||||
deviceProps.maxThreadsDim[2] = info.maxWorkItemSizes_[2];
|
||||
deviceProps.maxGridSize[0] = INT32_MAX;
|
||||
deviceProps.maxGridSize[1] = INT32_MAX;
|
||||
deviceProps.maxGridSize[2] = INT32_MAX;
|
||||
deviceProps.clockRate = info.maxEngineClockFrequency_ * 1000;
|
||||
deviceProps.memoryClockRate = info.maxMemoryClockFrequency_ * 1000;
|
||||
deviceProps.memoryBusWidth = info.globalMemChannels_;
|
||||
deviceProps.totalConstMem = info.maxConstantBufferSize_;
|
||||
deviceProps.major = isa.versionMajor();
|
||||
deviceProps.minor = isa.versionMinor();
|
||||
deviceProps.multiProcessorCount = info.maxComputeUnits_;
|
||||
deviceProps.l2CacheSize = info.l2CacheSize_;
|
||||
deviceProps.maxThreadsPerMultiProcessor = info.maxThreadsPerCU_;
|
||||
deviceProps.computeMode = 0;
|
||||
deviceProps.clockInstructionRate = info.timeStampFrequency_;
|
||||
deviceProps.arch.hasGlobalInt32Atomics = 1;
|
||||
deviceProps.arch.hasGlobalFloatAtomicExch = 1;
|
||||
deviceProps.arch.hasSharedInt32Atomics = 1;
|
||||
deviceProps.arch.hasSharedFloatAtomicExch = 1;
|
||||
deviceProps.arch.hasFloatAtomicAdd = 1;
|
||||
deviceProps.arch.hasGlobalInt64Atomics = 1;
|
||||
deviceProps.arch.hasSharedInt64Atomics = 1;
|
||||
deviceProps.arch.hasDoubles = 1;
|
||||
deviceProps.arch.hasWarpVote = 1;
|
||||
deviceProps.arch.hasWarpBallot = 1;
|
||||
deviceProps.arch.hasWarpShuffle = 1;
|
||||
deviceProps.arch.hasFunnelShift = 0;
|
||||
deviceProps.arch.hasThreadFenceSystem = 1;
|
||||
deviceProps.arch.hasSyncThreadsExt = 0;
|
||||
deviceProps.arch.hasSurfaceFuncs = 0;
|
||||
deviceProps.arch.has3dGrid = 1;
|
||||
deviceProps.arch.hasDynamicParallelism = 0;
|
||||
deviceProps.concurrentKernels = 1;
|
||||
deviceProps.pciDomainID = info.pciDomainID;
|
||||
deviceProps.pciBusID = info.deviceTopology_.pcie.bus;
|
||||
deviceProps.pciDeviceID = info.deviceTopology_.pcie.device;
|
||||
deviceProps.maxSharedMemoryPerMultiProcessor = info.localMemSizePerCU_;
|
||||
deviceProps.canMapHostMemory = 1;
|
||||
//FIXME: This should be removed, targets can have character names as well.
|
||||
deviceProps.gcnArch = isa.versionMajor() * 100 + isa.versionMinor() * 10 + isa.versionStepping();
|
||||
sprintf(deviceProps.gcnArchName, "%s", isa.targetId());
|
||||
deviceProps.cooperativeLaunch = info.cooperativeGroups_;
|
||||
deviceProps.cooperativeMultiDeviceLaunch = info.cooperativeMultiDeviceGroups_;
|
||||
|
||||
deviceProps.cooperativeMultiDeviceUnmatchedFunc = info.cooperativeMultiDeviceGroups_;
|
||||
deviceProps.cooperativeMultiDeviceUnmatchedGridDim = info.cooperativeMultiDeviceGroups_;
|
||||
deviceProps.cooperativeMultiDeviceUnmatchedBlockDim = info.cooperativeMultiDeviceGroups_;
|
||||
deviceProps.cooperativeMultiDeviceUnmatchedSharedMem = info.cooperativeMultiDeviceGroups_;
|
||||
|
||||
deviceProps.maxTexture1DLinear = 16 * info.imageMaxBufferSize_; // Max pixel size is 16 bytes
|
||||
deviceProps.maxTexture1D = info.image1DMaxWidth_;
|
||||
deviceProps.maxTexture2D[0] = info.image2DMaxWidth_;
|
||||
deviceProps.maxTexture2D[1] = info.image2DMaxHeight_;
|
||||
deviceProps.maxTexture3D[0] = info.image3DMaxWidth_;
|
||||
deviceProps.maxTexture3D[1] = info.image3DMaxHeight_;
|
||||
deviceProps.maxTexture3D[2] = info.image3DMaxDepth_;
|
||||
deviceProps.hdpMemFlushCntl = info.hdpMemFlushCntl;
|
||||
deviceProps.hdpRegFlushCntl = info.hdpRegFlushCntl;
|
||||
|
||||
deviceProps.memPitch = info.maxMemAllocSize_;
|
||||
deviceProps.textureAlignment = info.imageBaseAddressAlignment_;
|
||||
deviceProps.texturePitchAlignment = info.imagePitchAlignment_;
|
||||
deviceProps.kernelExecTimeoutEnabled = 0;
|
||||
deviceProps.ECCEnabled = info.errorCorrectionSupport_? 1:0;
|
||||
deviceProps.isLargeBar = info.largeBar_ ? 1 : 0;
|
||||
deviceProps.asicRevision = info.asicRevision_;
|
||||
|
||||
// HMM capabilities
|
||||
deviceProps.managedMemory = info.hmmSupported_;
|
||||
deviceProps.concurrentManagedAccess = info.hmmSupported_;
|
||||
deviceProps.directManagedMemAccessFromHost = info.hmmDirectHostAccess_;
|
||||
deviceProps.pageableMemoryAccess = info.hmmCpuMemoryAccessible_;
|
||||
deviceProps.pageableMemoryAccessUsesHostPageTables = info.hostUnifiedMemory_;
|
||||
|
||||
*props = deviceProps;
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
+563
@@ -0,0 +1,563 @@
|
||||
/* Copyright (c) 2018-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
#include "hip_internal.hpp"
|
||||
|
||||
hipError_t hipChooseDevice(int* device, const hipDeviceProp_t* properties) {
|
||||
|
||||
HIP_INIT_API(hipChooseDevice, device, properties);
|
||||
|
||||
if (device == nullptr || properties == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
*device = 0;
|
||||
cl_uint maxMatchedCount = 0;
|
||||
int count = 0;
|
||||
ihipDeviceGetCount(&count);
|
||||
|
||||
for (cl_int i = 0; i< count; ++i) {
|
||||
hipDeviceProp_t currentProp = {0};
|
||||
cl_uint validPropCount = 0;
|
||||
cl_uint matchedCount = 0;
|
||||
hipError_t err = hipGetDeviceProperties(¤tProp, i);
|
||||
if (properties->major != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.major >= properties->major) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if (properties->minor != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.minor >= properties->minor) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(properties->totalGlobalMem != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.totalGlobalMem >= properties->totalGlobalMem) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(properties->sharedMemPerBlock != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.sharedMemPerBlock >= properties->sharedMemPerBlock) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(properties->maxThreadsPerBlock != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.maxThreadsPerBlock >= properties->maxThreadsPerBlock ) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(properties->totalConstMem != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.totalConstMem >= properties->totalConstMem ) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(properties->multiProcessorCount != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.multiProcessorCount >=
|
||||
properties->multiProcessorCount ) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(properties->maxThreadsPerMultiProcessor != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.maxThreadsPerMultiProcessor >=
|
||||
properties->maxThreadsPerMultiProcessor ) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(properties->memoryClockRate != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.memoryClockRate >= properties->memoryClockRate ) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(properties->memoryBusWidth != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.memoryBusWidth >= properties->memoryBusWidth ) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(properties->l2CacheSize != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.l2CacheSize >= properties->l2CacheSize ) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(properties->regsPerBlock != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.regsPerBlock >= properties->regsPerBlock ) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(properties->maxSharedMemoryPerMultiProcessor != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.maxSharedMemoryPerMultiProcessor >=
|
||||
properties->maxSharedMemoryPerMultiProcessor ) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(properties->warpSize != 0) {
|
||||
validPropCount++;
|
||||
if(currentProp.warpSize >= properties->warpSize ) {
|
||||
matchedCount++;
|
||||
}
|
||||
}
|
||||
if(validPropCount == matchedCount) {
|
||||
*device = matchedCount > maxMatchedCount ? i : *device;
|
||||
maxMatchedCount = std::max(matchedCount, maxMatchedCount);
|
||||
}
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceGetAttribute(int* pi, hipDeviceAttribute_t attr, int device) {
|
||||
|
||||
HIP_INIT_API(hipDeviceGetAttribute, pi, attr, device);
|
||||
|
||||
if (pi == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
ihipDeviceGetCount(&count);
|
||||
if (device < 0 || device >= count) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
//FIXME: should we cache the props, or just select from deviceHandle->info_?
|
||||
hipDeviceProp_t prop = {0};
|
||||
hipError_t err = hipGetDeviceProperties(&prop, device);
|
||||
if (err != hipSuccess) {
|
||||
HIP_RETURN(err);
|
||||
}
|
||||
|
||||
switch (attr) {
|
||||
case hipDeviceAttributeMaxThreadsPerBlock:
|
||||
*pi = prop.maxThreadsPerBlock;
|
||||
break;
|
||||
case hipDeviceAttributeMaxBlockDimX:
|
||||
*pi = prop.maxThreadsDim[0];
|
||||
break;
|
||||
case hipDeviceAttributeMaxBlockDimY:
|
||||
*pi = prop.maxThreadsDim[1];
|
||||
break;
|
||||
case hipDeviceAttributeMaxBlockDimZ:
|
||||
*pi = prop.maxThreadsDim[2];
|
||||
break;
|
||||
case hipDeviceAttributeMaxGridDimX:
|
||||
*pi = prop.maxGridSize[0];
|
||||
break;
|
||||
case hipDeviceAttributeMaxGridDimY:
|
||||
*pi = prop.maxGridSize[1];
|
||||
break;
|
||||
case hipDeviceAttributeMaxGridDimZ:
|
||||
*pi = prop.maxGridSize[2];
|
||||
break;
|
||||
case hipDeviceAttributeMaxSharedMemoryPerBlock:
|
||||
*pi = prop.sharedMemPerBlock;
|
||||
break;
|
||||
case hipDeviceAttributeTotalConstantMemory:
|
||||
*pi = prop.totalConstMem;
|
||||
break;
|
||||
case hipDeviceAttributeWarpSize:
|
||||
*pi = prop.warpSize;
|
||||
break;
|
||||
case hipDeviceAttributeMaxRegistersPerBlock:
|
||||
*pi = prop.regsPerBlock;
|
||||
break;
|
||||
case hipDeviceAttributeClockRate:
|
||||
*pi = prop.clockRate;
|
||||
break;
|
||||
case hipDeviceAttributeMemoryClockRate:
|
||||
*pi = prop.memoryClockRate;
|
||||
break;
|
||||
case hipDeviceAttributeMemoryBusWidth:
|
||||
*pi = prop.memoryBusWidth;
|
||||
break;
|
||||
case hipDeviceAttributeMultiprocessorCount:
|
||||
*pi = prop.multiProcessorCount;
|
||||
break;
|
||||
case hipDeviceAttributeComputeMode:
|
||||
*pi = prop.computeMode;
|
||||
break;
|
||||
case hipDeviceAttributeL2CacheSize:
|
||||
*pi = prop.l2CacheSize;
|
||||
break;
|
||||
case hipDeviceAttributeMaxThreadsPerMultiProcessor:
|
||||
*pi = prop.maxThreadsPerMultiProcessor;
|
||||
break;
|
||||
case hipDeviceAttributeComputeCapabilityMajor:
|
||||
*pi = prop.major;
|
||||
break;
|
||||
case hipDeviceAttributeComputeCapabilityMinor:
|
||||
*pi = prop.minor;
|
||||
break;
|
||||
case hipDeviceAttributePciBusId:
|
||||
*pi = prop.pciBusID;
|
||||
break;
|
||||
case hipDeviceAttributeConcurrentKernels:
|
||||
*pi = prop.concurrentKernels;
|
||||
break;
|
||||
case hipDeviceAttributePciDeviceId:
|
||||
*pi = prop.pciDeviceID;
|
||||
break;
|
||||
case hipDeviceAttributeMaxSharedMemoryPerMultiprocessor:
|
||||
*pi = prop.maxSharedMemoryPerMultiProcessor;
|
||||
break;
|
||||
case hipDeviceAttributeIsMultiGpuBoard:
|
||||
*pi = prop.isMultiGpuBoard;
|
||||
break;
|
||||
case hipDeviceAttributeCooperativeLaunch:
|
||||
*pi = prop.cooperativeLaunch;
|
||||
break;
|
||||
case hipDeviceAttributeCooperativeMultiDeviceLaunch:
|
||||
*pi = prop.cooperativeMultiDeviceLaunch;
|
||||
break;
|
||||
case hipDeviceAttributeIntegrated:
|
||||
*pi = prop.integrated;
|
||||
break;
|
||||
case hipDeviceAttributeMaxTexture1DWidth:
|
||||
*pi = prop.maxTexture1D;
|
||||
break;
|
||||
case hipDeviceAttributeMaxTexture2DWidth:
|
||||
*pi = prop.maxTexture2D[0];
|
||||
break;
|
||||
case hipDeviceAttributeMaxTexture2DHeight:
|
||||
*pi = prop.maxTexture2D[1];
|
||||
break;
|
||||
case hipDeviceAttributeMaxTexture3DWidth:
|
||||
*pi = prop.maxTexture3D[0];
|
||||
break;
|
||||
case hipDeviceAttributeMaxTexture3DHeight:
|
||||
*pi = prop.maxTexture3D[1];
|
||||
break;
|
||||
case hipDeviceAttributeMaxTexture3DDepth:
|
||||
*pi = prop.maxTexture3D[2];
|
||||
break;
|
||||
case hipDeviceAttributeHdpMemFlushCntl:
|
||||
*reinterpret_cast<unsigned int**>(pi) = prop.hdpMemFlushCntl;
|
||||
break;
|
||||
case hipDeviceAttributeHdpRegFlushCntl:
|
||||
*reinterpret_cast<unsigned int**>(pi) = prop.hdpRegFlushCntl;
|
||||
break;
|
||||
case hipDeviceAttributeMaxPitch:
|
||||
*pi = prop.memPitch;
|
||||
break;
|
||||
case hipDeviceAttributeTextureAlignment:
|
||||
*pi = prop.textureAlignment;
|
||||
break;
|
||||
case hipDeviceAttributeTexturePitchAlignment:
|
||||
*pi = prop.texturePitchAlignment;
|
||||
break;
|
||||
case hipDeviceAttributeKernelExecTimeout:
|
||||
*pi = prop.kernelExecTimeoutEnabled;
|
||||
break;
|
||||
case hipDeviceAttributeCanMapHostMemory:
|
||||
*pi = prop.canMapHostMemory;
|
||||
break;
|
||||
case hipDeviceAttributeEccEnabled:
|
||||
*pi = prop.ECCEnabled;
|
||||
break;
|
||||
case hipDeviceAttributeCooperativeMultiDeviceUnmatchedFunc:
|
||||
*pi = prop.cooperativeMultiDeviceUnmatchedFunc;
|
||||
break;
|
||||
case hipDeviceAttributeCooperativeMultiDeviceUnmatchedGridDim:
|
||||
*pi = prop.cooperativeMultiDeviceUnmatchedGridDim;
|
||||
break;
|
||||
case hipDeviceAttributeCooperativeMultiDeviceUnmatchedBlockDim:
|
||||
*pi = prop.cooperativeMultiDeviceUnmatchedBlockDim;
|
||||
break;
|
||||
case hipDeviceAttributeCooperativeMultiDeviceUnmatchedSharedMem:
|
||||
*pi = prop.cooperativeMultiDeviceUnmatchedSharedMem;
|
||||
break;
|
||||
case hipDeviceAttributeAsicRevision:
|
||||
*pi = prop.asicRevision;
|
||||
break;
|
||||
case hipDeviceAttributeManagedMemory:
|
||||
*pi = prop.managedMemory;
|
||||
break;
|
||||
case hipDeviceAttributeDirectManagedMemAccessFromHost:
|
||||
*pi = prop.directManagedMemAccessFromHost;
|
||||
break;
|
||||
case hipDeviceAttributeConcurrentManagedAccess:
|
||||
*pi = prop.concurrentManagedAccess;
|
||||
break;
|
||||
case hipDeviceAttributePageableMemoryAccess:
|
||||
*pi = prop.pageableMemoryAccess;
|
||||
break;
|
||||
case hipDeviceAttributePageableMemoryAccessUsesHostPageTables:
|
||||
*pi = prop.pageableMemoryAccessUsesHostPageTables;
|
||||
break;
|
||||
case hipDeviceAttributeCanUseStreamWaitValue:
|
||||
// hipStreamWaitValue64() and hipStreamWaitValue32() support
|
||||
*pi = g_devices[device]->devices()[0]->info().aqlBarrierValue_;
|
||||
break;
|
||||
default:
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceGetByPCIBusId(int* device, const char*pciBusIdstr) {
|
||||
|
||||
HIP_INIT_API(hipDeviceGetByPCIBusId, device, pciBusIdstr);
|
||||
|
||||
if (device == nullptr || pciBusIdstr == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
int pciBusID = -1;
|
||||
int pciDeviceID = -1;
|
||||
int pciDomainID = -1;
|
||||
bool found = false;
|
||||
if (sscanf (pciBusIdstr, "%04x:%02x:%02x", &pciDomainID, &pciBusID, &pciDeviceID) == 0x3) {
|
||||
int count = 0;
|
||||
ihipDeviceGetCount(&count);
|
||||
for (cl_int i = 0; i < count; i++) {
|
||||
hipDevice_t dev;
|
||||
hipDeviceGet(&dev, i);
|
||||
hipDeviceProp_t prop;
|
||||
hipGetDeviceProperties(&prop, dev);
|
||||
|
||||
if ((pciBusID == prop.pciBusID) && (pciDomainID == prop.pciDomainID)
|
||||
&& (pciDeviceID == prop.pciDeviceID)) {
|
||||
*device = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceGetCacheConfig ( hipFuncCache_t * cacheConfig ) {
|
||||
HIP_INIT_API(hipDeviceGetCacheConfig, cacheConfig);
|
||||
|
||||
if(cacheConfig == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
*cacheConfig = hipFuncCache_t();
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceGetLimit ( size_t* pValue, hipLimit_t limit ) {
|
||||
|
||||
HIP_INIT_API(hipDeviceGetLimit, pValue, limit);
|
||||
|
||||
if(pValue == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
if(limit == hipLimitMallocHeapSize) {
|
||||
hipDeviceProp_t prop;
|
||||
hipGetDeviceProperties(&prop, ihipGetDevice());
|
||||
|
||||
*pValue = prop.totalGlobalMem;
|
||||
HIP_RETURN(hipSuccess);
|
||||
} else {
|
||||
HIP_RETURN(hipErrorUnsupportedLimit);
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t hipDeviceGetPCIBusId ( char* pciBusId, int len, int device ) {
|
||||
|
||||
HIP_INIT_API(hipDeviceGetPCIBusId, (void*)pciBusId, len, device);
|
||||
|
||||
int count;
|
||||
ihipDeviceGetCount(&count);
|
||||
if (device < 0 || device >= count) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
if (pciBusId == nullptr || len <= 0) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
hipDeviceProp_t prop;
|
||||
hipGetDeviceProperties(&prop, device);
|
||||
|
||||
snprintf (pciBusId, len, "%04x:%02x:%02x.0",
|
||||
prop.pciDomainID,
|
||||
prop.pciBusID,
|
||||
prop.pciDeviceID);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceGetSharedMemConfig ( hipSharedMemConfig * pConfig ) {
|
||||
HIP_INIT_API(hipDeviceGetSharedMemConfig, pConfig);
|
||||
if (pConfig == nullptr) {
|
||||
return HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
*pConfig = hipSharedMemBankSizeFourByte;
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceReset ( void ) {
|
||||
HIP_INIT_API(hipDeviceReset);
|
||||
|
||||
/* FIXME */
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceSetCacheConfig ( hipFuncCache_t cacheConfig ) {
|
||||
HIP_INIT_API(hipDeviceSetCacheConfig, cacheConfig);
|
||||
|
||||
// No way to set cache config yet.
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceSetLimit ( hipLimit_t limit, size_t value ) {
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceSetSharedMemConfig ( hipSharedMemConfig config ) {
|
||||
HIP_INIT_API(hipDeviceSetSharedMemConfig, config);
|
||||
|
||||
// No way to set cache config yet.
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceSynchronize ( void ) {
|
||||
HIP_INIT_API(hipDeviceSynchronize);
|
||||
|
||||
amd::HostQueue* queue = hip::getNullStream();
|
||||
|
||||
if (!queue) {
|
||||
HIP_RETURN(hipErrorOutOfMemory);
|
||||
}
|
||||
|
||||
queue->finish();
|
||||
|
||||
hip::Stream::syncNonBlockingStreams();
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
int ihipGetDevice() {
|
||||
hip::Device* device = hip::getCurrentDevice();
|
||||
if(device == nullptr){
|
||||
return -1;
|
||||
}
|
||||
return device->deviceId();
|
||||
}
|
||||
|
||||
hipError_t hipGetDevice ( int* deviceId ) {
|
||||
HIP_INIT_API(hipGetDevice, deviceId);
|
||||
|
||||
if (deviceId != nullptr) {
|
||||
int dev = ihipGetDevice();
|
||||
if (dev == -1) {
|
||||
HIP_RETURN(hipErrorNoDevice);
|
||||
}
|
||||
*deviceId = dev;
|
||||
HIP_RETURN(hipSuccess);
|
||||
} else {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t hipGetDeviceCount ( int* count ) {
|
||||
HIP_INIT_API(hipGetDeviceCount, count);
|
||||
|
||||
HIP_RETURN(ihipDeviceGetCount(count));
|
||||
}
|
||||
|
||||
hipError_t hipGetDeviceFlags ( unsigned int* flags ) {
|
||||
HIP_INIT_API(hipGetDeviceFlags, flags);
|
||||
if (flags == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
*flags = hip::getCurrentDevice()->getFlags();
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipSetDevice ( int device ) {
|
||||
HIP_INIT_API(hipSetDevice, device);
|
||||
|
||||
if (static_cast<unsigned int>(device) < g_devices.size()) {
|
||||
hip::setCurrentDevice(device);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
hipError_t hipSetDeviceFlags ( unsigned int flags ) {
|
||||
HIP_INIT_API(hipSetDeviceFlags, flags);
|
||||
|
||||
constexpr uint32_t supportedFlags =
|
||||
hipDeviceScheduleMask | hipDeviceMapHost | hipDeviceLmemResizeToMax;
|
||||
|
||||
if (flags & ~supportedFlags) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
amd::Device* device = hip::getCurrentDevice()->devices()[0];
|
||||
switch (flags & hipDeviceScheduleMask) {
|
||||
case hipDeviceScheduleAuto:
|
||||
// Current behavior is different from the spec, due to MT usage in runtime
|
||||
if (hip::host_device->devices().size() >= std::thread::hardware_concurrency()) {
|
||||
device->SetActiveWait(false);
|
||||
break;
|
||||
}
|
||||
// Fall through for active wait...
|
||||
case hipDeviceScheduleSpin:
|
||||
case hipDeviceScheduleYield:
|
||||
// The both options falls into yield, because MT usage in runtime
|
||||
device->SetActiveWait(true);
|
||||
break;
|
||||
case hipDeviceScheduleBlockingSync:
|
||||
device->SetActiveWait(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hip::getCurrentDevice()->setFlags(flags & hipDeviceScheduleMask);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipSetValidDevices ( int* device_arr, int len ) {
|
||||
HIP_INIT_API(hipSetValidDevices, device_arr, len);
|
||||
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
#include "hip_internal.hpp"
|
||||
|
||||
hipError_t hipGetLastError()
|
||||
{
|
||||
HIP_INIT_API(hipGetLastError);
|
||||
hipError_t err = hip::g_lastError;
|
||||
hip::g_lastError = hipSuccess;
|
||||
return err;
|
||||
}
|
||||
|
||||
hipError_t hipPeekAtLastError()
|
||||
{
|
||||
HIP_INIT_API(hipPeekAtLastError);
|
||||
hipError_t err = hip::g_lastError;
|
||||
HIP_RETURN(err);
|
||||
}
|
||||
|
||||
const char *hipGetErrorName(hipError_t hip_error)
|
||||
{
|
||||
switch (hip_error) {
|
||||
case hipSuccess:
|
||||
return "hipSuccess";
|
||||
case hipErrorInvalidValue:
|
||||
return "hipErrorInvalidValue";
|
||||
case hipErrorOutOfMemory:
|
||||
return "hipErrorOutOfMemory";
|
||||
case hipErrorNotInitialized:
|
||||
return "hipErrorNotInitialized";
|
||||
case hipErrorDeinitialized:
|
||||
return "hipErrorDeinitialized";
|
||||
case hipErrorProfilerDisabled:
|
||||
return "hipErrorProfilerDisabled";
|
||||
case hipErrorProfilerNotInitialized:
|
||||
return "hipErrorProfilerNotInitialized";
|
||||
case hipErrorProfilerAlreadyStarted:
|
||||
return "hipErrorProfilerAlreadyStarted";
|
||||
case hipErrorProfilerAlreadyStopped:
|
||||
return "hipErrorProfilerAlreadyStopped";
|
||||
case hipErrorInvalidConfiguration:
|
||||
return "hipErrorInvalidConfiguration";
|
||||
case hipErrorInvalidSymbol:
|
||||
return "hipErrorInvalidSymbol";
|
||||
case hipErrorInvalidDevicePointer:
|
||||
return "hipErrorInvalidDevicePointer";
|
||||
case hipErrorInvalidMemcpyDirection:
|
||||
return "hipErrorInvalidMemcpyDirection";
|
||||
case hipErrorInsufficientDriver:
|
||||
return "hipErrorInsufficientDriver";
|
||||
case hipErrorMissingConfiguration:
|
||||
return "hipErrorMissingConfiguration";
|
||||
case hipErrorPriorLaunchFailure:
|
||||
return "hipErrorPriorLaunchFailure";
|
||||
case hipErrorInvalidDeviceFunction:
|
||||
return "hipErrorInvalidDeviceFunction";
|
||||
case hipErrorNoDevice:
|
||||
return "hipErrorNoDevice";
|
||||
case hipErrorInvalidDevice:
|
||||
return "hipErrorInvalidDevice";
|
||||
case hipErrorInvalidPitchValue:
|
||||
return "hipErrorInvalidPitchValue";
|
||||
case hipErrorInvalidImage:
|
||||
return "hipErrorInvalidImage";
|
||||
case hipErrorInvalidContext:
|
||||
return "hipErrorInvalidContext";
|
||||
case hipErrorContextAlreadyCurrent:
|
||||
return "hipErrorContextAlreadyCurrent";
|
||||
case hipErrorMapFailed:
|
||||
return "hipErrorMapFailed";
|
||||
case hipErrorUnmapFailed:
|
||||
return "hipErrorUnmapFailed";
|
||||
case hipErrorArrayIsMapped:
|
||||
return "hipErrorArrayIsMapped";
|
||||
case hipErrorAlreadyMapped:
|
||||
return "hipErrorAlreadyMapped";
|
||||
case hipErrorNoBinaryForGpu:
|
||||
return "hipErrorNoBinaryForGpu";
|
||||
case hipErrorAlreadyAcquired:
|
||||
return "hipErrorAlreadyAcquired";
|
||||
case hipErrorNotMapped:
|
||||
return "hipErrorNotMapped";
|
||||
case hipErrorNotMappedAsArray:
|
||||
return "hipErrorNotMappedAsArray";
|
||||
case hipErrorNotMappedAsPointer:
|
||||
return "hipErrorNotMappedAsPointer";
|
||||
case hipErrorECCNotCorrectable:
|
||||
return "hipErrorECCNotCorrectable";
|
||||
case hipErrorUnsupportedLimit:
|
||||
return "hipErrorUnsupportedLimit";
|
||||
case hipErrorContextAlreadyInUse:
|
||||
return "hipErrorContextAlreadyInUse";
|
||||
case hipErrorPeerAccessUnsupported:
|
||||
return "hipErrorPeerAccessUnsupported";
|
||||
case hipErrorInvalidKernelFile:
|
||||
return "hipErrorInvalidKernelFile";
|
||||
case hipErrorInvalidGraphicsContext:
|
||||
return "hipErrorInvalidGraphicsContext";
|
||||
case hipErrorInvalidSource:
|
||||
return "hipErrorInvalidSource";
|
||||
case hipErrorFileNotFound:
|
||||
return "hipErrorFileNotFound";
|
||||
case hipErrorSharedObjectSymbolNotFound:
|
||||
return "hipErrorSharedObjectSymbolNotFound";
|
||||
case hipErrorSharedObjectInitFailed:
|
||||
return "hipErrorSharedObjectInitFailed";
|
||||
case hipErrorOperatingSystem:
|
||||
return "hipErrorOperatingSystem";
|
||||
case hipErrorInvalidHandle:
|
||||
return "hipErrorInvalidHandle";
|
||||
case hipErrorNotFound:
|
||||
return "hipErrorNotFound";
|
||||
case hipErrorNotReady:
|
||||
return "hipErrorNotReady";
|
||||
case hipErrorIllegalAddress:
|
||||
return "hipErrorIllegalAddress";
|
||||
case hipErrorLaunchOutOfResources:
|
||||
return "hipErrorLaunchOutOfResources";
|
||||
case hipErrorLaunchTimeOut:
|
||||
return "hipErrorLaunchTimeOut";
|
||||
case hipErrorPeerAccessAlreadyEnabled:
|
||||
return "hipErrorPeerAccessAlreadyEnabled";
|
||||
case hipErrorPeerAccessNotEnabled:
|
||||
return "hipErrorPeerAccessNotEnabled";
|
||||
case hipErrorSetOnActiveProcess:
|
||||
return "hipErrorSetOnActiveProcess";
|
||||
case hipErrorAssert:
|
||||
return "hipErrorAssert";
|
||||
case hipErrorHostMemoryAlreadyRegistered:
|
||||
return "hipErrorHostMemoryAlreadyRegistered";
|
||||
case hipErrorHostMemoryNotRegistered:
|
||||
return "hipErrorHostMemoryNotRegistered";
|
||||
case hipErrorLaunchFailure:
|
||||
return "hipErrorLaunchFailure";
|
||||
case hipErrorNotSupported:
|
||||
return "hipErrorNotSupported";
|
||||
case hipErrorUnknown:
|
||||
return "hipErrorUnknown";
|
||||
case hipErrorRuntimeMemory:
|
||||
return "hipErrorRuntimeMemory";
|
||||
case hipErrorRuntimeOther:
|
||||
return "hipErrorRuntimeOther";
|
||||
case hipErrorCooperativeLaunchTooLarge:
|
||||
return "hipErrorCooperativeLaunchTooLarge";
|
||||
case hipErrorTbd:
|
||||
return "hipErrorTbd";
|
||||
default:
|
||||
return "hipErrorUnknown";
|
||||
};
|
||||
}
|
||||
|
||||
const char *hipGetErrorString(hipError_t hip_error)
|
||||
{
|
||||
return hipGetErrorName(hip_error);
|
||||
}
|
||||
|
||||
Executable
+431
@@ -0,0 +1,431 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
#include "hip_event.hpp"
|
||||
|
||||
void ipcEventCallback(hipStream_t stream, hipError_t status, void* user_data)
|
||||
{
|
||||
std::atomic<int> *signal = reinterpret_cast<std::atomic<int>*>(user_data);
|
||||
signal->store(0);
|
||||
return;
|
||||
}
|
||||
|
||||
namespace hip {
|
||||
|
||||
bool Event::ready() {
|
||||
if (event_->status() != CL_COMPLETE) {
|
||||
event_->notifyCmdQueue();
|
||||
}
|
||||
|
||||
return (event_->status() == CL_COMPLETE);
|
||||
}
|
||||
|
||||
hipError_t Event::query() {
|
||||
amd::ScopedLock lock(lock_);
|
||||
|
||||
// If event is not recorded, event_ is null, hence return hipSuccess
|
||||
if (event_ == nullptr) {
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
return ready() ? hipSuccess : hipErrorNotReady;
|
||||
}
|
||||
|
||||
hipError_t Event::synchronize() {
|
||||
amd::ScopedLock lock(lock_);
|
||||
|
||||
// If event is not recorded, event_ is null, hence return hipSuccess
|
||||
if (event_ == nullptr) {
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
event_->awaitCompletion();
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t Event::elapsedTime(Event& eStop, float& ms) {
|
||||
amd::ScopedLock startLock(lock_);
|
||||
|
||||
if (this == &eStop) {
|
||||
if (event_ == nullptr) {
|
||||
return hipErrorInvalidHandle;
|
||||
}
|
||||
|
||||
if (flags & hipEventDisableTiming) {
|
||||
return hipErrorInvalidHandle;
|
||||
}
|
||||
|
||||
if (!ready()) {
|
||||
return hipErrorNotReady;
|
||||
}
|
||||
|
||||
ms = 0.f;
|
||||
return hipSuccess;
|
||||
}
|
||||
amd::ScopedLock stopLock(eStop.lock_);
|
||||
|
||||
if (event_ == nullptr ||
|
||||
eStop.event_ == nullptr) {
|
||||
return hipErrorInvalidHandle;
|
||||
}
|
||||
|
||||
if ((flags | eStop.flags) & hipEventDisableTiming) {
|
||||
return hipErrorInvalidHandle;
|
||||
}
|
||||
|
||||
if (!ready() || !eStop.ready()) {
|
||||
return hipErrorNotReady;
|
||||
}
|
||||
|
||||
if (event_ == eStop.event_ && recorded_ && eStop.recorded_) {
|
||||
// Events are the same, which indicates the stream is empty and likely
|
||||
// eventRecord is called on another stream. For such cases insert and measure a
|
||||
// marker.
|
||||
amd::Command* command = new amd::Marker(*event_->command().queue(), kMarkerDisableFlush);
|
||||
command->enqueue();
|
||||
command->awaitCompletion();
|
||||
ms = static_cast<float>(static_cast<int64_t>(command->event().profilingInfo().end_) - time())/1000000.f;
|
||||
command->release();
|
||||
} else {
|
||||
ms = static_cast<float>(eStop.time() - time())/1000000.f;
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
int64_t Event::time() const {
|
||||
assert(event_ != nullptr);
|
||||
if (recorded_) {
|
||||
return static_cast<int64_t>(event_->profilingInfo().end_);
|
||||
} else {
|
||||
return static_cast<int64_t>(event_->profilingInfo().start_);
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t Event::streamWait(amd::HostQueue* hostQueue, uint flags) {
|
||||
if ((event_ == nullptr) || (event_->command().queue() == hostQueue)) {
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
amd::ScopedLock lock(lock_);
|
||||
bool retain = false;
|
||||
|
||||
if (!event_->notifyCmdQueue()) {
|
||||
return hipErrorLaunchOutOfResources;
|
||||
}
|
||||
amd::Command::EventWaitList eventWaitList;
|
||||
eventWaitList.push_back(event_);
|
||||
|
||||
amd::Command* command = new amd::Marker(*hostQueue, kMarkerDisableFlush, eventWaitList);
|
||||
if (command == NULL) {
|
||||
return hipErrorOutOfMemory;
|
||||
}
|
||||
command->enqueue();
|
||||
command->release();
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
void Event::addMarker(amd::HostQueue* queue, amd::Command* command, bool record) {
|
||||
// Keep the lock always at the beginning of this to avoid a race. SWDEV-277847
|
||||
amd::ScopedLock lock(lock_);
|
||||
|
||||
if (command == nullptr) {
|
||||
bool recordExplicitGpuTs = !queue->properties().test(CL_QUEUE_PROFILING_ENABLE) &&
|
||||
!(flags & hipEventDisableTiming);
|
||||
// Always submit a EventMarker. This would submit a NOP with a signal.
|
||||
command = new hip::EventMarker(*queue, !kMarkerDisableFlush, recordExplicitGpuTs);
|
||||
command->enqueue();
|
||||
}
|
||||
|
||||
if (event_ == &command->event()) return;
|
||||
|
||||
if (event_ != nullptr) {
|
||||
event_->release();
|
||||
}
|
||||
|
||||
event_ = &command->event();
|
||||
recorded_ = record;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
hipError_t ihipEventCreateWithFlags(hipEvent_t* event, unsigned flags) {
|
||||
if (event == nullptr) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
#if !defined(_MSC_VER)
|
||||
unsigned supportedFlags = hipEventDefault | hipEventBlockingSync | hipEventDisableTiming |
|
||||
hipEventReleaseToDevice | hipEventReleaseToSystem | hipEventInterprocess;
|
||||
#else
|
||||
unsigned supportedFlags = hipEventDefault | hipEventBlockingSync | hipEventDisableTiming |
|
||||
hipEventReleaseToDevice | hipEventReleaseToSystem;
|
||||
#endif
|
||||
const unsigned releaseFlags = (hipEventReleaseToDevice | hipEventReleaseToSystem);
|
||||
|
||||
const bool illegalFlags =
|
||||
(flags & ~supportedFlags) || // can't set any unsupported flags.
|
||||
(flags & releaseFlags) == releaseFlags; // can't set both release flags
|
||||
|
||||
if (!illegalFlags) {
|
||||
hip::Event* e = new hip::Event(flags);
|
||||
if (e == nullptr) {
|
||||
return hipErrorOutOfMemory;
|
||||
}
|
||||
*event = reinterpret_cast<hipEvent_t>(e);
|
||||
} else {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t ihipEventQuery(hipEvent_t event) {
|
||||
if (event == nullptr) {
|
||||
return hipErrorInvalidHandle;
|
||||
}
|
||||
|
||||
hip::Event* e = reinterpret_cast<hip::Event*>(event);
|
||||
if ((e->flags & hipEventInterprocess) && (e->ipc_evt_.ipc_shmem_)) {
|
||||
int prev_read_idx = e->ipc_evt_.ipc_shmem_->read_index;
|
||||
int offset = (prev_read_idx % IPC_SIGNALS_PER_EVENT);
|
||||
if (e->ipc_evt_.ipc_shmem_->read_index < prev_read_idx+IPC_SIGNALS_PER_EVENT && e->ipc_evt_.ipc_shmem_->signal[offset] != 0) {
|
||||
return hipErrorNotReady;
|
||||
}
|
||||
return hipSuccess;
|
||||
} else {
|
||||
return e->query();
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t hipEventCreateWithFlags(hipEvent_t* event, unsigned flags) {
|
||||
HIP_INIT_API(hipEventCreateWithFlags, event, flags);
|
||||
HIP_RETURN(ihipEventCreateWithFlags(event, flags), *event);
|
||||
}
|
||||
|
||||
hipError_t hipEventCreate(hipEvent_t* event) {
|
||||
HIP_INIT_API(hipEventCreate, event);
|
||||
HIP_RETURN(ihipEventCreateWithFlags(event, 0), *event);
|
||||
}
|
||||
|
||||
hipError_t hipEventDestroy(hipEvent_t event) {
|
||||
HIP_INIT_API(hipEventDestroy, event);
|
||||
|
||||
if (event == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidHandle);
|
||||
}
|
||||
|
||||
hip::Event* e = reinterpret_cast<hip::Event*>(event);
|
||||
if ((e->flags & hipEventInterprocess) && (e->ipc_evt_.ipc_shmem_)) {
|
||||
int owners = -- e->ipc_evt_.ipc_shmem_->owners;
|
||||
// Make sure event is synchronized
|
||||
hipEventSynchronize(event);
|
||||
if (!amd::Os::MemoryUnmapFile(e->ipc_evt_.ipc_shmem_,sizeof(hip::ihipIpcEventShmem_t))) {
|
||||
HIP_RETURN(hipErrorInvalidHandle);
|
||||
}
|
||||
}
|
||||
delete e;
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipEventElapsedTime(float *ms, hipEvent_t start, hipEvent_t stop) {
|
||||
HIP_INIT_API(hipEventElapsedTime, ms, start, stop);
|
||||
|
||||
if (start == nullptr || stop == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidHandle);
|
||||
}
|
||||
|
||||
if (ms == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
hip::Event* eStart = reinterpret_cast<hip::Event*>(start);
|
||||
hip::Event* eStop = reinterpret_cast<hip::Event*>(stop);
|
||||
|
||||
if (eStart->deviceId() != eStop->deviceId()) {
|
||||
HIP_RETURN(hipErrorInvalidHandle);
|
||||
}
|
||||
|
||||
HIP_RETURN(eStart->elapsedTime(*eStop, *ms), "Elapsed Time = ", *ms);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool createIpcEventShmemIfNeeded(hip::Event::ihipIpcEvent_t& ipc_evt) {
|
||||
#if !defined(_MSC_VER)
|
||||
if (ipc_evt.ipc_shmem_) {
|
||||
// ipc_shmem_ already created, no need to create it again
|
||||
return true;
|
||||
}
|
||||
char name_template[] = "/tmp/eventXXXXXX";
|
||||
int temp_fd = mkstemp(name_template);
|
||||
|
||||
ipc_evt.ipc_name_ = name_template;
|
||||
ipc_evt.ipc_name_.replace(0, 5, "/hip_");
|
||||
if (!amd::Os::MemoryMapFileTruncated(ipc_evt.ipc_name_.c_str(),
|
||||
const_cast<const void**> (reinterpret_cast<void**>(&(ipc_evt.ipc_shmem_))), sizeof(hip::ihipIpcEventShmem_t))) {
|
||||
return false;
|
||||
}
|
||||
ipc_evt.ipc_shmem_->owners = 1;
|
||||
ipc_evt.ipc_shmem_->read_index = -1;
|
||||
ipc_evt.ipc_shmem_->write_index = 0;
|
||||
for (uint32_t sig_idx = 0; sig_idx < IPC_SIGNALS_PER_EVENT; ++sig_idx) {
|
||||
ipc_evt.ipc_shmem_->signal[sig_idx] = 0;
|
||||
}
|
||||
|
||||
close(temp_fd);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
hipError_t hipEventRecord(hipEvent_t event, hipStream_t stream) {
|
||||
HIP_INIT_API(hipEventRecord, event, stream);
|
||||
|
||||
STREAM_CAPTURE(hipEventRecord, stream, event);
|
||||
|
||||
if (event == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidHandle);
|
||||
}
|
||||
|
||||
hip::Event* e = reinterpret_cast<hip::Event*>(event);
|
||||
|
||||
amd::HostQueue* queue = hip::getQueue(stream);
|
||||
|
||||
if (g_devices[e->deviceId()]->devices()[0] != &queue->device()) {
|
||||
HIP_RETURN(hipErrorInvalidHandle);
|
||||
}
|
||||
|
||||
bool isRecorded = e->isRecorded();
|
||||
if ((e->flags & hipEventInterprocess) && !isRecorded) {
|
||||
amd::Command* command = new amd::Marker(*queue, kMarkerDisableFlush);
|
||||
amd::Event& tEvent = command->event();
|
||||
createIpcEventShmemIfNeeded(e->ipc_evt_);
|
||||
int write_index = e->ipc_evt_.ipc_shmem_->write_index++;
|
||||
int offset = write_index % IPC_SIGNALS_PER_EVENT;
|
||||
while (e->ipc_evt_.ipc_shmem_->signal[offset] != 0) {
|
||||
amd::Os::sleep(1);
|
||||
}
|
||||
// Lock signal.
|
||||
e->ipc_evt_.ipc_shmem_->signal[offset] = 1;
|
||||
e->ipc_evt_.ipc_shmem_->owners_device_id = e->deviceId();
|
||||
|
||||
std::atomic<int> *signal = &e->ipc_evt_.ipc_shmem_->signal[offset];
|
||||
StreamCallback* cbo = new StreamCallback(stream,
|
||||
reinterpret_cast<hipStreamCallback_t> (ipcEventCallback), signal, command);
|
||||
if (!tEvent.setCallback(CL_COMPLETE, ihipStreamCallback,cbo)) {
|
||||
command->release();
|
||||
return hipErrorInvalidHandle;
|
||||
}
|
||||
command->enqueue();
|
||||
tEvent.notifyCmdQueue();
|
||||
// Update read index to indicate new signal.
|
||||
int expected = write_index - 1;
|
||||
while (!e->ipc_evt_.ipc_shmem_->read_index.compare_exchange_weak(expected, write_index)) {
|
||||
amd::Os::sleep(1);
|
||||
}
|
||||
} else {
|
||||
e->addMarker(queue, nullptr, true);
|
||||
}
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipEventSynchronize(hipEvent_t event) {
|
||||
HIP_INIT_API(hipEventSynchronize, event);
|
||||
|
||||
if (event == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidHandle);
|
||||
}
|
||||
|
||||
hip::Event* e = reinterpret_cast<hip::Event*>(event);
|
||||
if ((e->flags & hipEventInterprocess) && (e->ipc_evt_.ipc_shmem_)) {
|
||||
int prev_read_idx = e->ipc_evt_.ipc_shmem_->read_index;
|
||||
if (prev_read_idx >= 0) {
|
||||
int offset = (prev_read_idx % IPC_SIGNALS_PER_EVENT);
|
||||
while ((e->ipc_evt_.ipc_shmem_->read_index < prev_read_idx + IPC_SIGNALS_PER_EVENT)
|
||||
&& (e->ipc_evt_.ipc_shmem_->signal[offset] != 0)) {
|
||||
amd::Os::sleep(1);
|
||||
}
|
||||
}
|
||||
HIP_RETURN(hipSuccess);
|
||||
} else {
|
||||
HIP_RETURN(e->synchronize());
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t hipEventQuery(hipEvent_t event) {
|
||||
HIP_INIT_API(hipEventQuery, event);
|
||||
HIP_RETURN(ihipEventQuery(event));
|
||||
}
|
||||
|
||||
hipError_t hipIpcGetEventHandle(hipIpcEventHandle_t* handle, hipEvent_t event) {
|
||||
HIP_INIT_API(hipIpcGetEventHandle, handle, event);
|
||||
#if !defined(_MSC_VER)
|
||||
if (handle == nullptr || event == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
hip::Event* e = reinterpret_cast<hip::Event*>(event);
|
||||
if (!(e->flags & hipEventInterprocess)) {
|
||||
HIP_RETURN(hipErrorInvalidConfiguration);
|
||||
}
|
||||
if (!createIpcEventShmemIfNeeded(e->ipc_evt_)) {
|
||||
HIP_RETURN(hipErrorInvalidConfiguration);
|
||||
}
|
||||
ihipIpcEventHandle_t* iHandle = reinterpret_cast<ihipIpcEventHandle_t*>(handle);
|
||||
memset(iHandle->shmem_name, 0, HIP_IPC_HANDLE_SIZE);
|
||||
e->ipc_evt_.ipc_name_.copy(iHandle->shmem_name, std::string::npos);
|
||||
HIP_RETURN(hipSuccess);
|
||||
#else
|
||||
assert(0 && "Unimplemented");
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
#endif
|
||||
}
|
||||
|
||||
hipError_t hipIpcOpenEventHandle(hipEvent_t* event, hipIpcEventHandle_t handle) {
|
||||
HIP_INIT_API(NONE, event, handle);
|
||||
#if !defined(_MSC_VER)
|
||||
hipError_t hip_err = hipSuccess;
|
||||
if (event == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
hip_err = ihipEventCreateWithFlags(event, hipEventDisableTiming | hipEventInterprocess);
|
||||
if (hip_err != hipSuccess) {
|
||||
HIP_RETURN(hip_err);
|
||||
}
|
||||
hip::Event* e = reinterpret_cast<hip::Event*>(*event);
|
||||
ihipIpcEventHandle_t* iHandle = reinterpret_cast<ihipIpcEventHandle_t*>(&handle);
|
||||
hip::Event::ihipIpcEvent_t& ipc_evt = e->ipc_evt_;
|
||||
ipc_evt.ipc_name_ = iHandle->shmem_name;
|
||||
if (!amd::Os::MemoryMapFileTruncated(ipc_evt.ipc_name_.c_str(),
|
||||
(const void**) &(ipc_evt.ipc_shmem_), sizeof(hip::ihipIpcEventShmem_t))) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
ipc_evt.ipc_shmem_->owners += 1;
|
||||
e->setDeviceId(ipc_evt.ipc_shmem_->owners_device_id.load());
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
#else
|
||||
assert(0 && "Unimplemented");
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef HIP_EVENT_H
|
||||
#define HIP_EVENT_H
|
||||
|
||||
#include "hip_internal.hpp"
|
||||
#include "thread/monitor.hpp"
|
||||
|
||||
// Internal structure for stream callback handler
|
||||
class StreamCallback {
|
||||
public:
|
||||
StreamCallback(hipStream_t stream, hipStreamCallback_t callback, void* userData,
|
||||
amd::Command* command)
|
||||
: stream_(stream), callBack_(callback),
|
||||
userData_(userData), command_(command) {
|
||||
};
|
||||
hipStream_t stream_;
|
||||
hipStreamCallback_t callBack_;
|
||||
void* userData_;
|
||||
amd::Command* command_;
|
||||
};
|
||||
|
||||
void CL_CALLBACK ihipStreamCallback(cl_event event, cl_int command_exec_status, void* user_data);
|
||||
|
||||
|
||||
namespace hip {
|
||||
|
||||
class EventMarker: public amd::Marker {
|
||||
public:
|
||||
EventMarker(amd::HostQueue& queue, bool disableFlush, bool markerTs = false)
|
||||
: amd::Marker(queue, disableFlush) {
|
||||
profilingInfo_.enabled_ = true;
|
||||
profilingInfo_.callback_ = nullptr;
|
||||
profilingInfo_.marker_ts_ = markerTs;
|
||||
profilingInfo_.clear();
|
||||
}
|
||||
};
|
||||
|
||||
#define IPC_SIGNALS_PER_EVENT 32
|
||||
typedef struct ihipIpcEventShmem_s {
|
||||
std::atomic<int> owners;
|
||||
std::atomic<int> owners_device_id;
|
||||
std::atomic<int> read_index;
|
||||
std::atomic<int> write_index;
|
||||
std::atomic<int> signal[IPC_SIGNALS_PER_EVENT];
|
||||
} ihipIpcEventShmem_t;
|
||||
|
||||
class Event {
|
||||
/// event recorded on stream where capture is active
|
||||
bool onCapture_;
|
||||
/// capture stream where event is recorded
|
||||
hipStream_t captureStream_;
|
||||
/// Previous captured nodes before event record
|
||||
std::vector<hipGraphNode_t> nodesPrevToRecorded_;
|
||||
|
||||
public:
|
||||
Event(unsigned int flags) : flags(flags), lock_("hipEvent_t", true),
|
||||
event_(nullptr), recorded_(false) {
|
||||
// No need to init event_ here as addMarker does that
|
||||
onCapture_ = false;
|
||||
device_id_ = hip::getCurrentDevice()->deviceId(); // Created in current device ctx
|
||||
}
|
||||
|
||||
~Event() {
|
||||
if (event_ != nullptr) {
|
||||
event_->release();
|
||||
}
|
||||
}
|
||||
unsigned int flags;
|
||||
|
||||
hipError_t query();
|
||||
hipError_t synchronize();
|
||||
hipError_t elapsedTime(Event& stop, float& ms);
|
||||
hipError_t streamWait(amd::HostQueue* queue, uint flags);
|
||||
|
||||
void addMarker(amd::HostQueue* queue, amd::Command* command, bool record);
|
||||
bool isRecorded() { return recorded_; }
|
||||
amd::Monitor& lock() { return lock_; }
|
||||
const int deviceId() { return device_id_; }
|
||||
void setDeviceId(int id) { device_id_ = id; }
|
||||
|
||||
/// End capture on this event
|
||||
void EndCapture() {
|
||||
onCapture_ = false;
|
||||
captureStream_ = nullptr;
|
||||
}
|
||||
/// Start capture when waited on this event
|
||||
void StartCapture(hipStream_t stream) {
|
||||
onCapture_ = true;
|
||||
captureStream_ = stream;
|
||||
}
|
||||
/// Get capture status of the graph
|
||||
bool GetCaptureStatus() { return onCapture_; }
|
||||
/// Get capture stream where event is recorded
|
||||
hipStream_t GetCaptureStream() { return captureStream_; }
|
||||
/// Set capture stream where event is recorded
|
||||
void SetCaptureStream(hipStream_t stream) { captureStream_ = stream; }
|
||||
/// Returns previous captured nodes before event record
|
||||
std::vector<hipGraphNode_t> GetNodesPrevToRecorded() const { return nodesPrevToRecorded_; }
|
||||
/// Set last captured graph node before event record
|
||||
void SetNodesPrevToRecorded(std::vector<hipGraphNode_t>& graphNode) {
|
||||
nodesPrevToRecorded_ = graphNode;
|
||||
}
|
||||
|
||||
// IPC Events
|
||||
struct ihipIpcEvent_t {
|
||||
std::string ipc_name_;
|
||||
int ipc_fd_;
|
||||
ihipIpcEventShmem_t* ipc_shmem_;
|
||||
ihipIpcEvent_t(): ipc_name_("dummy"), ipc_fd_(0), ipc_shmem_(nullptr) {
|
||||
}
|
||||
void setipcname(const char* name) {
|
||||
ipc_name_ = std::string(name);
|
||||
}
|
||||
};
|
||||
ihipIpcEvent_t ipc_evt_;
|
||||
private:
|
||||
amd::Monitor lock_;
|
||||
amd::HostQueue* stream_;
|
||||
amd::Event* event_;
|
||||
int device_id_;
|
||||
//! Flag to indicate hipEventRecord has been called. This is needed except for
|
||||
//! hip*ModuleLaunchKernel API which takes start and stop events so no
|
||||
//! hipEventRecord is called. Cleanup needed once those APIs are deprecated.
|
||||
bool recorded_;
|
||||
|
||||
bool ready();
|
||||
int64_t time() const;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif // HIP_EVEMT_H
|
||||
Executable
+158
@@ -0,0 +1,158 @@
|
||||
#include "hip_fatbin.hpp"
|
||||
|
||||
#include "hip_code_object.hpp"
|
||||
|
||||
namespace hip {
|
||||
|
||||
FatBinaryDeviceInfo::~FatBinaryDeviceInfo() {
|
||||
if (program_ != nullptr) {
|
||||
program_->release();
|
||||
program_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
FatBinaryInfo::FatBinaryInfo(const char* fname, const void* image)
|
||||
: fdesc_(amd::Os::FDescInit()), fsize_(0), image_(image), uri_(std::string()) {
|
||||
|
||||
if (fname != nullptr) {
|
||||
fname_ = std::string(fname);
|
||||
} else {
|
||||
fname_ = std::string();
|
||||
}
|
||||
|
||||
fatbin_dev_info_.resize(g_devices.size());
|
||||
}
|
||||
|
||||
FatBinaryInfo::~FatBinaryInfo() {
|
||||
|
||||
for (auto& fbd: fatbin_dev_info_) {
|
||||
delete fbd;
|
||||
}
|
||||
|
||||
if (fdesc_ > 0) {
|
||||
if (fsize_ && !amd::Os::MemoryUnmapFile(image_, fsize_)) {
|
||||
guarantee(false, "Cannot unmap file");
|
||||
}
|
||||
if (!amd::Os::CloseFileHandle(fdesc_)) {
|
||||
guarantee(false, "Cannot close file");
|
||||
}
|
||||
}
|
||||
|
||||
fname_ = std::string();
|
||||
fdesc_ = amd::Os::FDescInit();
|
||||
fsize_ = 0;
|
||||
image_ = nullptr;
|
||||
uri_ = std::string();
|
||||
}
|
||||
|
||||
hipError_t FatBinaryInfo::ExtractFatBinary(const std::vector<hip::Device*>& devices) {
|
||||
hipError_t hip_error = hipSuccess;
|
||||
std::vector<std::pair<const void*, size_t>> code_objs;
|
||||
|
||||
// Copy device names for Extract Code object File
|
||||
std::vector<std::string> device_names;
|
||||
device_names.reserve(devices.size());
|
||||
for (size_t dev_idx = 0; dev_idx < devices.size(); ++dev_idx) {
|
||||
device_names.push_back(devices[dev_idx]->devices()[0]->isa().isaName());
|
||||
}
|
||||
|
||||
// We are given file name, get the file desc and file size
|
||||
if (fname_.size() > 0) {
|
||||
// Get File Handle & size of the file.
|
||||
if (!amd::Os::GetFileHandle(fname_.c_str(), &fdesc_, &fsize_)) {
|
||||
return hipErrorFileNotFound;
|
||||
}
|
||||
if (fsize_ == 0) {
|
||||
return hipErrorInvalidKernelFile;
|
||||
}
|
||||
|
||||
// Extract the code object from file
|
||||
hip_error = CodeObject::ExtractCodeObjectFromFile(fdesc_, fsize_, &image_,
|
||||
device_names, code_objs);
|
||||
|
||||
} else if (image_ != nullptr) {
|
||||
// We are directly given image pointer directly, try to extract file desc & file Size
|
||||
hip_error = CodeObject::ExtractCodeObjectFromMemory(image_,
|
||||
device_names, code_objs, uri_);
|
||||
} else {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
if (hip_error == hipErrorNoBinaryForGpu) {
|
||||
guarantee(false, "hipErrorNoBinaryForGpu: Couldn't find binary for current devices!");
|
||||
return hip_error;
|
||||
}
|
||||
|
||||
if (hip_error == hipErrorInvalidKernelFile) {
|
||||
for (size_t dev_idx = 0; dev_idx < devices.size(); ++dev_idx) {
|
||||
// the image type is no CLANG_OFFLOAD_BUNDLER, image for current device directly passed
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]
|
||||
= new FatBinaryDeviceInfo(image_, CodeObject::ElfSize(image_), 0);
|
||||
}
|
||||
} else if(hip_error == hipSuccess) {
|
||||
for (size_t dev_idx = 0; dev_idx < devices.size(); ++dev_idx) {
|
||||
// Calculate the offset wrt binary_image and the original image
|
||||
size_t offset_l
|
||||
= (reinterpret_cast<address>(const_cast<void*>(code_objs[dev_idx].first))
|
||||
- reinterpret_cast<address>(const_cast<void*>(image_)));
|
||||
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]
|
||||
= new FatBinaryDeviceInfo(code_objs[dev_idx].first, code_objs[dev_idx].second, offset_l);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t dev_idx = 0; dev_idx < devices.size(); ++dev_idx) {
|
||||
fatbin_dev_info_[devices[dev_idx]->deviceId()]->program_
|
||||
= new amd::Program(*devices[dev_idx]->asContext());
|
||||
if (fatbin_dev_info_[devices[dev_idx]->deviceId()]->program_ == NULL) {
|
||||
return hipErrorOutOfMemory;
|
||||
}
|
||||
}
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t FatBinaryInfo::AddDevProgram(const int device_id) {
|
||||
// Device Id bounds Check
|
||||
DeviceIdCheck(device_id);
|
||||
|
||||
FatBinaryDeviceInfo* fbd_info = fatbin_dev_info_[device_id];
|
||||
// If fat binary was already added, skip this step and return success
|
||||
if (fbd_info->add_dev_prog_ == false) {
|
||||
amd::Context* ctx = g_devices[device_id]->asContext();
|
||||
if (CL_SUCCESS != fbd_info->program_->addDeviceProgram(*ctx->devices()[0],
|
||||
fbd_info->binary_image_,
|
||||
fbd_info->binary_size_, false,
|
||||
nullptr, nullptr, fdesc_,
|
||||
fbd_info->binary_offset_, uri_)) {
|
||||
return hipErrorInvalidKernelFile;
|
||||
}
|
||||
fbd_info->add_dev_prog_ = true;
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t FatBinaryInfo::BuildProgram(const int device_id) {
|
||||
|
||||
// Device Id Check and Add DeviceProgram if not added so far
|
||||
DeviceIdCheck(device_id);
|
||||
IHIP_RETURN_ONFAIL(AddDevProgram(device_id));
|
||||
|
||||
// If Program was already built skip this step and return success
|
||||
FatBinaryDeviceInfo* fbd_info = fatbin_dev_info_[device_id];
|
||||
if (fbd_info->prog_built_ == false) {
|
||||
if(CL_SUCCESS != fbd_info->program_->build(g_devices[device_id]->devices(),
|
||||
nullptr, nullptr, nullptr,
|
||||
kOptionChangeable, kNewDevProg)) {
|
||||
return hipErrorSharedObjectInitFailed;
|
||||
}
|
||||
fbd_info->prog_built_ = true;
|
||||
}
|
||||
|
||||
if (!fbd_info->program_->load()) {
|
||||
return hipErrorSharedObjectInitFailed;
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
} //namespace : hip
|
||||
Executable
@@ -0,0 +1,87 @@
|
||||
#ifndef HIP_FAT_BINARY_HPP
|
||||
#define HIP_FAT_BINARY_HPP
|
||||
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "hip/hip_runtime_api.h"
|
||||
#include "hip_internal.hpp"
|
||||
#include "platform/program.hpp"
|
||||
|
||||
namespace hip {
|
||||
|
||||
//Fat Binary Per Device info
|
||||
class FatBinaryDeviceInfo {
|
||||
public:
|
||||
FatBinaryDeviceInfo (const void* binary_image, size_t binary_size, size_t binary_offset)
|
||||
: binary_image_(binary_image), binary_size_(binary_size),
|
||||
binary_offset_(binary_offset), program_(nullptr),
|
||||
add_dev_prog_(false), prog_built_(false) {}
|
||||
|
||||
~FatBinaryDeviceInfo();
|
||||
|
||||
private:
|
||||
const void* binary_image_; // binary image ptr
|
||||
size_t binary_size_; // binary image size
|
||||
size_t binary_offset_; // image offset from original
|
||||
|
||||
amd::Program* program_; // reinterpreted as hipModule_t
|
||||
friend class FatBinaryInfo;
|
||||
|
||||
//Control Variables
|
||||
bool add_dev_prog_;
|
||||
bool prog_built_;
|
||||
};
|
||||
|
||||
|
||||
// Fat Binary Info
|
||||
class FatBinaryInfo {
|
||||
public:
|
||||
FatBinaryInfo(const char* fname, const void* image);
|
||||
~FatBinaryInfo();
|
||||
|
||||
// Loads Fat binary from file or image, unbundles COs for devices.
|
||||
hipError_t ExtractFatBinary(const std::vector<hip::Device*>& devices);
|
||||
hipError_t AddDevProgram(const int device_id);
|
||||
hipError_t BuildProgram(const int device_id);
|
||||
|
||||
|
||||
// Device Id bounds check
|
||||
inline void DeviceIdCheck(const int device_id) const {
|
||||
guarantee(device_id >= 0, "Invalid DeviceId less than 0");
|
||||
guarantee(static_cast<size_t>(device_id) < fatbin_dev_info_.size(), "Invalid DeviceId, greater than no of fatbin device info!");
|
||||
}
|
||||
|
||||
// Getter Methods
|
||||
amd::Program* GetProgram(int device_id) {
|
||||
DeviceIdCheck(device_id);
|
||||
return fatbin_dev_info_[device_id]->program_;
|
||||
}
|
||||
|
||||
hipModule_t Module(int device_id) const {
|
||||
DeviceIdCheck(device_id);
|
||||
return reinterpret_cast<hipModule_t>(as_cl(fatbin_dev_info_[device_id]->program_));
|
||||
}
|
||||
|
||||
hipError_t GetModule(int device_id, hipModule_t* hmod) const {
|
||||
DeviceIdCheck(device_id);
|
||||
*hmod = reinterpret_cast<hipModule_t>(as_cl(fatbin_dev_info_[device_id]->program_));
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string fname_; // File name
|
||||
amd::Os::FileDesc fdesc_; // File descriptor
|
||||
size_t fsize_; // Total file size
|
||||
|
||||
// Even when file is passed image will be mmapped till ~desctructor.
|
||||
const void* image_; // Image
|
||||
|
||||
// Only used for FBs where image is directly passed
|
||||
std::string uri_; // Uniform resource indicator
|
||||
|
||||
// Per Device Info, like corresponding binary ptr, size.
|
||||
std::vector<FatBinaryDeviceInfo*> fatbin_dev_info_;
|
||||
};
|
||||
|
||||
}; /* namespace hip */
|
||||
|
||||
#endif /* HIP_FAT_BINARY_HPP */
|
||||
@@ -0,0 +1,853 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
#include <hip/hiprtc.h>
|
||||
#include <hip/hip_runtime_api.h>
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipTextureFilterMode& s) {
|
||||
switch (s) {
|
||||
case hipFilterModePoint:
|
||||
os << "hipFilterModePoint";
|
||||
break;
|
||||
case hipFilterModeLinear:
|
||||
os << "hipFilterModeLinear";
|
||||
break;
|
||||
default:
|
||||
os << "hipFilterModePoint";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipTextureReadMode& s) {
|
||||
switch (s) {
|
||||
case hipReadModeElementType:
|
||||
os << "hipReadModeElementType";
|
||||
break;
|
||||
case hipReadModeNormalizedFloat:
|
||||
os << "hipReadModeNormalizedFloat";
|
||||
break;
|
||||
default:
|
||||
os << "hipReadModeElementType";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipTextureAddressMode& s) {
|
||||
switch (s) {
|
||||
case hipAddressModeWrap:
|
||||
os << "hipAddressModeWrap";
|
||||
break;
|
||||
case hipAddressModeClamp:
|
||||
os << "hipAddressModeClamp";
|
||||
break;
|
||||
case hipAddressModeMirror:
|
||||
os << "hipAddressModeMirror";
|
||||
break;
|
||||
case hipAddressModeBorder:
|
||||
os << "hipAddressModeBorder";
|
||||
break;
|
||||
default:
|
||||
os << "hipAddressModeWrap";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipMemcpyKind& s) {
|
||||
switch (s) {
|
||||
case hipMemcpyHostToHost:
|
||||
os << "hipMemcpyHostToHost";
|
||||
break;
|
||||
case hipMemcpyHostToDevice:
|
||||
os << "hipMemcpyHostToDevice";
|
||||
break;
|
||||
case hipMemcpyDeviceToHost:
|
||||
os << "hipMemcpyDeviceToHost";
|
||||
break;
|
||||
case hipMemcpyDeviceToDevice:
|
||||
os << "hipMemcpyDeviceToDevice";
|
||||
break;
|
||||
case hipMemcpyDefault:
|
||||
os << "hipMemcpyDefault";
|
||||
break;
|
||||
default:
|
||||
os << "hipMemcpyDefault";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipChannelFormatKind& s) {
|
||||
switch (s) {
|
||||
case hipChannelFormatKindSigned:
|
||||
os << "hipChannelFormatKindSigned";
|
||||
break;
|
||||
case hipChannelFormatKindUnsigned:
|
||||
os << "hipMemcpyHostToDevice";
|
||||
break;
|
||||
case hipChannelFormatKindFloat:
|
||||
os << "hipChannelFormatKindFloat";
|
||||
break;
|
||||
case hipChannelFormatKindNone:
|
||||
os << "hipChannelFormatKindNone";
|
||||
break;
|
||||
default:
|
||||
os << "hipChannelFormatKindNone";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipArray_Format& s) {
|
||||
switch (s) {
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT8:
|
||||
os << "HIP_AD_FORMAT_UNSIGNED_INT8";
|
||||
break;
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT16:
|
||||
os << "HIP_AD_FORMAT_UNSIGNED_INT16";
|
||||
break;
|
||||
case HIP_AD_FORMAT_UNSIGNED_INT32:
|
||||
os << "HIP_AD_FORMAT_UNSIGNED_INT32";
|
||||
break;
|
||||
case HIP_AD_FORMAT_SIGNED_INT8:
|
||||
os << "HIP_AD_FORMAT_SIGNED_INT8";
|
||||
break;
|
||||
case HIP_AD_FORMAT_SIGNED_INT16:
|
||||
os << "HIP_AD_FORMAT_SIGNED_INT16";
|
||||
break;
|
||||
case HIP_AD_FORMAT_SIGNED_INT32:
|
||||
os << "HIP_AD_FORMAT_SIGNED_INT32";
|
||||
break;
|
||||
case HIP_AD_FORMAT_HALF:
|
||||
os << "HIP_AD_FORMAT_HALF";
|
||||
break;
|
||||
case HIP_AD_FORMAT_FLOAT:
|
||||
os << "HIP_AD_FORMAT_FLOAT";
|
||||
break;
|
||||
default:
|
||||
os << "HIP_AD_FORMAT_FLOAT";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipResourceViewFormat& s) {
|
||||
switch (s) {
|
||||
case hipResViewFormatNone:
|
||||
os << "hipResViewFormatNone";
|
||||
break;
|
||||
case hipResViewFormatUnsignedChar1:
|
||||
os << "hipResViewFormatUnsignedChar1";
|
||||
break;
|
||||
case hipResViewFormatUnsignedChar2:
|
||||
os << "hipResViewFormatUnsignedChar2";
|
||||
break;
|
||||
case hipResViewFormatUnsignedChar4:
|
||||
os << "hipResViewFormatUnsignedChar4";
|
||||
break;
|
||||
case hipResViewFormatSignedChar1:
|
||||
os << "hipResViewFormatSignedChar1";
|
||||
break;
|
||||
case hipResViewFormatSignedChar2:
|
||||
os << "hipResViewFormatSignedChar2";
|
||||
break;
|
||||
case hipResViewFormatSignedChar4:
|
||||
os << "hipResViewFormatSignedChar4";
|
||||
break;
|
||||
case hipResViewFormatUnsignedShort1:
|
||||
os << "hipResViewFormatUnsignedShort1";
|
||||
break;
|
||||
case hipResViewFormatUnsignedShort2:
|
||||
os << "hipResViewFormatUnsignedShort2";
|
||||
break;
|
||||
case hipResViewFormatUnsignedShort4:
|
||||
os << "hipResViewFormatUnsignedShort4";
|
||||
break;
|
||||
case hipResViewFormatSignedShort1:
|
||||
os << "hipResViewFormatSignedShort1";
|
||||
break;
|
||||
case hipResViewFormatSignedShort2:
|
||||
os << "hipResViewFormatSignedShort2";
|
||||
break;
|
||||
case hipResViewFormatSignedShort4:
|
||||
os << "hipResViewFormatSignedShort4";
|
||||
break;
|
||||
case hipResViewFormatUnsignedInt1:
|
||||
os << "hipResViewFormatUnsignedInt1";
|
||||
break;
|
||||
case hipResViewFormatUnsignedInt2:
|
||||
os << "hipResViewFormatUnsignedInt2";
|
||||
break;
|
||||
case hipResViewFormatUnsignedInt4:
|
||||
os << "hipResViewFormatUnsignedInt4";
|
||||
break;
|
||||
case hipResViewFormatSignedInt1:
|
||||
os << "hipResViewFormatSignedInt1";
|
||||
break;
|
||||
case hipResViewFormatSignedInt2:
|
||||
os << "hipResViewFormatSignedInt2";
|
||||
break;
|
||||
case hipResViewFormatSignedInt4:
|
||||
os << "hipResViewFormatSignedInt4";
|
||||
break;
|
||||
case hipResViewFormatHalf1:
|
||||
os << "hipResViewFormatHalf1";
|
||||
break;
|
||||
case hipResViewFormatHalf2:
|
||||
os << "hipResViewFormatHalf2";
|
||||
break;
|
||||
case hipResViewFormatHalf4:
|
||||
os << "hipResViewFormatHalf4";
|
||||
break;
|
||||
case hipResViewFormatFloat1:
|
||||
os << "hipResViewFormatFloat1";
|
||||
break;
|
||||
case hipResViewFormatFloat2:
|
||||
os << "hipResViewFormatFloat2";
|
||||
break;
|
||||
case hipResViewFormatFloat4:
|
||||
os << "hipResViewFormatFloat4";
|
||||
break;
|
||||
case hipResViewFormatUnsignedBlockCompressed1:
|
||||
os << "hipResViewFormatUnsignedBlockCompressed1";
|
||||
break;
|
||||
case hipResViewFormatUnsignedBlockCompressed2:
|
||||
os << "hipResViewFormatUnsignedBlockCompressed2";
|
||||
break;
|
||||
case hipResViewFormatUnsignedBlockCompressed3:
|
||||
os << "hipResViewFormatUnsignedBlockCompressed3";
|
||||
break;
|
||||
case hipResViewFormatUnsignedBlockCompressed4:
|
||||
os << "hipResViewFormatUnsignedBlockCompressed4";
|
||||
break;
|
||||
case hipResViewFormatSignedBlockCompressed4:
|
||||
os << "hipResViewFormatSignedBlockCompressed4";
|
||||
break;
|
||||
case hipResViewFormatUnsignedBlockCompressed5:
|
||||
os << "hipResViewFormatUnsignedBlockCompressed5";
|
||||
break;
|
||||
case hipResViewFormatSignedBlockCompressed5:
|
||||
os << "hipResViewFormatSignedBlockCompressed5";
|
||||
break;
|
||||
case hipResViewFormatUnsignedBlockCompressed6H:
|
||||
os << "hipResViewFormatUnsignedBlockCompressed6H";
|
||||
break;
|
||||
case hipResViewFormatSignedBlockCompressed6H:
|
||||
os << "hipResViewFormatSignedBlockCompressed6H";
|
||||
break;
|
||||
case hipResViewFormatUnsignedBlockCompressed7:
|
||||
os << "hipResViewFormatUnsignedBlockCompressed7";
|
||||
break;
|
||||
default:
|
||||
os << "hipResViewFormatNone";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipFunction_attribute& s) {
|
||||
switch (s) {
|
||||
case HIP_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK:
|
||||
os << "HIP_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK";
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_SHARED_SIZE_BYTES:
|
||||
os << "HIP_FUNC_ATTRIBUTE_SHARED_SIZE_BYTES";
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_CONST_SIZE_BYTES:
|
||||
os << "HIP_FUNC_ATTRIBUTE_CONST_SIZE_BYTES";
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_LOCAL_SIZE_BYTES:
|
||||
os << "HIP_FUNC_ATTRIBUTE_LOCAL_SIZE_BYTES";
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_NUM_REGS:
|
||||
os << "HIP_FUNC_ATTRIBUTE_NUM_REGS";
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_PTX_VERSION:
|
||||
os << "HIP_FUNC_ATTRIBUTE_PTX_VERSION";
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_BINARY_VERSION:
|
||||
os << "HIP_FUNC_ATTRIBUTE_BINARY_VERSION";
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_CACHE_MODE_CA:
|
||||
os << "HIP_FUNC_ATTRIBUTE_CACHE_MODE_CA";
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_MAX_DYNAMIC_SHARED_SIZE_BYTES:
|
||||
os << "HIP_FUNC_ATTRIBUTE_MAX_DYNAMIC_SHARED_SIZE_BYTES";
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_PREFERRED_SHARED_MEMORY_CARVEOUT:
|
||||
os << "HIP_FUNC_ATTRIBUTE_PREFERRED_SHARED_MEMORY_CARVEOUT";
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_MAX:
|
||||
os << "HIP_FUNC_ATTRIBUTE_MAX";
|
||||
break;
|
||||
default:
|
||||
os << "HIP_FUNC_ATTRIBUTE_MAX";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hiprtcResult& s) {
|
||||
switch (s) {
|
||||
case HIPRTC_SUCCESS:
|
||||
os << "HIPRTC_SUCCESS";
|
||||
break;
|
||||
case HIPRTC_ERROR_OUT_OF_MEMORY:
|
||||
os << "HIPRTC_ERROR_OUT_OF_MEMORY";
|
||||
break;
|
||||
case HIPRTC_ERROR_PROGRAM_CREATION_FAILURE:
|
||||
os << "HIPRTC_ERROR_PROGRAM_CREATION_FAILURE";
|
||||
break;
|
||||
case HIPRTC_ERROR_INVALID_INPUT:
|
||||
os << "HIPRTC_ERROR_INVALID_INPUT";
|
||||
break;
|
||||
case HIPRTC_ERROR_INVALID_PROGRAM:
|
||||
os << "HIPRTC_ERROR_INVALID_PROGRAM";
|
||||
break;
|
||||
case HIPRTC_ERROR_INVALID_OPTION:
|
||||
os << "HIPRTC_ERROR_INVALID_OPTION";
|
||||
break;
|
||||
case HIPRTC_ERROR_COMPILATION:
|
||||
os << "HIPRTC_ERROR_COMPILATION";
|
||||
break;
|
||||
case HIPRTC_ERROR_BUILTIN_OPERATION_FAILURE:
|
||||
os << "HIPRTC_ERROR_BUILTIN_OPERATION_FAILURE";
|
||||
break;
|
||||
case HIPRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION:
|
||||
os << "HIPRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION";
|
||||
break;
|
||||
case HIPRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION:
|
||||
os << "IPRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION";
|
||||
break;
|
||||
case HIPRTC_ERROR_NAME_EXPRESSION_NOT_VALID:
|
||||
os << "HIPRTC_ERROR_NAME_EXPRESSION_NOT_VALID";
|
||||
break;
|
||||
case HIPRTC_ERROR_INTERNAL_ERROR:
|
||||
os << "HIPRTC_ERROR_INTERNAL_ERROR";
|
||||
break;
|
||||
default:
|
||||
os << "HIPRTC_ERROR_INTERNAL_ERROR";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipJitOption& s) {
|
||||
switch (s) {
|
||||
case hipJitOptionMaxRegisters:
|
||||
os << "hipJitOptionMaxRegisters";
|
||||
break;
|
||||
case hipJitOptionThreadsPerBlock:
|
||||
os << "hipJitOptionThreadsPerBlock";
|
||||
break;
|
||||
case hipJitOptionWallTime:
|
||||
os << "hipJitOptionWallTime";
|
||||
break;
|
||||
case hipJitOptionInfoLogBuffer:
|
||||
os << "hipJitOptionInfoLogBuffer";
|
||||
break;
|
||||
case hipJitOptionInfoLogBufferSizeBytes:
|
||||
os << "hipJitOptionInfoLogBufferSizeBytes";
|
||||
break;
|
||||
case hipJitOptionErrorLogBuffer:
|
||||
os << "hipJitOptionErrorLogBuffer";
|
||||
break;
|
||||
case hipJitOptionErrorLogBufferSizeBytes:
|
||||
os << "hipJitOptionErrorLogBufferSizeBytes";
|
||||
break;
|
||||
case hipJitOptionOptimizationLevel:
|
||||
os << "hipJitOptionOptimizationLevel";
|
||||
break;
|
||||
case hipJitOptionTargetFromContext:
|
||||
os << "hipJitOptionTargetFromContext";
|
||||
break;
|
||||
case hipJitOptionTarget:
|
||||
os << "hipJitOptionTarget";
|
||||
break;
|
||||
case hipJitOptionFallbackStrategy:
|
||||
os << "hipJitOptionFallbackStrategy";
|
||||
break;
|
||||
case hipJitOptionGenerateDebugInfo:
|
||||
os << "hipJitOptionGenerateDebugInfo";
|
||||
break;
|
||||
case hipJitOptionCacheMode:
|
||||
os << "hipJitOptionCacheMode";
|
||||
break;
|
||||
case hipJitOptionSm3xOpt:
|
||||
os << "hipJitOptionSm3xOpt";
|
||||
break;
|
||||
case hipJitOptionFastCompile:
|
||||
os << "hipJitOptionFastCompile";
|
||||
break;
|
||||
case hipJitOptionNumOptions:
|
||||
os << "hipJitOptionNumOptions";
|
||||
break;
|
||||
default:
|
||||
os << "hipJitOptionMaxRegisters";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipFuncCache_t& s) {
|
||||
switch (s) {
|
||||
case hipFuncCachePreferNone:
|
||||
os << "hipFuncCachePreferNone";
|
||||
break;
|
||||
case hipFuncCachePreferShared:
|
||||
os << "hipFuncCachePreferShared";
|
||||
break;
|
||||
case hipFuncCachePreferL1:
|
||||
os << "hipFuncCachePreferL1";
|
||||
break;
|
||||
case hipFuncCachePreferEqual:
|
||||
os << "hipFuncCachePreferEqual";
|
||||
break;
|
||||
default:
|
||||
os << "hipFuncCachePreferNone";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipSharedMemConfig& s) {
|
||||
switch (s) {
|
||||
case hipSharedMemBankSizeDefault:
|
||||
os << "hipSharedMemBankSizeDefault";
|
||||
break;
|
||||
case hipSharedMemBankSizeFourByte:
|
||||
os << "hipSharedMemBankSizeFourByte";
|
||||
break;
|
||||
case hipSharedMemBankSizeEightByte:
|
||||
os << "hipSharedMemBankSizeEightByte";
|
||||
break;
|
||||
default:
|
||||
os << "hipSharedMemBankSizeDefault";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipDataType& s) {
|
||||
switch (s) {
|
||||
case HIP_R_16F:
|
||||
os << "HIP_R_16F";
|
||||
break;
|
||||
case HIP_R_32F:
|
||||
os << "HIP_R_32F";
|
||||
break;
|
||||
case HIP_R_64F:
|
||||
os << "HIP_R_64F";
|
||||
break;
|
||||
case HIP_C_16F:
|
||||
os << "HIP_C_16F";
|
||||
break;
|
||||
case HIP_C_32F:
|
||||
os << "HIP_C_32F";
|
||||
break;
|
||||
case HIP_C_64F:
|
||||
os << "HIP_C_64F";
|
||||
break;
|
||||
default:
|
||||
os << "HIP_R_16F";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipLibraryPropertyType& s) {
|
||||
switch (s) {
|
||||
case HIP_LIBRARY_MAJOR_VERSION:
|
||||
os << "HIP_LIBRARY_MAJOR_VERSION";
|
||||
break;
|
||||
case HIP_LIBRARY_MINOR_VERSION:
|
||||
os << "HIP_LIBRARY_MINOR_VERSION";
|
||||
break;
|
||||
case HIP_LIBRARY_PATCH_LEVEL:
|
||||
os << "HIP_LIBRARY_PATCH_LEVEL";
|
||||
break;
|
||||
default:
|
||||
os << "HIP_LIBRARY_MAJOR_VERSION";
|
||||
};
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hip_api_id_t& s) {
|
||||
os << hip_api_name(s);
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hip_api_id_t* s) {
|
||||
if (s) {
|
||||
os << *s;
|
||||
} else {
|
||||
os << "nullptr";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipTextureDesc& s) {
|
||||
os << '{'
|
||||
<< '{'
|
||||
<< s.addressMode[0]
|
||||
<< ','
|
||||
<< s.addressMode[1]
|
||||
<< ','
|
||||
<< s.addressMode[2]
|
||||
<< '}'
|
||||
<< ','
|
||||
<< s.filterMode
|
||||
<< ','
|
||||
<< s.readMode
|
||||
<< ','
|
||||
<< s.sRGB
|
||||
<< ','
|
||||
<< '{'
|
||||
<< s.borderColor[0]
|
||||
<< ','
|
||||
<< s.borderColor[1]
|
||||
<< ','
|
||||
<< s.borderColor[2]
|
||||
<< ','
|
||||
<< s.borderColor[3]
|
||||
<< '}'
|
||||
<< ','
|
||||
<< s.normalizedCoords
|
||||
<< ','
|
||||
<< s.mipmapFilterMode
|
||||
<< ','
|
||||
<< s.mipmapLevelBias
|
||||
<< ','
|
||||
<< s.minMipmapLevelClamp
|
||||
<< ','
|
||||
<< s.maxMipmapLevelClamp
|
||||
<< '}';
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipTextureDesc* s) {
|
||||
if (s) {
|
||||
os << *s;
|
||||
} else {
|
||||
os << "nullptr";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const dim3& s) {
|
||||
os << '{'
|
||||
<< s.x
|
||||
<< ','
|
||||
<< s.y
|
||||
<< ','
|
||||
<< s.z
|
||||
<< '}';
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const dim3* s) {
|
||||
if (s) {
|
||||
os << *s;
|
||||
} else {
|
||||
os << "nullptr";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipChannelFormatDesc& s) {
|
||||
os << '{'
|
||||
<< s.x
|
||||
<< ','
|
||||
<< s.y
|
||||
<< ','
|
||||
<< s.z
|
||||
<< ','
|
||||
<< s.w
|
||||
<< ','
|
||||
<< s.f
|
||||
<< '}';
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipChannelFormatDesc* s) {
|
||||
if (s) {
|
||||
os << *s;
|
||||
} else {
|
||||
os << "nullptr";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipMipmappedArray& s) {
|
||||
os << '{'
|
||||
<< s.data
|
||||
<< ','
|
||||
<< s.desc
|
||||
<< ','
|
||||
<< s.width
|
||||
<< ','
|
||||
<< s.height
|
||||
<< ','
|
||||
<< s.depth
|
||||
<< '}';
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipMipmappedArray* s) {
|
||||
if (s) {
|
||||
os << *s;
|
||||
} else {
|
||||
os << "nullptr";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipResourceDesc& s) {
|
||||
os << '{'
|
||||
<< s.resType
|
||||
<< ','
|
||||
<< '{';
|
||||
|
||||
switch (s.resType) {
|
||||
case hipResourceTypeLinear:
|
||||
os << s.res.linear.devPtr
|
||||
<< ','
|
||||
<< s.res.linear.desc
|
||||
<< ','
|
||||
<< s.res.linear.sizeInBytes;
|
||||
break;
|
||||
case hipResourceTypePitch2D:
|
||||
os << s.res.pitch2D.devPtr
|
||||
<< ','
|
||||
<< s.res.pitch2D.desc
|
||||
<< ','
|
||||
<< s.res.pitch2D.width
|
||||
<< ','
|
||||
<< s.res.pitch2D.height
|
||||
<< ','
|
||||
<< s.res.pitch2D.pitchInBytes;
|
||||
break;
|
||||
case hipResourceTypeArray:
|
||||
os << s.res.array.array;
|
||||
break;
|
||||
case hipResourceTypeMipmappedArray:
|
||||
os <<s.res.mipmap.mipmap;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
os << '}';
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipResourceDesc* s) {
|
||||
if (s) {
|
||||
os << *s;
|
||||
} else {
|
||||
os << "nullptr";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipArray& s) {
|
||||
os << '{'
|
||||
<< s.data
|
||||
<< ','
|
||||
<< s.desc
|
||||
<< ','
|
||||
<< s.type
|
||||
<< ','
|
||||
<< s.width
|
||||
<< ','
|
||||
<< s.height
|
||||
<< ','
|
||||
<< s.depth
|
||||
<< ','
|
||||
<< s.Format
|
||||
<< ','
|
||||
<< s.NumChannels
|
||||
<< ','
|
||||
<< s.isDrv
|
||||
<< ','
|
||||
<< s.textureType
|
||||
<< '}';
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipArray* s) {
|
||||
if (s) {
|
||||
os << *s;
|
||||
} else {
|
||||
os << "nullptr";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const textureReference& s) {
|
||||
os << '{'
|
||||
<< s.normalized
|
||||
<< ','
|
||||
<< s.readMode
|
||||
<< ','
|
||||
<< s.filterMode
|
||||
<< ','
|
||||
<< '{'
|
||||
<< s.addressMode[0]
|
||||
<< ','
|
||||
<< s.addressMode[1]
|
||||
<< ','
|
||||
<< s.addressMode[2]
|
||||
<< '}'
|
||||
<< ','
|
||||
<< s.channelDesc
|
||||
<< ','
|
||||
<< s.sRGB
|
||||
<< ','
|
||||
<< s.maxAnisotropy
|
||||
<< ','
|
||||
<< s.mipmapFilterMode
|
||||
<< ','
|
||||
<< s.mipmapLevelBias
|
||||
<< ','
|
||||
<< s.minMipmapLevelClamp
|
||||
<< ','
|
||||
<< s.maxMipmapLevelClamp
|
||||
<< ','
|
||||
<< s.textureObject
|
||||
<< '}';
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const textureReference* s) {
|
||||
if (s) {
|
||||
os << *s;
|
||||
} else {
|
||||
os << "nullptr";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipError_t& s) {
|
||||
os << hipGetErrorName(s);
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipError_t* s) {
|
||||
if (s) {
|
||||
os << *s;
|
||||
} else {
|
||||
os << "nullptr";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipResourceViewDesc& s) {
|
||||
os << '{'
|
||||
<< s.format
|
||||
<< ','
|
||||
<< s.width
|
||||
<< ','
|
||||
<< s.height
|
||||
<< ','
|
||||
<< s.depth
|
||||
<< ','
|
||||
<< s.firstMipmapLevel
|
||||
<< ','
|
||||
<< s.lastMipmapLevel
|
||||
<< ','
|
||||
<< s.firstLayer
|
||||
<< ','
|
||||
<< s.lastLayer
|
||||
<< '}';
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipResourceViewDesc* s) {
|
||||
if (s) {
|
||||
os << *s;
|
||||
} else {
|
||||
os << "nullptr";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const HIP_ARRAY_DESCRIPTOR& s) {
|
||||
os << '{'
|
||||
<< s.Width
|
||||
<< ','
|
||||
<< s.Height
|
||||
<< ','
|
||||
<< s.Format
|
||||
<< ','
|
||||
<< s.NumChannels
|
||||
<< '}';
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const HIP_ARRAY_DESCRIPTOR* s) {
|
||||
if (s) {
|
||||
os << *s;
|
||||
} else {
|
||||
os << "nullptr";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const HIP_ARRAY3D_DESCRIPTOR& s) {
|
||||
os << '{'
|
||||
<< s.Width
|
||||
<< ','
|
||||
<< s.Height
|
||||
<< ','
|
||||
<< s.Depth
|
||||
<< ','
|
||||
<< s.Format
|
||||
<< ','
|
||||
<< s.NumChannels
|
||||
<< ','
|
||||
<< s.Flags
|
||||
<< '}';
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const HIP_ARRAY3D_DESCRIPTOR* s) {
|
||||
if (s) {
|
||||
os << *s;
|
||||
} else {
|
||||
os << "nullptr";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipExtent& s) {
|
||||
os << '{'
|
||||
<< s.width
|
||||
<< ','
|
||||
<< s.height
|
||||
<< ','
|
||||
<< s.depth
|
||||
<< '}';
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipIpcEventHandle_t& s) {
|
||||
//TODO fill in later
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const hipIpcEventHandle_t* s) {
|
||||
//TODO fill in later
|
||||
return os;
|
||||
}
|
||||
Executable
+196
@@ -0,0 +1,196 @@
|
||||
#include "hip_global.hpp"
|
||||
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "hip_internal.hpp"
|
||||
#include "hip_code_object.hpp"
|
||||
#include "platform/program.hpp"
|
||||
|
||||
namespace hip {
|
||||
|
||||
//Device Vars
|
||||
DeviceVar::DeviceVar(std::string name, hipModule_t hmod) : shadowVptr(nullptr), name_(name),
|
||||
amd_mem_obj_(nullptr), device_ptr_(nullptr),
|
||||
size_(0) {
|
||||
amd::Program* program = as_amd(reinterpret_cast<cl_program>(hmod));
|
||||
device::Program* dev_program = program->getDeviceProgram(*hip::getCurrentDevice()->devices()[0]);
|
||||
if (dev_program == nullptr) {
|
||||
LogPrintfError("Cannot get Device Program for module: 0x%x \n", hmod);
|
||||
guarantee(false, "Cannot get Device Program");
|
||||
}
|
||||
|
||||
if(!dev_program->createGlobalVarObj(&amd_mem_obj_, &device_ptr_, &size_, name.c_str())) {
|
||||
LogPrintfError("Cannot create Global Var obj for symbol: %s \n", name.c_str());
|
||||
guarantee(false, "Cannot create GlobalVar Obj");
|
||||
}
|
||||
|
||||
// Handle size 0 symbols
|
||||
if (size_ != 0) {
|
||||
if (amd_mem_obj_ == nullptr || device_ptr_ == nullptr) {
|
||||
LogPrintfError("Cannot get memory for creating device Var: %s", name.c_str());
|
||||
guarantee(false, "Cannot get memory for creating device var");
|
||||
}
|
||||
amd::MemObjMap::AddMemObj(device_ptr_, amd_mem_obj_);
|
||||
}
|
||||
}
|
||||
|
||||
DeviceVar::~DeviceVar() {
|
||||
if (amd_mem_obj_ != nullptr) {
|
||||
amd::MemObjMap::RemoveMemObj(device_ptr_);
|
||||
amd_mem_obj_->release();
|
||||
}
|
||||
|
||||
if (shadowVptr != nullptr) {
|
||||
textureReference* texRef = reinterpret_cast<textureReference*>(shadowVptr);
|
||||
delete texRef;
|
||||
shadowVptr = nullptr;
|
||||
}
|
||||
|
||||
device_ptr_ = nullptr;
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
//Device Functions
|
||||
DeviceFunc::DeviceFunc(std::string name, hipModule_t hmod) : dflock_("function lock"),
|
||||
name_(name), kernel_(nullptr) {
|
||||
amd::Program* program = as_amd(reinterpret_cast<cl_program>(hmod));
|
||||
|
||||
const amd::Symbol *symbol = program->findSymbol(name.c_str());
|
||||
if (symbol == nullptr) {
|
||||
LogPrintfError("Cannot find Symbol with name: %s \n", name.c_str());
|
||||
guarantee(false, "Cannot find Symbol");
|
||||
}
|
||||
|
||||
kernel_ = new amd::Kernel(*program, *symbol, name);
|
||||
if (kernel_ == nullptr) {
|
||||
LogPrintfError("Cannot create kernel with name: %s \n", name.c_str());
|
||||
guarantee(false, "Cannot Create kernel");
|
||||
}
|
||||
}
|
||||
|
||||
DeviceFunc::~DeviceFunc() {
|
||||
if (kernel_ != nullptr) {
|
||||
kernel_->release();
|
||||
}
|
||||
}
|
||||
|
||||
//Abstract functions
|
||||
Function::Function(std::string name, FatBinaryInfo** modules)
|
||||
: name_(name), modules_(modules) {
|
||||
dFunc_.resize(g_devices.size());
|
||||
}
|
||||
|
||||
Function::~Function() {
|
||||
for (auto& elem : dFunc_) {
|
||||
delete elem;
|
||||
}
|
||||
name_ = "";
|
||||
modules_ = nullptr;
|
||||
}
|
||||
|
||||
hipError_t Function::getDynFunc(hipFunction_t* hfunc, hipModule_t hmod) {
|
||||
guarantee((dFunc_.size() == g_devices.size()), "dFunc Size mismatch");
|
||||
if (dFunc_[ihipGetDevice()] == nullptr) {
|
||||
dFunc_[ihipGetDevice()] = new DeviceFunc(name_, hmod);
|
||||
}
|
||||
*hfunc = dFunc_[ihipGetDevice()]->asHipFunction();
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t Function::getStatFunc(hipFunction_t* hfunc, int deviceId) {
|
||||
guarantee(modules_ != nullptr, "Module not initialized");
|
||||
|
||||
hipModule_t hmod = nullptr;
|
||||
IHIP_RETURN_ONFAIL((*modules_)->BuildProgram(deviceId));
|
||||
IHIP_RETURN_ONFAIL((*modules_)->GetModule(deviceId, &hmod));
|
||||
|
||||
if (dFunc_[deviceId] == nullptr) {
|
||||
dFunc_[deviceId] = new DeviceFunc(name_, hmod);
|
||||
}
|
||||
*hfunc = dFunc_[deviceId]->asHipFunction();
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t Function::getStatFuncAttr(hipFuncAttributes* func_attr, int deviceId) {
|
||||
guarantee((modules_ != nullptr), "Module not initialized");
|
||||
|
||||
hipModule_t hmod = nullptr;
|
||||
IHIP_RETURN_ONFAIL((*modules_)->BuildProgram(deviceId));
|
||||
IHIP_RETURN_ONFAIL((*modules_)->GetModule(deviceId, &hmod));
|
||||
|
||||
if (dFunc_[deviceId] == nullptr) {
|
||||
dFunc_[deviceId] = new DeviceFunc(name_, hmod);
|
||||
}
|
||||
|
||||
const std::vector<amd::Device*>& devices = amd::Device::getDevices(CL_DEVICE_TYPE_GPU, false);
|
||||
|
||||
amd::Kernel* kernel = dFunc_[deviceId]->kernel();
|
||||
const device::Kernel::WorkGroupInfo* wginfo = kernel->getDeviceKernel(*devices[deviceId])->workGroupInfo();
|
||||
func_attr->sharedSizeBytes = static_cast<int>(wginfo->localMemSize_);
|
||||
func_attr->binaryVersion = static_cast<int>(kernel->signature().version());
|
||||
func_attr->cacheModeCA = 0;
|
||||
func_attr->constSizeBytes = 0;
|
||||
func_attr->localSizeBytes = wginfo->privateMemSize_;
|
||||
func_attr->maxDynamicSharedSizeBytes = static_cast<int>(wginfo->availableLDSSize_
|
||||
- wginfo->localMemSize_);
|
||||
|
||||
func_attr->maxThreadsPerBlock = static_cast<int>(wginfo->size_);
|
||||
func_attr->numRegs = static_cast<int>(wginfo->usedVGPRs_);
|
||||
func_attr->preferredShmemCarveout = 0;
|
||||
func_attr->ptxVersion = 30;
|
||||
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
//Abstract Vars
|
||||
Var::Var(std::string name, DeviceVarKind dVarKind, size_t size, int type, int norm,
|
||||
FatBinaryInfo** modules) : name_(name), dVarKind_(dVarKind), size_(size),
|
||||
type_(type), norm_(norm), modules_(modules) {
|
||||
dVar_.resize(g_devices.size());
|
||||
}
|
||||
|
||||
Var::Var(std::string name, DeviceVarKind dVarKind, void *pointer, size_t size,
|
||||
unsigned align, FatBinaryInfo** modules) : name_(name), dVarKind_(dVarKind),
|
||||
size_(size), modules_(modules), managedVarPtr_(pointer), align_(align) {
|
||||
dVar_.resize(g_devices.size());
|
||||
}
|
||||
|
||||
Var::~Var() {
|
||||
for (auto& elem : dVar_) {
|
||||
delete elem;
|
||||
}
|
||||
modules_ = nullptr;
|
||||
}
|
||||
|
||||
hipError_t Var::getDeviceVar(DeviceVar** dvar, int deviceId, hipModule_t hmod) {
|
||||
guarantee((deviceId >= 0), "Invalid DeviceId, less than zero");
|
||||
guarantee((static_cast<size_t>(deviceId) < g_devices.size()),
|
||||
"Invalid DeviceId, greater than no of code objects");
|
||||
guarantee((dVar_.size() == g_devices.size()),
|
||||
"Device Var not initialized to size");
|
||||
|
||||
if (dVar_[deviceId] == nullptr) {
|
||||
dVar_[deviceId] = new DeviceVar(name_, hmod);
|
||||
}
|
||||
|
||||
*dvar = dVar_[deviceId];
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t Var::getStatDeviceVar(DeviceVar** dvar, int deviceId) {
|
||||
guarantee((deviceId >= 0) , "Invalid DeviceId, less than zero");
|
||||
guarantee((static_cast<size_t>(deviceId) < g_devices.size()),
|
||||
"Invalid DeviceId, greater than no of code objects");
|
||||
if (dVar_[deviceId] == nullptr) {
|
||||
hipModule_t hmod = nullptr;
|
||||
IHIP_RETURN_ONFAIL((*modules_)->BuildProgram(deviceId));
|
||||
IHIP_RETURN_ONFAIL((*modules_)->GetModule(deviceId, &hmod));
|
||||
dVar_[deviceId] = new DeviceVar(name_, hmod);
|
||||
}
|
||||
*dvar = dVar_[deviceId];
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
}; //namespace: hip
|
||||
Executable
+127
@@ -0,0 +1,127 @@
|
||||
#ifndef HIP_GLOBAL_HPP
|
||||
#define HIP_GLOBAL_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "hip/hip_runtime_api.h"
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "hip_internal.hpp"
|
||||
#include "hip_fatbin.hpp"
|
||||
#include "platform/program.hpp"
|
||||
|
||||
namespace hip {
|
||||
|
||||
//Forward Declaration
|
||||
class CodeObject;
|
||||
|
||||
//Device Structures
|
||||
class DeviceVar {
|
||||
public:
|
||||
DeviceVar(std::string name, hipModule_t hmod);
|
||||
~DeviceVar();
|
||||
|
||||
//Accessors for device ptr and size, populated during constructor.
|
||||
hipDeviceptr_t device_ptr() const { return device_ptr_; }
|
||||
size_t size() const { return size_; }
|
||||
std::string name() const { return name_; }
|
||||
void* shadowVptr;
|
||||
|
||||
private:
|
||||
std::string name_; //Name of the var
|
||||
amd::Memory* amd_mem_obj_; //amd_mem_obj abstraction
|
||||
hipDeviceptr_t device_ptr_; //Device Pointer
|
||||
size_t size_; //Size of the var
|
||||
};
|
||||
|
||||
class DeviceFunc {
|
||||
public:
|
||||
DeviceFunc(std::string name, hipModule_t hmod);
|
||||
~DeviceFunc();
|
||||
|
||||
amd::Monitor dflock_;
|
||||
|
||||
//Converts DeviceFunc to hipFunction_t(used by app) and vice versa.
|
||||
hipFunction_t asHipFunction() { return reinterpret_cast<hipFunction_t>(this); }
|
||||
static DeviceFunc* asFunction(hipFunction_t f) { return reinterpret_cast<DeviceFunc*>(f); }
|
||||
|
||||
//Accessor for kernel_ and name_ populated during constructor.
|
||||
std::string name() const { return name_; }
|
||||
amd::Kernel* kernel() const { return kernel_; }
|
||||
|
||||
private:
|
||||
std::string name_; //name of the func(not unique identifier)
|
||||
amd::Kernel* kernel_; //Kernel ptr referencing to ROCclr Symbol
|
||||
};
|
||||
|
||||
//Abstract Structures
|
||||
class Function {
|
||||
public:
|
||||
Function(std::string name, FatBinaryInfo** modules=nullptr);
|
||||
~Function();
|
||||
|
||||
//Return DeviceFunc for this this dynamically loaded module
|
||||
hipError_t getDynFunc(hipFunction_t* hfunc, hipModule_t hmod);
|
||||
|
||||
//Return Device Func & attr . Generate/build if not already done so.
|
||||
hipError_t getStatFunc(hipFunction_t *hfunc, int deviceId);
|
||||
hipError_t getStatFuncAttr(hipFuncAttributes* func_attr, int deviceId);
|
||||
void resize_dFunc(size_t size) { dFunc_.resize(size); }
|
||||
FatBinaryInfo** moduleInfo() { return modules_; };
|
||||
|
||||
private:
|
||||
std::vector<DeviceFunc*> dFunc_; //DeviceFuncObj per Device
|
||||
std::string name_; //name of the func(not unique identifier)
|
||||
FatBinaryInfo** modules_; // static module where it is referenced
|
||||
};
|
||||
|
||||
class Var {
|
||||
public:
|
||||
//Types of variable
|
||||
enum DeviceVarKind {
|
||||
DVK_Variable = 0,
|
||||
DVK_Surface,
|
||||
DVK_Texture,
|
||||
DVK_Managed
|
||||
};
|
||||
|
||||
Var(std::string name, DeviceVarKind dVarKind, size_t size, int type, int norm,
|
||||
FatBinaryInfo** modules = nullptr);
|
||||
|
||||
Var(std::string name, DeviceVarKind dVarKind, void *pointer, size_t size, unsigned align,
|
||||
FatBinaryInfo** modules = nullptr);
|
||||
|
||||
~Var();
|
||||
|
||||
//Return DeviceVar for this dynamically loaded module
|
||||
hipError_t getDeviceVar(DeviceVar** dvar, int deviceId, hipModule_t hmod);
|
||||
|
||||
//Return DeviceVar for module Generate/build if not already done so.
|
||||
hipError_t getStatDeviceVar(DeviceVar** dvar, int deviceId);
|
||||
void resize_dVar(size_t size) { dVar_.resize(size); }
|
||||
|
||||
FatBinaryInfo** moduleInfo() { return modules_; };
|
||||
DeviceVarKind getVarKind() const { return dVarKind_; }
|
||||
size_t getSize() const { return size_; }
|
||||
|
||||
void* getManagedVarPtr() { return managedVarPtr_; };
|
||||
void setManagedVarInfo(void* pointer, size_t size) {
|
||||
managedVarPtr_ = pointer;
|
||||
size_ = size;
|
||||
dVarKind_ = DVK_Managed;
|
||||
}
|
||||
private:
|
||||
std::vector<DeviceVar*> dVar_; // DeviceVarObj per Device
|
||||
std::string name_; // Variable name (not unique identifier)
|
||||
DeviceVarKind dVarKind_; // Variable kind
|
||||
size_t size_; // Size of the variable
|
||||
int type_; // Type(Textures/Surfaces only)
|
||||
int norm_; // Type(Textures/Surfaces only)
|
||||
FatBinaryInfo** modules_; // static module where it is referenced
|
||||
|
||||
void *managedVarPtr_; // Managed memory pointer with size_ & align_
|
||||
unsigned int align_; // Managed memory alignment
|
||||
};
|
||||
|
||||
}; //namespace: hip
|
||||
#endif /* HIP_GLOBAL_HPP */
|
||||
@@ -0,0 +1,415 @@
|
||||
/* Copyright (c) 2021-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include "hip_graph_internal.hpp"
|
||||
#include "platform/command.hpp"
|
||||
#include "hip_conversions.hpp"
|
||||
#include "hip_platform.hpp"
|
||||
#include "hip_event.hpp"
|
||||
|
||||
thread_local std::vector<hipStream_t> g_captureStreams;
|
||||
std::unordered_map<amd::Command*, hipGraphExec_t> hipGraphExec::activeGraphExec_;
|
||||
|
||||
hipError_t ihipGraphAddKernelNode(hipGraphNode_t* pGraphNode, hipGraph_t graph,
|
||||
const hipGraphNode_t* pDependencies, size_t numDependencies,
|
||||
const hipKernelNodeParams* pNodeParams) {
|
||||
if (pGraphNode == nullptr || graph == nullptr ||
|
||||
(numDependencies > 0 && pDependencies == nullptr) || pNodeParams == nullptr) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
hipFunction_t func = nullptr;
|
||||
hipError_t status =
|
||||
PlatformState::instance().getStatFunc(&func, pNodeParams->func, ihipGetDevice());
|
||||
if ((status != hipSuccess) || (func == nullptr)) {
|
||||
return hipErrorInvalidDeviceFunction;
|
||||
}
|
||||
size_t globalWorkSizeX = static_cast<size_t>(pNodeParams->gridDim.x) * pNodeParams->blockDim.x;
|
||||
size_t globalWorkSizeY = static_cast<size_t>(pNodeParams->gridDim.y) * pNodeParams->blockDim.y;
|
||||
size_t globalWorkSizeZ = static_cast<size_t>(pNodeParams->gridDim.z) * pNodeParams->blockDim.z;
|
||||
if (globalWorkSizeX > std::numeric_limits<uint32_t>::max() ||
|
||||
globalWorkSizeY > std::numeric_limits<uint32_t>::max() ||
|
||||
globalWorkSizeZ > std::numeric_limits<uint32_t>::max()) {
|
||||
return hipErrorInvalidConfiguration;
|
||||
}
|
||||
status = ihipLaunchKernel_validate(
|
||||
func, static_cast<uint32_t>(globalWorkSizeX), static_cast<uint32_t>(globalWorkSizeY),
|
||||
static_cast<uint32_t>(globalWorkSizeZ), pNodeParams->blockDim.x, pNodeParams->blockDim.y,
|
||||
pNodeParams->blockDim.z, pNodeParams->sharedMemBytes, pNodeParams->kernelParams,
|
||||
pNodeParams->extra, ihipGetDevice(), 0);
|
||||
if (status != hipSuccess) {
|
||||
return status;
|
||||
}
|
||||
*pGraphNode = new hipGraphKernelNode(pNodeParams, func);
|
||||
if (numDependencies == 0) {
|
||||
graph->AddNode(*pGraphNode);
|
||||
}
|
||||
for (size_t i = 0; i < numDependencies; i++) {
|
||||
if (graph->AddEdge(*(pDependencies + i), *pGraphNode) != hipSuccess) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t ihipGraphAddMemcpyNode(hipGraphNode_t* pGraphNode, hipGraph_t graph,
|
||||
const hipGraphNode_t* pDependencies, size_t numDependencies,
|
||||
const hipMemcpy3DParms* pCopyParams) {
|
||||
if (pGraphNode == nullptr || graph == nullptr ||
|
||||
(numDependencies > 0 && pDependencies == nullptr) || pCopyParams == nullptr) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
ihipMemcpy3D_validate(pCopyParams);
|
||||
*pGraphNode = new hipGraphMemcpyNode(pCopyParams);
|
||||
if (numDependencies == 0) {
|
||||
graph->AddNode(*pGraphNode);
|
||||
}
|
||||
for (size_t i = 0; i < numDependencies; i++) {
|
||||
if (graph->AddEdge(*(pDependencies + i), *pGraphNode) != hipSuccess) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t ihipGraphAddMemsetNode(hipGraphNode_t* pGraphNode, hipGraph_t graph,
|
||||
const hipGraphNode_t* pDependencies, size_t numDependencies,
|
||||
const hipMemsetParams* pMemsetParams) {
|
||||
if (pGraphNode == nullptr || graph == nullptr ||
|
||||
(numDependencies > 0 && pDependencies == nullptr) || pMemsetParams == nullptr) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
if (pMemsetParams->height == 1) {
|
||||
ihipMemset_validate(pMemsetParams->dst, pMemsetParams->value, pMemsetParams->elementSize,
|
||||
pMemsetParams->width * pMemsetParams->elementSize);
|
||||
} else {
|
||||
auto sizeBytes = pMemsetParams->width * pMemsetParams->height * 1;
|
||||
ihipMemset3D_validate(
|
||||
{pMemsetParams->dst, pMemsetParams->pitch, pMemsetParams->width, pMemsetParams->height},
|
||||
pMemsetParams->value, {pMemsetParams->width, pMemsetParams->height, 1}, sizeBytes);
|
||||
}
|
||||
|
||||
*pGraphNode = new hipGraphMemsetNode(pMemsetParams);
|
||||
if (numDependencies == 0) {
|
||||
graph->AddNode(*pGraphNode);
|
||||
}
|
||||
for (size_t i = 0; i < numDependencies; i++) {
|
||||
if (graph->AddEdge(*(pDependencies + i), *pGraphNode) != hipSuccess) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t capturehipLaunchKernel(hipStream_t& stream, const void*& hostFunction, dim3& gridDim,
|
||||
dim3& blockDim, void**& args, size_t& sharedMemBytes) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API,
|
||||
"[hipGraph] current capture node kernel launch on stream : %p", stream);
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
hipKernelNodeParams nodeParams;
|
||||
nodeParams.func = const_cast<void*>(hostFunction);
|
||||
nodeParams.blockDim = blockDim;
|
||||
nodeParams.extra = nullptr;
|
||||
nodeParams.gridDim = gridDim;
|
||||
nodeParams.kernelParams = args;
|
||||
nodeParams.sharedMemBytes = sharedMemBytes;
|
||||
|
||||
hipGraphNode_t pGraphNode;
|
||||
hipError_t status =
|
||||
ihipGraphAddKernelNode(&pGraphNode, s->GetCaptureGraph(), s->GetLastCapturedNodes().data(),
|
||||
s->GetLastCapturedNodes().size(), &nodeParams);
|
||||
if (status != hipSuccess) {
|
||||
return status;
|
||||
}
|
||||
s->SetLastCapturedNode(pGraphNode);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t capturehipMemcpy3DAsync(hipStream_t& stream, const hipMemcpy3DParms*& p) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API, "[hipGraph] current capture node Memcpy3D on stream : %p",
|
||||
stream);
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
hipGraphNode_t pGraphNode;
|
||||
hipError_t status =
|
||||
ihipGraphAddMemcpyNode(&pGraphNode, s->GetCaptureGraph(), s->GetLastCapturedNodes().data(),
|
||||
s->GetLastCapturedNodes().size(), p);
|
||||
if (status != hipSuccess) {
|
||||
return status;
|
||||
}
|
||||
s->SetLastCapturedNode(pGraphNode);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t capturehipMemcpyAsync(hipStream_t& stream, void*& dst, const void*& src,
|
||||
size_t& sizeBytes, hipMemcpyKind& kind) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API, "[hipGraph] current capture node Memcpy1D on stream : %p",
|
||||
stream);
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
hipGraphNode_t pGraphNode;
|
||||
hipGraph_t graph = nullptr;
|
||||
std::vector<hipGraphNode_t> pDependencies = s->GetLastCapturedNodes();
|
||||
size_t numDependencies = s->GetLastCapturedNodes().size();
|
||||
graph = s->GetCaptureGraph();
|
||||
ihipMemcpy_validate(dst, src, sizeBytes, kind);
|
||||
pGraphNode = new hipGraphMemcpyNode1D(dst, src, sizeBytes, kind);
|
||||
if (numDependencies == 0) {
|
||||
graph->AddNode(pGraphNode);
|
||||
}
|
||||
for (size_t i = 0; i < numDependencies; i++) {
|
||||
if (graph->AddEdge(pDependencies[i], pGraphNode) != hipSuccess) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
}
|
||||
s->SetLastCapturedNode(pGraphNode);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t capturehipMemcpyFromSymbolAsync(hipStream_t& stream, void*& dst, const void*& symbol,
|
||||
size_t& sizeBytes, size_t& offset, hipMemcpyKind& kind) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API,
|
||||
"[hipGraph] current capture node MemcpyFromSymbolNode on stream : %p", stream);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t capturehipMemcpyToSymbolAsync(hipStream_t& stream, const void*& symbol, const void*& src,
|
||||
size_t& sizeBytes, size_t& offset, hipMemcpyKind& kind) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API,
|
||||
"[hipGraph] current capture node MemcpyToSymbolNode on stream : %p", stream);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t capturehipMemsetAsync(hipStream_t& stream, void*& dst, int& value, size_t& valueSize,
|
||||
size_t& sizeBytes) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API, "[hipGraph] current capture node Memset1D on stream : %p",
|
||||
stream);
|
||||
|
||||
hipMemsetParams memsetParams = {0};
|
||||
memsetParams.dst = dst;
|
||||
memsetParams.value = value;
|
||||
memsetParams.elementSize = valueSize;
|
||||
memsetParams.width = sizeBytes / valueSize;
|
||||
memsetParams.height = 1;
|
||||
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
hipGraphNode_t pGraphNode;
|
||||
hipError_t status =
|
||||
ihipGraphAddMemsetNode(&pGraphNode, s->GetCaptureGraph(), s->GetLastCapturedNodes().data(),
|
||||
s->GetLastCapturedNodes().size(), &memsetParams);
|
||||
if (status != hipSuccess) {
|
||||
return status;
|
||||
}
|
||||
s->SetLastCapturedNode(pGraphNode);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t capturehipMemset2DAsync(hipStream_t& stream, void*& dst, size_t& pitch, int& value,
|
||||
size_t& width, size_t& height) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API, "[hipGraph] current capture node Memset2D on stream : %p",
|
||||
stream);
|
||||
hipMemsetParams memsetParams = {0};
|
||||
|
||||
memsetParams.dst = dst;
|
||||
memsetParams.value = value;
|
||||
memsetParams.width = width;
|
||||
memsetParams.height = height;
|
||||
memsetParams.pitch = pitch;
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
hipGraphNode_t pGraphNode;
|
||||
hipError_t status =
|
||||
ihipGraphAddMemsetNode(&pGraphNode, s->GetCaptureGraph(), s->GetLastCapturedNodes().data(),
|
||||
s->GetLastCapturedNodes().size(), &memsetParams);
|
||||
if (status != hipSuccess) {
|
||||
return status;
|
||||
}
|
||||
s->SetLastCapturedNode(pGraphNode);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t capturehipMemset3DAsync(hipStream_t& stream, hipPitchedPtr& pitchedDevPtr, int& value,
|
||||
hipExtent& extent) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API, "[hipGraph] current capture node Memset3D on stream : %p",
|
||||
stream);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t capturehipEventRecord(hipStream_t& stream, hipEvent_t& event) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API,
|
||||
"[hipGraph] current capture node EventRecord on stream : %p, Event %p", stream, event);
|
||||
if (event == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidHandle);
|
||||
}
|
||||
hip::Event* e = reinterpret_cast<hip::Event*>(event);
|
||||
e->StartCapture(stream);
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
std::vector<hipGraphNode_t> lastCapturedNodes = s->GetLastCapturedNodes();
|
||||
if (!lastCapturedNodes.empty()) {
|
||||
e->SetNodesPrevToRecorded(lastCapturedNodes);
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t capturehipStreamWaitEvent(hipEvent_t& event, hipStream_t& stream, unsigned int& flags) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API,
|
||||
"[hipGraph] current capture node StreamWaitEvent on stream : %p, Event %p", stream,
|
||||
event);
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
hip::Event* e = reinterpret_cast<hip::Event*>(event);
|
||||
|
||||
if (event == nullptr || stream == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
if (!s->IsOriginStream()) {
|
||||
s->SetCaptureGraph(reinterpret_cast<hip::Stream*>(e->GetCaptureStream())->GetCaptureGraph());
|
||||
s->SetCaptureMode(reinterpret_cast<hip::Stream*>(e->GetCaptureStream())->GetCaptureMode());
|
||||
s->SetParentStream(e->GetCaptureStream());
|
||||
}
|
||||
s->AddCrossCapturedNode(e->GetNodesPrevToRecorded());
|
||||
g_captureStreams.push_back(stream);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t hipStreamIsCapturing(hipStream_t stream, hipStreamCaptureStatus** pCaptureStatus) {
|
||||
HIP_INIT_API(hipStreamIsCapturing, stream, pCaptureStatus);
|
||||
if (stream == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
hipStreamCaptureStatus captureStatus = reinterpret_cast<hip::Stream*>(stream)->GetCaptureStatus();
|
||||
*pCaptureStatus = &captureStatus;
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipStreamBeginCapture(hipStream_t stream, hipStreamCaptureMode mode) {
|
||||
HIP_INIT_API(hipStreamBeginCapture, stream, mode);
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
// capture cannot be initiated on legacy stream
|
||||
// It can be initiated if the stream is not already in capture mode
|
||||
if (stream == nullptr || s->GetCaptureStatus() == hipStreamCaptureStatusActive) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
s->SetCaptureGraph(new hipGraph());
|
||||
s->SetCaptureMode(mode);
|
||||
s->SetOriginStream();
|
||||
g_captureStreams.push_back(stream);
|
||||
HIP_RETURN_DURATION(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipStreamEndCapture(hipStream_t stream, hipGraph_t* pGraph) {
|
||||
HIP_INIT_API(hipStreamEndCapture, stream, pGraph);
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
// Capture must be ended on the same stream in which it was initiated
|
||||
if (!s->IsOriginStream()) {
|
||||
HIP_RETURN(hipErrorStreamCaptureUnmatched);
|
||||
}
|
||||
// If mode is not hipStreamCaptureModeRelaxed, hipStreamEndCapture must be called on the stream
|
||||
// from the same thread
|
||||
if (s->GetCaptureMode() != hipStreamCaptureModeRelaxed &&
|
||||
std::find(g_captureStreams.begin(), g_captureStreams.end(), stream) ==
|
||||
g_captureStreams.end()) {
|
||||
HIP_RETURN(hipErrorStreamCaptureWrongThread);
|
||||
}
|
||||
// If capture was invalidated, due to a violation of the rules of stream capture
|
||||
if (s->GetCaptureStatus() == hipStreamCaptureStatusInvalidated) {
|
||||
*pGraph = nullptr;
|
||||
HIP_RETURN(hipErrorStreamCaptureInvalidated);
|
||||
}
|
||||
// check if all parallel streams have joined
|
||||
if (s->GetCaptureGraph()->GetLeafNodeCount() != 1) {
|
||||
return hipErrorStreamCaptureUnjoined;
|
||||
}
|
||||
*pGraph = s->GetCaptureGraph();
|
||||
// end capture on all streams/events part of graph capture
|
||||
HIP_RETURN_DURATION(s->EndCapture());
|
||||
}
|
||||
|
||||
hipError_t hipGraphCreate(hipGraph_t* pGraph, unsigned int flags) {
|
||||
HIP_INIT_API(hipGraphCreate, pGraph, flags);
|
||||
*pGraph = new hipGraph();
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipGraphDestroy(hipGraph_t graph) {
|
||||
HIP_INIT_API(hipGraphDestroy, graph);
|
||||
delete graph;
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipGraphAddKernelNode(hipGraphNode_t* pGraphNode, hipGraph_t graph,
|
||||
const hipGraphNode_t* pDependencies, size_t numDependencies,
|
||||
const hipKernelNodeParams* pNodeParams) {
|
||||
HIP_INIT_API(hipGraphAddKernelNode, pGraphNode, graph, pDependencies, numDependencies,
|
||||
pNodeParams);
|
||||
HIP_RETURN_DURATION(
|
||||
ihipGraphAddKernelNode(pGraphNode, graph, pDependencies, numDependencies, pNodeParams););
|
||||
}
|
||||
|
||||
hipError_t hipGraphAddMemcpyNode(hipGraphNode_t* pGraphNode, hipGraph_t graph,
|
||||
const hipGraphNode_t* pDependencies, size_t numDependencies,
|
||||
const hipMemcpy3DParms* pCopyParams) {
|
||||
HIP_INIT_API(hipGraphAddMemcpyNode, pGraphNode, graph, pDependencies, numDependencies,
|
||||
pCopyParams);
|
||||
|
||||
HIP_RETURN_DURATION(
|
||||
ihipGraphAddMemcpyNode(pGraphNode, graph, pDependencies, numDependencies, pCopyParams););
|
||||
}
|
||||
|
||||
hipError_t hipGraphAddMemsetNode(hipGraphNode_t* pGraphNode, hipGraph_t graph,
|
||||
const hipGraphNode_t* pDependencies, size_t numDependencies,
|
||||
const hipMemsetParams* pMemsetParams) {
|
||||
HIP_INIT_API(hipGraphAddMemsetNode, pGraphNode, graph, pDependencies, numDependencies,
|
||||
pMemsetParams);
|
||||
|
||||
HIP_RETURN_DURATION(
|
||||
ihipGraphAddMemsetNode(pGraphNode, graph, pDependencies, numDependencies, pMemsetParams););
|
||||
}
|
||||
|
||||
hipError_t ihipGraphInstantiate(hipGraphExec_t* pGraphExec, hipGraph_t graph,
|
||||
hipGraphNode_t* pErrorNode, char* pLogBuffer, size_t bufferSize) {
|
||||
std::vector<std::vector<Node>> parallelLists;
|
||||
std::unordered_map<Node, std::vector<Node>> nodeWaitLists;
|
||||
graph->GetRunList(parallelLists, nodeWaitLists);
|
||||
std::vector<Node> levelOrder;
|
||||
graph->LevelOrder(levelOrder);
|
||||
*pGraphExec = new hipGraphExec(levelOrder, parallelLists, nodeWaitLists);
|
||||
if (*pGraphExec != nullptr) {
|
||||
return (*pGraphExec)->Init();
|
||||
} else {
|
||||
return hipErrorOutOfMemory;
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t hipGraphInstantiate(hipGraphExec_t* pGraphExec, hipGraph_t graph,
|
||||
hipGraphNode_t* pErrorNode, char* pLogBuffer, size_t bufferSize) {
|
||||
HIP_INIT_API(hipGraphInstantiate, pGraphExec, graph);
|
||||
HIP_RETURN_DURATION(ihipGraphInstantiate(pGraphExec, graph, pErrorNode, pLogBuffer, bufferSize));
|
||||
}
|
||||
|
||||
hipError_t hipGraphExecDestroy(hipGraphExec_t pGraphExec) {
|
||||
HIP_INIT_API(hipGraphExecDestroy, pGraphExec);
|
||||
delete pGraphExec;
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t ihipGraphlaunch(hipGraphExec_t graphExec, hipStream_t stream) {
|
||||
return graphExec->Run(stream);
|
||||
}
|
||||
|
||||
hipError_t hipGraphLaunch(hipGraphExec_t graphExec, hipStream_t stream) {
|
||||
HIP_INIT_API(hipGraphLaunch, graphExec, stream);
|
||||
HIP_RETURN_DURATION(ihipGraphlaunch(graphExec, stream));
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/* Copyright (c) 2021-present Advanced Micro Devices, Inc.
|
||||
|
||||
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
|
||||
// forward declaration of capture methods
|
||||
hipError_t capturehipLaunchKernel(hipStream_t& stream, const void*& hostFunction, dim3& gridDim,
|
||||
dim3& blockDim, void**& args, size_t& sharedMemBytes);
|
||||
|
||||
hipError_t capturehipMemcpy3DAsync(hipStream_t& stream, const hipMemcpy3DParms*& p);
|
||||
|
||||
hipError_t capturehipMemcpyAsync(hipStream_t& stream, void*& dst, const void*& src,
|
||||
size_t& sizeBytes, hipMemcpyKind& kind);
|
||||
|
||||
hipError_t capturehipMemcpyFromSymbolAsync(hipStream_t& stream, void*& dst, const void*& symbol,
|
||||
size_t& sizeBytes, size_t& offset, hipMemcpyKind& kind);
|
||||
|
||||
hipError_t capturehipMemcpyToSymbolAsync(hipStream_t& stream, const void*& symbol, const void*& src,
|
||||
size_t& sizeBytes, size_t& offset, hipMemcpyKind& kind);
|
||||
|
||||
hipError_t capturehipMemsetAsync(hipStream_t& stream, void*& dst, int& value, size_t& valueSize,
|
||||
size_t& sizeBytes);
|
||||
|
||||
hipError_t capturehipMemset2DAsync(hipStream_t& stream, void*& dst, size_t& pitch, int& value,
|
||||
size_t& width, size_t& height);
|
||||
|
||||
hipError_t capturehipMemset3DAsync(hipStream_t& stream, hipPitchedPtr& pitchedDevPtr, int& value,
|
||||
hipExtent& extent);
|
||||
|
||||
hipError_t capturehipEventRecord(hipStream_t& stream, hipEvent_t& event);
|
||||
|
||||
hipError_t capturehipStreamWaitEvent(hipEvent_t& event, hipStream_t& stream, unsigned int& flags);
|
||||
@@ -0,0 +1,35 @@
|
||||
hipError_t ihipMemcpy3D_validate(const hipMemcpy3DParms* p);
|
||||
|
||||
hipError_t ihipMemcpy_validate(void* dst, const void* src, size_t sizeBytes, hipMemcpyKind kind);
|
||||
|
||||
hipError_t ihipMemcpyCommand(amd::Command*& command, void* dst, const void* src, size_t sizeBytes,
|
||||
hipMemcpyKind kind, amd::HostQueue& queue);
|
||||
|
||||
hipError_t ihipLaunchKernel_validate(hipFunction_t f, uint32_t globalWorkSizeX,
|
||||
uint32_t globalWorkSizeY, uint32_t globalWorkSizeZ,
|
||||
uint32_t blockDimX, uint32_t blockDimY, uint32_t blockDimZ,
|
||||
uint32_t sharedMemBytes, void** kernelParams, void** extra,
|
||||
int deviceId, uint32_t params);
|
||||
|
||||
hipError_t ihipMemset_validate(void* dst, int64_t value, size_t valueSize, size_t sizeBytes);
|
||||
|
||||
hipError_t ihipMemset3D_validate(hipPitchedPtr pitchedDevPtr, int value, hipExtent extent,
|
||||
size_t sizeBytes);
|
||||
|
||||
hipError_t ihipLaunchKernelCommand(amd::Command*& command, hipFunction_t f,
|
||||
uint32_t globalWorkSizeX, uint32_t globalWorkSizeY,
|
||||
uint32_t globalWorkSizeZ, uint32_t blockDimX, uint32_t blockDimY,
|
||||
uint32_t blockDimZ, uint32_t sharedMemBytes,
|
||||
amd::HostQueue* queue, void** kernelParams, void** extra,
|
||||
hipEvent_t startEvent, hipEvent_t stopEvent, uint32_t flags,
|
||||
uint32_t params, uint32_t gridId, uint32_t numGrids,
|
||||
uint64_t prevGridSum, uint64_t allGridSum, uint32_t firstDevice);
|
||||
|
||||
hipError_t ihipMemcpy3DCommand(amd::Command*& command, const hipMemcpy3DParms* p,
|
||||
amd::HostQueue* queue);
|
||||
|
||||
hipError_t ihipMemsetCommand(std::vector<amd::Command*>& commands, void* dst, int64_t value,
|
||||
size_t valueSize, size_t sizeBytes, amd::HostQueue* queue);
|
||||
|
||||
hipError_t ihipMemset3DCommand(std::vector<amd::Command*>& commands, hipPitchedPtr pitchedDevPtr,
|
||||
int value, hipExtent extent, amd::HostQueue* queue);
|
||||
@@ -0,0 +1,364 @@
|
||||
/* Copyright (c) 2021-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include "hip_graph_internal.hpp"
|
||||
#include <queue>
|
||||
|
||||
#define CASE_STRING(X, C) \
|
||||
case X: \
|
||||
case_string = #C; \
|
||||
break;
|
||||
const char* GetGraphNodeTypeString(uint32_t op) {
|
||||
const char* case_string;
|
||||
switch (static_cast<hipGraphNodeType>(op)) {
|
||||
CASE_STRING(hipGraphNodeTypeKernel, KernelNode)
|
||||
CASE_STRING(hipGraphNodeTypeMemcpy, Memcpy3DNode)
|
||||
CASE_STRING(hipGraphNodeTypeMemset, MemsetNode)
|
||||
CASE_STRING(hipGraphNodeTypeHost, HostNode)
|
||||
CASE_STRING(hipGraphNodeTypeGraph, GraphNode)
|
||||
CASE_STRING(hipGraphNodeTypeEmpty, EmptyNode)
|
||||
CASE_STRING(hipGraphNodeTypeWaitEvent, WaitEventNode)
|
||||
CASE_STRING(hipGraphNodeTypeEventRecord, EventRecordNode)
|
||||
CASE_STRING(hipGraphNodeTypeMemcpy1D, Memcpy1DNode)
|
||||
CASE_STRING(hipGraphNodeTypeMemcpyFromSymbol, MemcpyFromSymbolNode)
|
||||
CASE_STRING(hipGraphNodeTypeMemcpyToSymbol, MemcpyToSymbolNode)
|
||||
default:
|
||||
case_string = "Unknown node type";
|
||||
};
|
||||
return case_string;
|
||||
};
|
||||
|
||||
hipError_t hipGraph::AddNode(const Node& node) {
|
||||
vertices_.emplace_back(node);
|
||||
nodeOutDegree_[node] = 0;
|
||||
nodeInDegree_[node] = 0;
|
||||
node->SetLevel(0);
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_CODE, "[hipGraph] Add %s(%p)\n",
|
||||
GetGraphNodeTypeString(node->GetType()), node);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t hipGraph::AddEdge(const Node& parentNode, const Node& childNode) {
|
||||
// if vertice doesn't exist, add it to the graph
|
||||
if (std::find(vertices_.begin(), vertices_.end(), parentNode) == vertices_.end()) {
|
||||
AddNode(parentNode);
|
||||
}
|
||||
if (std::find(vertices_.begin(), vertices_.end(), childNode) == vertices_.end()) {
|
||||
AddNode(childNode);
|
||||
}
|
||||
// Check if edge already exists
|
||||
auto connectedEdges = edges_.find(parentNode);
|
||||
if (connectedEdges != edges_.end()) {
|
||||
if (std::find(connectedEdges->second.begin(), connectedEdges->second.end(), childNode) !=
|
||||
connectedEdges->second.end()) {
|
||||
return hipSuccess;
|
||||
}
|
||||
connectedEdges->second.emplace_back(childNode);
|
||||
} else {
|
||||
edges_[parentNode] = {childNode};
|
||||
}
|
||||
nodeOutDegree_[parentNode]++;
|
||||
nodeInDegree_[childNode]++;
|
||||
childNode->SetLevel(std::max(childNode->GetLevel(), parentNode->GetLevel() + 1));
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_CODE, "[hipGraph] Add edge btwn %s(%p) - %s(%p)\n",
|
||||
GetGraphNodeTypeString(parentNode->GetType()), parentNode,
|
||||
GetGraphNodeTypeString(childNode->GetType()), childNode);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
// root nodes are all vertices with 0 in-degrees
|
||||
std::vector<Node> hipGraph::GetRootNodes() const {
|
||||
std::vector<Node> roots;
|
||||
for (auto entry : vertices_) {
|
||||
if (nodeInDegree_.at(entry) == 0) {
|
||||
roots.push_back(entry);
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_CODE, "[hipGraph] root node: %s(%p)\n",
|
||||
GetGraphNodeTypeString(entry->GetType()), entry);
|
||||
}
|
||||
}
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_CODE, "\n");
|
||||
return roots;
|
||||
}
|
||||
|
||||
// leaf nodes are all vertices with 0 out-degrees
|
||||
std::vector<Node> hipGraph::GetLeafNodes() const {
|
||||
std::vector<Node> leafNodes;
|
||||
for (auto entry : vertices_) {
|
||||
if (nodeOutDegree_.at(entry) == 0) {
|
||||
leafNodes.push_back(entry);
|
||||
}
|
||||
}
|
||||
return leafNodes;
|
||||
}
|
||||
|
||||
size_t hipGraph::GetLeafNodeCount() const {
|
||||
int numLeafNodes = 0;
|
||||
for (auto entry : vertices_) {
|
||||
if (nodeOutDegree_.at(entry) == 0) {
|
||||
numLeafNodes++;
|
||||
}
|
||||
}
|
||||
return numLeafNodes;
|
||||
}
|
||||
|
||||
std::vector<std::pair<Node, Node>> hipGraph::GetEdges() const {
|
||||
std::vector<std::pair<Node, Node>> edges;
|
||||
for (const auto& i : edges_) {
|
||||
for (const auto& j : i.second) {
|
||||
edges.push_back(std::make_pair(i.first, j));
|
||||
}
|
||||
}
|
||||
return edges;
|
||||
}
|
||||
|
||||
void hipGraph::GetRunListUtil(Node v, std::unordered_map<Node, bool>& visited,
|
||||
std::vector<Node>& singleList,
|
||||
std::vector<std::vector<Node>>& parallelLists,
|
||||
std::unordered_map<Node, std::vector<Node>>& dependencies) {
|
||||
// Mark the current node as visited.
|
||||
visited[v] = true;
|
||||
singleList.push_back(v);
|
||||
// Recurse for all the vertices adjacent to this vertex
|
||||
for (auto& adjNode : edges_[v]) {
|
||||
if (!visited[adjNode]) {
|
||||
// For the parallel list nodes add parent as the dependency
|
||||
if (singleList.empty()) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_CODE,
|
||||
"[hipGraph] For %s(%p)- add parent as dependency %s(%p)\n",
|
||||
GetGraphNodeTypeString(adjNode->GetType()), adjNode,
|
||||
GetGraphNodeTypeString(v->GetType()), v);
|
||||
dependencies[adjNode].push_back(v);
|
||||
}
|
||||
GetRunListUtil(adjNode, visited, singleList, parallelLists, dependencies);
|
||||
} else {
|
||||
for (auto& list : parallelLists) {
|
||||
// Merge singleList when adjNode matches with the first element of the list in existing
|
||||
// lists
|
||||
if (adjNode == list[0]) {
|
||||
for (auto k = singleList.rbegin(); k != singleList.rend(); ++k) {
|
||||
list.insert(list.begin(), *k);
|
||||
}
|
||||
singleList.erase(singleList.begin(), singleList.end());
|
||||
}
|
||||
}
|
||||
// If the list cannot be merged with the existing list add as dependancy
|
||||
if (!singleList.empty()) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_CODE, "[hipGraph] For %s(%p)- add dependency %s(%p)\n",
|
||||
GetGraphNodeTypeString(adjNode->GetType()), adjNode,
|
||||
GetGraphNodeTypeString(v->GetType()), v);
|
||||
dependencies[adjNode].push_back(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!singleList.empty()) {
|
||||
parallelLists.push_back(singleList);
|
||||
singleList.erase(singleList.begin(), singleList.end());
|
||||
}
|
||||
}
|
||||
// The function to do Topological Sort.
|
||||
// It uses recursive GetRunListUtil()
|
||||
void hipGraph::GetRunList(std::vector<std::vector<Node>>& parallelLists,
|
||||
std::unordered_map<Node, std::vector<Node>>& dependencies) {
|
||||
std::vector<Node> singleList;
|
||||
|
||||
// Mark all the vertices as not visited
|
||||
std::unordered_map<Node, bool> visited;
|
||||
for (auto node : vertices_) visited[node] = false;
|
||||
|
||||
// Call the recursive helper function for all vertices one by one
|
||||
for (auto node : vertices_) {
|
||||
if (visited[node] == false) {
|
||||
GetRunListUtil(node, visited, singleList, parallelLists, dependencies);
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < parallelLists.size(); i++) {
|
||||
for (size_t j = 0; j < parallelLists[i].size(); j++) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_CODE, "[hipGraph] list %d - %s(%p)\n", i + 1,
|
||||
GetGraphNodeTypeString(parallelLists[i][j]->GetType()), parallelLists[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t hipGraph::LevelOrder(std::vector<Node>& levelOrder) {
|
||||
std::vector<Node> roots = GetRootNodes();
|
||||
std::unordered_map<Node, bool> visited;
|
||||
std::queue<Node> q;
|
||||
for (auto it = roots.begin(); it != roots.end(); it++) {
|
||||
q.push(*it);
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_CODE, "[hipGraph] %s(%p) level:%d \n",
|
||||
GetGraphNodeTypeString((*it)->GetType()), *it, (*it)->GetLevel());
|
||||
}
|
||||
while (!q.empty()) {
|
||||
Node& node = q.front();
|
||||
q.pop();
|
||||
levelOrder.push_back(node);
|
||||
for (const auto& i : edges_[node]) {
|
||||
if (visited.find(i) == visited.end() && i->GetLevel() == (node->GetLevel() + 1)) {
|
||||
q.push(i);
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_CODE, "[hipGraph] %s(%p) level:%d \n",
|
||||
GetGraphNodeTypeString(i->GetType()), i, i->GetLevel());
|
||||
visited[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t hipGraphExec::CreateQueues() {
|
||||
parallelQueues_.reserve(parallelLists_.size());
|
||||
for (size_t i = 0; i < parallelLists_.size(); i++) {
|
||||
amd::HostQueue* queue;
|
||||
cl_command_queue_properties properties =
|
||||
(callbacks_table.is_enabled() || HIP_FORCE_QUEUE_PROFILING) ? CL_QUEUE_PROFILING_ENABLE : 0;
|
||||
queue = new amd::HostQueue(*hip::getCurrentDevice()->asContext(),
|
||||
*hip::getCurrentDevice()->devices()[0], properties);
|
||||
|
||||
bool result = (queue != nullptr) ? queue->create() : false;
|
||||
// Create a host queue
|
||||
if (result) {
|
||||
parallelQueues_.push_back(queue);
|
||||
} else {
|
||||
ClPrint(amd::LOG_ERROR, amd::LOG_CODE, "[hipGraph] Failed to create host queue\n");
|
||||
return hipErrorOutOfMemory;
|
||||
}
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t hipGraphExec::FillCommands() {
|
||||
// Create commands
|
||||
int i = 0;
|
||||
hipError_t status;
|
||||
for (const auto& list : parallelLists_) {
|
||||
for (auto& node : list) {
|
||||
status = node->CreateCommand(parallelQueues_[i]);
|
||||
if (status != hipSuccess) return status;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// Add waitlists for all the commands
|
||||
for (auto& node : levelOrder_) {
|
||||
auto nodeWaitList = nodeWaitLists_.find(node);
|
||||
if (nodeWaitList != nodeWaitLists_.end()) {
|
||||
amd::Command::EventWaitList waitList;
|
||||
for (auto depNode : nodeWaitList->second) {
|
||||
for (auto command : depNode->GetCommands()) {
|
||||
waitList.push_back(command);
|
||||
}
|
||||
}
|
||||
for (auto command : nodeWaitList->first->GetCommands()) {
|
||||
command->updateEventWaitList(waitList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
hipError_t hipGraphExec::Init() {
|
||||
hipError_t status;
|
||||
status = CreateQueues();
|
||||
if (status != hipSuccess) {
|
||||
return status;
|
||||
}
|
||||
status = FillCommands();
|
||||
if (status != hipSuccess) {
|
||||
return status;
|
||||
}
|
||||
rootCommand_ = nullptr;
|
||||
/// stream should execute next command after graph finishes
|
||||
/// Add marker to the stream that waits for all the last commands in parallel queues of graph
|
||||
for (auto& singleList : parallelLists_) {
|
||||
graphLastCmdWaitList_.push_back(singleList.back()->GetCommands().back());
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void hipGraphExec::ResetGraph(cl_event event, cl_int command_exec_status, void* user_data) {
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_CODE, "[hipGraph] Inside resetGraph!\n");
|
||||
hipGraphExec_t graphExec =
|
||||
hipGraphExec::activeGraphExec_[reinterpret_cast<amd::Command*>(user_data)];
|
||||
if (graphExec != nullptr) {
|
||||
for (auto& node : graphExec->levelOrder_) {
|
||||
for (auto& command : node->GetCommands()) {
|
||||
command->resetStatus(CL_INT_MAX);
|
||||
}
|
||||
}
|
||||
graphExec->rootCommand_->resetStatus(CL_INT_MAX);
|
||||
graphExec->bExecPending_.store(false);
|
||||
} else {
|
||||
ClPrint(amd::LOG_ERROR, amd::LOG_CODE, "[hipGraph] graphExec is nullptr during resetGraph!\n");
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t hipGraphExec::UpdateGraphToWaitOnRoot() {
|
||||
for (auto& singleList : parallelLists_) {
|
||||
amd::Command::EventWaitList waitList;
|
||||
waitList.push_back(rootCommand_);
|
||||
if (!singleList.empty()) {
|
||||
auto commands = singleList[0]->GetCommands();
|
||||
if (!commands.empty()) {
|
||||
commands[0]->updateEventWaitList(waitList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t hipGraphExec::Run(hipStream_t stream) {
|
||||
if (bExecPending_.load() == true) {
|
||||
ClPrint(
|
||||
amd::LOG_INFO, amd::LOG_CODE,
|
||||
"[hipGraph] Same graph launched while previous one is active, wait for it to finish!\n");
|
||||
lastEnqueuedGraphCmd_->awaitCompletion();
|
||||
}
|
||||
amd::HostQueue* queue = hip::getQueue(stream);
|
||||
if (queue == nullptr) {
|
||||
return hipErrorInvalidResourceHandle;
|
||||
}
|
||||
if (rootCommand_ == nullptr || rootCommand_->queue() != queue) {
|
||||
if (rootCommand_ != nullptr) {
|
||||
rootCommand_->release();
|
||||
}
|
||||
rootCommand_ = new amd::Marker(*queue, false, {});
|
||||
UpdateGraphToWaitOnRoot();
|
||||
}
|
||||
rootCommand_->enqueue();
|
||||
for (auto& node : levelOrder_) {
|
||||
for (auto& command : node->GetCommands()) {
|
||||
command->enqueue();
|
||||
}
|
||||
}
|
||||
|
||||
amd::Command* command = new amd::Marker(*queue, false, graphLastCmdWaitList_);
|
||||
if (command == nullptr) {
|
||||
return hipErrorOutOfMemory;
|
||||
}
|
||||
amd::Event& event = command->event();
|
||||
if (!event.setCallback(CL_COMPLETE, hipGraphExec::ResetGraph, command)) {
|
||||
return hipErrorInvalidHandle;
|
||||
}
|
||||
hipGraphExec::activeGraphExec_[command] = this;
|
||||
lastEnqueuedGraphCmd_ = command;
|
||||
bExecPending_.store(true);
|
||||
command->enqueue();
|
||||
command->release();
|
||||
return hipSuccess;
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
/* Copyright (c) 2021-present Advanced Micro Devices, Inc.
|
||||
|
||||
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 <algorithm>
|
||||
#include <queue>
|
||||
#include <stack>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "hip_internal.hpp"
|
||||
#include "hip_graph_helper.hpp"
|
||||
|
||||
typedef hipGraphNode* Node;
|
||||
|
||||
class hipGraphNode {
|
||||
protected:
|
||||
uint32_t level_;
|
||||
hipGraphNodeType type_;
|
||||
std::vector<amd::Command*> commands_;
|
||||
bool visited_;
|
||||
|
||||
public:
|
||||
hipGraphNode(hipGraphNodeType type) {
|
||||
type_ = type;
|
||||
level_ = 0;
|
||||
visited_ = false;
|
||||
}
|
||||
virtual ~hipGraphNode() {
|
||||
for (auto command : commands_) {
|
||||
delete command;
|
||||
}
|
||||
}
|
||||
virtual hipError_t CreateCommand(amd::HostQueue* queue) { return hipSuccess; }
|
||||
std::vector<amd::Command*>& GetCommands() { return commands_; }
|
||||
hipGraphNodeType GetType() { return type_; }
|
||||
uint32_t GetLevel() { return level_; }
|
||||
void SetLevel(uint32_t level) { level_ = level; }
|
||||
};
|
||||
|
||||
class hipGraph {
|
||||
std::unordered_map<Node, size_t> nodeInDegree_; // count of in coming edges for every vertex
|
||||
std::unordered_map<Node, size_t> nodeOutDegree_; // count of outgoing edges for every vertex
|
||||
std::vector<Node> vertices_;
|
||||
std::unordered_map<Node, std::vector<Node>> edges_;
|
||||
|
||||
public:
|
||||
hipGraph() {}
|
||||
~hipGraph(){};
|
||||
/// add node to the graph
|
||||
hipError_t AddNode(const Node& node);
|
||||
/// add edge to the graph
|
||||
hipError_t AddEdge(const Node& parentNode, const Node& childNode);
|
||||
/// Returns root nodes, all vertices with 0 in-degrees
|
||||
std::vector<Node> GetRootNodes() const;
|
||||
/// Returns leaf nodes, all vertices with 0 out-degrees
|
||||
std::vector<Node> GetLeafNodes() const;
|
||||
/// Returns number of leaf nodes
|
||||
size_t GetLeafNodeCount() const;
|
||||
/// Returns total numbers of nodes in the graph
|
||||
size_t GetNodeCount() const { return vertices_.size(); }
|
||||
/// returns all the nodes in the graph
|
||||
std::vector<Node> GetNodes() const { return vertices_; }
|
||||
/// returns all the edges in the graph
|
||||
std::vector<std::pair<Node, Node>> GetEdges() const;
|
||||
void GetRunListUtil(Node v, std::unordered_map<Node, bool>& visited,
|
||||
std::vector<Node>& singleList, std::vector<std::vector<Node>>& parallelList,
|
||||
std::unordered_map<Node, std::vector<Node>>& dependencies);
|
||||
void GetRunList(std::vector<std::vector<Node>>& parallelList,
|
||||
std::unordered_map<Node, std::vector<Node>>& dependencies);
|
||||
hipError_t LevelOrder(std::vector<Node>& levelOrder);
|
||||
};
|
||||
|
||||
class hipGraphKernelNode : public hipGraphNode {
|
||||
hipKernelNodeParams* pKernelParams_;
|
||||
hipFunction_t func_;
|
||||
|
||||
public:
|
||||
hipGraphKernelNode(const hipKernelNodeParams* pNodeParams, const hipFunction_t func)
|
||||
: hipGraphNode(hipGraphNodeTypeKernel) {
|
||||
pKernelParams_ = new hipKernelNodeParams(*pNodeParams);
|
||||
func_ = func;
|
||||
}
|
||||
~hipGraphKernelNode() { delete pKernelParams_; }
|
||||
|
||||
hipError_t CreateCommand(amd::HostQueue* queue) {
|
||||
commands_.reserve(1);
|
||||
amd::Command* command;
|
||||
hipError_t status = ihipLaunchKernelCommand(
|
||||
command, func_, pKernelParams_->gridDim.x * pKernelParams_->blockDim.x,
|
||||
pKernelParams_->gridDim.y * pKernelParams_->blockDim.y,
|
||||
pKernelParams_->gridDim.z * pKernelParams_->blockDim.z, pKernelParams_->blockDim.x,
|
||||
pKernelParams_->blockDim.y, pKernelParams_->blockDim.z, pKernelParams_->sharedMemBytes,
|
||||
queue, pKernelParams_->kernelParams, pKernelParams_->extra, nullptr, nullptr, 0, 0, 0, 0, 0,
|
||||
0, 0);
|
||||
commands_.emplace_back(command);
|
||||
return status;
|
||||
}
|
||||
|
||||
void GetParams(hipKernelNodeParams* params) {
|
||||
std::memcpy(params, pKernelParams_, sizeof(hipKernelNodeParams));
|
||||
}
|
||||
void SetParams(hipKernelNodeParams* params) {
|
||||
std::memcpy(pKernelParams_, params, sizeof(hipKernelNodeParams));
|
||||
}
|
||||
};
|
||||
|
||||
class hipGraphMemcpyNode : public hipGraphNode {
|
||||
hipMemcpy3DParms* pCopyParams_;
|
||||
|
||||
public:
|
||||
hipGraphMemcpyNode(const hipMemcpy3DParms* pCopyParams) : hipGraphNode(hipGraphNodeTypeMemcpy) {
|
||||
pCopyParams_ = new hipMemcpy3DParms(*pCopyParams);
|
||||
}
|
||||
~hipGraphMemcpyNode() { delete pCopyParams_; }
|
||||
|
||||
hipError_t CreateCommand(amd::HostQueue* queue) {
|
||||
commands_.reserve(1);
|
||||
amd::Command* command;
|
||||
hipError_t status = ihipMemcpy3DCommand(command, pCopyParams_, queue);
|
||||
commands_.emplace_back(command);
|
||||
return status;
|
||||
}
|
||||
|
||||
void GetParams(hipMemcpy3DParms* params) {
|
||||
std::memcpy(params, pCopyParams_, sizeof(hipMemcpy3DParms));
|
||||
}
|
||||
void SetParams(hipMemcpy3DParms* params) {
|
||||
std::memcpy(pCopyParams_, params, sizeof(hipMemcpy3DParms));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class hipGraphMemcpyNode1D : public hipGraphNode {
|
||||
void* dst_;
|
||||
const void* src_;
|
||||
size_t count_;
|
||||
hipMemcpyKind kind_;
|
||||
|
||||
public:
|
||||
hipGraphMemcpyNode1D(void* dst, const void* src, size_t count, hipMemcpyKind kind)
|
||||
: hipGraphNode(hipGraphNodeTypeMemcpy1D), dst_(dst), src_(src), count_(count), kind_(kind) {}
|
||||
~hipGraphMemcpyNode1D() {}
|
||||
|
||||
hipError_t CreateCommand(amd::HostQueue* queue) {
|
||||
commands_.reserve(1);
|
||||
amd::Command* command = nullptr;
|
||||
hipError_t status = ihipMemcpyCommand(command, dst_, src_, count_, kind_, *queue);
|
||||
commands_.emplace_back(command);
|
||||
return status;
|
||||
}
|
||||
|
||||
void SetParams(void* dst, const void* src, size_t count, hipMemcpyKind kind) {
|
||||
dst_ = dst;
|
||||
src_ = src;
|
||||
count_ = count;
|
||||
kind_ = kind;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> class hipGraphMemcpyNodeFromSymbol : public hipGraphNode {
|
||||
void* dst_;
|
||||
const T& symbol_;
|
||||
size_t count_;
|
||||
size_t offset_;
|
||||
hipMemcpyKind kind_;
|
||||
|
||||
public:
|
||||
hipGraphMemcpyNodeFromSymbol(void* dst, const void* symbol, size_t count, size_t offset,
|
||||
hipMemcpyKind kind)
|
||||
: hipGraphNode(hipGraphNodeTypeMemcpyFromSymbol),
|
||||
dst_(dst),
|
||||
symbol_(symbol),
|
||||
count_(count),
|
||||
offset_(offset),
|
||||
kind_(kind) {}
|
||||
~hipGraphMemcpyNodeFromSymbol() {}
|
||||
|
||||
hipError_t CreateCommand(amd::HostQueue* queue);
|
||||
|
||||
void SetParams(void* dst, const void* symbol, size_t count, size_t offset, hipMemcpyKind kind) {
|
||||
dst_ = dst;
|
||||
symbol_ = symbol;
|
||||
count_ = count;
|
||||
offset_ = offset;
|
||||
kind_ = kind;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> class hipGraphMemcpyNodeToSymbol : public hipGraphNode {
|
||||
const T& symbol_;
|
||||
const void* src_;
|
||||
size_t count_;
|
||||
size_t offset_;
|
||||
hipMemcpyKind kind_;
|
||||
|
||||
public:
|
||||
hipGraphMemcpyNodeToSymbol(const T& symbol, void* src, size_t count, size_t offset,
|
||||
hipMemcpyKind kind)
|
||||
: hipGraphNode(hipGraphNodeTypeMemcpyToSymbol),
|
||||
symbol_(symbol),
|
||||
src_(src),
|
||||
count_(count),
|
||||
offset_(offset),
|
||||
kind_(kind) {}
|
||||
~hipGraphMemcpyNodeToSymbol() {}
|
||||
|
||||
hipError_t CreateCommand(amd::HostQueue* queue);
|
||||
|
||||
void SetParams(const T& symbol, void* src, size_t count, size_t offset, hipMemcpyKind kind) {
|
||||
symbol_ = symbol;
|
||||
src_ = src;
|
||||
count_ = count;
|
||||
offset_ = offset;
|
||||
kind_ = kind;
|
||||
}
|
||||
};
|
||||
|
||||
class hipGraphMemsetNode : public hipGraphNode {
|
||||
hipMemsetParams* pMemsetParams_;
|
||||
|
||||
public:
|
||||
hipGraphMemsetNode(const hipMemsetParams* pMemsetParams) : hipGraphNode(hipGraphNodeTypeMemset) {
|
||||
pMemsetParams_ = new hipMemsetParams(*pMemsetParams);
|
||||
}
|
||||
~hipGraphMemsetNode() { delete pMemsetParams_; }
|
||||
|
||||
hipError_t CreateCommand(amd::HostQueue* queue) {
|
||||
if (pMemsetParams_->height == 1) {
|
||||
return ihipMemsetCommand(commands_, pMemsetParams_->dst, pMemsetParams_->value,
|
||||
pMemsetParams_->elementSize,
|
||||
pMemsetParams_->width * pMemsetParams_->elementSize, queue);
|
||||
} else {
|
||||
return ihipMemset3DCommand(commands_,
|
||||
{pMemsetParams_->dst, pMemsetParams_->pitch, pMemsetParams_->width,
|
||||
pMemsetParams_->height},
|
||||
pMemsetParams_->elementSize,
|
||||
{pMemsetParams_->width, pMemsetParams_->height, 1}, queue);
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
void GetParams(hipMemsetParams* params) {
|
||||
std::memcpy(params, pMemsetParams_, sizeof(hipMemsetParams));
|
||||
}
|
||||
void SetParams(hipMemsetParams* params) {
|
||||
std::memcpy(pMemsetParams_, params, sizeof(hipMemsetParams));
|
||||
}
|
||||
};
|
||||
|
||||
class hipGraphEventRecordNode : public hipGraphNode {
|
||||
hipEvent_t event_;
|
||||
|
||||
public:
|
||||
hipGraphEventRecordNode(hipEvent_t event)
|
||||
: hipGraphNode(hipGraphNodeTypeEventRecord), event_(event) {}
|
||||
~hipGraphEventRecordNode() {}
|
||||
|
||||
hipError_t CreateCommand(amd::HostQueue* queue);
|
||||
|
||||
void GetParams(hipEvent_t* event) { *event = event_; }
|
||||
void SetParams(hipEvent_t event) { event_ = event; }
|
||||
};
|
||||
|
||||
class hipGraphEventWaitNode : public hipGraphNode {
|
||||
hipEvent_t event_;
|
||||
|
||||
public:
|
||||
hipGraphEventWaitNode(hipEvent_t event)
|
||||
: hipGraphNode(hipGraphNodeTypeWaitEvent), event_(event) {}
|
||||
~hipGraphEventWaitNode() {}
|
||||
|
||||
hipError_t CreateCommand(amd::HostQueue* queue);
|
||||
|
||||
void GetParams(hipEvent_t* event) { *event = event_; }
|
||||
void SetParams(hipEvent_t event) { event_ = event; }
|
||||
};
|
||||
|
||||
class hipGraphHostNode : public hipGraphNode {
|
||||
hipHostNodeParams* pNodeParams_;
|
||||
|
||||
public:
|
||||
hipGraphHostNode(const hipHostNodeParams* pNodeParams) : hipGraphNode(hipGraphNodeTypeHost) {
|
||||
pNodeParams_ = new hipHostNodeParams(*pNodeParams);
|
||||
}
|
||||
~hipGraphHostNode() { delete pNodeParams_; }
|
||||
|
||||
hipError_t CreateCommand(amd::HostQueue* queue);
|
||||
|
||||
void GetParams(hipHostNodeParams* params) {
|
||||
std::memcpy(params, pNodeParams_, sizeof(hipHostNodeParams));
|
||||
}
|
||||
void SetParams(hipHostNodeParams* params) {
|
||||
std::memcpy(pNodeParams_, params, sizeof(hipHostNodeParams));
|
||||
}
|
||||
};
|
||||
|
||||
class hipGraphExec {
|
||||
std::vector<std::vector<Node>> parallelLists_;
|
||||
std::vector<Node> levelOrder_;
|
||||
std::unordered_map<Node, std::vector<Node>> nodeWaitLists_;
|
||||
std::vector<amd::HostQueue*> parallelQueues_;
|
||||
static std::unordered_map<amd::Command*, hipGraphExec_t> activeGraphExec_;
|
||||
amd::Command::EventWaitList graphLastCmdWaitList_;
|
||||
amd::Command* lastEnqueuedGraphCmd_;
|
||||
std::atomic<bool> bExecPending_;
|
||||
amd::Command* rootCommand_;
|
||||
|
||||
public:
|
||||
hipGraphExec(std::vector<Node>& levelOrder, std::vector<std::vector<Node>>& lists,
|
||||
std::unordered_map<Node, std::vector<Node>>& nodeWaitLists)
|
||||
: parallelLists_(lists),
|
||||
levelOrder_(levelOrder),
|
||||
nodeWaitLists_(nodeWaitLists),
|
||||
lastEnqueuedGraphCmd_(nullptr),
|
||||
rootCommand_(nullptr) {
|
||||
bExecPending_.store(false);
|
||||
}
|
||||
|
||||
~hipGraphExec() {
|
||||
for (auto queue : parallelQueues_) {
|
||||
queue->release();
|
||||
}
|
||||
for (auto node : levelOrder_) {
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t CreateQueues();
|
||||
hipError_t FillCommands();
|
||||
hipError_t Init();
|
||||
hipError_t UpdateGraphToWaitOnRoot();
|
||||
hipError_t Run(hipStream_t stream);
|
||||
static void ResetGraph(cl_event event, cl_int command_exec_status, void* user_data);
|
||||
};
|
||||
Executable
+293
@@ -0,0 +1,293 @@
|
||||
EXPORTS
|
||||
hipChooseDevice
|
||||
hipCtxCreate
|
||||
hipCtxDestroy
|
||||
hipCtxDisablePeerAccess
|
||||
hipCtxEnablePeerAccess
|
||||
hipCtxGetApiVersion
|
||||
hipCtxGetCacheConfig
|
||||
hipCtxGetCurrent
|
||||
hipCtxGetDevice
|
||||
hipCtxGetFlags
|
||||
hipCtxGetSharedMemConfig
|
||||
hipCtxPopCurrent
|
||||
hipCtxPushCurrent
|
||||
hipCtxSetCacheConfig
|
||||
hipCtxSetCurrent
|
||||
hipCtxSetSharedMemConfig
|
||||
hipCtxSynchronize
|
||||
hipDeviceCanAccessPeer
|
||||
hipDeviceComputeCapability
|
||||
hipDeviceDisablePeerAccess
|
||||
hipDeviceEnablePeerAccess
|
||||
hipDeviceGet
|
||||
hipDeviceGetAttribute
|
||||
hipDeviceGetByPCIBusId
|
||||
hipDeviceGetCacheConfig
|
||||
hipDeviceGetStreamPriorityRange
|
||||
hipDeviceGetLimit
|
||||
hipDeviceGetName
|
||||
hipDeviceGetPCIBusId
|
||||
hipDeviceGetSharedMemConfig
|
||||
hipDeviceGetP2PAttribute
|
||||
hipDevicePrimaryCtxGetState
|
||||
hipDevicePrimaryCtxRelease
|
||||
hipDevicePrimaryCtxReset
|
||||
hipDevicePrimaryCtxRetain
|
||||
hipDevicePrimaryCtxSetFlags
|
||||
hipDeviceReset
|
||||
hipDeviceSetCacheConfig
|
||||
hipDeviceSetSharedMemConfig
|
||||
hipDeviceSynchronize
|
||||
hipDeviceTotalMem
|
||||
hipDriverGetVersion
|
||||
hipEventCreate
|
||||
hipEventCreateWithFlags
|
||||
hipEventDestroy
|
||||
hipEventElapsedTime
|
||||
hipEventQuery
|
||||
hipEventRecord
|
||||
hipEventSynchronize
|
||||
hipExtGetLinkTypeAndHopCount
|
||||
hipExtLaunchMultiKernelMultiDevice
|
||||
hipExtMallocWithFlags
|
||||
hipExtModuleLaunchKernel
|
||||
hipExtLaunchKernel
|
||||
hipFree
|
||||
hipFreeArray
|
||||
hipFuncSetAttribute
|
||||
hipFuncSetCacheConfig
|
||||
hipFuncSetSharedMemConfig
|
||||
hipGetDevice
|
||||
hipGetDeviceCount
|
||||
hipGetDeviceProperties
|
||||
hipGetErrorName
|
||||
hipGetErrorString
|
||||
hipGetLastError
|
||||
hipMemAllocHost
|
||||
hipHostAlloc
|
||||
hipHostFree
|
||||
hipHostGetDevicePointer
|
||||
hipHostGetFlags
|
||||
hipHostMalloc
|
||||
hipHostRegister
|
||||
hipHostUnregister
|
||||
hipInit
|
||||
hipIpcCloseMemHandle
|
||||
hipIpcGetMemHandle
|
||||
hipIpcOpenMemHandle
|
||||
hipIpcGetEventHandle
|
||||
hipIpcOpenEventHandle
|
||||
hipMalloc
|
||||
hipMalloc3D
|
||||
hipMalloc3DArray
|
||||
hipMallocManaged
|
||||
hipArrayCreate
|
||||
hipArray3DCreate
|
||||
hipArrayDestroy
|
||||
hipMallocArray
|
||||
hipMemAdvise
|
||||
hipMemAllocPitch
|
||||
hipMallocPitch
|
||||
hipMemcpy
|
||||
hipMemcpyWithStream
|
||||
hipMemcpyParam2D
|
||||
hipMemcpy2D
|
||||
hipMemcpy2DAsync
|
||||
hipMemcpy2DToArray
|
||||
hipMemcpy2DToArrayAsync
|
||||
hipMemcpy3D
|
||||
hipMemcpy3DAsync
|
||||
hipDrvMemcpy3D
|
||||
hipDrvMemcpy3DAsync
|
||||
hipMemcpyAsync
|
||||
hipMemcpyDtoD
|
||||
hipMemcpyDtoDAsync
|
||||
hipMemcpyDtoH
|
||||
hipMemcpyDtoHAsync
|
||||
hipMemcpyFromSymbol
|
||||
hipMemcpyFromSymbolAsync
|
||||
hipMemcpyHtoD
|
||||
hipMemcpyHtoDAsync
|
||||
hipMemcpyPeer
|
||||
hipMemcpyPeerAsync
|
||||
hipMemcpyToArray
|
||||
hipMemcpyFromArray
|
||||
hipMemcpyToSymbol
|
||||
hipMemcpyToSymbolAsync
|
||||
hipMemGetAddressRange
|
||||
hipGetSymbolAddress
|
||||
hipGetSymbolSize
|
||||
hipMemGetInfo
|
||||
hipMemPrefetchAsync
|
||||
hipMemPtrGetInfo
|
||||
hipMemRangeGetAttribute
|
||||
hipMemRangeGetAttributes
|
||||
hipMemset
|
||||
hipMemsetAsync
|
||||
hipMemsetD8
|
||||
hipMemsetD8Async
|
||||
hipMemsetD16
|
||||
hipMemsetD16Async
|
||||
hipMemsetD32
|
||||
hipMemsetD32Async
|
||||
hipMemset2D
|
||||
hipMemset2DAsync
|
||||
hipMemset3D
|
||||
hipMemset3DAsync
|
||||
hipModuleGetFunction
|
||||
hipModuleGetGlobal
|
||||
hipModuleGetTexRef
|
||||
hipModuleLaunchKernel
|
||||
hipModuleLaunchKernelExt
|
||||
hipLaunchCooperativeKernel
|
||||
hipLaunchCooperativeKernelMultiDevice
|
||||
hipHccModuleLaunchKernel
|
||||
hipModuleLoad
|
||||
hipModuleLoadData
|
||||
hipModuleLoadDataEx
|
||||
hipModuleUnload
|
||||
hipModuleOccupancyMaxPotentialBlockSize
|
||||
hipModuleOccupancyMaxPotentialBlockSizeWithFlags
|
||||
hipModuleOccupancyMaxActiveBlocksPerMultiprocessor
|
||||
hipModuleOccupancyMaxActiveBlocksPerMultiprocessorWithFlags
|
||||
hipOccupancyMaxPotentialBlockSize
|
||||
hipOccupancyMaxActiveBlocksPerMultiprocessor
|
||||
hipOccupancyMaxActiveBlocksPerMultiprocessorWithFlags
|
||||
hipFuncGetAttribute
|
||||
hipFuncGetAttributes
|
||||
hipPeekAtLastError
|
||||
hipPointerGetAttributes
|
||||
hipProfilerStart
|
||||
hipProfilerStop
|
||||
hipRuntimeGetVersion
|
||||
hipGetDeviceFlags
|
||||
hipSetDevice
|
||||
hipSetDeviceFlags
|
||||
hipStreamAddCallback
|
||||
hipStreamAttachMemAsync
|
||||
hipStreamCreate
|
||||
hipStreamCreateWithFlags
|
||||
hipStreamCreateWithPriority
|
||||
hipStreamDestroy
|
||||
hipStreamGetFlags
|
||||
hipStreamQuery
|
||||
hipStreamSynchronize
|
||||
hipStreamWaitEvent
|
||||
__hipPopCallConfiguration
|
||||
__hipPushCallConfiguration
|
||||
__hipRegisterFatBinary
|
||||
__hipRegisterFunction
|
||||
__hipRegisterVar
|
||||
__hipRegisterSurface
|
||||
__hipRegisterTexture
|
||||
__hipRegisterManagedVar
|
||||
__hipUnregisterFatBinary
|
||||
hipConfigureCall
|
||||
hipSetupArgument
|
||||
hipLaunchByPtr
|
||||
hipLaunchKernel
|
||||
hipRegisterApiCallback
|
||||
hipRemoveApiCallback
|
||||
hipRegisterActivityCallback
|
||||
hipRemoveActivityCallback
|
||||
hipApiName
|
||||
hipKernelNameRef
|
||||
hipBindTexture
|
||||
hipBindTexture2D
|
||||
hipBindTextureToArray
|
||||
hipBindTextureToMipmappedArray
|
||||
hipGetTextureAlignmentOffset
|
||||
hipGetTextureReference
|
||||
hipUnbindTexture
|
||||
hipCreateChannelDesc
|
||||
hipCreateTextureObject
|
||||
hipDestroyTextureObject
|
||||
hipGetChannelDesc
|
||||
hipGetTextureObjectResourceDesc
|
||||
hipGetTextureObjectResourceViewDesc
|
||||
hipGetTextureObjectTextureDesc
|
||||
hipTexRefGetAddress
|
||||
hipTexRefGetAddressMode
|
||||
hipTexRefGetArray
|
||||
hipTexRefGetBorderColor
|
||||
hipTexRefGetFilterMode
|
||||
hipTexRefGetFlags
|
||||
hipTexRefGetFormat
|
||||
hipTexRefGetMaxAnisotropy
|
||||
hipTexRefGetMipmapFilterMode
|
||||
hipTexRefGetMipmapLevelBias
|
||||
hipTexRefGetMipmapLevelClamp
|
||||
hipTexRefGetMipmappedArray
|
||||
hipTexRefSetAddress
|
||||
hipTexRefSetAddress2D
|
||||
hipTexRefSetAddressMode
|
||||
hipTexRefSetArray
|
||||
hipTexRefSetBorderColor
|
||||
hipTexRefSetFilterMode
|
||||
hipTexRefSetFlags
|
||||
hipTexRefSetFormat
|
||||
hipTexRefSetMaxAnisotropy
|
||||
hipTexRefSetMipmapFilterMode
|
||||
hipTexRefSetMipmapLevelBias
|
||||
hipTexRefSetMipmapLevelClamp
|
||||
hipTexRefSetMipmappedArray
|
||||
hipProfilerStart
|
||||
hipProfilerStop
|
||||
hipCreateSurfaceObject
|
||||
hipDestroySurfaceObject
|
||||
hipInitActivityCallback
|
||||
hipEnableActivityCallback
|
||||
hipGetCmdName
|
||||
hiprtcAddNameExpression
|
||||
hiprtcCompileProgram
|
||||
hiprtcCreateProgram
|
||||
hiprtcDestroyProgram
|
||||
hiprtcGetLoweredName
|
||||
hiprtcGetProgramLog
|
||||
hiprtcGetProgramLogSize
|
||||
hiprtcGetCode
|
||||
hiprtcGetCodeSize
|
||||
hiprtcGetErrorString
|
||||
hipMipmappedArrayCreate
|
||||
hipMallocMipmappedArray
|
||||
hipMipmappedArrayDestroy
|
||||
hipFreeMipmappedArray
|
||||
hipMipmappedArrayGetLevel
|
||||
hipGetMipmappedArrayLevel
|
||||
hipMallocHost
|
||||
hipFreeHost
|
||||
hipTexObjectCreate
|
||||
hipTexObjectDestroy
|
||||
hipTexObjectGetResourceDesc
|
||||
hipTexObjectGetResourceViewDesc
|
||||
hipTexObjectGetTextureDesc
|
||||
hipExtStreamCreateWithCUMask
|
||||
hipStreamGetPriority
|
||||
hipMemcpy2DFromArray
|
||||
hipMemcpy2DFromArrayAsync
|
||||
hipDrvMemcpy2DUnaligned
|
||||
hipMemcpyAtoH
|
||||
hipMemcpyHtoA
|
||||
hipMemcpyParam2DAsync
|
||||
__gnu_h2f_ieee
|
||||
__gnu_f2h_ieee
|
||||
hipExtStreamGetCUMask
|
||||
hipImportExternalMemory
|
||||
hipExternalMemoryGetMappedBuffer
|
||||
hipDestroyExternalMemory
|
||||
hipGraphCreate
|
||||
hipGraphDestroy
|
||||
hipGraphAddKernelNode
|
||||
hipGraphAddMemsetNode
|
||||
hipGraphAddMemcpyNode
|
||||
hipGraphInstantiate
|
||||
hipGraphLaunch
|
||||
hipStreamIsCapturing
|
||||
hipStreamBeginCapture
|
||||
hipStreamEndCapture
|
||||
hipGraphExecDestroy
|
||||
hipImportExternalSemaphore
|
||||
hipSignalExternalSemaphoresAsync
|
||||
hipWaitExternalSemaphoresAsync
|
||||
hipDestroyExternalSemaphore
|
||||
Executable
+310
@@ -0,0 +1,310 @@
|
||||
{
|
||||
global:
|
||||
hipChooseDevice;
|
||||
hipCtxCreate;
|
||||
hipCtxDestroy;
|
||||
hipCtxDisablePeerAccess;
|
||||
hipCtxEnablePeerAccess;
|
||||
hipCtxGetApiVersion;
|
||||
hipCtxGetCacheConfig;
|
||||
hipCtxGetCurrent;
|
||||
hipCtxGetDevice;
|
||||
hipCtxGetFlags;
|
||||
hipCtxGetSharedMemConfig;
|
||||
hipCtxPopCurrent;
|
||||
hipCtxPushCurrent;
|
||||
hipCtxSetCacheConfig;
|
||||
hipCtxSetCurrent;
|
||||
hipCtxSetSharedMemConfig;
|
||||
hipCtxSynchronize;
|
||||
hipDeviceCanAccessPeer;
|
||||
hipDeviceComputeCapability;
|
||||
hipDeviceDisablePeerAccess;
|
||||
hipDeviceEnablePeerAccess;
|
||||
hipDeviceGet;
|
||||
hipDeviceGetAttribute;
|
||||
hipDeviceGetByPCIBusId;
|
||||
hipDeviceGetCacheConfig;
|
||||
hipDeviceGetStreamPriorityRange;
|
||||
hipDeviceGetLimit;
|
||||
hipDeviceGetName;
|
||||
hipDeviceGetPCIBusId;
|
||||
hipDeviceGetSharedMemConfig;
|
||||
hipDeviceGetP2PAttribute;
|
||||
hipDevicePrimaryCtxGetState;
|
||||
hipDevicePrimaryCtxRelease;
|
||||
hipDevicePrimaryCtxReset;
|
||||
hipDevicePrimaryCtxRetain;
|
||||
hipDevicePrimaryCtxSetFlags;
|
||||
hipDeviceReset;
|
||||
hipDeviceSetCacheConfig;
|
||||
hipDeviceSetSharedMemConfig;
|
||||
hipDeviceSynchronize;
|
||||
hipDeviceTotalMem;
|
||||
hipDriverGetVersion;
|
||||
hipEventCreate;
|
||||
hipEventCreateWithFlags;
|
||||
hipEventDestroy;
|
||||
hipEventElapsedTime;
|
||||
hipEventQuery;
|
||||
hipEventRecord;
|
||||
hipEventSynchronize;
|
||||
hipExtGetLinkTypeAndHopCount;
|
||||
hipExtLaunchMultiKernelMultiDevice;
|
||||
hipExtMallocWithFlags;
|
||||
hipExtModuleLaunchKernel;
|
||||
hipExtLaunchKernel;
|
||||
hipFree;
|
||||
hipFreeArray;
|
||||
hipFuncSetAttribute;
|
||||
hipFuncSetCacheConfig;
|
||||
hipFuncSetSharedMemConfig;
|
||||
hipGetDevice;
|
||||
hipGetDeviceCount;
|
||||
hipGetDeviceProperties;
|
||||
hipGetErrorName;
|
||||
hipGetErrorString;
|
||||
hipGetLastError;
|
||||
hipMemAdvise;
|
||||
hipMemAllocHost;
|
||||
hipHostAlloc;
|
||||
hipHostFree;
|
||||
hipHostGetDevicePointer;
|
||||
hipHostGetFlags;
|
||||
hipHostMalloc;
|
||||
hipHostRegister;
|
||||
hipHostUnregister;
|
||||
hipInit;
|
||||
hipIpcCloseMemHandle;
|
||||
hipIpcGetMemHandle;
|
||||
hipIpcOpenMemHandle;
|
||||
hipIpcGetEventHandle;
|
||||
hipIpcOpenEventHandle;
|
||||
hipMalloc;
|
||||
hipMalloc3D;
|
||||
hipMalloc3DArray;
|
||||
hipMallocManaged;
|
||||
hipArrayCreate;
|
||||
hipArrayDestroy;
|
||||
hipArray3DCreate;
|
||||
hipMallocArray;
|
||||
hipMallocPitch;
|
||||
hipMemAllocPitch;
|
||||
hipMemcpy;
|
||||
hipMemcpyWithStream;
|
||||
hipMemcpyParam2D;
|
||||
hipMemcpy2D;
|
||||
hipMemcpy2DAsync;
|
||||
hipMemcpy2DToArray;
|
||||
hipMemcpy2DToArrayAsync;
|
||||
hipDrvMemcpy2DUnaligned;
|
||||
hipMemcpy3D;
|
||||
hipMemcpy3DAsync;
|
||||
hipDrvMemcpy3D;
|
||||
hipDrvMemcpy3DAsync;
|
||||
hipMemcpyAsync;
|
||||
hipMemcpyDtoD;
|
||||
hipMemcpyDtoDAsync;
|
||||
hipMemcpyDtoH;
|
||||
hipMemcpyDtoHAsync;
|
||||
hipMemcpyFromSymbol;
|
||||
hipMemcpyFromSymbolAsync;
|
||||
hipMemcpyHtoD;
|
||||
hipMemcpyHtoDAsync;
|
||||
hipMemcpyPeer;
|
||||
hipMemcpyPeerAsync;
|
||||
hipMemcpyToArray;
|
||||
hipMemcpyFromArray;
|
||||
hipMemcpyToSymbol;
|
||||
hipMemcpyToSymbolAsync;
|
||||
hipMemGetAddressRange;
|
||||
hipGetSymbolAddress;
|
||||
hipGetSymbolSize;
|
||||
hipMemGetInfo;
|
||||
hipMemPrefetchAsync;
|
||||
hipMemPtrGetInfo;
|
||||
hipMemRangeGetAttribute;
|
||||
hipMemRangeGetAttributes;
|
||||
hipMemset;
|
||||
hipMemsetAsync;
|
||||
hipMemsetD8;
|
||||
hipMemsetD8Async;
|
||||
hipMemsetD16;
|
||||
hipMemsetD16Async;
|
||||
hipMemsetD32;
|
||||
hipMemsetD32Async;
|
||||
hipMemset2D;
|
||||
hipMemset2DAsync;
|
||||
hipMemset3D;
|
||||
hipMemset3DAsync;
|
||||
hipModuleGetFunction;
|
||||
hipModuleGetGlobal;
|
||||
hipModuleGetTexRef;
|
||||
hipModuleLaunchKernel;
|
||||
hipModuleLaunchKernelExt;
|
||||
hipLaunchCooperativeKernel;
|
||||
hipLaunchCooperativeKernelMultiDevice;
|
||||
hipModuleLoad;
|
||||
hipModuleLoadData;
|
||||
hipModuleLoadDataEx;
|
||||
hipModuleUnload;
|
||||
hipModuleOccupancyMaxPotentialBlockSize;
|
||||
hipModuleOccupancyMaxPotentialBlockSizeWithFlags;
|
||||
hipModuleOccupancyMaxActiveBlocksPerMultiprocessor;
|
||||
hipModuleOccupancyMaxActiveBlocksPerMultiprocessorWithFlags;
|
||||
hipOccupancyMaxPotentialBlockSize;
|
||||
hipOccupancyMaxActiveBlocksPerMultiprocessor;
|
||||
hipOccupancyMaxActiveBlocksPerMultiprocessorWithFlags;
|
||||
hipFuncGetAttribute;
|
||||
hipFuncGetAttributes;
|
||||
hipPeekAtLastError;
|
||||
hipPointerGetAttributes;
|
||||
hipProfilerStart;
|
||||
hipProfilerStop;
|
||||
hipRuntimeGetVersion;
|
||||
hipGetDeviceFlags;
|
||||
hipSetDevice;
|
||||
hipSetDeviceFlags;
|
||||
hipStreamAddCallback;
|
||||
hipStreamAttachMemAsync;
|
||||
hipStreamCreate;
|
||||
hipStreamCreateWithFlags;
|
||||
hipStreamCreateWithPriority;
|
||||
hipStreamDestroy;
|
||||
hipStreamGetFlags;
|
||||
hipStreamQuery;
|
||||
hipStreamSynchronize;
|
||||
hipStreamWaitEvent;
|
||||
hipStreamWaitValue32;
|
||||
hipStreamWaitValue64;
|
||||
hipStreamWriteValue32;
|
||||
hipStreamWriteValue64;
|
||||
__hipPopCallConfiguration;
|
||||
__hipPushCallConfiguration;
|
||||
__hipRegisterFatBinary;
|
||||
__hipRegisterFunction;
|
||||
__hipRegisterVar;
|
||||
__hipRegisterSurface;
|
||||
__hipRegisterTexture;
|
||||
__hipRegisterManagedVar;
|
||||
__hipUnregisterFatBinary;
|
||||
__gnu_h2f_ieee;
|
||||
__gnu_f2h_ieee;
|
||||
hipConfigureCall;
|
||||
hipSetupArgument;
|
||||
hipLaunchByPtr;
|
||||
hipLaunchKernel;
|
||||
hipRegisterApiCallback;
|
||||
hipRemoveApiCallback;
|
||||
hipRegisterActivityCallback;
|
||||
hipRemoveActivityCallback;
|
||||
hipApiName;
|
||||
hipKernelNameRef;
|
||||
hipKernelNameRefByPtr;
|
||||
hipGetStreamDeviceId;
|
||||
hipProfilerStart;
|
||||
hipProfilerStop;
|
||||
hiprtcCompileProgram;
|
||||
hiprtcCreateProgram;
|
||||
hiprtcDestroyProgram;
|
||||
hiprtcGetLoweredName;
|
||||
hiprtcGetProgramLog;
|
||||
hiprtcGetProgramLogSize;
|
||||
hiprtcGetCode;
|
||||
hiprtcGetCodeSize;
|
||||
hiprtcGetErrorString;
|
||||
hiprtcAddNameExpression;
|
||||
hiprtcVersion;
|
||||
hipBindTexture;
|
||||
hipBindTexture2D;
|
||||
hipBindTextureToArray;
|
||||
hipBindTextureToMipmappedArray;
|
||||
hipGetTextureAlignmentOffset;
|
||||
hipGetTextureReference;
|
||||
hipUnbindTexture;
|
||||
hipCreateChannelDesc;
|
||||
hipCreateTextureObject;
|
||||
hipDestroyTextureObject;
|
||||
hipGetChannelDesc;
|
||||
hipGetTextureObjectResourceDesc;
|
||||
hipGetTextureObjectResourceViewDesc;
|
||||
hipGetTextureObjectTextureDesc;
|
||||
hipTexRefGetAddress;
|
||||
hipTexRefGetAddressMode;
|
||||
hipTexRefGetArray;
|
||||
hipTexRefGetBorderColor;
|
||||
hipTexRefGetFilterMode;
|
||||
hipTexRefGetFlags;
|
||||
hipTexRefGetFormat;
|
||||
hipTexRefGetMaxAnisotropy;
|
||||
hipTexRefGetMipmapFilterMode;
|
||||
hipTexRefGetMipmapLevelBias;
|
||||
hipTexRefGetMipmapLevelClamp;
|
||||
hipTexRefGetMipmappedArray;
|
||||
hipTexRefSetAddress;
|
||||
hipTexRefSetAddress2D;
|
||||
hipTexRefSetAddressMode;
|
||||
hipTexRefSetArray;
|
||||
hipTexRefSetBorderColor;
|
||||
hipTexRefSetFilterMode;
|
||||
hipTexRefSetFlags;
|
||||
hipTexRefSetFormat;
|
||||
hipTexRefSetMaxAnisotropy;
|
||||
hipTexRefSetMipmapFilterMode;
|
||||
hipTexRefSetMipmapLevelBias;
|
||||
hipTexRefSetMipmapLevelClamp;
|
||||
hipTexRefSetMipmappedArray;
|
||||
hipMipmappedArrayCreate;
|
||||
hipMallocMipmappedArray;
|
||||
hipMipmappedArrayDestroy;
|
||||
hipFreeMipmappedArray;
|
||||
hipMipmappedArrayGetLevel;
|
||||
hipGetMipmappedArrayLevel;
|
||||
hipMallocHost;
|
||||
hipFreeHost;
|
||||
hipTexObjectCreate;
|
||||
hipTexObjectDestroy;
|
||||
hipTexObjectGetResourceDesc;
|
||||
hipTexObjectGetResourceViewDesc;
|
||||
hipTexObjectGetTextureDesc;
|
||||
hipImportExternalMemory;
|
||||
hipExternalMemoryGetMappedBuffer;
|
||||
hipDestroyExternalMemory;
|
||||
hipGraphCreate;
|
||||
hipGraphDestroy;
|
||||
hipGraphAddKernelNode;
|
||||
hipGraphAddMemsetNode;
|
||||
hipGraphAddMemcpyNode;
|
||||
hipGraphInstantiate;
|
||||
hipGraphLaunch;
|
||||
hipStreamIsCapturing;
|
||||
hipStreamBeginCapture;
|
||||
hipStreamEndCapture;
|
||||
hipGraphExecDestroy;
|
||||
hipImportExternalSemaphore;
|
||||
hipSignalExternalSemaphoresAsync;
|
||||
hipWaitExternalSemaphoresAsync;
|
||||
hipDestroyExternalSemaphore;
|
||||
extern "C++" {
|
||||
hip_impl::hipLaunchKernelGGLImpl*;
|
||||
hip_impl::demangle*;
|
||||
hipCreateSurfaceObject*;
|
||||
hipDestroySurfaceObject*;
|
||||
hipHccModuleLaunchKernel*;
|
||||
hipExtModuleLaunchKernel*;
|
||||
hipInitActivityCallback*;
|
||||
hipEnableActivityCallback*;
|
||||
hipGetCmdName*;
|
||||
hipExtStreamCreateWithCUMask;
|
||||
hipStreamGetPriority;
|
||||
hipMemcpy2DFromArray;
|
||||
hipMemcpy2DFromArrayAsync;
|
||||
hipMemcpyAtoH;
|
||||
hipMemcpyHtoA;
|
||||
hipMemcpyParam2DAsync;
|
||||
__hipGetPCH;
|
||||
hipExtStreamGetCUMask;
|
||||
};
|
||||
local:
|
||||
*;
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
#define STR(__macro__) #__macro__
|
||||
#define XSTR(__macro__) STR(__macro__)
|
||||
|
||||
#if defined(_DEBUG)
|
||||
#define DEBUG_ONLY(x) x
|
||||
#else
|
||||
#define DEBUG_ONLY(x)
|
||||
#endif
|
||||
|
||||
#define VERSION_PREFIX_MAJOR 2
|
||||
#define VERSION_PREFIX_MINOR 0
|
||||
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winresrc.h"
|
||||
#include "utils/versions.hpp"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 10,0,AMD_PLATFORM_BUILD_NUMBER,AMD_PLATFORM_REVISION_NUMBER
|
||||
PRODUCTVERSION 10,0,AMD_PLATFORM_BUILD_NUMBER,AMD_PLATFORM_REVISION_NUMBER
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", " \0"
|
||||
VALUE "CompanyName", "Advanced Micro Devices Inc.\0"
|
||||
VALUE "FileDescription", AMD_PLATFORM_NAME " OpenCL " XSTR(VERSION_PREFIX_MAJOR) "." XSTR(VERSION_PREFIX_MINOR) " Runtime\0"
|
||||
VALUE "FileVersion", "10.0." XSTR(AMD_PLATFORM_BUILD_NUMBER) "." XSTR(AMD_PLATFORM_REVISION_NUMBER)
|
||||
VALUE "InternalName", "OpenCL"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2011 Advanced Micro Devices Inc.\0"
|
||||
VALUE "OriginalFilename", "OpenCL.dll"
|
||||
VALUE "ProductName", "OpenCL " XSTR(VERSION_PREFIX_MAJOR) "." XSTR(VERSION_PREFIX_MINOR) " " AMD_PLATFORM_INFO "\0"
|
||||
VALUE "ProductVersion", "10.0." XSTR(AMD_PLATFORM_BUILD_NUMBER) "." XSTR(AMD_PLATFORM_REVISION_NUMBER)
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,224 @@
|
||||
/* Copyright (c) 2020-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include "hip_internal.hpp"
|
||||
#include "hip_conversions.hpp"
|
||||
#include "platform/context.hpp"
|
||||
#include "platform/command.hpp"
|
||||
#include "platform/memory.hpp"
|
||||
|
||||
// Forward declaraiton of a function
|
||||
hipError_t ihipMallocManaged(void** ptr, size_t size, unsigned int align = 0);
|
||||
|
||||
// Make sure HIP defines match ROCclr to avoid double conversion
|
||||
static_assert(hipCpuDeviceId == amd::CpuDeviceId, "CPU device ID mismatch with ROCclr!");
|
||||
static_assert(hipInvalidDeviceId == amd::InvalidDeviceId,
|
||||
"Invalid device ID mismatch with ROCclr!");
|
||||
|
||||
static_assert(static_cast<uint32_t>(hipMemAdviseSetReadMostly) ==
|
||||
amd::MemoryAdvice::SetReadMostly, "Enum mismatch with ROCclr!");
|
||||
static_assert(static_cast<uint32_t>(hipMemAdviseUnsetReadMostly) ==
|
||||
amd::MemoryAdvice::UnsetReadMostly, "Enum mismatch with ROCclr!");
|
||||
static_assert(static_cast<uint32_t>(hipMemAdviseSetPreferredLocation) ==
|
||||
amd::MemoryAdvice::SetPreferredLocation, "Enum mismatch with ROCclr!");
|
||||
static_assert(static_cast<uint32_t>(hipMemAdviseUnsetPreferredLocation) ==
|
||||
amd::MemoryAdvice::UnsetPreferredLocation, "Enum mismatch with ROCclr!");
|
||||
static_assert(static_cast<uint32_t>(hipMemAdviseSetAccessedBy) ==
|
||||
amd::MemoryAdvice::SetAccessedBy, "Enum mismatch with ROCclr!");
|
||||
static_assert(static_cast<uint32_t>(hipMemAdviseUnsetAccessedBy) ==
|
||||
amd::MemoryAdvice::UnsetAccessedBy, "Enum mismatch with ROCclr!");
|
||||
static_assert(static_cast<uint32_t>(hipMemAdviseSetCoarseGrain) ==
|
||||
amd::MemoryAdvice::SetCoarseGrain, "Enum mismatch with ROCclr!");
|
||||
static_assert(static_cast<uint32_t>(hipMemAdviseUnsetCoarseGrain) ==
|
||||
amd::MemoryAdvice::UnsetCoarseGrain, "Enum mismatch with ROCclr!");
|
||||
|
||||
static_assert(static_cast<uint32_t>(hipMemRangeAttributeReadMostly) ==
|
||||
amd::MemRangeAttribute::ReadMostly, "Enum mismatch with ROCclr!");
|
||||
static_assert(static_cast<uint32_t>(hipMemRangeAttributePreferredLocation) ==
|
||||
amd::MemRangeAttribute::PreferredLocation, "Enum mismatch with ROCclr!");
|
||||
static_assert(static_cast<uint32_t>(hipMemRangeAttributeAccessedBy) ==
|
||||
amd::MemRangeAttribute::AccessedBy, "Enum mismatch with ROCclr!");
|
||||
static_assert(static_cast<uint32_t>(hipMemRangeAttributeLastPrefetchLocation) ==
|
||||
amd::MemRangeAttribute::LastPrefetchLocation, "Enum mismatch with ROCclr!");
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipMallocManaged(void** dev_ptr, size_t size, unsigned int flags) {
|
||||
HIP_INIT_API(hipMallocManaged, dev_ptr, size, flags);
|
||||
|
||||
if ((dev_ptr == nullptr) || (size == 0) ||
|
||||
((flags != hipMemAttachGlobal) && (flags != hipMemAttachHost))) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_RETURN(ihipMallocManaged(dev_ptr, size), *dev_ptr);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipMemPrefetchAsync(const void* dev_ptr, size_t count, int device,
|
||||
hipStream_t stream) {
|
||||
HIP_INIT_API(hipMemPrefetchAsync, dev_ptr, count, device, stream);
|
||||
|
||||
if ((dev_ptr == nullptr) || (count == 0)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
amd::HostQueue* queue = nullptr;
|
||||
bool cpu_access = (device == hipCpuDeviceId) ? true : false;
|
||||
|
||||
// Pick the specified stream or Null one from the provided device
|
||||
if (stream != nullptr) {
|
||||
queue = hip::getQueue(stream);
|
||||
} else {
|
||||
if (!cpu_access) {
|
||||
queue = g_devices[device]->NullStream();
|
||||
} else {
|
||||
queue = hip::getCurrentDevice()->NullStream();
|
||||
}
|
||||
}
|
||||
if (queue == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
amd::Command::EventWaitList waitList;
|
||||
amd::SvmPrefetchAsyncCommand* command =
|
||||
new amd::SvmPrefetchAsyncCommand(*queue, waitList, dev_ptr, count, cpu_access);
|
||||
if (command == nullptr) {
|
||||
return hipErrorOutOfMemory;
|
||||
}
|
||||
|
||||
if (!command->validateMemory()) {
|
||||
delete command;
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
command->enqueue();
|
||||
command->release();
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipMemAdvise(const void* dev_ptr, size_t count, hipMemoryAdvise advice, int device) {
|
||||
HIP_INIT_API(hipMemAdvise, dev_ptr, count, advice, device);
|
||||
|
||||
if ((dev_ptr == nullptr) || (count == 0) ||
|
||||
((device != hipCpuDeviceId) && (static_cast<size_t>(device) >= g_devices.size()))) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
amd::Device* dev = (device == hipCpuDeviceId) ?
|
||||
g_devices[0]->devices()[0] : g_devices[device]->devices()[0];
|
||||
bool use_cpu = (device == hipCpuDeviceId) ? true : false;
|
||||
|
||||
// Set the allocation attributes in AMD HMM
|
||||
if (!dev->SetSvmAttributes(dev_ptr, count, static_cast<amd::MemoryAdvice>(advice), use_cpu)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipMemRangeGetAttribute(void* data, size_t data_size, hipMemRangeAttribute attribute,
|
||||
const void* dev_ptr, size_t count) {
|
||||
HIP_INIT_API(hipMemRangeGetAttribute, data, data_size, attribute, dev_ptr, count);
|
||||
|
||||
if ((data == nullptr) || (data_size == 0) || (dev_ptr == nullptr) || (count == 0)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
// Shouldn't matter for which device the interface is called
|
||||
amd::Device* dev = g_devices[0]->devices()[0];
|
||||
|
||||
// Get the allocation attribute from AMD HMM
|
||||
if (!dev->GetSvmAttributes(&data, &data_size, reinterpret_cast<int*>(&attribute), 1,
|
||||
dev_ptr, count)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipMemRangeGetAttributes(void** data, size_t* data_sizes,
|
||||
hipMemRangeAttribute* attributes, size_t num_attributes,
|
||||
const void* dev_ptr, size_t count) {
|
||||
HIP_INIT_API(hipMemRangeGetAttributes, data, data_sizes,
|
||||
attributes, num_attributes, dev_ptr, count);
|
||||
|
||||
if ((data == nullptr) || (data_sizes == nullptr) || (attributes == nullptr) ||
|
||||
(num_attributes == 0) || (dev_ptr == nullptr) || (count == 0)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
// Shouldn't matter for which device the interface is called
|
||||
amd::Device* dev = g_devices[0]->devices()[0];
|
||||
// Get the allocation attributes from AMD HMM
|
||||
if (!dev->GetSvmAttributes(data, data_sizes, reinterpret_cast<int*>(attributes),
|
||||
num_attributes, dev_ptr, count)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipStreamAttachMemAsync(hipStream_t stream, hipDeviceptr_t* dev_ptr,
|
||||
size_t length, unsigned int flags) {
|
||||
HIP_INIT_API(hipStreamAttachMemAsync, stream, dev_ptr, length, flags);
|
||||
|
||||
if ((stream == nullptr) || (dev_ptr == nullptr) || (length == 0)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
// Unclear what should be done for this interface in AMD HMM, since it's generic SVM alloc
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t ihipMallocManaged(void** ptr, size_t size, unsigned int align) {
|
||||
if (ptr == nullptr) {
|
||||
return hipErrorInvalidValue;
|
||||
} else if (size == 0) {
|
||||
*ptr = nullptr;
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
assert((hip::host_device->asContext()!= nullptr) && "Current host context must be valid");
|
||||
amd::Context& ctx = *hip::host_device->asContext();
|
||||
|
||||
const amd::Device& dev = *ctx.devices()[0];
|
||||
|
||||
// For now limit to the max allocation size on the device.
|
||||
// The apps should be able to go over the limit in the future
|
||||
if (dev.info().maxMemAllocSize_ < size) {
|
||||
return hipErrorMemoryAllocation;
|
||||
}
|
||||
|
||||
// Allocate SVM fine grain buffer with the forced host pointer, avoiding explicit memory
|
||||
// allocation in the device driver
|
||||
*ptr = amd::SvmBuffer::malloc(ctx, CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_ALLOC_HOST_PTR,
|
||||
size, (align == 0) ? dev.info().memBaseAddrAlign_ : align);
|
||||
if (*ptr == nullptr) {
|
||||
return hipErrorMemoryAllocation;
|
||||
}
|
||||
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API, "%-5d: [%zx] ihipMallocManaged ptr=0x%zx", getpid(),
|
||||
std::this_thread::get_id(), *ptr);
|
||||
return hipSuccess;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/* Copyright (c) 2019-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "hip_internal.hpp"
|
||||
#include "hip_platform.hpp"
|
||||
#include "hip_prof_api.h"
|
||||
|
||||
// HIP API callback/activity
|
||||
|
||||
api_callbacks_table_t callbacks_table;
|
||||
|
||||
extern const std::string& FunctionName(const hipFunction_t f);
|
||||
|
||||
const char* hipKernelNameRef(const hipFunction_t f) { return FunctionName(f).c_str(); }
|
||||
|
||||
int hipGetStreamDeviceId(hipStream_t stream) {
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
return (s != nullptr)? s->DeviceId() : ihipGetDevice();
|
||||
}
|
||||
|
||||
const char* hipKernelNameRefByPtr(const void* hostFunction, hipStream_t stream) {
|
||||
if (hostFunction == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
int deviceId = hipGetStreamDeviceId(stream);
|
||||
if (deviceId == -1) {
|
||||
LogPrintfError("Wrong Device Id: %d \n", deviceId);
|
||||
return NULL;
|
||||
}
|
||||
hipFunction_t func = nullptr;
|
||||
hipError_t hip_error = PlatformState::instance().getStatFunc(&func, hostFunction, deviceId);
|
||||
if (hip_error != hipSuccess) {
|
||||
return NULL;
|
||||
}
|
||||
return hipKernelNameRef(func);
|
||||
}
|
||||
|
||||
hipError_t hipRegisterApiCallback(uint32_t id, void* fun, void* arg) {
|
||||
return callbacks_table.set_callback(id, reinterpret_cast<api_callbacks_table_t::fun_t>(fun), arg) ?
|
||||
hipSuccess : hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
hipError_t hipRemoveApiCallback(uint32_t id) {
|
||||
return callbacks_table.set_callback(id, NULL, NULL) ? hipSuccess : hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
hipError_t hipRegisterActivityCallback(uint32_t id, void* fun, void* arg) {
|
||||
return callbacks_table.set_activity(id, reinterpret_cast<api_callbacks_table_t::act_t>(fun), arg) ?
|
||||
hipSuccess : hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
hipError_t hipRemoveActivityCallback(uint32_t id) {
|
||||
return callbacks_table.set_activity(id, NULL, NULL) ? hipSuccess : hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
hipError_t hipEnableTracing(bool enabled) {
|
||||
callbacks_table.set_enabled(enabled);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
const char* hipApiName(uint32_t id) {
|
||||
return hip_api_name(id);
|
||||
}
|
||||
Executable
+353
@@ -0,0 +1,353 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef HIP_SRC_HIP_INTERNAL_H
|
||||
#define HIP_SRC_HIP_INTERNAL_H
|
||||
|
||||
#include "vdi_common.hpp"
|
||||
#include "hip_prof_api.h"
|
||||
#include "trace_helper.h"
|
||||
#include "utils/debug.hpp"
|
||||
#include "hip_formatting.hpp"
|
||||
|
||||
#include "hip_graph_capture.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <thread>
|
||||
#include <stack>
|
||||
#include <mutex>
|
||||
#include <iterator>
|
||||
#ifdef _WIN32
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define KNRM "\x1B[0m"
|
||||
#define KRED "\x1B[31m"
|
||||
#define KGRN "\x1B[32m"
|
||||
#define KYEL "\x1B[33m"
|
||||
#define KBLU "\x1B[34m"
|
||||
#define KMAG "\x1B[35m"
|
||||
#define KCYN "\x1B[36m"
|
||||
#define KWHT "\x1B[37m"
|
||||
|
||||
/*! IHIP IPC MEMORY Structure */
|
||||
#define IHIP_IPC_MEM_HANDLE_SIZE 32
|
||||
#define IHIP_IPC_MEM_RESERVED_SIZE LP64_SWITCH(24,16)
|
||||
|
||||
typedef struct ihipIpcMemHandle_st {
|
||||
char ipc_handle[IHIP_IPC_MEM_HANDLE_SIZE]; ///< ipc memory handle on ROCr
|
||||
size_t psize;
|
||||
size_t poffset;
|
||||
char reserved[IHIP_IPC_MEM_RESERVED_SIZE];
|
||||
} ihipIpcMemHandle_t;
|
||||
|
||||
#define IHIP_IPC_EVENT_HANDLE_SIZE 32
|
||||
#define IHIP_IPC_EVENT_RESERVED_SIZE LP64_SWITCH(28,24)
|
||||
typedef struct ihipIpcEventHandle_st {
|
||||
//hsa_amd_ipc_signal_t ipc_handle; ///< ipc signal handle on ROCr
|
||||
//char ipc_handle[IHIP_IPC_EVENT_HANDLE_SIZE];
|
||||
//char reserved[IHIP_IPC_EVENT_RESERVED_SIZE];
|
||||
char shmem_name[IHIP_IPC_EVENT_HANDLE_SIZE];
|
||||
}ihipIpcEventHandle_t;
|
||||
|
||||
#ifdef _WIN32
|
||||
inline int getpid() { return _getpid(); }
|
||||
#endif
|
||||
|
||||
#define HIP_INIT() \
|
||||
std::call_once(hip::g_ihipInitialized, hip::init); \
|
||||
if (hip::g_device == nullptr && g_devices.size() > 0) { \
|
||||
hip::g_device = g_devices[0]; \
|
||||
}
|
||||
|
||||
#define HIP_API_PRINT(...) \
|
||||
uint64_t startTimeUs=0 ; HIPPrintDuration(amd::LOG_INFO, amd::LOG_API, &startTimeUs, "%-5d: [%zx] %s%s ( %s )%s", getpid(), std::this_thread::get_id(), KGRN, \
|
||||
__func__, ToString( __VA_ARGS__ ).c_str(),KNRM);
|
||||
|
||||
#define HIP_ERROR_PRINT(err, ...) \
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API, "%-5d: [%zx] %s: Returned %s : %s", getpid(), std::this_thread::get_id(), \
|
||||
__func__, hipGetErrorName(err), ToString( __VA_ARGS__ ).c_str());
|
||||
|
||||
// This macro should be called at the beginning of every HIP API.
|
||||
#define HIP_INIT_API(cid, ...) \
|
||||
HIP_API_PRINT(__VA_ARGS__) \
|
||||
amd::Thread* thread = amd::Thread::current(); \
|
||||
if (!VDI_CHECK_THREAD(thread)) { \
|
||||
HIP_RETURN(hipErrorOutOfMemory); \
|
||||
} \
|
||||
HIP_INIT() \
|
||||
HIP_CB_SPAWNER_OBJECT(cid);
|
||||
|
||||
#define HIP_RETURN_DURATION(ret, ...) \
|
||||
hip::g_lastError = ret; \
|
||||
HIPPrintDuration(amd::LOG_INFO, amd::LOG_API, &startTimeUs, "%-5d: [%zx] %s: Returned %s : %s", getpid(), std::this_thread::get_id(), \
|
||||
__func__, hipGetErrorName(hip::g_lastError), ToString( __VA_ARGS__ ).c_str()); \
|
||||
return hip::g_lastError;
|
||||
|
||||
#define HIP_RETURN(ret, ...) \
|
||||
hip::g_lastError = ret; \
|
||||
HIP_ERROR_PRINT(hip::g_lastError, __VA_ARGS__) \
|
||||
return hip::g_lastError;
|
||||
|
||||
#define HIP_RETURN_ONFAIL(func) \
|
||||
do { \
|
||||
hipError_t herror = (func); \
|
||||
if (herror != hipSuccess) { \
|
||||
HIP_RETURN(herror); \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
// Cannot be use in place of HIP_RETURN.
|
||||
// Refrain from using for external HIP APIs
|
||||
#define IHIP_RETURN_ONFAIL(func) \
|
||||
do { \
|
||||
hipError_t herror = (func); \
|
||||
if (herror != hipSuccess) { \
|
||||
return herror; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define STREAM_CAPTURE(name, stream, ...) \
|
||||
if (stream != nullptr && \
|
||||
reinterpret_cast<hip::Stream*>(stream)->GetCaptureStatus() == \
|
||||
hipStreamCaptureStatusActive) { \
|
||||
hipError_t status = capture##name(stream, ##__VA_ARGS__); \
|
||||
HIP_RETURN(status); \
|
||||
}
|
||||
|
||||
#define EVENT_CAPTURE(name, event, ...) \
|
||||
if (event != nullptr && reinterpret_cast<hip::Event*>(event)->GetCaptureStatus() == true) { \
|
||||
hipError_t status = capture##name(event, ##__VA_ARGS__); \
|
||||
HIP_RETURN(status); \
|
||||
}
|
||||
|
||||
namespace hc {
|
||||
class accelerator;
|
||||
class accelerator_view;
|
||||
};
|
||||
|
||||
namespace hip {
|
||||
class Device;
|
||||
|
||||
class Stream {
|
||||
public:
|
||||
enum Priority : int { High = -1, Normal = 0, Low = 1 };
|
||||
|
||||
private:
|
||||
amd::HostQueue* queue_;
|
||||
mutable amd::Monitor lock_;
|
||||
Device* device_;
|
||||
Priority priority_;
|
||||
unsigned int flags_;
|
||||
bool null_;
|
||||
const std::vector<uint32_t> cuMask_;
|
||||
|
||||
/// Stream capture related parameters
|
||||
|
||||
/// Current capture status of the stream
|
||||
hipStreamCaptureStatus captureStatus_;
|
||||
/// Graph that is constructed with capture
|
||||
hipGraph_t pCaptureGraph_;
|
||||
/// Based on mode stream capture places restrictions on API calls that can be made within or
|
||||
/// concurrently
|
||||
hipStreamCaptureMode captureMode_;
|
||||
bool originStream_;
|
||||
/// Origin sream has no parent. Parent stream for the derived captured streams with event
|
||||
/// dependencies
|
||||
hipStream_t parentStream_;
|
||||
/// Last graph node captured in the stream
|
||||
std::vector<hipGraphNode_t> lastCapturedNodes_;
|
||||
/// Derived streams/Paralell branches from the origin stream
|
||||
std::vector<hipStream_t> parallelCaptureStreams_;
|
||||
/// Capture events
|
||||
std::vector<hipEvent_t> captureEvents_;
|
||||
|
||||
public:
|
||||
Stream(Device* dev, Priority p = Priority::Normal, unsigned int f = 0, bool null_stream = false,
|
||||
const std::vector<uint32_t>& cuMask = {},
|
||||
hipStreamCaptureStatus captureStatus = hipStreamCaptureStatusNone);
|
||||
~Stream();
|
||||
/// Creates the hip stream object, including AMD host queue
|
||||
bool Create();
|
||||
|
||||
/// Get device AMD host queue object. The method can allocate the queue
|
||||
amd::HostQueue* asHostQueue(bool skip_alloc = false);
|
||||
|
||||
void Finish() const;
|
||||
/// Get device ID associated with the current stream;
|
||||
int DeviceId() const;
|
||||
/// Get device ID associated with a stream;
|
||||
static int DeviceId(const hipStream_t hStream);
|
||||
/// Returns if stream is null stream
|
||||
bool Null() const { return null_; }
|
||||
/// Returns the lock object for the current stream
|
||||
amd::Monitor& Lock() const { return lock_; }
|
||||
/// Returns the creation flags for the current stream
|
||||
unsigned int Flags() const { return flags_; }
|
||||
/// Returns the priority for the current stream
|
||||
Priority GetPriority() const { return priority_; }
|
||||
/// Returns the CU mask for the current stream
|
||||
const std::vector<uint32_t> GetCUMask() const { return cuMask_; }
|
||||
|
||||
/// Sync all non-blocking streams
|
||||
static void syncNonBlockingStreams();
|
||||
|
||||
/// Returns capture status of the current stream
|
||||
hipStreamCaptureStatus GetCaptureStatus() const { return captureStatus_; }
|
||||
/// Returns capture mode of the current stream
|
||||
hipStreamCaptureMode GetCaptureMode() const { return captureMode_; }
|
||||
/// Returns if stream is origin stream
|
||||
bool IsOriginStream() const { return originStream_; }
|
||||
void SetOriginStream() { originStream_ = true; }
|
||||
/// Returns captured graph
|
||||
hipGraph_t GetCaptureGraph() const { return pCaptureGraph_; }
|
||||
/// Returns last captured graph node
|
||||
std::vector<hipGraphNode_t> GetLastCapturedNodes() const { return lastCapturedNodes_; }
|
||||
/// Set last captured graph node
|
||||
void SetLastCapturedNode(hipGraphNode_t graphNode) {
|
||||
lastCapturedNodes_.clear();
|
||||
lastCapturedNodes_.push_back(graphNode);
|
||||
}
|
||||
/// Append captured node via the wait event cross stream
|
||||
void AddCrossCapturedNode(std::vector<hipGraphNode_t> graphNodes) {
|
||||
for (auto node : graphNodes) {
|
||||
lastCapturedNodes_.push_back(node);
|
||||
}
|
||||
}
|
||||
/// Set graph that is being captured
|
||||
void SetCaptureGraph(hipGraph_t pGraph) {
|
||||
pCaptureGraph_ = pGraph;
|
||||
captureStatus_ = hipStreamCaptureStatusActive;
|
||||
}
|
||||
/// reset capture parameters
|
||||
hipError_t EndCapture();
|
||||
/// Set capture status
|
||||
void SetCaptureStatus(hipStreamCaptureStatus captureStatus) { captureStatus_ = captureStatus; }
|
||||
/// Set capture mode
|
||||
void SetCaptureMode(hipStreamCaptureMode captureMode) { captureMode_ = captureMode; }
|
||||
/// Set parent stream
|
||||
void SetParentStream(hipStream_t parentStream) { parentStream_ = parentStream; }
|
||||
/// Get parent stream
|
||||
hipStream_t GetParentStream() { return parentStream_; }
|
||||
};
|
||||
|
||||
/// HIP Device class
|
||||
class Device {
|
||||
amd::Monitor lock_{"Device lock"};
|
||||
/// ROCclr context
|
||||
amd::Context* context_;
|
||||
/// Device's ID
|
||||
/// Store it here so we don't have to loop through the device list every time
|
||||
int deviceId_;
|
||||
/// ROCclr host queue for default streams
|
||||
Stream null_stream_;
|
||||
/// Store device flags
|
||||
unsigned int flags_;
|
||||
/// Maintain list of user enabled peers
|
||||
std::list<int> userEnabledPeers;
|
||||
|
||||
public:
|
||||
Device(amd::Context* ctx, int devId):
|
||||
context_(ctx), deviceId_(devId), null_stream_(this, Stream::Priority::Normal, 0, true), flags_(hipDeviceScheduleSpin)
|
||||
{ assert(ctx != nullptr); }
|
||||
~Device() {}
|
||||
|
||||
amd::Context* asContext() const { return context_; }
|
||||
int deviceId() const { return deviceId_; }
|
||||
void retain() const { context_->retain(); }
|
||||
void release() const { context_->release(); }
|
||||
const std::vector<amd::Device*>& devices() const { return context_->devices(); }
|
||||
hipError_t EnablePeerAccess(int peerDeviceId){
|
||||
amd::ScopedLock lock(lock_);
|
||||
bool found = (std::find(userEnabledPeers.begin(), userEnabledPeers.end(), peerDeviceId) != userEnabledPeers.end());
|
||||
if (found) {
|
||||
return hipErrorPeerAccessAlreadyEnabled;
|
||||
}
|
||||
userEnabledPeers.push_back(peerDeviceId);
|
||||
return hipSuccess;
|
||||
}
|
||||
hipError_t DisablePeerAccess(int peerDeviceId) {
|
||||
amd::ScopedLock lock(lock_);
|
||||
bool found = (std::find(userEnabledPeers.begin(), userEnabledPeers.end(), peerDeviceId) != userEnabledPeers.end());
|
||||
if (found) {
|
||||
userEnabledPeers.remove(peerDeviceId);
|
||||
return hipSuccess;
|
||||
} else {
|
||||
return hipErrorPeerAccessNotEnabled;
|
||||
}
|
||||
}
|
||||
unsigned int getFlags() const { return flags_; }
|
||||
void setFlags(unsigned int flags) { flags_ = flags; }
|
||||
amd::HostQueue* NullStream(bool skip_alloc = false);
|
||||
};
|
||||
|
||||
extern std::once_flag g_ihipInitialized;
|
||||
/// Current thread's device
|
||||
extern thread_local Device* g_device;
|
||||
extern thread_local hipError_t g_lastError;
|
||||
/// Device representing the host - for pinned memory
|
||||
extern Device* host_device;
|
||||
|
||||
extern void init();
|
||||
|
||||
extern Device* getCurrentDevice();
|
||||
|
||||
extern void setCurrentDevice(unsigned int index);
|
||||
|
||||
/// Get ROCclr queue associated with hipStream
|
||||
/// Note: This follows the CUDA spec to sync with default streams
|
||||
/// and Blocking streams
|
||||
extern amd::HostQueue* getQueue(hipStream_t s);
|
||||
/// Get default stream associated with the ROCclr context
|
||||
extern amd::HostQueue* getNullStream(amd::Context&);
|
||||
/// Get default stream of the thread
|
||||
extern amd::HostQueue* getNullStream();
|
||||
/// Check if stream is valid
|
||||
extern bool isValid(hipStream_t stream);
|
||||
};
|
||||
|
||||
struct ihipExec_t {
|
||||
dim3 gridDim_;
|
||||
dim3 blockDim_;
|
||||
size_t sharedMem_;
|
||||
hipStream_t hStream_;
|
||||
std::vector<char> arguments_;
|
||||
};
|
||||
|
||||
/// Wait all active streams on the blocking queue. The method enqueues a wait command and
|
||||
/// doesn't stall the current thread
|
||||
extern void iHipWaitActiveStreams(amd::HostQueue* blocking_queue, bool wait_null_stream = false);
|
||||
|
||||
extern std::vector<hip::Device*> g_devices;
|
||||
extern hipError_t ihipDeviceGetCount(int* count);
|
||||
extern int ihipGetDevice();
|
||||
|
||||
extern hipError_t ihipMalloc(void** ptr, size_t sizeBytes, unsigned int flags);
|
||||
extern amd::Memory* getMemoryObject(const void* ptr, size_t& offset);
|
||||
extern amd::Memory* getMemoryObjectWithOffset(const void* ptr, const size_t size);
|
||||
|
||||
constexpr bool kOptionChangeable = true;
|
||||
constexpr bool kNewDevProg = false;
|
||||
|
||||
constexpr bool kMarkerDisableFlush = true; //!< Avoids command batch flush in ROCclr
|
||||
|
||||
#endif // HIP_SRC_HIP_INTERNAL_H
|
||||
Executable
+2852
File diff suppressed because it is too large.
Load diff
Executable
+675
@@ -0,0 +1,675 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <elf/elf.hpp>
|
||||
#include <fstream>
|
||||
|
||||
#include "hip_internal.hpp"
|
||||
#include "platform/program.hpp"
|
||||
#include "hip_event.hpp"
|
||||
#include "hip_platform.hpp"
|
||||
|
||||
hipError_t ihipModuleLoadData(hipModule_t* module, const void* mmap_ptr, size_t mmap_size);
|
||||
|
||||
extern hipError_t ihipLaunchKernel(const void* hostFunction,
|
||||
dim3 gridDim,
|
||||
dim3 blockDim,
|
||||
void** args,
|
||||
size_t sharedMemBytes,
|
||||
hipStream_t stream,
|
||||
hipEvent_t startEvent,
|
||||
hipEvent_t stopEvent,
|
||||
int flags);
|
||||
|
||||
const std::string& FunctionName(const hipFunction_t f) {
|
||||
return hip::DeviceFunc::asFunction(f)->kernel()->name();
|
||||
}
|
||||
|
||||
static uint64_t ElfSize(const void *emi)
|
||||
{
|
||||
return amd::Elf::getElfSize(emi);
|
||||
}
|
||||
|
||||
hipError_t hipModuleUnload(hipModule_t hmod) {
|
||||
HIP_INIT_API(hipModuleUnload, hmod);
|
||||
|
||||
HIP_RETURN(PlatformState::instance().unloadModule(hmod));
|
||||
}
|
||||
|
||||
hipError_t hipModuleLoad(hipModule_t* module, const char* fname) {
|
||||
HIP_INIT_API(hipModuleLoad, module, fname);
|
||||
|
||||
HIP_RETURN(PlatformState::instance().loadModule(module, fname));
|
||||
}
|
||||
|
||||
hipError_t hipModuleLoadData(hipModule_t *module, const void *image)
|
||||
{
|
||||
HIP_INIT_API(hipModuleLoadData, module, image);
|
||||
|
||||
HIP_RETURN(PlatformState::instance().loadModule(module, 0, image));
|
||||
}
|
||||
|
||||
hipError_t hipModuleLoadDataEx(hipModule_t *module, const void *image,
|
||||
unsigned int numOptions, hipJitOption* options,
|
||||
void** optionsValues)
|
||||
{
|
||||
/* TODO: Pass options to Program */
|
||||
HIP_INIT_API(hipModuleLoadDataEx, module, image);
|
||||
|
||||
HIP_RETURN(PlatformState::instance().loadModule(module, 0, image));
|
||||
}
|
||||
|
||||
extern hipError_t __hipExtractCodeObjectFromFatBinary(const void* data,
|
||||
const std::vector<std::string>& devices,
|
||||
std::vector<std::pair<const void*, size_t>>& code_objs);
|
||||
|
||||
hipError_t hipModuleGetFunction(hipFunction_t *hfunc, hipModule_t hmod, const char *name) {
|
||||
HIP_INIT_API(hipModuleGetFunction, hfunc, hmod, name);
|
||||
|
||||
if(hfunc == nullptr || name == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
if (hipSuccess != PlatformState::instance().getDynFunc(hfunc, hmod, name)) {
|
||||
LogPrintfError("Cannot find the function: %s for module: 0x%x \n", name, hmod);
|
||||
HIP_RETURN(hipErrorNotFound);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipModuleGetGlobal(hipDeviceptr_t* dptr, size_t* bytes, hipModule_t hmod, const char* name)
|
||||
{
|
||||
HIP_INIT_API(hipModuleGetGlobal, dptr, bytes, hmod, name);
|
||||
|
||||
if(dptr == nullptr || bytes == nullptr || name == nullptr) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
/* Get address and size for the global symbol */
|
||||
if (hipSuccess != PlatformState::instance().getDynGlobalVar(name, hmod, dptr, bytes)) {
|
||||
LogPrintfError("Cannot find global Var: %s for module: 0x%x at device: %d \n", name, hmod,
|
||||
ihipGetDevice());
|
||||
HIP_RETURN(hipErrorNotFound);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipFuncGetAttribute(int* value, hipFunction_attribute attrib, hipFunction_t hfunc) {
|
||||
HIP_INIT_API(hipFuncGetAttribute, value, attrib, hfunc);
|
||||
|
||||
if ((value == nullptr) || (hfunc == nullptr)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
hip::DeviceFunc* function = hip::DeviceFunc::asFunction(hfunc);
|
||||
if (function == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidHandle);
|
||||
}
|
||||
|
||||
amd::Kernel* kernel = function->kernel();
|
||||
if (kernel == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidDeviceFunction);
|
||||
}
|
||||
|
||||
const device::Kernel::WorkGroupInfo* wrkGrpInfo
|
||||
= kernel->getDeviceKernel(*(hip::getCurrentDevice()->devices()[0]))->workGroupInfo();
|
||||
if (wrkGrpInfo == nullptr) {
|
||||
HIP_RETURN(hipErrorMissingConfiguration);
|
||||
}
|
||||
|
||||
switch(attrib) {
|
||||
case HIP_FUNC_ATTRIBUTE_SHARED_SIZE_BYTES:
|
||||
*value = static_cast<int>(wrkGrpInfo->localMemSize_);
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK:
|
||||
*value = static_cast<int>(wrkGrpInfo->size_);
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_CONST_SIZE_BYTES:
|
||||
*value = 0;
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_LOCAL_SIZE_BYTES:
|
||||
*value = static_cast<int>(wrkGrpInfo->privateMemSize_);
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_NUM_REGS:
|
||||
*value = static_cast<int>(wrkGrpInfo->usedVGPRs_);
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_PTX_VERSION:
|
||||
*value = 30; // Defaults to 3.0 as HCC
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_BINARY_VERSION:
|
||||
*value = static_cast<int>(kernel->signature().version());
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_CACHE_MODE_CA:
|
||||
*value = 0;
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_MAX_DYNAMIC_SHARED_SIZE_BYTES:
|
||||
*value = static_cast<int>(wrkGrpInfo->availableLDSSize_ - wrkGrpInfo->localMemSize_);
|
||||
break;
|
||||
case HIP_FUNC_ATTRIBUTE_PREFERRED_SHARED_MEMORY_CARVEOUT:
|
||||
*value = 0;
|
||||
break;
|
||||
default:
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipFuncGetAttributes(hipFuncAttributes* attr, const void* func)
|
||||
{
|
||||
HIP_INIT_API(hipFuncGetAttributes, attr, func);
|
||||
|
||||
HIP_RETURN_ONFAIL(PlatformState::instance().getStatFuncAttr(attr, func, ihipGetDevice()));
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipFuncSetAttribute ( const void* func, hipFuncAttribute attr, int value ) {
|
||||
HIP_INIT_API(hipFuncSetAttribute, func, attr, value);
|
||||
|
||||
// No way to set function attribute yet.
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipFuncSetCacheConfig (const void* func, hipFuncCache_t cacheConfig) {
|
||||
|
||||
HIP_INIT_API(hipFuncSetCacheConfig, cacheConfig);
|
||||
|
||||
// No way to set cache config yet.
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipFuncSetSharedMemConfig ( const void* func, hipSharedMemConfig config) {
|
||||
HIP_INIT_API(hipFuncSetSharedMemConfig, func, config);
|
||||
|
||||
// No way to set Shared Memory config function yet.
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t ihipLaunchKernel_validate(hipFunction_t f, uint32_t globalWorkSizeX,
|
||||
uint32_t globalWorkSizeY, uint32_t globalWorkSizeZ,
|
||||
uint32_t blockDimX, uint32_t blockDimY,
|
||||
uint32_t blockDimZ, uint32_t sharedMemBytes,
|
||||
void** kernelParams, void** extra, int deviceId,
|
||||
uint32_t params = 0) {
|
||||
if (f == nullptr) {
|
||||
LogPrintfError("%s", "Function passed is null");
|
||||
return hipErrorInvalidImage;
|
||||
}
|
||||
if ((kernelParams != nullptr) && (extra != nullptr)) {
|
||||
LogPrintfError("%s",
|
||||
"Both, kernelParams and extra Params are provided, only one should be provided");
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
if (globalWorkSizeX == 0 || globalWorkSizeY == 0 || globalWorkSizeZ == 0 || blockDimX == 0 ||
|
||||
blockDimY == 0 || blockDimZ == 0) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
if (extra != nullptr) {
|
||||
if (extra[0] != HIP_LAUNCH_PARAM_BUFFER_POINTER || extra[2] != HIP_LAUNCH_PARAM_BUFFER_SIZE ||
|
||||
extra[4] != HIP_LAUNCH_PARAM_END) {
|
||||
return hipErrorNotInitialized;
|
||||
}
|
||||
}
|
||||
|
||||
const amd::Device* device = g_devices[deviceId]->devices()[0];
|
||||
// Make sure dispatch doesn't exceed max workgroup size limit
|
||||
if (blockDimX * blockDimY * blockDimZ > device->info().maxWorkGroupSize_) {
|
||||
return hipErrorInvalidConfiguration;
|
||||
}
|
||||
hip::DeviceFunc* function = hip::DeviceFunc::asFunction(f);
|
||||
amd::Kernel* kernel = function->kernel();
|
||||
// Make sure the launch params are not larger than if specified launch_bounds
|
||||
// If it exceeds, then return a failure
|
||||
if (blockDimX * blockDimY * blockDimZ >
|
||||
kernel->getDeviceKernel(*device)->workGroupInfo()->size_) {
|
||||
LogPrintfError("Launch params (%u, %u, %u) are larger than launch bounds (%lu) for kernel %s",
|
||||
blockDimX, blockDimY, blockDimZ,
|
||||
kernel->getDeviceKernel(*device)->workGroupInfo()->size_,
|
||||
function->name().c_str());
|
||||
return hipErrorLaunchFailure;
|
||||
}
|
||||
|
||||
if (params & amd::NDRangeKernelCommand::CooperativeGroups) {
|
||||
if (!device->info().cooperativeGroups_) {
|
||||
return hipErrorLaunchFailure;
|
||||
}
|
||||
int num_blocks = 0;
|
||||
int max_blocks_per_grid = 0;
|
||||
int best_block_size = 0;
|
||||
int block_size = blockDimX * blockDimY * blockDimZ;
|
||||
hip_impl::ihipOccupancyMaxActiveBlocksPerMultiprocessor(&num_blocks, &max_blocks_per_grid,
|
||||
&best_block_size, *device, f,
|
||||
block_size, sharedMemBytes, true);
|
||||
if (((globalWorkSizeX * globalWorkSizeY * globalWorkSizeZ) / block_size) >
|
||||
unsigned(max_blocks_per_grid)) {
|
||||
return hipErrorCooperativeLaunchTooLarge;
|
||||
}
|
||||
}
|
||||
if (params & amd::NDRangeKernelCommand::CooperativeMultiDeviceGroups) {
|
||||
if (!device->info().cooperativeMultiDeviceGroups_) {
|
||||
return hipErrorLaunchFailure;
|
||||
}
|
||||
}
|
||||
address kernargs = nullptr;
|
||||
// 'extra' is a struct that contains the following info: {
|
||||
// HIP_LAUNCH_PARAM_BUFFER_POINTER, kernargs,
|
||||
// HIP_LAUNCH_PARAM_BUFFER_SIZE, &kernargs_size,
|
||||
// HIP_LAUNCH_PARAM_END }
|
||||
if (extra != nullptr) {
|
||||
if (extra[0] != HIP_LAUNCH_PARAM_BUFFER_POINTER || extra[2] != HIP_LAUNCH_PARAM_BUFFER_SIZE ||
|
||||
extra[4] != HIP_LAUNCH_PARAM_END) {
|
||||
return hipErrorNotInitialized;
|
||||
}
|
||||
kernargs = reinterpret_cast<address>(extra[1]);
|
||||
}
|
||||
|
||||
const amd::KernelSignature& signature = kernel->signature();
|
||||
for (size_t i = 0; i < signature.numParameters(); ++i) {
|
||||
const amd::KernelParameterDescriptor& desc = signature.at(i);
|
||||
if (kernelParams == nullptr) {
|
||||
assert(kernargs != nullptr);
|
||||
kernel->parameters().set(i, desc.size_, kernargs + desc.offset_,
|
||||
desc.type_ == T_POINTER /*svmBound*/);
|
||||
} else {
|
||||
assert(extra == nullptr);
|
||||
kernel->parameters().set(i, desc.size_, kernelParams[i],
|
||||
desc.type_ == T_POINTER /*svmBound*/);
|
||||
}
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t ihipLaunchKernelCommand(amd::Command*& command, hipFunction_t f,
|
||||
uint32_t globalWorkSizeX, uint32_t globalWorkSizeY,
|
||||
uint32_t globalWorkSizeZ, uint32_t blockDimX, uint32_t blockDimY,
|
||||
uint32_t blockDimZ, uint32_t sharedMemBytes,
|
||||
amd::HostQueue* queue, void** kernelParams, void** extra,
|
||||
hipEvent_t startEvent = nullptr, hipEvent_t stopEvent = nullptr,
|
||||
uint32_t flags = 0, uint32_t params = 0, uint32_t gridId = 0,
|
||||
uint32_t numGrids = 0, uint64_t prevGridSum = 0,
|
||||
uint64_t allGridSum = 0, uint32_t firstDevice = 0) {
|
||||
hip::DeviceFunc* function = hip::DeviceFunc::asFunction(f);
|
||||
amd::Kernel* kernel = function->kernel();
|
||||
|
||||
size_t globalWorkOffset[3] = {0};
|
||||
size_t globalWorkSize[3] = {globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ};
|
||||
size_t localWorkSize[3] = {blockDimX, blockDimY, blockDimZ};
|
||||
amd::NDRangeContainer ndrange(3, globalWorkOffset, globalWorkSize, localWorkSize);
|
||||
amd::Command::EventWaitList waitList;
|
||||
bool profileNDRange = false;
|
||||
address kernargs = nullptr;
|
||||
|
||||
profileNDRange = (startEvent != nullptr || stopEvent != nullptr);
|
||||
|
||||
// Flag set to 1 signifies that kernel can be launched in anyorder
|
||||
if (flags & hipExtAnyOrderLaunch) {
|
||||
params |= amd::NDRangeKernelCommand::AnyOrderLaunch;
|
||||
}
|
||||
|
||||
amd::NDRangeKernelCommand* kernelCommand = new amd::NDRangeKernelCommand(
|
||||
*queue, waitList, *kernel, ndrange, sharedMemBytes, params, gridId, numGrids, prevGridSum,
|
||||
allGridSum, firstDevice, profileNDRange);
|
||||
if (!kernelCommand) {
|
||||
return hipErrorOutOfMemory;
|
||||
}
|
||||
|
||||
// Capture the kernel arguments
|
||||
if (CL_SUCCESS != kernelCommand->captureAndValidate()) {
|
||||
delete kernelCommand;
|
||||
return hipErrorOutOfMemory;
|
||||
}
|
||||
command = kernelCommand;
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t ihipModuleLaunchKernel(hipFunction_t f, uint32_t globalWorkSizeX,
|
||||
uint32_t globalWorkSizeY, uint32_t globalWorkSizeZ,
|
||||
uint32_t blockDimX, uint32_t blockDimY, uint32_t blockDimZ,
|
||||
uint32_t sharedMemBytes, hipStream_t hStream, void** kernelParams,
|
||||
void** extra, hipEvent_t startEvent, hipEvent_t stopEvent,
|
||||
uint32_t flags = 0, uint32_t params = 0, uint32_t gridId = 0,
|
||||
uint32_t numGrids = 0, uint64_t prevGridSum = 0,
|
||||
uint64_t allGridSum = 0, uint32_t firstDevice = 0) {
|
||||
HIP_INIT_API(ihipModuleLaunchKernel, f, globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ,
|
||||
blockDimX, blockDimY, blockDimZ, sharedMemBytes, hStream, kernelParams, extra,
|
||||
startEvent, stopEvent, flags, params);
|
||||
|
||||
int deviceId = hip::Stream::DeviceId(hStream);
|
||||
HIP_RETURN_ONFAIL(PlatformState::instance().initStatManagedVarDevicePtr(deviceId));
|
||||
if (f == nullptr) {
|
||||
LogPrintfError("%s", "Function passed is null");
|
||||
return hipErrorInvalidImage;
|
||||
}
|
||||
hip::DeviceFunc* function = hip::DeviceFunc::asFunction(f);
|
||||
amd::Kernel* kernel = function->kernel();
|
||||
amd::ScopedLock lock(function->dflock_);
|
||||
|
||||
hipError_t status =
|
||||
ihipLaunchKernel_validate(f, globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ, blockDimX,
|
||||
blockDimY, blockDimZ, sharedMemBytes, kernelParams, extra, deviceId, params);
|
||||
if (status != hipSuccess) {
|
||||
return status;
|
||||
}
|
||||
amd::Command* command = nullptr;
|
||||
amd::HostQueue* queue = hip::getQueue(hStream);
|
||||
status = ihipLaunchKernelCommand(command, f, globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ,
|
||||
blockDimX, blockDimY, blockDimZ, sharedMemBytes, queue,
|
||||
kernelParams, extra, startEvent, stopEvent, flags, params,
|
||||
gridId, numGrids, prevGridSum, allGridSum, firstDevice);
|
||||
if (status != hipSuccess) {
|
||||
return status;
|
||||
}
|
||||
|
||||
hip::Event* eStart = reinterpret_cast<hip::Event*>(startEvent);
|
||||
hip::Event* eStop = reinterpret_cast<hip::Event*>(stopEvent);
|
||||
command->enqueue();
|
||||
|
||||
if (startEvent != nullptr) {
|
||||
eStart->addMarker(queue, command, false);
|
||||
command->retain();
|
||||
}
|
||||
if (stopEvent != nullptr) {
|
||||
eStop->addMarker(queue, command, true);
|
||||
command->retain();
|
||||
}
|
||||
command->release();
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t hipModuleLaunchKernel(hipFunction_t f,
|
||||
uint32_t gridDimX, uint32_t gridDimY, uint32_t gridDimZ,
|
||||
uint32_t blockDimX, uint32_t blockDimY, uint32_t blockDimZ,
|
||||
uint32_t sharedMemBytes, hipStream_t hStream,
|
||||
void **kernelParams, void **extra)
|
||||
{
|
||||
HIP_INIT_API(hipModuleLaunchKernel, f, gridDimX, gridDimY, gridDimZ,
|
||||
blockDimX, blockDimY, blockDimZ,
|
||||
sharedMemBytes, hStream,
|
||||
kernelParams, extra);
|
||||
size_t globalWorkSizeX = static_cast<size_t>(gridDimX) * blockDimX;
|
||||
size_t globalWorkSizeY = static_cast<size_t>(gridDimY) * blockDimY;
|
||||
size_t globalWorkSizeZ = static_cast<size_t>(gridDimZ) * blockDimZ;
|
||||
if (globalWorkSizeX > std::numeric_limits<uint32_t>::max() ||
|
||||
globalWorkSizeY > std::numeric_limits<uint32_t>::max() ||
|
||||
globalWorkSizeZ > std::numeric_limits<uint32_t>::max()) {
|
||||
HIP_RETURN(hipErrorInvalidConfiguration);
|
||||
}
|
||||
HIP_RETURN(ihipModuleLaunchKernel(f, static_cast<uint32_t>(globalWorkSizeX),
|
||||
static_cast<uint32_t>(globalWorkSizeY),
|
||||
static_cast<uint32_t>(globalWorkSizeZ),
|
||||
blockDimX, blockDimY, blockDimZ,
|
||||
sharedMemBytes, hStream, kernelParams, extra, nullptr, nullptr));
|
||||
}
|
||||
|
||||
hipError_t hipExtModuleLaunchKernel(hipFunction_t f, uint32_t globalWorkSizeX,
|
||||
uint32_t globalWorkSizeY, uint32_t globalWorkSizeZ,
|
||||
uint32_t localWorkSizeX, uint32_t localWorkSizeY,
|
||||
uint32_t localWorkSizeZ, size_t sharedMemBytes,
|
||||
hipStream_t hStream, void** kernelParams, void** extra,
|
||||
hipEvent_t startEvent, hipEvent_t stopEvent, uint32_t flags)
|
||||
{
|
||||
HIP_INIT_API(hipExtModuleLaunchKernel, f, globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ,
|
||||
localWorkSizeX, localWorkSizeY, localWorkSizeZ,
|
||||
sharedMemBytes, hStream,
|
||||
kernelParams, extra, startEvent, stopEvent, flags);
|
||||
|
||||
HIP_RETURN(ihipModuleLaunchKernel(f, globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ, localWorkSizeX, localWorkSizeY,
|
||||
localWorkSizeZ, sharedMemBytes, hStream, kernelParams, extra, startEvent, stopEvent, flags));
|
||||
}
|
||||
|
||||
|
||||
|
||||
hipError_t hipHccModuleLaunchKernel(hipFunction_t f, uint32_t globalWorkSizeX,
|
||||
uint32_t globalWorkSizeY, uint32_t globalWorkSizeZ,
|
||||
uint32_t blockDimX, uint32_t blockDimY,
|
||||
uint32_t blockDimZ, size_t sharedMemBytes,
|
||||
hipStream_t hStream, void** kernelParams, void** extra,
|
||||
hipEvent_t startEvent,
|
||||
hipEvent_t stopEvent)
|
||||
{
|
||||
HIP_INIT_API(hipHccModuleLaunchKernel, f, globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ,
|
||||
blockDimX, blockDimY, blockDimZ,
|
||||
sharedMemBytes, hStream,
|
||||
kernelParams, extra, startEvent, stopEvent);
|
||||
|
||||
HIP_RETURN(ihipModuleLaunchKernel(f, globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ, blockDimX, blockDimY, blockDimZ,
|
||||
sharedMemBytes, hStream, kernelParams, extra, startEvent, stopEvent));
|
||||
}
|
||||
|
||||
hipError_t hipModuleLaunchKernelExt(hipFunction_t f, uint32_t globalWorkSizeX,
|
||||
uint32_t globalWorkSizeY, uint32_t globalWorkSizeZ,
|
||||
uint32_t blockDimX, uint32_t blockDimY,
|
||||
uint32_t blockDimZ, size_t sharedMemBytes,
|
||||
hipStream_t hStream, void** kernelParams, void** extra,
|
||||
hipEvent_t startEvent,
|
||||
hipEvent_t stopEvent)
|
||||
{
|
||||
HIP_INIT_API(hipModuleLaunchKernelExt, f, globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ,
|
||||
blockDimX, blockDimY, blockDimZ,
|
||||
sharedMemBytes, hStream,
|
||||
kernelParams, extra, startEvent, stopEvent);
|
||||
|
||||
HIP_RETURN(ihipModuleLaunchKernel(f, globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ, blockDimX, blockDimY, blockDimZ,
|
||||
sharedMemBytes, hStream, kernelParams, extra, startEvent, stopEvent));
|
||||
}
|
||||
|
||||
extern "C" hipError_t hipLaunchKernel(const void *hostFunction,
|
||||
dim3 gridDim,
|
||||
dim3 blockDim,
|
||||
void** args,
|
||||
size_t sharedMemBytes,
|
||||
hipStream_t stream)
|
||||
{
|
||||
HIP_INIT_API(hipLaunchKernel, hostFunction, gridDim, blockDim, args, sharedMemBytes, stream);
|
||||
STREAM_CAPTURE(hipLaunchKernel, stream, hostFunction, gridDim, blockDim, args, sharedMemBytes);
|
||||
HIP_RETURN(ihipLaunchKernel(hostFunction, gridDim, blockDim, args, sharedMemBytes, stream,
|
||||
nullptr, nullptr, 0));
|
||||
}
|
||||
|
||||
extern "C" hipError_t hipExtLaunchKernel(const void* hostFunction,
|
||||
dim3 gridDim,
|
||||
dim3 blockDim,
|
||||
void** args,
|
||||
size_t sharedMemBytes,
|
||||
hipStream_t stream,
|
||||
hipEvent_t startEvent,
|
||||
hipEvent_t stopEvent,
|
||||
int flags)
|
||||
{
|
||||
HIP_INIT_API(hipExtLaunchKernel, hostFunction, gridDim, blockDim, args, sharedMemBytes, stream);
|
||||
HIP_RETURN(ihipLaunchKernel(hostFunction, gridDim, blockDim, args, sharedMemBytes, stream, startEvent, stopEvent, flags));
|
||||
}
|
||||
|
||||
hipError_t hipLaunchCooperativeKernel(const void* f,
|
||||
dim3 gridDim, dim3 blockDim,
|
||||
void **kernelParams, uint32_t sharedMemBytes, hipStream_t hStream)
|
||||
{
|
||||
HIP_INIT_API(hipLaunchCooperativeKernel, f, gridDim, blockDim,
|
||||
sharedMemBytes, hStream);
|
||||
|
||||
hipFunction_t func = nullptr;
|
||||
int deviceId = hip::Stream::DeviceId(hStream);
|
||||
HIP_RETURN_ONFAIL(PlatformState::instance().getStatFunc(&func, f, deviceId));
|
||||
size_t globalWorkSizeX = static_cast<size_t>(gridDim.x) * blockDim.x;
|
||||
size_t globalWorkSizeY = static_cast<size_t>(gridDim.y) * blockDim.y;
|
||||
size_t globalWorkSizeZ = static_cast<size_t>(gridDim.z) * blockDim.z;
|
||||
if (globalWorkSizeX > std::numeric_limits<uint32_t>::max() ||
|
||||
globalWorkSizeY > std::numeric_limits<uint32_t>::max() ||
|
||||
globalWorkSizeZ > std::numeric_limits<uint32_t>::max()) {
|
||||
HIP_RETURN(hipErrorInvalidConfiguration);
|
||||
}
|
||||
HIP_RETURN(ihipModuleLaunchKernel(func, static_cast<uint32_t>(globalWorkSizeX),
|
||||
static_cast<uint32_t>(globalWorkSizeY),
|
||||
static_cast<uint32_t>(globalWorkSizeZ),
|
||||
blockDim.x, blockDim.y, blockDim.z,
|
||||
sharedMemBytes, hStream, kernelParams, nullptr, nullptr, nullptr, 0,
|
||||
amd::NDRangeKernelCommand::CooperativeGroups));
|
||||
}
|
||||
|
||||
hipError_t ihipLaunchCooperativeKernelMultiDevice(hipLaunchParams* launchParamsList,
|
||||
int numDevices, unsigned int flags, uint32_t extFlags)
|
||||
{
|
||||
int numActiveGPUs = 0;
|
||||
ihipDeviceGetCount(&numActiveGPUs);
|
||||
|
||||
if ((numDevices > numActiveGPUs) || (launchParamsList == nullptr)) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
hipError_t result = hipErrorUnknown;
|
||||
uint64_t allGridSize = 0;
|
||||
uint32_t blockDims = 0;
|
||||
std::vector<const amd::Device*> mgpu_list(numDevices);
|
||||
|
||||
for (int i = 0; i < numDevices; ++i) {
|
||||
const hipLaunchParams& launch = launchParamsList[i];
|
||||
blockDims = launch.blockDim.x * launch.blockDim.y * launch.blockDim.z;
|
||||
allGridSize += launch.gridDim.x * launch.gridDim.y * launch.gridDim.z *
|
||||
blockDims;
|
||||
|
||||
// Make sure block dimensions are valid
|
||||
if (0 == blockDims) {
|
||||
return hipErrorInvalidConfiguration;
|
||||
}
|
||||
if (launch.stream != nullptr) {
|
||||
// Validate devices to make sure it dosn't have duplicates
|
||||
amd::HostQueue* queue = reinterpret_cast<hip::Stream*>(launch.stream)->asHostQueue();
|
||||
auto device = &queue->vdev()->device();
|
||||
for (int j = 0; j < numDevices; ++j) {
|
||||
if (mgpu_list[j] == device) {
|
||||
return hipErrorInvalidDevice;
|
||||
}
|
||||
}
|
||||
mgpu_list[i] = device;
|
||||
} else {
|
||||
return hipErrorInvalidResourceHandle;
|
||||
}
|
||||
}
|
||||
uint64_t prevGridSize = 0;
|
||||
uint32_t firstDevice = 0;
|
||||
|
||||
// Sync the execution streams on all devices
|
||||
if ((flags & hipCooperativeLaunchMultiDeviceNoPreSync) == 0) {
|
||||
for (int i = 0; i < numDevices; ++i) {
|
||||
amd::HostQueue* queue =
|
||||
reinterpret_cast<hip::Stream*>(launchParamsList[i].stream)->asHostQueue();
|
||||
queue->finish();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < numDevices; ++i) {
|
||||
const hipLaunchParams& launch = launchParamsList[i];
|
||||
amd::HostQueue* queue = reinterpret_cast<hip::Stream*>(launch.stream)->asHostQueue();
|
||||
hipFunction_t func = nullptr;
|
||||
// The order of devices in the launch may not match the order in the global array
|
||||
for (size_t dev = 0; dev < g_devices.size(); ++dev) {
|
||||
// Find the matching device and request the kernel function
|
||||
if (&queue->vdev()->device() == g_devices[dev]->devices()[0]) {
|
||||
IHIP_RETURN_ONFAIL(PlatformState::instance().getStatFunc(&func, launch.func, dev));
|
||||
// Save ROCclr index of the first device in the launch
|
||||
if (i == 0) {
|
||||
firstDevice = queue->vdev()->device().index();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (func == nullptr) {
|
||||
result = hipErrorInvalidDeviceFunction;
|
||||
HIP_RETURN(result);
|
||||
}
|
||||
size_t globalWorkSizeX = static_cast<size_t>(launch.gridDim.x) * launch.blockDim.x;
|
||||
size_t globalWorkSizeY = static_cast<size_t>(launch.gridDim.y) * launch.blockDim.y;
|
||||
size_t globalWorkSizeZ = static_cast<size_t>(launch.gridDim.z) * launch.blockDim.z;
|
||||
if (globalWorkSizeX > std::numeric_limits<uint32_t>::max() ||
|
||||
globalWorkSizeY > std::numeric_limits<uint32_t>::max() ||
|
||||
globalWorkSizeZ > std::numeric_limits<uint32_t>::max()) {
|
||||
HIP_RETURN(hipErrorInvalidConfiguration);
|
||||
}
|
||||
result = ihipModuleLaunchKernel(func, static_cast<uint32_t>(globalWorkSizeX),
|
||||
static_cast<uint32_t>(globalWorkSizeY), static_cast<uint32_t>(globalWorkSizeZ),
|
||||
launch.blockDim.x, launch.blockDim.y, launch.blockDim.z,
|
||||
launch.sharedMem, launch.stream, launch.args, nullptr, nullptr, nullptr,
|
||||
flags, extFlags, i, numDevices, prevGridSize, allGridSize, firstDevice);
|
||||
if (result != hipSuccess) {
|
||||
break;
|
||||
}
|
||||
prevGridSize += globalWorkSizeX * globalWorkSizeY * globalWorkSizeZ;
|
||||
}
|
||||
|
||||
// Sync the execution streams on all devices
|
||||
if ((flags & hipCooperativeLaunchMultiDeviceNoPostSync) == 0) {
|
||||
for (int i = 0; i < numDevices; ++i) {
|
||||
amd::HostQueue* queue =
|
||||
reinterpret_cast<hip::Stream*>(launchParamsList[i].stream)->asHostQueue();
|
||||
queue->finish();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
hipError_t hipLaunchCooperativeKernelMultiDevice(hipLaunchParams* launchParamsList,
|
||||
int numDevices, unsigned int flags)
|
||||
{
|
||||
HIP_INIT_API(hipLaunchCooperativeKernelMultiDevice, launchParamsList, numDevices, flags);
|
||||
|
||||
return HIP_RETURN(ihipLaunchCooperativeKernelMultiDevice(launchParamsList, numDevices, flags,
|
||||
(amd::NDRangeKernelCommand::CooperativeGroups |
|
||||
amd::NDRangeKernelCommand::CooperativeMultiDeviceGroups)));
|
||||
}
|
||||
|
||||
hipError_t hipExtLaunchMultiKernelMultiDevice(hipLaunchParams* launchParamsList,
|
||||
int numDevices, unsigned int flags) {
|
||||
HIP_INIT_API(hipExtLaunchMultiKernelMultiDevice, launchParamsList, numDevices, flags);
|
||||
|
||||
return HIP_RETURN(ihipLaunchCooperativeKernelMultiDevice(launchParamsList, numDevices, flags, 0));
|
||||
}
|
||||
|
||||
hipError_t hipModuleGetTexRef(textureReference** texRef, hipModule_t hmod, const char* name) {
|
||||
HIP_INIT_API(hipModuleGetTexRef, texRef, hmod, name);
|
||||
|
||||
/* input args check */
|
||||
if ((texRef == nullptr) || (name == nullptr)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
/* Get address and size for the global symbol */
|
||||
if (hipSuccess != PlatformState::instance().getDynTexRef(name, hmod, texRef)) {
|
||||
LogPrintfError("Cannot get texRef for name: %s at module:0x%x \n", name, hmod);
|
||||
HIP_RETURN(hipErrorNotFound);
|
||||
}
|
||||
|
||||
// Texture references created by HIP driver API
|
||||
// have the default read mode set to normalized float.
|
||||
(*texRef)->readMode = hipReadModeNormalizedFloat;
|
||||
|
||||
PlatformState::instance().registerTexRef(*texRef, hmod, std::string(name));
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
Executable
+250
@@ -0,0 +1,250 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
#include "hip_internal.hpp"
|
||||
|
||||
hipError_t hipDeviceCanAccessPeer(int* canAccessPeer, hipCtx_t thisCtx, hipCtx_t peerCtx) {
|
||||
HIP_INIT_API(NONE, canAccessPeer, thisCtx, peerCtx);
|
||||
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
|
||||
hipError_t hipMemcpyPeer(void* dst, hipCtx_t dstCtx, const void* src, hipCtx_t srcCtx,
|
||||
size_t sizeBytes) {
|
||||
HIP_INIT_API(NONE, dst, dstCtx, src, srcCtx, sizeBytes);
|
||||
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
|
||||
hipError_t hipMemcpyPeerAsync(void* dst, hipCtx_t dstDevice, const void* src, hipCtx_t srcDevice,
|
||||
size_t sizeBytes, hipStream_t stream) {
|
||||
HIP_INIT_API(NONE, dst, dstDevice, src, srcDevice, sizeBytes, stream);
|
||||
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
|
||||
hipError_t canAccessPeer(int* canAccessPeer, int deviceId, int peerDeviceId){
|
||||
amd::Device* device = nullptr;
|
||||
amd::Device* peer_device = nullptr;
|
||||
if (canAccessPeer == nullptr) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
/* Peer cannot be self */
|
||||
if (deviceId == peerDeviceId) {
|
||||
*canAccessPeer = 0;
|
||||
return hipSuccess;
|
||||
}
|
||||
/* Cannot exceed the max number of devices */
|
||||
if (static_cast<size_t>(deviceId) >= g_devices.size()
|
||||
|| static_cast<size_t>(peerDeviceId) >= g_devices.size()) {
|
||||
return hipErrorInvalidDevice;
|
||||
}
|
||||
device = g_devices[deviceId]->devices()[0];
|
||||
peer_device = g_devices[peerDeviceId]->devices()[0];
|
||||
*canAccessPeer = static_cast<int>(std::find(device->p2pDevices_.begin(),
|
||||
device->p2pDevices_.end(), as_cl(peer_device))
|
||||
!= device->p2pDevices_.end());
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t findLinkInfo(int device1, int device2,
|
||||
std::vector<amd::Device::LinkAttrType>* link_attrs) {
|
||||
|
||||
amd::Device* amd_dev_obj1 = nullptr;
|
||||
amd::Device* amd_dev_obj2 = nullptr;
|
||||
const int numDevices = static_cast<int>(g_devices.size());
|
||||
|
||||
if ((device1 < 0) || (device1 >= numDevices) || (device2 < 0) || (device2 >= numDevices)) {
|
||||
return hipErrorInvalidDevice;
|
||||
}
|
||||
|
||||
amd_dev_obj1 = g_devices[device1]->devices()[0];
|
||||
amd_dev_obj2 = g_devices[device2]->devices()[0];
|
||||
|
||||
if (!amd_dev_obj1->findLinkInfo(*amd_dev_obj2, link_attrs)) {
|
||||
return hipErrorInvalidHandle;
|
||||
}
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t hipExtGetLinkTypeAndHopCount(int device1, int device2,
|
||||
uint32_t* linktype, uint32_t* hopcount) {
|
||||
HIP_INIT_API(hipExtGetLinkTypeAndHopCount, device1, device2, linktype, hopcount);
|
||||
|
||||
if (linktype == nullptr || hopcount == nullptr ||
|
||||
device1 == device2 || device1 < 0 || device2 < 0) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
// Fill out the list of LinkAttributes
|
||||
std::vector<amd::Device::LinkAttrType> link_attrs;
|
||||
link_attrs.push_back(std::make_pair(amd::Device::LinkAttribute::kLinkLinkType, 0));
|
||||
link_attrs.push_back(std::make_pair(amd::Device::LinkAttribute::kLinkHopCount, 0));
|
||||
|
||||
HIP_RETURN_ONFAIL(findLinkInfo(device1, device2, &link_attrs));
|
||||
|
||||
*linktype = static_cast<uint32_t>(link_attrs[0].second);
|
||||
*hopcount = static_cast<uint32_t>(link_attrs[1].second);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceGetP2PAttribute(int* value, hipDeviceP2PAttr attr,
|
||||
int srcDevice, int dstDevice) {
|
||||
HIP_INIT_API(hipDeviceGetP2PAttribute, value, attr, srcDevice, dstDevice);
|
||||
|
||||
if (value == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
if (srcDevice == dstDevice || srcDevice >= static_cast<int>(g_devices.size())
|
||||
|| dstDevice >= static_cast<int>(g_devices.size())) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
std::vector<amd::Device::LinkAttrType> link_attrs;
|
||||
|
||||
switch (attr) {
|
||||
case hipDevP2PAttrPerformanceRank : {
|
||||
link_attrs.push_back(std::make_pair(amd::Device::LinkAttribute::kLinkLinkType, 0));
|
||||
break;
|
||||
}
|
||||
case hipDevP2PAttrAccessSupported : {
|
||||
HIP_RETURN_ONFAIL(canAccessPeer(value, srcDevice, dstDevice));
|
||||
break;
|
||||
}
|
||||
case hipDevP2PAttrNativeAtomicSupported : {
|
||||
link_attrs.push_back(std::make_pair(amd::Device::LinkAttribute::kLinkLinkType, 0));
|
||||
break;
|
||||
}
|
||||
case hipDevP2PAttrHipArrayAccessSupported : {
|
||||
hipDeviceProp_t srcDeviceProp;
|
||||
hipDeviceProp_t dstDeviceProp;
|
||||
HIP_RETURN_ONFAIL(hipGetDeviceProperties(&srcDeviceProp, srcDevice));
|
||||
HIP_RETURN_ONFAIL(hipGetDeviceProperties(&dstDeviceProp, dstDevice));
|
||||
|
||||
// Linear layout access is supported if P2P is enabled
|
||||
// Opaque Images are supported only on homogeneous systems
|
||||
// Might have more conditions to check, in future.
|
||||
if (srcDeviceProp.gcnArch == dstDeviceProp.gcnArch) {
|
||||
HIP_RETURN_ONFAIL(canAccessPeer(value, srcDevice, dstDevice));
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default : {
|
||||
LogPrintfError("Invalid attribute attr: %d ", attr);
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((attr != hipDevP2PAttrAccessSupported) && (attr != hipDevP2PAttrHipArrayAccessSupported)) {
|
||||
HIP_RETURN_ONFAIL(findLinkInfo(srcDevice, dstDevice, &link_attrs));
|
||||
*value = static_cast<int>(link_attrs[0].second);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipDeviceCanAccessPeer(int* canAccess, int deviceId, int peerDeviceId) {
|
||||
HIP_INIT_API(hipDeviceCanAccessPeer, canAccess, deviceId, peerDeviceId);
|
||||
HIP_RETURN(canAccessPeer(canAccess, deviceId, peerDeviceId));
|
||||
}
|
||||
|
||||
hipError_t hipDeviceDisablePeerAccess(int peerDeviceId) {
|
||||
HIP_INIT_API(hipDeviceDisablePeerAccess, peerDeviceId);
|
||||
int deviceId = hip::getCurrentDevice()->deviceId();
|
||||
int canAccess = 0;
|
||||
if ((hipSuccess != canAccessPeer(&canAccess, deviceId, peerDeviceId)) || (canAccess == 0)) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
amd::Device* device = g_devices[deviceId]->devices()[0];
|
||||
amd::Device* peer_device = g_devices[peerDeviceId]->devices()[0];
|
||||
peer_device->disableP2P(device);
|
||||
|
||||
HIP_RETURN(hip::getCurrentDevice()->DisablePeerAccess(peerDeviceId));
|
||||
}
|
||||
|
||||
hipError_t hipDeviceEnablePeerAccess(int peerDeviceId, unsigned int flags) {
|
||||
HIP_INIT_API(hipDeviceEnablePeerAccess, peerDeviceId, flags);
|
||||
int deviceId = hip::getCurrentDevice()->deviceId();
|
||||
int canAccess = 0;
|
||||
if (flags != 0) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
if ((hipSuccess != canAccessPeer(&canAccess, deviceId, peerDeviceId)) || (canAccess == 0)) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
amd::Device* device = g_devices[deviceId]->asContext()->devices()[0];
|
||||
amd::Device* peer_device = g_devices[peerDeviceId]->asContext()->devices()[0];
|
||||
peer_device->enableP2P(device);
|
||||
|
||||
HIP_RETURN(hip::getCurrentDevice()->EnablePeerAccess(peerDeviceId));
|
||||
}
|
||||
|
||||
hipError_t hipMemcpyPeer(void* dst, int dstDevice, const void* src, int srcDevice,
|
||||
size_t sizeBytes) {
|
||||
HIP_INIT_API(hipMemcpyPeer, dst, dstDevice, src, srcDevice, sizeBytes);
|
||||
|
||||
if (srcDevice >= static_cast<int>(g_devices.size()) ||
|
||||
dstDevice >= static_cast<int>(g_devices.size()) ||
|
||||
srcDevice < 0 || dstDevice < 0) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipMemcpy(dst, src, sizeBytes, hipMemcpyDeviceToDevice));
|
||||
}
|
||||
|
||||
hipError_t hipMemcpyPeerAsync(void* dst, int dstDevice, const void* src, int srcDevice,
|
||||
size_t sizeBytes, hipStream_t stream) {
|
||||
HIP_INIT_API(hipMemcpyPeerAsync, dst, dstDevice, src, srcDevice, sizeBytes, stream);
|
||||
|
||||
if (srcDevice >= static_cast<int>(g_devices.size()) ||
|
||||
dstDevice >= static_cast<int>(g_devices.size()) ||
|
||||
srcDevice < 0 || dstDevice < 0) {
|
||||
HIP_RETURN(hipErrorInvalidDevice);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipMemcpyAsync(dst, src, sizeBytes, hipMemcpyDeviceToDevice, stream));
|
||||
}
|
||||
|
||||
hipError_t hipCtxEnablePeerAccess(hipCtx_t peerCtx, unsigned int flags) {
|
||||
HIP_INIT_API(hipCtxEnablePeerAccess, peerCtx, flags);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
hipError_t hipCtxDisablePeerAccess(hipCtx_t peerCtx) {
|
||||
HIP_INIT_API(hipCtxDisablePeerAccess, peerCtx);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
Executable
+945
@@ -0,0 +1,945 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <hip/amd_detail/amd_texture_types.h>
|
||||
#include "hip_platform.hpp"
|
||||
#include "hip_internal.hpp"
|
||||
#include "platform/program.hpp"
|
||||
#include "platform/runtime.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
constexpr unsigned __hipFatMAGIC2 = 0x48495046; // "HIPF"
|
||||
|
||||
thread_local std::stack<ihipExec_t> execStack_;
|
||||
PlatformState* PlatformState::platform_; // Initiaized as nullptr by default
|
||||
|
||||
//forward declaration of methods required for __hipRegisrterManagedVar
|
||||
hipError_t ihipMallocManaged(void** ptr, size_t size, unsigned int align = 0);
|
||||
hipError_t ihipMemcpy(void* dst, const void* src, size_t sizeBytes, hipMemcpyKind kind,
|
||||
amd::HostQueue& queue, bool isAsync = false);
|
||||
|
||||
struct __CudaFatBinaryWrapper {
|
||||
unsigned int magic;
|
||||
unsigned int version;
|
||||
void* binary;
|
||||
void* dummy1;
|
||||
};
|
||||
|
||||
hipError_t hipModuleGetGlobal(hipDeviceptr_t* dptr, size_t* bytes,
|
||||
hipModule_t hmod, const char* name);
|
||||
|
||||
hipError_t ihipCreateGlobalVarObj(const char* name, hipModule_t hmod, amd::Memory** amd_mem_obj,
|
||||
hipDeviceptr_t* dptr, size_t* bytes);
|
||||
|
||||
extern hipError_t ihipModuleLaunchKernel(hipFunction_t f,
|
||||
uint32_t gridDimX, uint32_t gridDimY, uint32_t gridDimZ,
|
||||
uint32_t blockDimX, uint32_t blockDimY, uint32_t blockDimZ,
|
||||
uint32_t sharedMemBytes, hipStream_t hStream,
|
||||
void **kernelParams, void **extra,
|
||||
hipEvent_t startEvent, hipEvent_t stopEvent, uint32_t flags = 0,
|
||||
uint32_t params = 0, uint32_t gridId = 0, uint32_t numGrids = 0,
|
||||
uint64_t prevGridSum = 0, uint64_t allGridSum = 0, uint32_t firstDevice = 0);
|
||||
static bool isCompatibleCodeObject(const std::string& codeobj_target_id,
|
||||
const char* device_name) {
|
||||
// Workaround for device name mismatch.
|
||||
// Device name may contain feature strings delimited by '+', e.g.
|
||||
// gfx900+xnack. Currently HIP-Clang does not include feature strings
|
||||
// in code object target id in fat binary. Therefore drop the feature
|
||||
// strings from device name before comparing it with code object target id.
|
||||
std::string short_name(device_name);
|
||||
auto feature_loc = short_name.find('+');
|
||||
if (feature_loc != std::string::npos) {
|
||||
short_name.erase(feature_loc);
|
||||
}
|
||||
return codeobj_target_id == short_name;
|
||||
}
|
||||
|
||||
extern "C" hip::FatBinaryInfo** __hipRegisterFatBinary(const void* data)
|
||||
{
|
||||
const __CudaFatBinaryWrapper* fbwrapper = reinterpret_cast<const __CudaFatBinaryWrapper*>(data);
|
||||
if (fbwrapper->magic != __hipFatMAGIC2 || fbwrapper->version != 1) {
|
||||
LogPrintfError("Cannot Register fat binary. FatMagic: %u version: %u ", fbwrapper->magic,
|
||||
fbwrapper->version);
|
||||
return nullptr;
|
||||
}
|
||||
return PlatformState::instance().addFatBinary(fbwrapper->binary);
|
||||
}
|
||||
|
||||
extern "C" void __hipRegisterFunction(
|
||||
hip::FatBinaryInfo** modules,
|
||||
const void* hostFunction,
|
||||
char* deviceFunction,
|
||||
const char* deviceName,
|
||||
unsigned int threadLimit,
|
||||
uint3* tid,
|
||||
uint3* bid,
|
||||
dim3* blockDim,
|
||||
dim3* gridDim,
|
||||
int* wSize) {
|
||||
static int enable_deferred_loading { []() {
|
||||
char *var = getenv("HIP_ENABLE_DEFERRED_LOADING");
|
||||
return var ? atoi(var) : 1;
|
||||
}() };
|
||||
|
||||
hip::Function* func = new hip::Function(std::string(deviceName), modules);
|
||||
PlatformState::instance().registerStatFunction(hostFunction, func);
|
||||
|
||||
if (!enable_deferred_loading) {
|
||||
HIP_INIT();
|
||||
hipFunction_t hfunc = nullptr;
|
||||
hipError_t hip_error = hipSuccess;
|
||||
for (size_t dev_idx = 0; dev_idx < g_devices.size(); ++dev_idx) {
|
||||
hip_error = PlatformState::instance().getStatFunc(&hfunc, hostFunction, dev_idx);
|
||||
guarantee((hip_error == hipSuccess), "Cannot Retrieve Static function");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Registers a device-side global variable.
|
||||
// For each global variable in device code, there is a corresponding shadow
|
||||
// global variable in host code. The shadow host variable is used to keep
|
||||
// track of the value of the device side global variable between kernel
|
||||
// executions.
|
||||
extern "C" void __hipRegisterVar(
|
||||
hip::FatBinaryInfo** modules, // The device modules containing code object
|
||||
void* var, // The shadow variable in host code
|
||||
char* hostVar, // Variable name in host code
|
||||
char* deviceVar, // Variable name in device code
|
||||
int ext, // Whether this variable is external
|
||||
size_t size, // Size of the variable
|
||||
int constant, // Whether this variable is constant
|
||||
int global) // Unknown, always 0
|
||||
{
|
||||
hip::Var* var_ptr = new hip::Var(std::string(hostVar), hip::Var::DeviceVarKind::DVK_Variable, size, 0, 0, modules);
|
||||
PlatformState::instance().registerStatGlobalVar(var, var_ptr);
|
||||
}
|
||||
|
||||
extern "C" void __hipRegisterSurface(hip::FatBinaryInfo** modules, // The device modules containing code object
|
||||
void* var, // The shadow variable in host code
|
||||
char* hostVar, // Variable name in host code
|
||||
char* deviceVar, // Variable name in device code
|
||||
int type, int ext) {
|
||||
hip::Var* var_ptr = new hip::Var(std::string(hostVar), hip::Var::DeviceVarKind::DVK_Surface, sizeof(surfaceReference), 0, 0, modules);
|
||||
PlatformState::instance().registerStatGlobalVar(var, var_ptr);
|
||||
}
|
||||
|
||||
extern "C" void __hipRegisterManagedVar(void *hipModule, // Pointer to hip module returned from __hipRegisterFatbinary
|
||||
void **pointer, // Pointer to a chunk of managed memory with size \p size and alignment \p align
|
||||
// HIP runtime allocates such managed memory and assign it to \p pointer
|
||||
void *init_value, // Initial value to be copied into \p pointer
|
||||
const char *name, // Name of the variable in code object
|
||||
size_t size,
|
||||
unsigned align) {
|
||||
HIP_INIT();
|
||||
hipError_t status = ihipMallocManaged(pointer, size, align);
|
||||
if( status == hipSuccess) {
|
||||
amd::HostQueue* queue = hip::getNullStream();
|
||||
if(queue != nullptr) {
|
||||
ihipMemcpy(*pointer, init_value, size, hipMemcpyHostToDevice, *queue);
|
||||
} else {
|
||||
ClPrint(amd::LOG_ERROR, amd::LOG_API, "Host Queue is NULL");
|
||||
}
|
||||
} else {
|
||||
guarantee(false, "Error during allocation of managed memory!");
|
||||
}
|
||||
hip::Var* var_ptr = new hip::Var(std::string(name), hip::Var::DeviceVarKind::DVK_Managed, pointer,
|
||||
size, align, reinterpret_cast<hip::FatBinaryInfo**>(hipModule));
|
||||
PlatformState::instance().registerStatManagedVar(var_ptr);
|
||||
}
|
||||
|
||||
extern "C" void __hipRegisterTexture(hip::FatBinaryInfo** modules, // The device modules containing code object
|
||||
void* var, // The shadow variable in host code
|
||||
char* hostVar, // Variable name in host code
|
||||
char* deviceVar, // Variable name in device code
|
||||
int type, int norm, int ext) {
|
||||
hip::Var* var_ptr = new hip::Var(std::string(hostVar), hip::Var::DeviceVarKind::DVK_Texture, sizeof(textureReference), 0, 0, modules);
|
||||
PlatformState::instance().registerStatGlobalVar(var, var_ptr);
|
||||
}
|
||||
|
||||
extern "C" void __hipUnregisterFatBinary(hip::FatBinaryInfo** modules)
|
||||
{
|
||||
PlatformState::instance().removeFatBinary(modules);
|
||||
}
|
||||
|
||||
extern "C" hipError_t hipConfigureCall(
|
||||
dim3 gridDim,
|
||||
dim3 blockDim,
|
||||
size_t sharedMem,
|
||||
hipStream_t stream)
|
||||
{
|
||||
HIP_INIT_API(hipConfigureCall, gridDim, blockDim, sharedMem, stream);
|
||||
|
||||
PlatformState::instance().configureCall(gridDim, blockDim, sharedMem, stream);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
extern "C" hipError_t __hipPushCallConfiguration(
|
||||
dim3 gridDim,
|
||||
dim3 blockDim,
|
||||
size_t sharedMem,
|
||||
hipStream_t stream)
|
||||
{
|
||||
HIP_INIT_API(__hipPushCallConfiguration, gridDim, blockDim, sharedMem, stream);
|
||||
|
||||
PlatformState::instance().configureCall(gridDim, blockDim, sharedMem, stream);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
extern "C" hipError_t __hipPopCallConfiguration(dim3 *gridDim,
|
||||
dim3 *blockDim,
|
||||
size_t *sharedMem,
|
||||
hipStream_t *stream) {
|
||||
HIP_INIT_API(__hipPopCallConfiguration, gridDim, blockDim, sharedMem, stream);
|
||||
|
||||
ihipExec_t exec;
|
||||
PlatformState::instance().popExec(exec);
|
||||
*gridDim = exec.gridDim_;
|
||||
*blockDim = exec.blockDim_;
|
||||
*sharedMem = exec.sharedMem_;
|
||||
*stream = exec.hStream_;
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
extern "C" hipError_t hipSetupArgument(
|
||||
const void *arg,
|
||||
size_t size,
|
||||
size_t offset)
|
||||
{
|
||||
HIP_INIT_API(hipSetupArgument, arg, size, offset);
|
||||
|
||||
PlatformState::instance().setupArgument(arg, size, offset);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
extern "C" hipError_t hipLaunchByPtr(const void *hostFunction)
|
||||
{
|
||||
HIP_INIT_API(hipLaunchByPtr, hostFunction);
|
||||
|
||||
ihipExec_t exec;
|
||||
PlatformState::instance().popExec(exec);
|
||||
|
||||
hip::Stream* stream = reinterpret_cast<hip::Stream*>(exec.hStream_);
|
||||
int deviceId = (stream != nullptr)? stream->DeviceId() : ihipGetDevice();
|
||||
if (deviceId == -1) {
|
||||
LogPrintfError("Wrong DeviceId: %d \n", deviceId);
|
||||
HIP_RETURN(hipErrorNoDevice);
|
||||
}
|
||||
hipFunction_t func = nullptr;
|
||||
hipError_t hip_error = PlatformState::instance().getStatFunc(&func, hostFunction, deviceId);
|
||||
if ((hip_error != hipSuccess) || (func == nullptr)) {
|
||||
LogPrintfError("Could not retrieve hostFunction: 0x%x \n", hostFunction);
|
||||
HIP_RETURN(hipErrorInvalidDeviceFunction);
|
||||
}
|
||||
|
||||
size_t size = exec.arguments_.size();
|
||||
void *extra[] = {
|
||||
HIP_LAUNCH_PARAM_BUFFER_POINTER, &exec.arguments_[0],
|
||||
HIP_LAUNCH_PARAM_BUFFER_SIZE, &size,
|
||||
HIP_LAUNCH_PARAM_END
|
||||
};
|
||||
|
||||
HIP_RETURN(hipModuleLaunchKernel(func,
|
||||
exec.gridDim_.x, exec.gridDim_.y, exec.gridDim_.z,
|
||||
exec.blockDim_.x, exec.blockDim_.y, exec.blockDim_.z,
|
||||
exec.sharedMem_, exec.hStream_, nullptr, extra));
|
||||
}
|
||||
|
||||
hipError_t hipGetSymbolAddress(void** devPtr, const void* symbol) {
|
||||
HIP_INIT_API(hipGetSymbolAddress, devPtr, symbol);
|
||||
|
||||
hipError_t hip_error = hipSuccess;
|
||||
size_t sym_size = 0;
|
||||
|
||||
HIP_RETURN_ONFAIL(PlatformState::instance().getStatGlobalVar(symbol, ihipGetDevice(), devPtr, &sym_size));
|
||||
|
||||
HIP_RETURN(hipSuccess, *devPtr);
|
||||
}
|
||||
|
||||
hipError_t hipGetSymbolSize(size_t* sizePtr, const void* symbol) {
|
||||
HIP_INIT_API(hipGetSymbolSize, sizePtr, symbol);
|
||||
|
||||
hipDeviceptr_t device_ptr = nullptr;
|
||||
HIP_RETURN_ONFAIL(PlatformState::instance().getStatGlobalVar(symbol, ihipGetDevice(), &device_ptr, sizePtr));
|
||||
|
||||
HIP_RETURN(hipSuccess, *sizePtr);
|
||||
}
|
||||
|
||||
hipError_t ihipCreateGlobalVarObj(const char* name, hipModule_t hmod, amd::Memory** amd_mem_obj,
|
||||
hipDeviceptr_t* dptr, size_t* bytes)
|
||||
{
|
||||
HIP_INIT();
|
||||
|
||||
amd::Program* program = nullptr;
|
||||
device::Program* dev_program = nullptr;
|
||||
|
||||
/* Get Device Program pointer*/
|
||||
program = as_amd(reinterpret_cast<cl_program>(hmod));
|
||||
dev_program = program->getDeviceProgram(*hip::getCurrentDevice()->devices()[0]);
|
||||
|
||||
if (dev_program == nullptr) {
|
||||
LogPrintfError("Cannot get Device Function for module: 0x%x \n", hmod);
|
||||
HIP_RETURN(hipErrorInvalidDeviceFunction);
|
||||
}
|
||||
/* Find the global Symbols */
|
||||
if (!dev_program->createGlobalVarObj(amd_mem_obj, dptr, bytes, name)) {
|
||||
LogPrintfError("Cannot create Global Var obj for symbol: %s \n", name);
|
||||
HIP_RETURN(hipErrorInvalidSymbol);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
|
||||
namespace hip_impl {
|
||||
hipError_t ihipOccupancyMaxActiveBlocksPerMultiprocessor(
|
||||
int* maxBlocksPerCU, int* numBlocksPerGrid, int* bestBlockSize,
|
||||
const amd::Device& device, hipFunction_t func, int inputBlockSize,
|
||||
size_t dynamicSMemSize, bool bCalcPotentialBlkSz)
|
||||
{
|
||||
hip::DeviceFunc* function = hip::DeviceFunc::asFunction(func);
|
||||
const amd::Kernel& kernel = *function->kernel();
|
||||
|
||||
const device::Kernel::WorkGroupInfo* wrkGrpInfo = kernel.getDeviceKernel(device)->workGroupInfo();
|
||||
if (bCalcPotentialBlkSz == false) {
|
||||
if (inputBlockSize <= 0) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
*bestBlockSize = 0;
|
||||
// Make sure the requested block size is smaller than max supported
|
||||
if (inputBlockSize > int(device.info().maxWorkGroupSize_)) {
|
||||
*maxBlocksPerCU = 0;
|
||||
*numBlocksPerGrid = 0;
|
||||
return hipSuccess;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (inputBlockSize > int(device.info().maxWorkGroupSize_) ||
|
||||
inputBlockSize <= 0) {
|
||||
// The user wrote the kernel to work with a workgroup size
|
||||
// bigger than this hardware can support. Or they do not care
|
||||
// about the size So just assume its maximum size is
|
||||
// constrained by hardware
|
||||
inputBlockSize = device.info().maxWorkGroupSize_;
|
||||
}
|
||||
}
|
||||
// Find wave occupancy per CU => simd_per_cu * GPR usage
|
||||
size_t MaxWavesPerSimd;
|
||||
|
||||
if (device.isa().versionMajor() <= 9) {
|
||||
MaxWavesPerSimd = 8; // Limited by SPI 32 per CU, hence 8 per SIMD
|
||||
} else {
|
||||
MaxWavesPerSimd = 16;
|
||||
}
|
||||
size_t VgprWaves = MaxWavesPerSimd;
|
||||
size_t maxVGPRs;
|
||||
uint32_t VgprGranularity;
|
||||
if (device.isa().versionMajor() <= 9) {
|
||||
if (device.isa().versionMajor() == 9 &&
|
||||
device.isa().versionMinor() == 0 &&
|
||||
device.isa().versionStepping() == 10) {
|
||||
maxVGPRs = 512;
|
||||
VgprGranularity = 8;
|
||||
}
|
||||
else {
|
||||
maxVGPRs = 256;
|
||||
VgprGranularity = 4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
maxVGPRs = 1024;
|
||||
VgprGranularity = 8;
|
||||
}
|
||||
if (wrkGrpInfo->usedSGPRs_ > 0) {
|
||||
VgprWaves = maxVGPRs / amd::alignUp(wrkGrpInfo->usedVGPRs_, VgprGranularity);
|
||||
}
|
||||
|
||||
size_t GprWaves = VgprWaves;
|
||||
if (wrkGrpInfo->usedSGPRs_ > 0) {
|
||||
size_t maxSGPRs;
|
||||
if (device.isa().versionMajor() < 8) {
|
||||
maxSGPRs = 512;
|
||||
}
|
||||
else if (device.isa().versionMajor() < 10) {
|
||||
maxSGPRs = 800;
|
||||
}
|
||||
else {
|
||||
maxSGPRs = SIZE_MAX; // gfx10+ does not share SGPRs between waves
|
||||
}
|
||||
const size_t SgprWaves = maxSGPRs / amd::alignUp(wrkGrpInfo->usedSGPRs_, 16);
|
||||
GprWaves = std::min(VgprWaves, SgprWaves);
|
||||
}
|
||||
|
||||
const size_t alu_occupancy = device.info().simdPerCU_ * std::min(MaxWavesPerSimd, GprWaves);
|
||||
const int alu_limited_threads = alu_occupancy * wrkGrpInfo->wavefrontSize_;
|
||||
|
||||
int lds_occupancy_wgs = INT_MAX;
|
||||
const size_t total_used_lds = wrkGrpInfo->usedLDSSize_ + dynamicSMemSize;
|
||||
if (total_used_lds != 0) {
|
||||
lds_occupancy_wgs = static_cast<int>(device.info().localMemSize_ / total_used_lds);
|
||||
}
|
||||
// Calculate how many blocks of inputBlockSize we can fit per CU
|
||||
// Need to align with hardware wavefront size. If they want 65 threads, but
|
||||
// waves are 64, then we need 128 threads per block.
|
||||
// So this calculates how many blocks we can fit.
|
||||
*maxBlocksPerCU = alu_limited_threads / amd::alignUp(inputBlockSize, wrkGrpInfo->wavefrontSize_);
|
||||
// Unless those blocks are further constrained by LDS size.
|
||||
*maxBlocksPerCU = std::min(*maxBlocksPerCU, lds_occupancy_wgs);
|
||||
|
||||
// Some callers of this function want to return the block size, in threads, that
|
||||
// leads to the maximum occupancy. In that case, inputBlockSize is the maximum
|
||||
// workgroup size the user wants to allow, or that the hardware can allow.
|
||||
// It is either the number of threads that we are limited to due to occupancy, or
|
||||
// the maximum available block size for this kernel, which could have come from the
|
||||
// user. e.g., if the user indicates the maximum block size is 64 threads, but we
|
||||
// calculate that 128 threads can fit in each CU, we have to give up and return 64.
|
||||
*bestBlockSize = std::min(alu_limited_threads, amd::alignUp(inputBlockSize, wrkGrpInfo->wavefrontSize_));
|
||||
// If the best block size is smaller than the block size used to fit the maximum,
|
||||
// then we need to make the grid bigger for full occupancy.
|
||||
const int bestBlocksPerCU = alu_limited_threads / (*bestBlockSize);
|
||||
// Unless those blocks are further constrained by LDS size.
|
||||
*numBlocksPerGrid = device.info().maxComputeUnits_ * std::min(bestBlocksPerCU, lds_occupancy_wgs);
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
hipError_t hipOccupancyMaxPotentialBlockSize(int* gridSize, int* blockSize,
|
||||
const void* f, size_t dynSharedMemPerBlk,
|
||||
int blockSizeLimit)
|
||||
{
|
||||
HIP_INIT_API(hipOccupancyMaxPotentialBlockSize, f, dynSharedMemPerBlk, blockSizeLimit);
|
||||
if ((gridSize == nullptr) || (blockSize == nullptr)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
hipFunction_t func = nullptr;
|
||||
hipError_t hip_error = PlatformState::instance().getStatFunc(&func, f, ihipGetDevice());
|
||||
if ((hip_error != hipSuccess) || (func == nullptr)) {
|
||||
return HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
const amd::Device& device = *hip::getCurrentDevice()->devices()[0];
|
||||
int max_blocks_per_grid = 0;
|
||||
int num_blocks = 0;
|
||||
int best_block_size = 0;
|
||||
hipError_t ret = hip_impl::ihipOccupancyMaxActiveBlocksPerMultiprocessor(
|
||||
&num_blocks, &max_blocks_per_grid, &best_block_size, device, func, blockSizeLimit, dynSharedMemPerBlk,true);
|
||||
if (ret == hipSuccess) {
|
||||
*blockSize = best_block_size;
|
||||
*gridSize = max_blocks_per_grid;
|
||||
}
|
||||
HIP_RETURN(ret);
|
||||
}
|
||||
|
||||
hipError_t hipModuleOccupancyMaxPotentialBlockSize(int* gridSize, int* blockSize,
|
||||
hipFunction_t f, size_t dynSharedMemPerBlk,
|
||||
int blockSizeLimit)
|
||||
{
|
||||
HIP_INIT_API(hipModuleOccupancyMaxPotentialBlockSize, f, dynSharedMemPerBlk, blockSizeLimit);
|
||||
if ((gridSize == nullptr) || (blockSize == nullptr)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
const amd::Device& device = *hip::getCurrentDevice()->devices()[0];
|
||||
int max_blocks_per_grid = 0;
|
||||
int num_blocks = 0;
|
||||
int best_block_size = 0;
|
||||
hipError_t ret = hip_impl::ihipOccupancyMaxActiveBlocksPerMultiprocessor(
|
||||
&num_blocks, &max_blocks_per_grid, &best_block_size, device, f, blockSizeLimit, dynSharedMemPerBlk,true);
|
||||
if (ret == hipSuccess) {
|
||||
*blockSize = best_block_size;
|
||||
*gridSize = max_blocks_per_grid;
|
||||
}
|
||||
HIP_RETURN(ret);
|
||||
}
|
||||
|
||||
hipError_t hipModuleOccupancyMaxPotentialBlockSizeWithFlags(int* gridSize, int* blockSize,
|
||||
hipFunction_t f, size_t dynSharedMemPerBlk,
|
||||
int blockSizeLimit, unsigned int flags)
|
||||
{
|
||||
HIP_INIT_API(hipModuleOccupancyMaxPotentialBlockSizeWithFlags, f, dynSharedMemPerBlk, blockSizeLimit, flags);
|
||||
if ((gridSize == nullptr) || (blockSize == nullptr)) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
const amd::Device& device = *hip::getCurrentDevice()->devices()[0];
|
||||
int max_blocks_per_grid = 0;
|
||||
int num_blocks = 0;
|
||||
int best_block_size = 0;
|
||||
hipError_t ret = hip_impl::ihipOccupancyMaxActiveBlocksPerMultiprocessor(
|
||||
&num_blocks, &max_blocks_per_grid, &best_block_size, device, f, blockSizeLimit, dynSharedMemPerBlk,true);
|
||||
if (ret == hipSuccess) {
|
||||
*blockSize = best_block_size;
|
||||
*gridSize = max_blocks_per_grid;
|
||||
}
|
||||
HIP_RETURN(ret);
|
||||
}
|
||||
|
||||
hipError_t hipModuleOccupancyMaxActiveBlocksPerMultiprocessor(int* numBlocks,
|
||||
hipFunction_t f, int blockSize, size_t dynSharedMemPerBlk)
|
||||
{
|
||||
HIP_INIT_API(hipModuleOccupancyMaxActiveBlocksPerMultiprocessor, f, blockSize, dynSharedMemPerBlk);
|
||||
if (numBlocks == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
const amd::Device& device = *hip::getCurrentDevice()->devices()[0];
|
||||
|
||||
int num_blocks = 0;
|
||||
int max_blocks_per_grid = 0;
|
||||
int best_block_size = 0;
|
||||
hipError_t ret = hip_impl::ihipOccupancyMaxActiveBlocksPerMultiprocessor(
|
||||
&num_blocks, &max_blocks_per_grid, &best_block_size, device, f, blockSize, dynSharedMemPerBlk, false);
|
||||
*numBlocks = num_blocks;
|
||||
HIP_RETURN(ret);
|
||||
}
|
||||
|
||||
hipError_t hipModuleOccupancyMaxActiveBlocksPerMultiprocessorWithFlags(int* numBlocks,
|
||||
hipFunction_t f, int blockSize,
|
||||
size_t dynSharedMemPerBlk, unsigned int flags)
|
||||
{
|
||||
HIP_INIT_API(hipModuleOccupancyMaxActiveBlocksPerMultiprocessorWithFlags, f, blockSize, dynSharedMemPerBlk, flags);
|
||||
if (numBlocks == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
const amd::Device& device = *hip::getCurrentDevice()->devices()[0];
|
||||
|
||||
int num_blocks = 0;
|
||||
int max_blocks_per_grid = 0;
|
||||
int best_block_size = 0;
|
||||
hipError_t ret = hip_impl::ihipOccupancyMaxActiveBlocksPerMultiprocessor(
|
||||
&num_blocks, &max_blocks_per_grid, &best_block_size, device, f, blockSize, dynSharedMemPerBlk, false);
|
||||
*numBlocks = num_blocks;
|
||||
HIP_RETURN(ret);
|
||||
}
|
||||
|
||||
hipError_t hipOccupancyMaxActiveBlocksPerMultiprocessor(int* numBlocks,
|
||||
const void* f, int blockSize, size_t dynamicSMemSize)
|
||||
{
|
||||
HIP_INIT_API(hipOccupancyMaxActiveBlocksPerMultiprocessor, f, blockSize, dynamicSMemSize);
|
||||
if (numBlocks == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
hipFunction_t func = nullptr;
|
||||
hipError_t hip_error = PlatformState::instance().getStatFunc(&func, f, ihipGetDevice());
|
||||
if ((hip_error != hipSuccess) || (func == nullptr)) {
|
||||
return HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
const amd::Device& device = *hip::getCurrentDevice()->devices()[0];
|
||||
|
||||
int num_blocks = 0;
|
||||
int max_blocks_per_grid = 0;
|
||||
int best_block_size = 0;
|
||||
hipError_t ret = hip_impl::ihipOccupancyMaxActiveBlocksPerMultiprocessor(
|
||||
&num_blocks, &max_blocks_per_grid, &best_block_size, device, func, blockSize, dynamicSMemSize, false);
|
||||
*numBlocks = num_blocks;
|
||||
HIP_RETURN(ret);
|
||||
}
|
||||
|
||||
hipError_t hipOccupancyMaxActiveBlocksPerMultiprocessorWithFlags(int* numBlocks,
|
||||
const void* f,
|
||||
int blockSize, size_t dynamicSMemSize, unsigned int flags)
|
||||
{
|
||||
HIP_INIT_API(hipOccupancyMaxActiveBlocksPerMultiprocessorWithFlags, f, blockSize, dynamicSMemSize, flags);
|
||||
if (numBlocks == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
hipFunction_t func = nullptr;
|
||||
hipError_t hip_error = PlatformState::instance().getStatFunc(&func, f, ihipGetDevice());
|
||||
if ((hip_error != hipSuccess) || (func == nullptr)) {
|
||||
return HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
const amd::Device& device = *hip::getCurrentDevice()->devices()[0];
|
||||
|
||||
int num_blocks = 0;
|
||||
int max_blocks_per_grid = 0;
|
||||
int best_block_size = 0;
|
||||
hipError_t ret = hip_impl::ihipOccupancyMaxActiveBlocksPerMultiprocessor(
|
||||
&num_blocks, &max_blocks_per_grid, &best_block_size, device, func, blockSize, dynamicSMemSize, false);
|
||||
*numBlocks = num_blocks;
|
||||
HIP_RETURN(ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(ATI_OS_LINUX)
|
||||
|
||||
namespace hip_impl {
|
||||
|
||||
void hipLaunchKernelGGLImpl(
|
||||
uintptr_t function_address,
|
||||
const dim3& numBlocks,
|
||||
const dim3& dimBlocks,
|
||||
uint32_t sharedMemBytes,
|
||||
hipStream_t stream,
|
||||
void** kernarg)
|
||||
{
|
||||
HIP_INIT();
|
||||
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
int deviceId = (s != nullptr)? s->DeviceId() : ihipGetDevice();
|
||||
if (deviceId == -1) {
|
||||
LogPrintfError("Wrong Device Id: %d \n", deviceId);
|
||||
}
|
||||
|
||||
hipFunction_t func = nullptr;
|
||||
hipError_t hip_error = PlatformState::instance().getStatFunc(&func, reinterpret_cast<void*>(function_address), deviceId);
|
||||
if ((hip_error != hipSuccess) || (func == nullptr)) {
|
||||
LogPrintfError("Cannot find the static function: 0x%x", function_address);
|
||||
}
|
||||
|
||||
hipModuleLaunchKernel(func,
|
||||
numBlocks.x, numBlocks.y, numBlocks.z,
|
||||
dimBlocks.x, dimBlocks.y, dimBlocks.z,
|
||||
sharedMemBytes, stream, nullptr, kernarg);
|
||||
}
|
||||
|
||||
void hipLaunchCooperativeKernelGGLImpl(
|
||||
uintptr_t function_address,
|
||||
const dim3& numBlocks,
|
||||
const dim3& dimBlocks,
|
||||
uint32_t sharedMemBytes,
|
||||
hipStream_t stream,
|
||||
void** kernarg)
|
||||
{
|
||||
HIP_INIT();
|
||||
|
||||
hipLaunchCooperativeKernel(reinterpret_cast<void*>(function_address),
|
||||
numBlocks, dimBlocks, kernarg, sharedMemBytes, stream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // defined(ATI_OS_LINUX)
|
||||
|
||||
hipError_t ihipLaunchKernel(const void* hostFunction,
|
||||
dim3 gridDim,
|
||||
dim3 blockDim,
|
||||
void** args,
|
||||
size_t sharedMemBytes,
|
||||
hipStream_t stream,
|
||||
hipEvent_t startEvent,
|
||||
hipEvent_t stopEvent,
|
||||
int flags)
|
||||
{
|
||||
hipFunction_t func = nullptr;
|
||||
int deviceId = hip::Stream::DeviceId(stream);
|
||||
hipError_t hip_error = PlatformState::instance().getStatFunc(&func, hostFunction, deviceId);
|
||||
if ((hip_error != hipSuccess) || (func == nullptr)) {
|
||||
HIP_RETURN(hipErrorInvalidDeviceFunction);
|
||||
}
|
||||
size_t globalWorkSizeX = static_cast<size_t>(gridDim.x) * blockDim.x;
|
||||
size_t globalWorkSizeY = static_cast<size_t>(gridDim.y) * blockDim.y;
|
||||
size_t globalWorkSizeZ = static_cast<size_t>(gridDim.z) * blockDim.z;
|
||||
if (globalWorkSizeX > std::numeric_limits<uint32_t>::max() ||
|
||||
globalWorkSizeY > std::numeric_limits<uint32_t>::max() ||
|
||||
globalWorkSizeZ > std::numeric_limits<uint32_t>::max()) {
|
||||
HIP_RETURN(hipErrorInvalidConfiguration);
|
||||
}
|
||||
HIP_RETURN(ihipModuleLaunchKernel(func, static_cast<uint32_t>(globalWorkSizeX),
|
||||
static_cast<uint32_t>(globalWorkSizeY),
|
||||
static_cast<uint32_t>(globalWorkSizeZ),
|
||||
blockDim.x, blockDim.y, blockDim.z,
|
||||
sharedMemBytes, stream, args, nullptr, startEvent, stopEvent,
|
||||
flags));
|
||||
}
|
||||
|
||||
// conversion routines between float and half precision
|
||||
|
||||
static inline std::uint32_t f32_as_u32(float f) { union { float f; std::uint32_t u; } v; v.f = f; return v.u; }
|
||||
|
||||
static inline float u32_as_f32(std::uint32_t u) { union { float f; std::uint32_t u; } v; v.u = u; return v.f; }
|
||||
|
||||
static inline int clamp_int(int i, int l, int h) { return std::min(std::max(i, l), h); }
|
||||
|
||||
|
||||
// half float, the f16 is in the low 16 bits of the input argument
|
||||
|
||||
static inline float __convert_half_to_float(std::uint32_t a) noexcept {
|
||||
|
||||
std::uint32_t u = ((a << 13) + 0x70000000U) & 0x8fffe000U;
|
||||
|
||||
std::uint32_t v = f32_as_u32(u32_as_f32(u) * u32_as_f32(0x77800000U)/*0x1.0p+112f*/) + 0x38000000U;
|
||||
|
||||
u = (a & 0x7fff) != 0 ? v : u;
|
||||
|
||||
return u32_as_f32(u) * u32_as_f32(0x07800000U)/*0x1.0p-112f*/;
|
||||
|
||||
}
|
||||
|
||||
// float half with nearest even rounding
|
||||
// The lower 16 bits of the result is the bit pattern for the f16
|
||||
static inline std::uint32_t __convert_float_to_half(float a) noexcept {
|
||||
std::uint32_t u = f32_as_u32(a);
|
||||
int e = static_cast<int>((u >> 23) & 0xff) - 127 + 15;
|
||||
std::uint32_t m = ((u >> 11) & 0xffe) | ((u & 0xfff) != 0);
|
||||
std::uint32_t i = 0x7c00 | (m != 0 ? 0x0200 : 0);
|
||||
std::uint32_t n = ((std::uint32_t)e << 12) | m;
|
||||
std::uint32_t s = (u >> 16) & 0x8000;
|
||||
int b = clamp_int(1-e, 0, 13);
|
||||
std::uint32_t d = (0x1000 | m) >> b;
|
||||
d |= (d << b) != (0x1000 | m);
|
||||
std::uint32_t v = e < 1 ? d : n;
|
||||
v = (v >> 2) + (((v & 0x7) == 3) | ((v & 0x7) > 5));
|
||||
v = e > 30 ? 0x7c00 : v;
|
||||
v = e == 143 ? i : v;
|
||||
return s | v;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
#if !defined(_MSC_VER)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
float __gnu_h2f_ieee(unsigned short h){
|
||||
return __convert_half_to_float((std::uint32_t) h);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
#if !defined(_MSC_VER)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
unsigned short __gnu_f2h_ieee(float f){
|
||||
return (unsigned short)__convert_float_to_half(f);
|
||||
}
|
||||
|
||||
void PlatformState::init()
|
||||
{
|
||||
amd::ScopedLock lock(lock_);
|
||||
if(initialized_ || g_devices.empty()) {
|
||||
return;
|
||||
}
|
||||
initialized_ = true;
|
||||
for (auto& it : statCO_.modules_) {
|
||||
digestFatBinary(it.first, it.second);
|
||||
}
|
||||
for (auto &it : statCO_.vars_) {
|
||||
it.second->resize_dVar(g_devices.size());
|
||||
}
|
||||
for (auto &it : statCO_.functions_) {
|
||||
it.second->resize_dFunc(g_devices.size());
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t PlatformState::loadModule(hipModule_t *module, const char* fname, const void* image) {
|
||||
amd::ScopedLock lock(lock_);
|
||||
|
||||
if(module == nullptr) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
hip::DynCO* dynCo = new hip::DynCO();
|
||||
hipError_t hip_error = dynCo->loadCodeObject(fname, image);
|
||||
if (hip_error != hipSuccess) {
|
||||
delete dynCo;
|
||||
return hip_error;
|
||||
}
|
||||
|
||||
*module = dynCo->module();
|
||||
assert(*module != nullptr);
|
||||
|
||||
if (dynCO_map_.find(*module) != dynCO_map_.end()) {
|
||||
return hipErrorAlreadyMapped;
|
||||
}
|
||||
dynCO_map_.insert(std::make_pair(*module, dynCo));
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t PlatformState::unloadModule(hipModule_t hmod) {
|
||||
amd::ScopedLock lock(lock_);
|
||||
|
||||
auto it = dynCO_map_.find(hmod);
|
||||
if (it == dynCO_map_.end()) {
|
||||
return hipErrorNotFound;
|
||||
}
|
||||
|
||||
delete it->second;
|
||||
dynCO_map_.erase(hmod);
|
||||
|
||||
auto tex_it = texRef_map_.begin();
|
||||
while (tex_it != texRef_map_.end()) {
|
||||
if (tex_it->second.first == hmod) {
|
||||
tex_it = texRef_map_.erase(tex_it);
|
||||
} else {
|
||||
++tex_it;
|
||||
}
|
||||
}
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t PlatformState::getDynFunc(hipFunction_t* hfunc, hipModule_t hmod,
|
||||
const char* func_name) {
|
||||
amd::ScopedLock lock(lock_);
|
||||
|
||||
auto it = dynCO_map_.find(hmod);
|
||||
if (it == dynCO_map_.end()) {
|
||||
LogPrintfError("Cannot find the module: 0x%x", hmod);
|
||||
return hipErrorNotFound;
|
||||
}
|
||||
if (0 == strlen(func_name)) {
|
||||
return hipErrorNotFound;
|
||||
}
|
||||
|
||||
return it->second->getDynFunc(hfunc, func_name);
|
||||
}
|
||||
|
||||
hipError_t PlatformState::getDynGlobalVar(const char* hostVar, hipModule_t hmod,
|
||||
hipDeviceptr_t* dev_ptr, size_t* size_ptr) {
|
||||
amd::ScopedLock lock(lock_);
|
||||
|
||||
if(hostVar == nullptr || dev_ptr == nullptr || size_ptr == nullptr) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
auto it = dynCO_map_.find(hmod);
|
||||
if (it == dynCO_map_.end()) {
|
||||
LogPrintfError("Cannot find the module: 0x%x", hmod);
|
||||
return hipErrorNotFound;
|
||||
}
|
||||
*dev_ptr = nullptr;
|
||||
it->second->getManagedVarPointer(hostVar, dev_ptr, size_ptr);
|
||||
// if dev_ptr is nullptr, hostvar is not in managed variable list
|
||||
if (*dev_ptr == nullptr) {
|
||||
hip::DeviceVar* dvar = nullptr;
|
||||
IHIP_RETURN_ONFAIL(it->second->getDeviceVar(&dvar, hostVar));
|
||||
*dev_ptr = dvar->device_ptr();
|
||||
*size_ptr = dvar->size();
|
||||
}
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t PlatformState::registerTexRef(textureReference* texRef, hipModule_t hmod,
|
||||
std::string name) {
|
||||
amd::ScopedLock lock(lock_);
|
||||
texRef_map_.insert(std::make_pair(texRef, std::make_pair(hmod, name)));
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t PlatformState::getDynTexGlobalVar(textureReference* texRef, hipDeviceptr_t* dev_ptr,
|
||||
size_t* size_ptr) {
|
||||
amd::ScopedLock lock(lock_);
|
||||
|
||||
auto tex_it = texRef_map_.find(texRef);
|
||||
if (tex_it == texRef_map_.end()) {
|
||||
LogPrintfError("Cannot find the texRef Entry: 0x%x", texRef);
|
||||
return hipErrorNotFound;
|
||||
}
|
||||
|
||||
auto it = dynCO_map_.find(tex_it->second.first);
|
||||
if (it == dynCO_map_.end()) {
|
||||
LogPrintfError("Cannot find the module: 0x%x", tex_it->second.first);
|
||||
return hipErrorNotFound;
|
||||
}
|
||||
|
||||
hip::DeviceVar* dvar = nullptr;
|
||||
IHIP_RETURN_ONFAIL(it->second->getDeviceVar(&dvar, tex_it->second.second));
|
||||
*dev_ptr = dvar->device_ptr();
|
||||
*size_ptr = dvar->size();
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t PlatformState::getDynTexRef(const char* hostVar, hipModule_t hmod, textureReference** texRef) {
|
||||
amd::ScopedLock lock(lock_);
|
||||
|
||||
auto it = dynCO_map_.find(hmod);
|
||||
if (it == dynCO_map_.end()) {
|
||||
LogPrintfError("Cannot find the module: 0x%x", hmod);
|
||||
return hipErrorNotFound;
|
||||
}
|
||||
|
||||
hip::DeviceVar* dvar = nullptr;
|
||||
IHIP_RETURN_ONFAIL(it->second->getDeviceVar(&dvar, hostVar));
|
||||
|
||||
dvar->shadowVptr = new texture<char>();
|
||||
*texRef = reinterpret_cast<textureReference*>(dvar->shadowVptr);
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t PlatformState::digestFatBinary(const void* data, hip::FatBinaryInfo*& programs) {
|
||||
return statCO_.digestFatBinary(data, programs);
|
||||
}
|
||||
|
||||
hip::FatBinaryInfo** PlatformState::addFatBinary(const void* data) {
|
||||
return statCO_.addFatBinary(data, initialized_);
|
||||
}
|
||||
|
||||
hipError_t PlatformState::removeFatBinary(hip::FatBinaryInfo** module) {
|
||||
return statCO_.removeFatBinary(module);
|
||||
}
|
||||
|
||||
hipError_t PlatformState::registerStatFunction(const void* hostFunction, hip::Function* func) {
|
||||
return statCO_.registerStatFunction(hostFunction, func);
|
||||
}
|
||||
|
||||
hipError_t PlatformState::registerStatGlobalVar(const void* hostVar, hip::Var* var) {
|
||||
return statCO_.registerStatGlobalVar(hostVar, var);
|
||||
}
|
||||
|
||||
hipError_t PlatformState::registerStatManagedVar(hip::Var* var) {
|
||||
return statCO_.registerStatManagedVar(var);
|
||||
}
|
||||
|
||||
hipError_t PlatformState::getStatFunc(hipFunction_t* hfunc, const void* hostFunction, int deviceId) {
|
||||
return statCO_.getStatFunc(hfunc, hostFunction, deviceId);
|
||||
}
|
||||
|
||||
hipError_t PlatformState::getStatFuncAttr(hipFuncAttributes* func_attr, const void* hostFunction, int deviceId) {
|
||||
if(func_attr == nullptr || hostFunction == nullptr) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
return statCO_.getStatFuncAttr(func_attr, hostFunction, deviceId);
|
||||
}
|
||||
|
||||
hipError_t PlatformState::getStatGlobalVar(const void* hostVar, int deviceId, hipDeviceptr_t* dev_ptr,
|
||||
size_t* size_ptr) {
|
||||
return statCO_.getStatGlobalVar(hostVar, deviceId, dev_ptr, size_ptr);
|
||||
}
|
||||
|
||||
hipError_t PlatformState::initStatManagedVarDevicePtr(int deviceId) {
|
||||
return statCO_.initStatManagedVarDevicePtr(deviceId);
|
||||
}
|
||||
|
||||
void PlatformState::setupArgument(const void *arg, size_t size, size_t offset) {
|
||||
auto& arguments = execStack_.top().arguments_;
|
||||
|
||||
if (arguments.size() < offset + size) {
|
||||
arguments.resize(offset + size);
|
||||
}
|
||||
|
||||
::memcpy(&arguments[offset], arg, size);
|
||||
}
|
||||
|
||||
void PlatformState::configureCall(dim3 gridDim, dim3 blockDim, size_t sharedMem,
|
||||
hipStream_t stream) {
|
||||
execStack_.push(ihipExec_t{gridDim, blockDim, sharedMem, stream});
|
||||
}
|
||||
|
||||
void PlatformState::popExec(ihipExec_t& exec) {
|
||||
exec = std::move(execStack_.top());
|
||||
execStack_.pop();
|
||||
}
|
||||
Executable
@@ -0,0 +1,97 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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 "hip_internal.hpp"
|
||||
#include "hip_fatbin.hpp"
|
||||
#include "device/device.hpp"
|
||||
#include "hip_code_object.hpp"
|
||||
|
||||
namespace hip_impl {
|
||||
|
||||
hipError_t ihipOccupancyMaxActiveBlocksPerMultiprocessor(
|
||||
int* maxBlocksPerCU, int* numBlocksPerGrid, int* bestBlockSize,
|
||||
const amd::Device& device, hipFunction_t func, int blockSize,
|
||||
size_t dynamicSMemSize, bool bCalcPotentialBlkSz);
|
||||
} /* namespace hip_impl*/
|
||||
|
||||
class PlatformState {
|
||||
amd::Monitor lock_{"Guards PlatformState globals", true};
|
||||
|
||||
/* Singleton object */
|
||||
static PlatformState* platform_;
|
||||
PlatformState() {}
|
||||
~PlatformState() {}
|
||||
|
||||
public:
|
||||
void init();
|
||||
|
||||
//Dynamic Code Objects functions
|
||||
hipError_t loadModule(hipModule_t* module, const char* fname, const void* image = nullptr);
|
||||
hipError_t unloadModule(hipModule_t hmod);
|
||||
|
||||
hipError_t getDynFunc(hipFunction_t *hfunc, hipModule_t hmod, const char* func_name);
|
||||
hipError_t getDynGlobalVar(const char* hostVar, hipModule_t hmod, hipDeviceptr_t* dev_ptr,
|
||||
size_t* size_ptr);
|
||||
hipError_t getDynTexRef(const char* hostVar, hipModule_t hmod, textureReference** texRef);
|
||||
|
||||
hipError_t registerTexRef(textureReference* texRef, hipModule_t hmod, std::string name);
|
||||
hipError_t getDynTexGlobalVar(textureReference* texRef, hipDeviceptr_t* dev_ptr,
|
||||
size_t* size_ptr);
|
||||
|
||||
/* Singleton instance */
|
||||
static PlatformState& instance() {
|
||||
if (platform_ == nullptr) {
|
||||
// __hipRegisterFatBinary() will call this when app starts, thus
|
||||
// there is no multiple entry issue here.
|
||||
platform_ = new PlatformState();
|
||||
}
|
||||
return *platform_;
|
||||
}
|
||||
|
||||
//Static Code Objects functions
|
||||
hip::FatBinaryInfo** addFatBinary(const void* data);
|
||||
hipError_t removeFatBinary(hip::FatBinaryInfo** module);
|
||||
hipError_t digestFatBinary(const void* data, hip::FatBinaryInfo*& programs);
|
||||
|
||||
hipError_t registerStatFunction(const void* hostFunction, hip::Function* func);
|
||||
hipError_t registerStatGlobalVar(const void* hostVar, hip::Var* var);
|
||||
hipError_t registerStatManagedVar(hip::Var* var);
|
||||
|
||||
|
||||
hipError_t getStatFunc(hipFunction_t* hfunc, const void* hostFunction, int deviceId);
|
||||
hipError_t getStatFuncAttr(hipFuncAttributes* func_attr, const void* hostFunction, int deviceId);
|
||||
hipError_t getStatGlobalVar(const void* hostVar, int deviceId, hipDeviceptr_t* dev_ptr,
|
||||
size_t* size_ptr);
|
||||
|
||||
hipError_t initStatManagedVarDevicePtr(int deviceId);
|
||||
|
||||
//Exec Functions
|
||||
void setupArgument(const void *arg, size_t size, size_t offset);
|
||||
void configureCall(dim3 gridDim, dim3 blockDim, size_t sharedMem, hipStream_t stream);
|
||||
void popExec(ihipExec_t& exec);
|
||||
|
||||
private:
|
||||
//Dynamic Code Object map, keyin module to get the corresponding object
|
||||
std::unordered_map<hipModule_t, hip::DynCO*> dynCO_map_;
|
||||
hip::StatCO statCO_; //Static Code object var
|
||||
bool initialized_{false};
|
||||
std::unordered_map<textureReference*, std::pair<hipModule_t, std::string>> texRef_map_;
|
||||
};
|
||||
@@ -0,0 +1,270 @@
|
||||
/* Copyright (c) 2019-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef HIP_SRC_HIP_PROF_API_H
|
||||
#define HIP_SRC_HIP_PROF_API_H
|
||||
|
||||
#include <atomic>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
|
||||
#if USE_PROF_API
|
||||
#include "hip/amd_detail/hip_prof_str.h"
|
||||
#include "platform/prof_protocol.h"
|
||||
|
||||
// HIP API callbacks spawner object macro
|
||||
#define HIP_CB_SPAWNER_OBJECT(CB_ID) \
|
||||
api_callbacks_spawner_t<HIP_API_ID_##CB_ID> __api_tracer; \
|
||||
{ \
|
||||
hip_api_data_t* api_data = __api_tracer.get_api_data_ptr(); \
|
||||
if (api_data != NULL) { \
|
||||
hip_api_data_t& api_data_ref = *api_data; \
|
||||
INIT_CB_ARGS_DATA(CB_ID, api_data_ref); \
|
||||
__api_tracer.call(); \
|
||||
} \
|
||||
}
|
||||
|
||||
static const uint32_t HIP_DOMAIN_ID = ACTIVITY_DOMAIN_HIP_API;
|
||||
typedef activity_record_t hip_api_record_t;
|
||||
typedef activity_rtapi_callback_t hip_api_callback_t;
|
||||
typedef activity_sync_callback_t hip_act_callback_t;
|
||||
|
||||
class api_callbacks_table_t {
|
||||
public:
|
||||
typedef std::mutex mutex_t;
|
||||
|
||||
typedef hip_api_record_t record_t;
|
||||
typedef hip_api_callback_t fun_t;
|
||||
typedef hip_act_callback_t act_t;
|
||||
|
||||
// HIP API callbacks table
|
||||
struct hip_cb_table_entry_t {
|
||||
volatile std::atomic<bool> sync;
|
||||
volatile std::atomic<uint32_t> sem;
|
||||
act_t act;
|
||||
void* a_arg;
|
||||
fun_t fun;
|
||||
void* arg;
|
||||
};
|
||||
|
||||
struct hip_cb_table_t {
|
||||
hip_cb_table_entry_t arr[HIP_API_ID_NUMBER];
|
||||
};
|
||||
|
||||
api_callbacks_table_t() {
|
||||
memset(&callbacks_table_, 0, sizeof(callbacks_table_));
|
||||
}
|
||||
|
||||
bool set_activity(uint32_t id, act_t fun, void* arg) {
|
||||
std::lock_guard<mutex_t> lock(mutex_);
|
||||
bool ret = true;
|
||||
|
||||
if (id < HIP_API_ID_NUMBER) {
|
||||
cb_sync(id);
|
||||
/*
|
||||
'fun != nullptr' indicates it is activity register call,
|
||||
increment should happen only once but client is free to call
|
||||
register CB multiple times for same API id hence the check
|
||||
|
||||
'fun == nullptr' indicates it is de-register call and
|
||||
decrement should happen only once hence the check
|
||||
*/
|
||||
if (fun != nullptr) {
|
||||
if (callbacks_table_.arr[id].act == nullptr) {
|
||||
enabled_api_count_++;
|
||||
}
|
||||
} else {
|
||||
if (callbacks_table_.arr[id].act != nullptr) {
|
||||
enabled_api_count_--;
|
||||
}
|
||||
}
|
||||
if (enabled_api_count_ > 0) {
|
||||
amd::IS_PROFILER_ON = true;
|
||||
} else {
|
||||
amd::IS_PROFILER_ON = false;
|
||||
}
|
||||
callbacks_table_.arr[id].act = fun;
|
||||
callbacks_table_.arr[id].a_arg = arg;
|
||||
cb_release(id);
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool set_callback(uint32_t id, fun_t fun, void* arg) {
|
||||
std::lock_guard<mutex_t> lock(mutex_);
|
||||
bool ret = true;
|
||||
|
||||
if (id < HIP_API_ID_NUMBER) {
|
||||
cb_sync(id);
|
||||
callbacks_table_.arr[id].fun = fun;
|
||||
callbacks_table_.arr[id].arg = arg;
|
||||
cb_release(id);
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void set_enabled(const bool& enabled) {
|
||||
amd::IS_PROFILER_ON = enabled;
|
||||
}
|
||||
|
||||
inline hip_cb_table_entry_t& entry(const uint32_t& id) {
|
||||
return callbacks_table_.arr[id];
|
||||
}
|
||||
|
||||
inline void sem_sync(const uint32_t& id) {
|
||||
sem_increment(id);
|
||||
if (entry(id).sync.load() == true) sync_wait(id);
|
||||
}
|
||||
|
||||
inline void sem_release(const uint32_t& id) {
|
||||
sem_decrement(id);
|
||||
}
|
||||
|
||||
inline bool is_enabled() const {
|
||||
return amd::IS_PROFILER_ON;
|
||||
}
|
||||
|
||||
private:
|
||||
inline void cb_sync(const uint32_t& id) {
|
||||
entry(id).sync.store(true);
|
||||
while (entry(id).sem.load() != 0) {}
|
||||
}
|
||||
|
||||
inline void cb_release(const uint32_t& id) {
|
||||
entry(id).sync.store(false);
|
||||
}
|
||||
|
||||
inline void sem_increment(const uint32_t& id) {
|
||||
const uint32_t prev = entry(id).sem.fetch_add(1);
|
||||
if (prev == UINT32_MAX) {
|
||||
std::cerr << "sem overflow id = " << id << std::endl << std::flush;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
inline void sem_decrement(const uint32_t& id) {
|
||||
const uint32_t prev = entry(id).sem.fetch_sub(1);
|
||||
if (prev == 0) {
|
||||
std::cerr << "sem corrupted id = " << id << std::endl << std::flush;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void sync_wait(const uint32_t& id) {
|
||||
sem_decrement(id);
|
||||
while (entry(id).sync.load() == true) {}
|
||||
sem_increment(id);
|
||||
}
|
||||
|
||||
mutex_t mutex_;
|
||||
hip_cb_table_t callbacks_table_;
|
||||
uint32_t enabled_api_count_;
|
||||
};
|
||||
|
||||
extern api_callbacks_table_t callbacks_table;
|
||||
|
||||
template <int cid_>
|
||||
class api_callbacks_spawner_t {
|
||||
public:
|
||||
api_callbacks_spawner_t() :
|
||||
api_data_(NULL)
|
||||
{
|
||||
if (!is_enabled()) return;
|
||||
|
||||
if (cid_ >= HIP_API_ID_NUMBER) {
|
||||
fprintf(stderr, "HIP %s bad id %d\n", __FUNCTION__, cid_);
|
||||
abort();
|
||||
}
|
||||
callbacks_table.sem_sync(cid_);
|
||||
|
||||
hip_act_callback_t act = entry(cid_).act;
|
||||
if (act != NULL) api_data_ = (hip_api_data_t*) act(cid_, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void call() {
|
||||
hip_api_callback_t fun = entry(cid_).fun;
|
||||
void* arg = entry(cid_).arg;
|
||||
if (fun != NULL) {
|
||||
fun(HIP_DOMAIN_ID, cid_, api_data_, arg);
|
||||
api_data_->phase = ACTIVITY_API_PHASE_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
~api_callbacks_spawner_t() {
|
||||
if (!is_enabled()) return;
|
||||
|
||||
if (api_data_ != NULL) {
|
||||
hip_api_callback_t fun = entry(cid_).fun;
|
||||
void* arg = entry(cid_).arg;
|
||||
hip_act_callback_t act = entry(cid_).act;
|
||||
void* a_arg = entry(cid_).a_arg;
|
||||
if (fun != NULL) fun(HIP_DOMAIN_ID, cid_, api_data_, arg);
|
||||
if (act != NULL) act(cid_, NULL, NULL, a_arg);
|
||||
}
|
||||
|
||||
callbacks_table.sem_release(cid_);
|
||||
}
|
||||
|
||||
hip_api_data_t* get_api_data_ptr() {
|
||||
return api_data_;
|
||||
}
|
||||
|
||||
bool is_enabled() const {
|
||||
return callbacks_table.is_enabled();
|
||||
}
|
||||
|
||||
private:
|
||||
inline api_callbacks_table_t::hip_cb_table_entry_t& entry(const uint32_t& id) {
|
||||
return callbacks_table.entry(id);
|
||||
}
|
||||
|
||||
hip_api_data_t* api_data_;
|
||||
};
|
||||
|
||||
template <>
|
||||
class api_callbacks_spawner_t<HIP_API_ID_NUMBER> {
|
||||
public:
|
||||
api_callbacks_spawner_t() {}
|
||||
void call() {}
|
||||
hip_api_data_t* get_api_data_ptr() { return NULL; }
|
||||
bool is_enabled() const { return false; }
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define HIP_CB_SPAWNER_OBJECT(x) do {} while(0)
|
||||
|
||||
class api_callbacks_table_t {
|
||||
public:
|
||||
typedef void* act_t;
|
||||
typedef void* fun_t;
|
||||
bool set_activity(uint32_t id, act_t fun, void* arg) { return false; }
|
||||
bool set_callback(uint32_t id, fun_t fun, void* arg) { return false; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // HIP_SRC_HIP_PROF_API_H
|
||||
Executable
+673
@@ -0,0 +1,673 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (c) 2019-present 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.
|
||||
|
||||
import os, sys, re
|
||||
|
||||
PROF_HEADER = "hip_prof_str.h"
|
||||
OUTPUT = PROF_HEADER
|
||||
REC_MAX_LEN = 1024
|
||||
|
||||
# Recursive sources processing
|
||||
recursive_mode = 0
|
||||
# HIP_INIT_API macro patching
|
||||
hip_patch_mode = 0
|
||||
# API matching types check
|
||||
types_check_mode = 0
|
||||
# Private API check
|
||||
private_check_mode = 0
|
||||
|
||||
# Messages and errors controll
|
||||
verbose = 0
|
||||
errexit = 0
|
||||
inp_file = 'none'
|
||||
line_num = -1
|
||||
|
||||
# Verbose message
|
||||
def message(msg):
|
||||
if verbose: sys.stdout.write(msg + '\n')
|
||||
|
||||
# Fatal error termination
|
||||
def error(msg):
|
||||
if line_num != -1:
|
||||
msg += ", file '" + inp_file + "', line (" + str(line_num) + ")"
|
||||
if errexit:
|
||||
msg = " Error: " + msg
|
||||
else:
|
||||
msg = " Warning: " + msg
|
||||
|
||||
sys.stdout.write(msg + '\n')
|
||||
sys.stderr.write(sys.argv[0] + msg +'\n')
|
||||
|
||||
def fatal(msg):
|
||||
error(msg)
|
||||
sys.exit(1)
|
||||
|
||||
#############################################################
|
||||
# Normalizing API name
|
||||
def filtr_api_name(name):
|
||||
name = re.sub(r'\s*$', r'', name);
|
||||
return name
|
||||
|
||||
def filtr_api_decl(record):
|
||||
record = re.sub("\s__dparm\([^\)]*\)", r'', record);
|
||||
record = re.sub("\(void\*\)", r'', record);
|
||||
return record
|
||||
|
||||
# Normalizing API arguments
|
||||
def filtr_api_args(args_str):
|
||||
args_str = re.sub(r'^\s*', r'', args_str);
|
||||
args_str = re.sub(r'\s*$', r'', args_str);
|
||||
args_str = re.sub(r'\s*,\s*', r',', args_str);
|
||||
args_str = re.sub(r'\s+', r' ', args_str);
|
||||
args_str = re.sub(r'\s*(\*+)\s*', r'\1 ', args_str);
|
||||
args_str = re.sub(r'(enum|struct) ', '', args_str);
|
||||
return args_str
|
||||
|
||||
# Normalizing types
|
||||
def norm_api_types(type_str):
|
||||
type_str = re.sub(r'uint32_t', r'unsigned int', type_str)
|
||||
type_str = re.sub(r'^unsigned$', r'unsigned int', type_str)
|
||||
return type_str
|
||||
|
||||
# Creating a list of arguments [(type, name), ...]
|
||||
def list_api_args(args_str):
|
||||
args_str = filtr_api_args(args_str)
|
||||
args_list = []
|
||||
if args_str != '':
|
||||
for arg_pair in args_str.split(','):
|
||||
if arg_pair == 'void': continue
|
||||
arg_pair = re.sub(r'\s*=\s*\S+$','', arg_pair);
|
||||
m = re.match("^(.*)\s(\S+)$", arg_pair);
|
||||
if m:
|
||||
arg_type = norm_api_types(m.group(1))
|
||||
arg_name = m.group(2)
|
||||
args_list.append((arg_type, arg_name))
|
||||
else:
|
||||
fatal("bad args: args_str: '" + args_str + "' arg_pair: '" + arg_pair + "'")
|
||||
return args_list;
|
||||
|
||||
# Creating arguments string "type0, type1, ..."
|
||||
def filtr_api_types(args_str):
|
||||
args_list = list_api_args(args_str)
|
||||
types_str = ''
|
||||
for arg_tuple in args_list:
|
||||
types_str += arg_tuple[0] + ', '
|
||||
return types_str
|
||||
|
||||
# Creating options list [opt0, opt1, ...]
|
||||
def filtr_api_opts(args_str):
|
||||
args_list = list_api_args(args_str)
|
||||
opts_list = []
|
||||
for arg_tuple in args_list:
|
||||
opts_list.append(arg_tuple[1])
|
||||
return opts_list
|
||||
|
||||
# Checking for pointer non-void arg type
|
||||
def pointer_ck(arg_type):
|
||||
ptr_type = ''
|
||||
m = re.match(r'(.*)\*$', arg_type)
|
||||
if m:
|
||||
ptr_type = m.group(1)
|
||||
ptr_type = re.sub(r'const ', '', ptr_type)
|
||||
if ptr_type == 'void': ptr_type = ''
|
||||
return ptr_type
|
||||
#############################################################
|
||||
# Parsing API header
|
||||
# hipError_t hipSetupArgument(const void* arg, size_t size, size_t offset);
|
||||
def parse_api(inp_file_p, out):
|
||||
global inp_file
|
||||
global line_num
|
||||
inp_file = inp_file_p
|
||||
|
||||
beg_pattern = re.compile("^(hipError_t|const char\s*\*)\s+([^\(]+)\(");
|
||||
api_pattern = re.compile("^(hipError_t|const char\s*\*)\s+([^\(]+)\(([^\)]*)\)");
|
||||
end_pattern = re.compile("Texture");
|
||||
hidden_pattern = re.compile(r'__attribute__\(\(visibility\("hidden"\)\)\)')
|
||||
nms_open_pattern = re.compile(r'namespace hip_impl {')
|
||||
nms_close_pattern = re.compile(r'}')
|
||||
|
||||
inp = open(inp_file, 'r')
|
||||
|
||||
found = 0
|
||||
hidden = 0
|
||||
nms_level = 0;
|
||||
record = ""
|
||||
line_num = -1
|
||||
|
||||
for line in inp.readlines():
|
||||
record += re.sub(r'^\s+', r' ', line[:-1])
|
||||
line_num += 1
|
||||
|
||||
if len(record) > REC_MAX_LEN:
|
||||
fatal("bad record \"" + record + "\"")
|
||||
|
||||
m = beg_pattern.match(line)
|
||||
if m:
|
||||
name = m.group(2)
|
||||
if hidden != 0:
|
||||
message("api: " + name + " - hidden")
|
||||
elif nms_level != 0:
|
||||
message("api: " + name + " - hip_impl")
|
||||
else:
|
||||
message("api: " + name)
|
||||
found = 1
|
||||
|
||||
if found != 0:
|
||||
record = re.sub("\s__dparm\([^\)]*\)", '', record);
|
||||
m = api_pattern.match(record)
|
||||
if m:
|
||||
found = 0
|
||||
if end_pattern.search(record): break
|
||||
api_name = filtr_api_name(m.group(2))
|
||||
api_args = m.group(3)
|
||||
if not api_name in out:
|
||||
out[api_name] = api_args
|
||||
else: continue
|
||||
|
||||
hidden = 0
|
||||
if hidden_pattern.match(line): hidden = 1
|
||||
|
||||
if nms_open_pattern.match(line): nms_level += 1
|
||||
if (nms_level > 0) and nms_close_pattern.match(line): nms_level -= 1
|
||||
if nms_level < 0:
|
||||
fatal("nms level < 0")
|
||||
|
||||
record = ""
|
||||
|
||||
inp.close()
|
||||
line_num = -1
|
||||
#############################################################
|
||||
# Parsing API implementation
|
||||
# hipError_t hipSetupArgument(const void* arg, size_t size, size_t offset) {
|
||||
# HIP_INIT_API(hipSetupArgument, arg, size, offset);
|
||||
# inp_file - input implementation source file
|
||||
# api_map - input public API map [<api name>] => <api args>
|
||||
# out - output map [<api name>] => [opt0, opt1, ...]
|
||||
def parse_content(inp_file_p, api_map, out):
|
||||
global hip_patch_mode
|
||||
global types_check_mode
|
||||
global private_check_mode
|
||||
global inp_file
|
||||
global line_num
|
||||
inp_file = inp_file_p
|
||||
|
||||
# API method begin pattern
|
||||
beg_pattern = re.compile("^(hipError_t|const char\s*\*)\s+[^\(]+\(");
|
||||
# API declaration pattern
|
||||
decl_pattern = re.compile("^(hipError_t|const char\s*\*)\s+([^\(]+)\(([^\)]*)\)\s*;");
|
||||
# API definition pattern
|
||||
api_pattern = re.compile("^(hipError_t|const char\s*\*)\s+([^\(]+)\(([^\)]*)\)\s*{");
|
||||
# API init macro pattern
|
||||
init_pattern = re.compile("(^\s*HIP_INIT_API\s*)\((([^,]+)(,.*|)|)(\);|,)\s*$");
|
||||
|
||||
# Open input file
|
||||
inp = open(inp_file, 'r')
|
||||
|
||||
# API name
|
||||
api_name = ""
|
||||
# Valid public API found flag
|
||||
api_valid = 0
|
||||
# API overload (parameters mismatch)
|
||||
api_overload = 0
|
||||
|
||||
# Input file patched content
|
||||
content = ''
|
||||
# Sub content for found API defiition
|
||||
sub_content = ''
|
||||
# Current record, accumulating several API definition related lines
|
||||
record = ''
|
||||
# Current input file line number
|
||||
line_num = -1
|
||||
# API beginning found flag
|
||||
found = 0
|
||||
|
||||
# Reading input file
|
||||
for line in inp.readlines():
|
||||
# Accumulating record
|
||||
record += re.sub(r'^\s+', r' ', line[:-1])
|
||||
line_num += 1
|
||||
|
||||
if len(record) > REC_MAX_LEN:
|
||||
fatal("bad record \"" + record + "\"")
|
||||
break;
|
||||
|
||||
# Looking for API begin
|
||||
if found == 0:
|
||||
record = re.sub(r'\s*extern\s+"C"\s+', r'', record);
|
||||
if beg_pattern.match(record):
|
||||
found = 1
|
||||
record = filtr_api_decl(record)
|
||||
|
||||
# Matching API declaration
|
||||
if found == 1:
|
||||
if decl_pattern.match(record):
|
||||
found = 0
|
||||
|
||||
# Matching API definition
|
||||
if found == 1:
|
||||
m = api_pattern.match(record)
|
||||
# Checking if complete API matched
|
||||
if m:
|
||||
found = 2
|
||||
api_valid = 0
|
||||
api_overload = 0
|
||||
api_name = filtr_api_name(m.group(2))
|
||||
# Checking if API name is in the API map
|
||||
if (private_check_mode == 0) or (api_name in api_map):
|
||||
if not api_name in api_map: api_map[api_name] = ''
|
||||
# Getting API arguments
|
||||
api_args = m.group(3)
|
||||
# Getting etalon arguments from the API map
|
||||
eta_args = api_map[api_name]
|
||||
if eta_args == '':
|
||||
eta_args = api_args
|
||||
api_map[api_name] = eta_args
|
||||
# Normalizing API arguments
|
||||
api_types = filtr_api_types(api_args)
|
||||
# Normalizing etalon arguments
|
||||
eta_types = filtr_api_types(eta_args)
|
||||
if (api_types == eta_types) or ((types_check_mode == 0) and (not api_name in out)):
|
||||
# API is already found and not is mismatched
|
||||
if (api_name in out):
|
||||
fatal("API redefined \"" + api_name + "\", record \"" + record + "\"")
|
||||
# Set valid public API found flag
|
||||
api_valid = 1
|
||||
# Set output API map with API arguments list
|
||||
out[api_name] = filtr_api_opts(api_args)
|
||||
# Register missmatched API methods
|
||||
else:
|
||||
api_overload = 1
|
||||
# Warning about mismatched API, possible non public overloaded version
|
||||
api_diff = '\t\t' + inp_file + " line(" + str(line_num) + ")\n\t\tapi: " + api_types + "\n\t\teta: " + eta_types
|
||||
message("\t" + api_name + ' args mismatch:\n' + api_diff + '\n')
|
||||
|
||||
# API found action
|
||||
if found == 2:
|
||||
if hip_patch_mode != 0:
|
||||
# Looking for INIT macro
|
||||
m = init_pattern.match(line)
|
||||
if m:
|
||||
init_name = api_name
|
||||
if api_overload == 1: init_name = 'NONE'
|
||||
init_args = m.group(4)
|
||||
line = m.group(1) + '(' + init_name + init_args + m.group(5) + '\n'
|
||||
|
||||
m = init_pattern.match(line)
|
||||
if m:
|
||||
found = 0
|
||||
if api_valid == 1: message("\t" + api_name)
|
||||
# Ignore if it is initialized as NONE
|
||||
init_name = m.group(3)
|
||||
if init_name != 'NONE':
|
||||
# Check if init name matching API name
|
||||
if init_name != api_name:
|
||||
fatal("init name mismatch: '" + init_name + "' <> '" + api_name + "'")
|
||||
# Registering dummy API for non public API if the name in INIT is not NONE
|
||||
if api_valid == 0:
|
||||
# If init name is not in public API map then it is private API
|
||||
# else it was not identified and will be checked on finish
|
||||
if not init_name in api_map:
|
||||
if init_name in out:
|
||||
fatal("API reinit \"" + api_name + "\", record \"" + record + "\"")
|
||||
out[init_name] = []
|
||||
elif re.search('}', line):
|
||||
found = 0
|
||||
# Expect INIT macro for valid public API
|
||||
# Removing and registering non-conformant APIs with missing HIP_INIT macro
|
||||
if api_valid == 1:
|
||||
if api_name in out:
|
||||
del out[api_name]
|
||||
del api_map[api_name]
|
||||
# Registering non-conformant APIs
|
||||
out['.' + api_name] = 1
|
||||
else:
|
||||
fatal("API is not in out \"" + api_name + "\", record \"" + record + "\"")
|
||||
|
||||
if found != 1: record = ""
|
||||
content += line
|
||||
|
||||
inp.close()
|
||||
line_num = -1
|
||||
|
||||
if len(out) != 0:
|
||||
return content
|
||||
else:
|
||||
return ''
|
||||
|
||||
# src path walk
|
||||
def parse_src(api_map, src_path, src_patt, out):
|
||||
global recursive_mode
|
||||
|
||||
pattern = re.compile(src_patt)
|
||||
src_path = re.sub(r'\s', '', src_path)
|
||||
for src_dir in src_path.split(':'):
|
||||
message("Parsing " + src_dir + " for '" + src_patt + "'")
|
||||
for root, dirs, files in os.walk(src_dir):
|
||||
for fnm in files:
|
||||
if pattern.search(fnm):
|
||||
file = root + '/' + fnm
|
||||
message(file)
|
||||
content = parse_content(file, api_map, out);
|
||||
if (hip_patch_mode != 0) and (content != ''):
|
||||
f = open(file, 'w')
|
||||
f.write(content)
|
||||
f.close()
|
||||
if recursive_mode == 0: break
|
||||
#############################################################
|
||||
# Generating profiling primitives header
|
||||
# api_map - public API map [<api name>] => [(type, name), ...]
|
||||
# opts_map - opts map [<api name>] => [opt0, opt1, ...]
|
||||
def generate_prof_header(f, api_map, opts_map):
|
||||
# Private API list
|
||||
priv_lst = []
|
||||
|
||||
f.write('// automatically generated sources\n')
|
||||
f.write('#ifndef _HIP_PROF_STR_H\n');
|
||||
f.write('#define _HIP_PROF_STR_H\n');
|
||||
f.write('#define HIP_PROF_VER 1\n')
|
||||
|
||||
# Generating dummy macro for non-public API
|
||||
f.write('\n// Dummy API primitives\n')
|
||||
f.write('#define INIT_NONE_CB_ARGS_DATA(cb_data) {};\n')
|
||||
for name in opts_map:
|
||||
if not name in api_map:
|
||||
opts_lst = opts_map[name]
|
||||
if len(opts_lst) != 0:
|
||||
fatal("bad dummy API \"" + name + "\", args: " + str(opts_lst))
|
||||
f.write('#define INIT_'+ name + '_CB_ARGS_DATA(cb_data) {};\n')
|
||||
priv_lst.append(name)
|
||||
|
||||
for name in priv_lst:
|
||||
message("Private: " + name)
|
||||
|
||||
# Generating the callbacks ID enumaration
|
||||
f.write('\n// HIP API callbacks ID enumaration\n')
|
||||
f.write('enum hip_api_id_t {\n')
|
||||
cb_id = 0
|
||||
for name in api_map.keys():
|
||||
f.write(' HIP_API_ID_' + name + ' = ' + str(cb_id) + ',\n')
|
||||
cb_id += 1
|
||||
f.write(' HIP_API_ID_NUMBER = ' + str(cb_id) + ',\n')
|
||||
f.write('\n')
|
||||
f.write(' HIP_API_ID_NONE = HIP_API_ID_NUMBER,\n')
|
||||
for name in priv_lst:
|
||||
f.write(' HIP_API_ID_' + name + ' = HIP_API_ID_NUMBER,\n')
|
||||
f.write('};\n')
|
||||
|
||||
# Generating the method to return API name by ID
|
||||
f.write('\n// Return HIP API string by given ID\n')
|
||||
f.write('static inline const char* hip_api_name(const uint32_t id) {\n')
|
||||
f.write(' switch(id) {\n')
|
||||
for name in api_map.keys():
|
||||
f.write(' case HIP_API_ID_' + name + ': return "' + name + '";\n')
|
||||
f.write(' };\n')
|
||||
f.write(' return "unknown";\n')
|
||||
f.write('};\n')
|
||||
|
||||
# Generating the method for querying API ID by name
|
||||
f.write('\n')
|
||||
f.write('#include <string.h>\n');
|
||||
f.write('// Return HIP API ID by given name\n')
|
||||
f.write('static inline uint32_t hipApiIdByName(const char* name) {\n')
|
||||
for name, args in api_map.items():
|
||||
f.write(' if (strcmp("' + name + '", name) == 0) return HIP_API_ID_' + name + ';\n')
|
||||
f.write(' return HIP_API_ID_NUMBER;\n')
|
||||
f.write('}\n')
|
||||
|
||||
# Generating the callbacks data structure
|
||||
f.write('\n// HIP API callbacks data structure\n')
|
||||
f.write(
|
||||
'typedef struct hip_api_data_s {\n' +
|
||||
' uint64_t correlation_id;\n' +
|
||||
' uint32_t phase;\n' +
|
||||
' union {\n'
|
||||
)
|
||||
for name, args in api_map.items():
|
||||
if len(args) != 0:
|
||||
f.write(' struct {\n')
|
||||
for arg_tuple in args:
|
||||
arg_type = arg_tuple[0]
|
||||
ptr_type = pointer_ck(arg_type)
|
||||
arg_name = arg_tuple[1]
|
||||
# Checking for enum type
|
||||
if arg_type == "hipLimit_t": arg_type = 'enum ' + arg_type
|
||||
# Structuer field code
|
||||
f.write(' ' + arg_type + ' ' + arg_name + ';\n')
|
||||
if ptr_type != '':
|
||||
f.write(' ' + ptr_type + ' ' + arg_name + '__val;\n')
|
||||
f.write(' } ' + name + ';\n')
|
||||
f.write(
|
||||
' } args;\n' +
|
||||
'} hip_api_data_t;\n'
|
||||
)
|
||||
|
||||
# Generating the callbacks args data filling macros
|
||||
f.write('\n// HIP API callbacks args data filling macros\n')
|
||||
for name, args in api_map.items():
|
||||
f.write('// ' + name + str(args) + '\n')
|
||||
f.write('#define INIT_' + name + '_CB_ARGS_DATA(cb_data) { \\\n')
|
||||
if name in opts_map:
|
||||
opts_list = opts_map[name]
|
||||
if len(args) != len(opts_list):
|
||||
fatal("\"" + name + "\" API args and opts mismatch, args: " + str(args) + ", opts: " + str(opts_list))
|
||||
# API args iterating:
|
||||
# type is args[<ind>][0]
|
||||
# name is args[<ind>][1]
|
||||
for ind in range(0, len(args)):
|
||||
arg_tuple = args[ind]
|
||||
arg_type = arg_tuple[0]
|
||||
ptr_type = pointer_ck(arg_type)
|
||||
fld_name = arg_tuple[1]
|
||||
opt_name = opts_list[ind]
|
||||
if arg_type == "const char*":
|
||||
f.write(' cb_data.args.' + name + '.' + fld_name + ' = (' + opt_name + ') ? strdup(' + opt_name + ') : NULL; \\\n')
|
||||
else:
|
||||
f.write(' cb_data.args.' + name + '.' + fld_name + ' = (' + arg_type + ')' + opt_name + '; \\\n')
|
||||
f.write('};\n')
|
||||
f.write('#define INIT_CB_ARGS_DATA(cb_id, cb_data) INIT_##cb_id##_CB_ARGS_DATA(cb_data)\n')
|
||||
|
||||
f.write('#if HIP_PROF_HIP_API_STRING\n')
|
||||
# Generating the method for the API args filling
|
||||
f.write('\n')
|
||||
f.write('// HIP API args filling method\n')
|
||||
f.write('static inline void hipApiArgsInit(hip_api_id_t id, hip_api_data_t* data) {\n')
|
||||
f.write(' switch (id) {\n')
|
||||
for name, args in api_map.items():
|
||||
f.write('// ' + name + str(args) + '\n')
|
||||
f.write(' case HIP_API_ID_' + name + ':\n')
|
||||
for ind in range(0, len(args)):
|
||||
arg_tuple = args[ind]
|
||||
arg_type = arg_tuple[0]
|
||||
ptr_type = pointer_ck(arg_type)
|
||||
fld_name = arg_tuple[1]
|
||||
var_name = 'data->args.' + name + '.' + fld_name
|
||||
if arg_type == "char*":
|
||||
f.write(' ' + var_name + ' = (' + var_name + ') ? strdup(' + var_name + ') : NULL;\n')
|
||||
else:
|
||||
if ptr_type != '':
|
||||
f.write(' if (' + var_name + ') ' + var_name + '__val = *(' + var_name + ');\n')
|
||||
f.write(' break;\n')
|
||||
f.write(' default: break;\n')
|
||||
f.write(' };\n')
|
||||
f.write('}\n')
|
||||
|
||||
# Generating the method for the API string, name and parameters
|
||||
f.write('\n')
|
||||
f.write('#include <sstream>\n');
|
||||
f.write('#include <string>\n');
|
||||
f.write('// HIP API string method, method name and parameters\n')
|
||||
f.write('static inline const char* hipApiString(hip_api_id_t id, const hip_api_data_t* data) {\n')
|
||||
f.write(' std::ostringstream oss;\n')
|
||||
f.write(' switch (id) {\n')
|
||||
for name, args in api_map.items():
|
||||
f.write(' case HIP_API_ID_' + name + ':\n')
|
||||
f.write(' oss << "' + name + '(";\n')
|
||||
for ind in range(0, len(args)):
|
||||
arg_tuple = args[ind]
|
||||
arg_type = arg_tuple[0]
|
||||
ptr_type = pointer_ck(arg_type)
|
||||
arg_name = arg_tuple[1]
|
||||
var_name = 'data->args.' + name + '.' + arg_name
|
||||
delim = '' if ind == 0 else ', ';
|
||||
oss_stream = 'oss << "' + delim + arg_name + '='
|
||||
line_shift = ' '
|
||||
f.write(line_shift)
|
||||
if ptr_type != '':
|
||||
f.write('if (' + var_name + ' == NULL) ' + oss_stream + 'NULL";\n' + line_shift + 'else ')
|
||||
if pointer_ck(ptr_type) != '':
|
||||
f.write(oss_stream + '" << (void*)' + var_name + '__val' + ';\n')
|
||||
else:
|
||||
f.write(oss_stream + '" << ' + var_name + '__val' + ';\n')
|
||||
else:
|
||||
f.write(oss_stream + '" << ' + var_name + ';\n')
|
||||
f.write(' oss << ")";\n')
|
||||
f.write(' break;\n')
|
||||
f.write(' default: oss << "unknown";\n')
|
||||
f.write(' };\n')
|
||||
f.write(' return strdup(oss.str().c_str());\n')
|
||||
f.write('}\n')
|
||||
f.write('#endif // HIP_PROF_HIP_API_STRING\n')
|
||||
|
||||
f.write('#endif // _HIP_PROF_STR_H\n');
|
||||
|
||||
#############################################################
|
||||
# main
|
||||
while len(sys.argv) > 1:
|
||||
if not re.match(r'-', sys.argv[1]): break
|
||||
|
||||
if (sys.argv[1] == '-v'):
|
||||
verbose = 1
|
||||
sys.argv.pop(1)
|
||||
|
||||
if (sys.argv[1] == '-r'):
|
||||
recursive_mode = 1
|
||||
sys.argv.pop(1)
|
||||
|
||||
if (sys.argv[1] == '-t'):
|
||||
types_check_mode = 1
|
||||
sys.argv.pop(1)
|
||||
|
||||
if (sys.argv[1] == '--priv'):
|
||||
private_check_mode = 1
|
||||
sys.argv.pop(1)
|
||||
|
||||
if (sys.argv[1] == '-e'):
|
||||
errexit = 1
|
||||
sys.argv.pop(1)
|
||||
|
||||
if (sys.argv[1] == '-p'):
|
||||
hip_patch_mode = 1
|
||||
sys.argv.pop(1)
|
||||
|
||||
# Usage
|
||||
if (len(sys.argv) < 3):
|
||||
fatal ("Usage: " + sys.argv[0] + " [-v] <input HIP API .h file> <patched srcs path> [<output>]\n" +
|
||||
" -v - verbose messages\n" +
|
||||
" -r - process source directory recursively\n" +
|
||||
" -t - API types matching check\n" +
|
||||
" --priv - private API check\n" +
|
||||
" -e - on error exit mode\n" +
|
||||
" -p - HIP_INIT_API macro patching mode\n" +
|
||||
"\n" +
|
||||
" Example:\n" +
|
||||
" $ " + sys.argv[0] + " -v -p -t --priv ./api/hip/include/hip/amd_detail/hip_runtime_api.h ./api/hip ./api/hip/include/hip/amd_detail/hip_prof_str.h");
|
||||
|
||||
# API header file given as an argument
|
||||
src_pat = "\.cpp$"
|
||||
api_hfile = sys.argv[1]
|
||||
if not os.path.isfile(api_hfile):
|
||||
fatal("input file '" + api_hfile + "' not found")
|
||||
|
||||
# Srcs directory given as an argument
|
||||
src_dir = sys.argv[2]
|
||||
if not os.path.isdir(src_dir):
|
||||
fatal("src directory " + src_dir + "' not found")
|
||||
|
||||
if len(sys.argv) > 3: OUTPUT = sys.argv[3]
|
||||
|
||||
# API declaration map
|
||||
api_map = {
|
||||
'hipSetupArgument': '',
|
||||
'hipMalloc3DArray': '',
|
||||
'hipFuncGetAttribute': '',
|
||||
'hipMemset3DAsync': '',
|
||||
'hipKernelNameRef': '',
|
||||
'hipStreamGetPriority': '',
|
||||
'hipLaunchByPtr': '',
|
||||
'hipFreeHost': '',
|
||||
'hipGetErrorName': '',
|
||||
'hipMemcpy3DAsync': '',
|
||||
'hipMemcpyParam2DAsync': '',
|
||||
'hipArray3DCreate': '',
|
||||
'hipOccupancyMaxActiveBlocksPerMultiprocessorWithFlags': '',
|
||||
'hipOccupancyMaxPotentialBlockSize': '',
|
||||
'hipMallocManaged': '',
|
||||
'hipOccupancyMaxActiveBlocksPerMultiprocessor': '',
|
||||
'hipGetErrorString': '',
|
||||
'hipMallocHost': '',
|
||||
'hipModuleLoadDataEx': '',
|
||||
'hipGetDeviceProperties': '',
|
||||
'hipConfigureCall': '',
|
||||
'hipHccModuleLaunchKernel': '',
|
||||
'hipExtModuleLaunchKernel': '',
|
||||
}
|
||||
# API options map
|
||||
opts_map = {}
|
||||
|
||||
# Parsing API header
|
||||
parse_api(api_hfile, api_map)
|
||||
|
||||
# Parsing sources
|
||||
parse_src(api_map, src_dir, src_pat, opts_map)
|
||||
|
||||
# Checking for non-conformant APIs with missing HIP_INIT macro
|
||||
for name in list(opts_map.keys()):
|
||||
m = re.match(r'\.(\S*)', name)
|
||||
if m:
|
||||
message("Init missing: " + m.group(1))
|
||||
del opts_map[name]
|
||||
|
||||
# Converting api map to map of lists
|
||||
# Checking for not found APIs
|
||||
not_found = 0
|
||||
if len(opts_map) != 0:
|
||||
for name in api_map.keys():
|
||||
args_str = api_map[name];
|
||||
api_map[name] = list_api_args(args_str)
|
||||
if not name in opts_map:
|
||||
error("implementation not found: " + name)
|
||||
not_found += 1
|
||||
if not_found != 0:
|
||||
error(str(not_found) + " API calls missing in interception layer")
|
||||
|
||||
# The output subdirectory seems to exist or not depending on the
|
||||
# version of cmake.
|
||||
output_dir = os.path.dirname(OUTPUT)
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
# Generating output header file
|
||||
with open(OUTPUT, 'w') as f:
|
||||
generate_prof_header(f, api_map, opts_map)
|
||||
|
||||
# Successfull exit
|
||||
sys.exit(0)
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
#include "hip_internal.hpp"
|
||||
|
||||
hipError_t hipProfilerStart() {
|
||||
HIP_INIT_API(hipProfilerStart);
|
||||
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
|
||||
|
||||
hipError_t hipProfilerStop() {
|
||||
HIP_INIT_API(hipProfilerStop);
|
||||
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
Executable
+419
@@ -0,0 +1,419 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include "hiprtc_internal.hpp"
|
||||
#include <hip/hiprtc.h>
|
||||
#include "platform/program.hpp"
|
||||
|
||||
#ifdef __HIP_ENABLE_PCH
|
||||
extern const char __hip_pch[];
|
||||
extern unsigned __hip_pch_size;
|
||||
void __hipGetPCH(const char** pch, unsigned int *size) {
|
||||
*pch = __hip_pch;
|
||||
*size = __hip_pch_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace hiprtc {
|
||||
thread_local hiprtcResult g_lastRtcError = HIPRTC_SUCCESS;
|
||||
}
|
||||
|
||||
class ProgramState {
|
||||
amd::Monitor lock_;
|
||||
private:
|
||||
static ProgramState* programState_;
|
||||
|
||||
ProgramState() : lock_("Guards program state") {}
|
||||
~ProgramState() {}
|
||||
public:
|
||||
std::unordered_map<amd::Program*,
|
||||
std::pair<std::vector<std::string>, std::vector<std::string>>> progHeaders_;
|
||||
|
||||
std::map<std::string, std::pair<std::string, std::string>> nameExpresssion_;
|
||||
|
||||
static ProgramState& instance();
|
||||
uint32_t addNameExpression(const char* name_expression);
|
||||
char* getLoweredName(const char* name_expression);
|
||||
};
|
||||
|
||||
ProgramState* ProgramState::programState_ = nullptr;
|
||||
|
||||
ProgramState& ProgramState::instance() {
|
||||
if (programState_ == nullptr) {
|
||||
programState_ = new ProgramState;
|
||||
}
|
||||
return *programState_;
|
||||
}
|
||||
|
||||
uint32_t ProgramState::addNameExpression(const char* name_expression) {
|
||||
amd::ScopedLock lock(lock_);
|
||||
|
||||
// Strip clean of any '(' or ')' or '&'
|
||||
std::string strippedName(name_expression);
|
||||
if (strippedName.back() == ')') {
|
||||
strippedName.pop_back();
|
||||
strippedName.erase(0, strippedName.find('('));
|
||||
}
|
||||
if (strippedName.front() == '&') {
|
||||
strippedName.erase(0, 1);
|
||||
}
|
||||
auto it = nameExpresssion_.find(name_expression);
|
||||
if (it == nameExpresssion_.end()) {
|
||||
nameExpresssion_.insert(std::pair<std::string, std::pair<std::string, std::string>>
|
||||
(name_expression, std::make_pair(strippedName,"")));
|
||||
}
|
||||
return nameExpresssion_.size();
|
||||
}
|
||||
|
||||
char* demangle(const char* loweredName) {
|
||||
if (!loweredName) {
|
||||
return nullptr;
|
||||
}
|
||||
#if __linux__
|
||||
int status = 0;
|
||||
char* demangledName = DEMANGLE(loweredName, nullptr, nullptr, &status);
|
||||
if (status != 0) {
|
||||
LogPrintfError("Cannot demangle loweredName: %s \n", loweredName);
|
||||
return nullptr;
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
char* demangledName = (char*)malloc(UNDECORATED_SIZE);
|
||||
|
||||
if (!UnDecorateSymbolName(loweredName, demangledName,
|
||||
UNDECORATED_SIZE/ sizeof(*demangledName), UNDNAME_COMPLETE))
|
||||
{
|
||||
free(demangledName);
|
||||
LogPrintfError("Cannot undecorate loweredName: %s demangledName: %s \n",
|
||||
loweredName, demangledName);
|
||||
return nullptr;
|
||||
}
|
||||
#else
|
||||
#error "Only Linux and Windows are supported"
|
||||
#endif // __linux__
|
||||
return demangledName;
|
||||
}
|
||||
|
||||
static std::string handleMangledName(std::string name) {
|
||||
std::string loweredName;
|
||||
char* demangled = demangle(name.c_str());
|
||||
loweredName.assign(demangled == nullptr ? std::string() : demangled);
|
||||
free(demangled);
|
||||
|
||||
if (loweredName.empty()) {
|
||||
return name;
|
||||
}
|
||||
|
||||
if (loweredName.find(".kd") != std::string::npos) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (loweredName.find("void ") == 0) {
|
||||
loweredName.erase(0, strlen("void "));
|
||||
}
|
||||
|
||||
auto dx{loweredName.find_first_of("(<")};
|
||||
|
||||
if (dx == std::string::npos) {
|
||||
return loweredName;
|
||||
}
|
||||
|
||||
if (loweredName[dx] == '<') {
|
||||
uint32_t count = 1;
|
||||
do {
|
||||
++dx;
|
||||
count += (loweredName[dx] == '<') ? 1 : ((loweredName[dx] == '>') ? -1 : 0);
|
||||
} while (count);
|
||||
|
||||
loweredName.erase(++dx);
|
||||
} else {
|
||||
loweredName.erase(dx);
|
||||
}
|
||||
|
||||
return loweredName;
|
||||
}
|
||||
|
||||
static std::string getValueOf(const std::string& option) {
|
||||
std::string res;
|
||||
auto f = std::find(option.begin(), option.end(), '=');
|
||||
if (f != option.end()) res = std::string(f + 1, option.end());
|
||||
return res;
|
||||
}
|
||||
|
||||
static void transformOptions(std::vector<std::string>& options, amd::Program* program) {
|
||||
std::vector<const char*> t_option;
|
||||
for (auto& i : options) {
|
||||
#ifdef __HIP_ENABLE_PCH
|
||||
// Use precompiled header for hip
|
||||
if (i == "-hip-pch") {
|
||||
const char* pch = nullptr;
|
||||
unsigned int pch_size = 0;
|
||||
__hipGetPCH(&pch, &pch_size);
|
||||
program->addPreCompiledHeader(std::string(pch, pch_size));
|
||||
i = "-nogpuinc";
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
// Some rtc samples use --gpu-architecture
|
||||
if (i.rfind("--gpu-architecture=", 0) == 0) {
|
||||
auto val = getValueOf(i);
|
||||
i = "--offload-arch=" + val;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* hiprtcGetErrorString(hiprtcResult x) {
|
||||
switch (x) {
|
||||
case HIPRTC_SUCCESS:
|
||||
return "HIPRTC_SUCCESS";
|
||||
case HIPRTC_ERROR_OUT_OF_MEMORY:
|
||||
return "HIPRTC_ERROR_OUT_OF_MEMORY";
|
||||
case HIPRTC_ERROR_PROGRAM_CREATION_FAILURE:
|
||||
return "HIPRTC_ERROR_PROGRAM_CREATION_FAILURE";
|
||||
case HIPRTC_ERROR_INVALID_INPUT:
|
||||
return "HIPRTC_ERROR_INVALID_INPUT";
|
||||
case HIPRTC_ERROR_INVALID_PROGRAM:
|
||||
return "HIPRTC_ERROR_INVALID_PROGRAM";
|
||||
case HIPRTC_ERROR_INVALID_OPTION:
|
||||
return "HIPRTC_ERROR_INVALID_OPTION";
|
||||
case HIPRTC_ERROR_COMPILATION:
|
||||
return "HIPRTC_ERROR_COMPILATION";
|
||||
case HIPRTC_ERROR_BUILTIN_OPERATION_FAILURE:
|
||||
return "HIPRTC_ERROR_BUILTIN_OPERATION_FAILURE";
|
||||
case HIPRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION:
|
||||
return "HIPRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION";
|
||||
case HIPRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION:
|
||||
return "HIPRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION";
|
||||
case HIPRTC_ERROR_NAME_EXPRESSION_NOT_VALID:
|
||||
return "HIPRTC_ERROR_NAME_EXPRESSION_NOT_VALID";
|
||||
case HIPRTC_ERROR_INTERNAL_ERROR:
|
||||
return "HIPRTC_ERROR_INTERNAL_ERROR";
|
||||
default:
|
||||
LogPrintfError("Invalid HIPRTC error code: %d \n", x);
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
ShouldNotReachHere();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcCreateProgram(hiprtcProgram* prog, const char* src, const char* name,
|
||||
int numHeaders, const char** headers, const char** headerNames) {
|
||||
HIPRTC_INIT_API(prog, src, name, numHeaders, headers, headerNames);
|
||||
|
||||
if (prog == nullptr) {
|
||||
HIPRTC_RETURN(HIPRTC_ERROR_INVALID_PROGRAM);
|
||||
}
|
||||
if (numHeaders < 0) {
|
||||
HIPRTC_RETURN(HIPRTC_ERROR_INVALID_INPUT);
|
||||
}
|
||||
if (numHeaders && (headers == nullptr || headerNames == nullptr)) {
|
||||
HIPRTC_RETURN(HIPRTC_ERROR_INVALID_INPUT);
|
||||
}
|
||||
|
||||
amd::Program* program = new amd::Program(*hip::getCurrentDevice()->asContext(), src, amd::Program::HIP,
|
||||
numHeaders, headers, headerNames);
|
||||
if (program == NULL) {
|
||||
HIPRTC_RETURN(HIPRTC_ERROR_INVALID_INPUT);
|
||||
}
|
||||
|
||||
if (CL_SUCCESS != program->addDeviceProgram(*hip::getCurrentDevice()->devices()[0])) {
|
||||
program->release();
|
||||
HIPRTC_RETURN(HIPRTC_ERROR_PROGRAM_CREATION_FAILURE);
|
||||
}
|
||||
|
||||
*prog = reinterpret_cast<hiprtcProgram>(as_cl(program));
|
||||
|
||||
HIPRTC_RETURN(HIPRTC_SUCCESS);
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcCompileProgram(hiprtcProgram prog, int numOptions, const char** options) {
|
||||
|
||||
// FIXME[skudchad] Add headers to amd::Program::build and device::Program::build,
|
||||
// pass the saved from ProgramState to amd::Program::build
|
||||
HIPRTC_INIT_API(prog, numOptions, options);
|
||||
|
||||
amd::Program* program = as_amd(reinterpret_cast<cl_program>(prog));
|
||||
|
||||
std::ostringstream ostrstr;
|
||||
std::vector<std::string> oarr(&options[0], &options[numOptions]);
|
||||
|
||||
const std::string hipVerOpt{"--hip-version=" + std::to_string(HIP_VERSION_MAJOR) + '.' +
|
||||
std::to_string(HIP_VERSION_MINOR) + '.' +
|
||||
std::to_string(HIP_VERSION_PATCH)};
|
||||
const std::string hipVerMajor{"-DHIP_VERSION_MAJOR=" + std::to_string(HIP_VERSION_MAJOR)};
|
||||
const std::string hipVerMinor{"-DHIP_VERSION_MINOR=" + std::to_string(HIP_VERSION_MINOR)};
|
||||
const std::string hipVerPatch{"-DHIP_VERSION_PATCH=" + std::to_string(HIP_VERSION_PATCH)};
|
||||
|
||||
oarr.push_back(hipVerOpt);
|
||||
oarr.push_back(hipVerMajor);
|
||||
oarr.push_back(hipVerMinor);
|
||||
oarr.push_back(hipVerPatch);
|
||||
|
||||
transformOptions(oarr, program);
|
||||
std::copy(oarr.begin(), oarr.end(), std::ostream_iterator<std::string>(ostrstr, " "));
|
||||
|
||||
std::vector<amd::Device*> devices{hip::getCurrentDevice()->devices()[0]};
|
||||
if (CL_SUCCESS != program->build(devices, ostrstr.str().c_str(), nullptr, nullptr)) {
|
||||
HIPRTC_RETURN(HIPRTC_ERROR_COMPILATION);
|
||||
}
|
||||
|
||||
HIPRTC_RETURN(HIPRTC_SUCCESS);
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcAddNameExpression(hiprtcProgram prog, const char* name_expression) {
|
||||
HIPRTC_INIT_API(prog, name_expression);
|
||||
|
||||
if (name_expression == nullptr) {
|
||||
HIPRTC_RETURN(HIPRTC_ERROR_INVALID_INPUT);
|
||||
}
|
||||
amd::Program* program = as_amd(reinterpret_cast<cl_program>(prog));
|
||||
|
||||
uint32_t id = ProgramState::instance().addNameExpression(name_expression);
|
||||
|
||||
const auto var{"__hiprtc_" + std::to_string(id)};
|
||||
const auto code{"\nextern \"C\" constexpr auto " + var + " = " + name_expression + ';'};
|
||||
|
||||
program->appendToSource(code.c_str());
|
||||
|
||||
HIPRTC_RETURN(HIPRTC_SUCCESS);
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcGetLoweredName(hiprtcProgram prog, const char* name_expression,
|
||||
const char** loweredName) {
|
||||
HIPRTC_INIT_API(prog, name_expression, loweredName);
|
||||
|
||||
if (name_expression == nullptr || loweredName == nullptr) {
|
||||
HIPRTC_RETURN(HIPRTC_ERROR_INVALID_INPUT);
|
||||
}
|
||||
|
||||
amd::Program* program = as_amd(reinterpret_cast<cl_program>(prog));
|
||||
|
||||
device::Program* dev_program
|
||||
= program->getDeviceProgram(*hip::getCurrentDevice()->devices()[0]);
|
||||
|
||||
auto it = ProgramState::instance().nameExpresssion_.find(name_expression);
|
||||
if (it == ProgramState::instance().nameExpresssion_.end()) {
|
||||
return HIPRTC_ERROR_NAME_EXPRESSION_NOT_VALID;
|
||||
}
|
||||
|
||||
std::string strippedName = it->second.first;
|
||||
std::vector<std::string> mangledNames;
|
||||
|
||||
if (!dev_program->getLoweredNames(&mangledNames)) {
|
||||
HIPRTC_RETURN(HIPRTC_ERROR_COMPILATION);
|
||||
}
|
||||
|
||||
for (auto &name : mangledNames) {
|
||||
std::string demangledName = handleMangledName(name);
|
||||
if (demangledName == strippedName) {
|
||||
it->second.second.assign(name);
|
||||
}
|
||||
}
|
||||
|
||||
*loweredName = it->second.second.c_str();
|
||||
|
||||
HIPRTC_RETURN(HIPRTC_SUCCESS);
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcDestroyProgram(hiprtcProgram* prog) {
|
||||
HIPRTC_INIT_API(prog);
|
||||
|
||||
if (prog == NULL) {
|
||||
HIPRTC_RETURN(HIPRTC_ERROR_INVALID_INPUT);
|
||||
}
|
||||
|
||||
// Release program. hiprtcProgram is a double pointer so free *prog
|
||||
amd::Program* program = as_amd(reinterpret_cast<cl_program>(*prog));
|
||||
|
||||
program->release();
|
||||
|
||||
HIPRTC_RETURN(HIPRTC_SUCCESS);
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcGetCode(hiprtcProgram prog, char* binaryMem) {
|
||||
HIPRTC_INIT_API(prog, binaryMem);
|
||||
|
||||
|
||||
amd::Program* program = as_amd(reinterpret_cast<cl_program>(prog));
|
||||
const device::Program::binary_t& binary =
|
||||
program->getDeviceProgram(*hip::getCurrentDevice()->devices()[0])->binary();
|
||||
|
||||
::memcpy(binaryMem, binary.first, binary.second);
|
||||
|
||||
HIPRTC_RETURN(HIPRTC_SUCCESS);
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcGetCodeSize(hiprtcProgram prog, size_t* binarySizeRet) {
|
||||
|
||||
HIPRTC_INIT_API(prog, binarySizeRet);
|
||||
|
||||
amd::Program* program = as_amd(reinterpret_cast<cl_program>(prog));
|
||||
|
||||
*binarySizeRet =
|
||||
program->getDeviceProgram(*hip::getCurrentDevice()->devices()[0])->binary().second;
|
||||
|
||||
HIPRTC_RETURN(HIPRTC_SUCCESS);
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcGetProgramLog(hiprtcProgram prog, char* dst) {
|
||||
|
||||
HIPRTC_INIT_API(prog, dst);
|
||||
amd::Program* program = as_amd(reinterpret_cast<cl_program>(prog));
|
||||
const device::Program* devProgram =
|
||||
program->getDeviceProgram(*hip::getCurrentDevice()->devices()[0]);
|
||||
|
||||
auto log = program->programLog() + devProgram->buildLog().c_str();
|
||||
|
||||
log.copy(dst, log.size());
|
||||
dst[log.size()] = '\0';
|
||||
|
||||
HIPRTC_RETURN(HIPRTC_SUCCESS);
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcGetProgramLogSize(hiprtcProgram prog, size_t* logSizeRet) {
|
||||
|
||||
HIPRTC_INIT_API(prog, logSizeRet);
|
||||
|
||||
amd::Program* program = as_amd(reinterpret_cast<cl_program>(prog));
|
||||
const device::Program* devProgram =
|
||||
program->getDeviceProgram(*hip::getCurrentDevice()->devices()[0]);
|
||||
|
||||
auto log = program->programLog() + devProgram->buildLog().c_str();
|
||||
|
||||
*logSizeRet = log.size() + 1;
|
||||
|
||||
HIPRTC_RETURN(HIPRTC_SUCCESS);
|
||||
}
|
||||
|
||||
hiprtcResult hiprtcVersion(int* major, int* minor) {
|
||||
HIPRTC_INIT_API(major, minor);
|
||||
|
||||
if (major == nullptr || minor == nullptr) {
|
||||
HIPRTC_RETURN(HIPRTC_ERROR_INVALID_INPUT);
|
||||
}
|
||||
|
||||
*major = 9;
|
||||
*minor = 0;
|
||||
|
||||
HIPRTC_RETURN(HIPRTC_SUCCESS);
|
||||
}
|
||||
Executable
+598
@@ -0,0 +1,598 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include "hip_internal.hpp"
|
||||
#include "hip_event.hpp"
|
||||
#include "thread/monitor.hpp"
|
||||
#include "hip_prof_api.h"
|
||||
|
||||
extern api_callbacks_table_t callbacks_table;
|
||||
|
||||
static amd::Monitor streamSetLock{"Guards global stream set"};
|
||||
static std::unordered_set<hip::Stream*> streamSet;
|
||||
namespace hip {
|
||||
|
||||
// ================================================================================================
|
||||
Stream::Stream(hip::Device* dev, Priority p, unsigned int f, bool null_stream,
|
||||
const std::vector<uint32_t>& cuMask, hipStreamCaptureStatus captureStatus)
|
||||
: queue_(nullptr),
|
||||
lock_("Stream Callback lock"),
|
||||
device_(dev),
|
||||
priority_(p),
|
||||
flags_(f),
|
||||
null_(null_stream),
|
||||
cuMask_(cuMask),
|
||||
captureStatus_(captureStatus) {}
|
||||
|
||||
// ================================================================================================
|
||||
Stream::~Stream() {
|
||||
if (queue_ != nullptr) {
|
||||
amd::ScopedLock lock(streamSetLock);
|
||||
streamSet.erase(this);
|
||||
|
||||
queue_->release();
|
||||
queue_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
hipError_t Stream::EndCapture() {
|
||||
for (auto event : captureEvents_) {
|
||||
hip::Event* e = reinterpret_cast<hip::Event*>(event);
|
||||
e->EndCapture();
|
||||
}
|
||||
for (auto stream : parallelCaptureStreams_) {
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
s->EndCapture();
|
||||
}
|
||||
captureStatus_ = hipStreamCaptureStatusNone;
|
||||
pCaptureGraph_ = nullptr;
|
||||
originStream_ = false;
|
||||
parentStream_ = nullptr;
|
||||
lastCapturedNodes_.clear();
|
||||
parallelCaptureStreams_.clear();
|
||||
captureEvents_.clear();
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
// ================================================================================================
|
||||
bool Stream::Create() {
|
||||
// Enable queue profiling if a profiler is attached which sets the callback_table flag
|
||||
// or if we force it with env var. This would enable time stamp collection for every
|
||||
// command submitted to the stream(queue).
|
||||
bool isProfilerAttached = callbacks_table.is_enabled();
|
||||
cl_command_queue_properties properties = (isProfilerAttached || HIP_FORCE_QUEUE_PROFILING) ?
|
||||
CL_QUEUE_PROFILING_ENABLE : 0;
|
||||
amd::CommandQueue::Priority p;
|
||||
switch (priority_) {
|
||||
case Priority::High:
|
||||
p = amd::CommandQueue::Priority::High;
|
||||
break;
|
||||
case Priority::Low:
|
||||
p = amd::CommandQueue::Priority::Low;
|
||||
break;
|
||||
case Priority::Normal:
|
||||
default:
|
||||
p = amd::CommandQueue::Priority::Normal;
|
||||
break;
|
||||
}
|
||||
amd::HostQueue* queue = new amd::HostQueue(*device_->asContext(), *device_->devices()[0],
|
||||
properties, amd::CommandQueue::RealTimeDisabled,
|
||||
p, cuMask_);
|
||||
|
||||
// Create a host queue
|
||||
bool result = (queue != nullptr) ? queue->create() : false;
|
||||
// Insert just created stream into the list of the blocking queues
|
||||
if (result) {
|
||||
amd::ScopedLock lock(streamSetLock);
|
||||
streamSet.insert(this);
|
||||
queue_ = queue;
|
||||
queue->vdev()->profilerAttach(isProfilerAttached);
|
||||
} else if (queue != nullptr) {
|
||||
queue->release();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
amd::HostQueue* Stream::asHostQueue(bool skip_alloc) {
|
||||
if (queue_ != nullptr) {
|
||||
return queue_;
|
||||
}
|
||||
// Access to the stream object is lock protected, because possible allocation
|
||||
amd::ScopedLock l(Lock());
|
||||
if (queue_ == nullptr) {
|
||||
// Create the host queue for the first time
|
||||
if (!skip_alloc) {
|
||||
Create();
|
||||
}
|
||||
}
|
||||
return queue_;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Stream::Finish() const {
|
||||
if (queue_ != nullptr) {
|
||||
queue_->finish();
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
int Stream::DeviceId() const {
|
||||
return device_->deviceId();
|
||||
}
|
||||
|
||||
int Stream::DeviceId(const hipStream_t hStream) {
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(hStream);
|
||||
int deviceId = (s != nullptr)? s->DeviceId() : ihipGetDevice();
|
||||
assert(deviceId >= 0 && deviceId < static_cast<int>(g_devices.size()));
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
void Stream::syncNonBlockingStreams() {
|
||||
amd::ScopedLock lock(streamSetLock);
|
||||
for (auto& it : streamSet) {
|
||||
if (it->Flags() & hipStreamNonBlocking) {
|
||||
it->asHostQueue()->finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool isValid(hipStream_t stream) {
|
||||
// NULL stream is always valid
|
||||
if (stream == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
|
||||
amd::ScopedLock lock(streamSetLock);
|
||||
if (streamSet.find(s) == streamSet.end()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
};// hip namespace
|
||||
|
||||
// ================================================================================================
|
||||
void iHipWaitActiveStreams(amd::HostQueue* blocking_queue, bool wait_null_stream) {
|
||||
amd::Command::EventWaitList eventWaitList;
|
||||
{
|
||||
amd::ScopedLock lock(streamSetLock);
|
||||
|
||||
for (const auto& stream : streamSet) {
|
||||
amd::HostQueue* active_queue = stream->asHostQueue();
|
||||
// If it's the current device
|
||||
if ((&active_queue->device() == &blocking_queue->device()) &&
|
||||
// Make sure it's a default stream
|
||||
((stream->Flags() & hipStreamNonBlocking) == 0) &&
|
||||
// and it's not the current stream
|
||||
(active_queue != blocking_queue) &&
|
||||
// check for a wait on the null stream
|
||||
(stream->Null() == wait_null_stream)) {
|
||||
// Get the last valid command
|
||||
amd::Command* command = active_queue->getLastQueuedCommand(true);
|
||||
if (command != nullptr) {
|
||||
// Check the current active status
|
||||
if (command->status() != CL_COMPLETE) {
|
||||
command->notifyCmdQueue();
|
||||
eventWaitList.push_back(command);
|
||||
} else {
|
||||
command->release();
|
||||
}
|
||||
}
|
||||
// Nullstream, hence there is nothing else to wait
|
||||
if (wait_null_stream) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have to wait anything
|
||||
if (eventWaitList.size() > 0) {
|
||||
amd::Command* command = new amd::Marker(*blocking_queue, kMarkerDisableFlush, eventWaitList);
|
||||
if (command != nullptr) {
|
||||
command->enqueue();
|
||||
command->release();
|
||||
}
|
||||
}
|
||||
|
||||
// Release all active commands. It's safe after the marker was enqueued
|
||||
for (const auto& it : eventWaitList) {
|
||||
it->release();
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void CL_CALLBACK ihipStreamCallback(cl_event event, cl_int command_exec_status, void* user_data) {
|
||||
hipError_t status = hipSuccess;
|
||||
StreamCallback* cbo = reinterpret_cast<StreamCallback*>(user_data);
|
||||
cbo->callBack_(cbo->stream_, status, cbo->userData_);
|
||||
cbo->command_->release();
|
||||
delete cbo;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
static hipError_t ihipStreamCreate(hipStream_t* stream,
|
||||
unsigned int flags, hip::Stream::Priority priority,
|
||||
const std::vector<uint32_t>& cuMask = {}) {
|
||||
if (flags != hipStreamDefault && flags != hipStreamNonBlocking) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
hip::Stream* hStream = new hip::Stream(hip::getCurrentDevice(), priority, flags, false, cuMask);
|
||||
|
||||
if (hStream == nullptr || !hStream->Create()) {
|
||||
delete hStream;
|
||||
return hipErrorOutOfMemory;
|
||||
}
|
||||
|
||||
*stream = reinterpret_cast<hipStream_t>(hStream);
|
||||
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipStreamCreateWithFlags(hipStream_t *stream, unsigned int flags) {
|
||||
HIP_INIT_API(hipStreamCreateWithFlags, stream, flags);
|
||||
|
||||
if (stream == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_RETURN(ihipStreamCreate(stream, flags, hip::Stream::Priority::Normal), *stream);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipStreamCreate(hipStream_t *stream) {
|
||||
HIP_INIT_API(hipStreamCreate, stream);
|
||||
|
||||
if (stream == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_RETURN(ihipStreamCreate(stream, hipStreamDefault, hip::Stream::Priority::Normal), *stream);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipStreamCreateWithPriority(hipStream_t* stream, unsigned int flags, int priority) {
|
||||
HIP_INIT_API(hipStreamCreateWithPriority, stream, flags, priority);
|
||||
|
||||
if (stream == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
hip::Stream::Priority streamPriority;
|
||||
if (priority <= hip::Stream::Priority::High) {
|
||||
streamPriority = hip::Stream::Priority::High;
|
||||
} else if (priority >= hip::Stream::Priority::Low) {
|
||||
streamPriority = hip::Stream::Priority::Low;
|
||||
} else {
|
||||
streamPriority = hip::Stream::Priority::Normal;
|
||||
}
|
||||
|
||||
HIP_RETURN(ihipStreamCreate(stream, flags, streamPriority), *stream);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipDeviceGetStreamPriorityRange(int* leastPriority, int* greatestPriority) {
|
||||
HIP_INIT_API(hipDeviceGetStreamPriorityRange, leastPriority, greatestPriority);
|
||||
|
||||
if (leastPriority != nullptr) {
|
||||
*leastPriority = hip::Stream::Priority::Low;
|
||||
}
|
||||
if (greatestPriority != nullptr) {
|
||||
*greatestPriority = hip::Stream::Priority::High;
|
||||
}
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipStreamGetFlags(hipStream_t stream, unsigned int* flags) {
|
||||
HIP_INIT_API(hipStreamGetFlags, stream, flags);
|
||||
|
||||
if ((flags != nullptr) && (stream != nullptr)) {
|
||||
if (!hip::isValid(stream)) {
|
||||
return HIP_RETURN(hipErrorContextIsDestroyed);
|
||||
}
|
||||
*flags = reinterpret_cast<hip::Stream*>(stream)->Flags();
|
||||
} else {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipStreamSynchronize(hipStream_t stream) {
|
||||
HIP_INIT_API(hipStreamSynchronize, stream);
|
||||
|
||||
if (!hip::isValid(stream)) {
|
||||
return HIP_RETURN(hipErrorContextIsDestroyed);
|
||||
}
|
||||
|
||||
// Wait for the current host queue
|
||||
hip::getQueue(stream)->finish();
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipStreamDestroy(hipStream_t stream) {
|
||||
HIP_INIT_API(hipStreamDestroy, stream);
|
||||
|
||||
if (stream == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidHandle);
|
||||
}
|
||||
|
||||
if (!hip::isValid(stream)) {
|
||||
return HIP_RETURN(hipErrorContextIsDestroyed);
|
||||
}
|
||||
|
||||
delete reinterpret_cast<hip::Stream*>(stream);
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
struct CallbackData {
|
||||
int previous_read_index;
|
||||
hip::ihipIpcEventShmem_t *shmem;
|
||||
};
|
||||
|
||||
void WaitThenDecrementSignal(hipStream_t stream, hipError_t status, void* user_data){
|
||||
CallbackData *data = (CallbackData *)user_data;
|
||||
int offset = data->previous_read_index % IPC_SIGNALS_PER_EVENT;
|
||||
while (data->shmem->read_index < data->previous_read_index+IPC_SIGNALS_PER_EVENT
|
||||
&& data->shmem->signal[offset] != 0) {
|
||||
}
|
||||
delete data;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipStreamWaitEvent(hipStream_t stream, hipEvent_t event, unsigned int flags) {
|
||||
HIP_INIT_API(hipStreamWaitEvent, stream, event, flags);
|
||||
|
||||
EVENT_CAPTURE(hipStreamWaitEvent, event, stream, flags);
|
||||
|
||||
if (event == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidHandle);
|
||||
}
|
||||
|
||||
if (!hip::isValid(stream)) {
|
||||
return HIP_RETURN(hipErrorContextIsDestroyed);
|
||||
}
|
||||
|
||||
amd::HostQueue* queue = hip::getQueue(stream);
|
||||
|
||||
hip::Event* e = reinterpret_cast<hip::Event*>(event);
|
||||
if (e->flags & hipEventInterprocess) {
|
||||
amd::Command* command = new amd::Marker(*queue, false);
|
||||
auto t{new CallbackData{e->ipc_evt_.ipc_shmem_->read_index, e->ipc_evt_.ipc_shmem_}};
|
||||
StreamCallback* cbo = new StreamCallback(stream,
|
||||
reinterpret_cast<hipStreamCallback_t> (WaitThenDecrementSignal), t, command);
|
||||
if (!command->setCallback(CL_COMPLETE, ihipStreamCallback,cbo)) {
|
||||
command->release();
|
||||
return hipErrorInvalidHandle;
|
||||
}
|
||||
command->enqueue();
|
||||
command->awaitCompletion();
|
||||
HIP_RETURN(hipSuccess);
|
||||
} else {
|
||||
HIP_RETURN(e->streamWait(queue, flags));
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipStreamQuery(hipStream_t stream) {
|
||||
HIP_INIT_API(hipStreamQuery, stream);
|
||||
|
||||
if (!hip::isValid(stream)) {
|
||||
return HIP_RETURN(hipErrorContextIsDestroyed);
|
||||
}
|
||||
|
||||
amd::HostQueue* hostQueue = hip::getQueue(stream);
|
||||
|
||||
amd::Command* command = hostQueue->getLastQueuedCommand(true);
|
||||
if (command == nullptr) {
|
||||
// Nothing was submitted to the queue
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
amd::Event& event = command->event();
|
||||
if (command->type() != 0) {
|
||||
event.notifyCmdQueue();
|
||||
}
|
||||
hipError_t status = (command->status() == CL_COMPLETE) ? hipSuccess : hipErrorNotReady;
|
||||
command->release();
|
||||
HIP_RETURN(status);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipStreamAddCallback(hipStream_t stream, hipStreamCallback_t callback, void* userData,
|
||||
unsigned int flags) {
|
||||
HIP_INIT_API(hipStreamAddCallback, stream, callback, userData, flags);
|
||||
//flags - Reserved for future use, must be 0
|
||||
if (callback == nullptr || flags != 0) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
if (!hip::isValid(stream)) {
|
||||
return HIP_RETURN(hipErrorContextIsDestroyed);
|
||||
}
|
||||
|
||||
amd::HostQueue* hostQueue = hip::getQueue(stream);
|
||||
amd::Command* last_command = hostQueue->getLastQueuedCommand(true);
|
||||
amd::Command::EventWaitList eventWaitList;
|
||||
if (last_command != nullptr) {
|
||||
eventWaitList.push_back(last_command);
|
||||
}
|
||||
amd::Command* command = new amd::Marker(*hostQueue, !kMarkerDisableFlush, eventWaitList);
|
||||
if (command == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
StreamCallback* cbo = new StreamCallback(stream, callback, userData, command);
|
||||
|
||||
if ((cbo == nullptr) || !command->setCallback(CL_COMPLETE, ihipStreamCallback, cbo)) {
|
||||
command->release();
|
||||
if (last_command != nullptr) {
|
||||
last_command->release();
|
||||
}
|
||||
return hipErrorInvalidHandle;
|
||||
}
|
||||
// Retain callback command for the blocking marker
|
||||
command->retain();
|
||||
command->enqueue();
|
||||
// @note: don't release the command here, because it will be released after HIP callback
|
||||
if (last_command != nullptr) {
|
||||
last_command->release();
|
||||
}
|
||||
// Add the new barrier to stall the stream, until the callback is done
|
||||
eventWaitList.clear();
|
||||
eventWaitList.push_back(command);
|
||||
amd::Command* block_command = new amd::Marker(*hostQueue, !kMarkerDisableFlush, eventWaitList);
|
||||
if (block_command == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
block_command->enqueue();
|
||||
block_command->release();
|
||||
// Release the callback marker
|
||||
command->release();
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipExtStreamCreateWithCUMask(hipStream_t* stream, uint32_t cuMaskSize,
|
||||
const uint32_t* cuMask) {
|
||||
HIP_INIT_API(hipExtStreamCreateWithCUMask, stream, cuMaskSize, cuMask);
|
||||
|
||||
if (stream == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidHandle);
|
||||
}
|
||||
if (cuMaskSize == 0 || cuMask == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
const std::vector<uint32_t> cuMaskv(cuMask, cuMask + cuMaskSize);
|
||||
|
||||
HIP_RETURN(ihipStreamCreate(stream, hipStreamDefault, hip::Stream::Priority::Normal, cuMaskv), *stream);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipStreamGetPriority(hipStream_t stream, int* priority) {
|
||||
HIP_INIT_API(hipStreamGetPriority, stream, priority);
|
||||
if ((priority != nullptr) && (stream != nullptr)) {
|
||||
if (!hip::isValid(stream)) {
|
||||
return HIP_RETURN(hipErrorContextIsDestroyed);
|
||||
}
|
||||
*priority = static_cast<int>(reinterpret_cast<hip::Stream*>(stream)->GetPriority());
|
||||
} else {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_RETURN(hipSuccess);
|
||||
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
hipError_t hipExtStreamGetCUMask(hipStream_t stream, uint32_t cuMaskSize, uint32_t* cuMask) {
|
||||
HIP_INIT_API(hipExtStreamGetCUMask, stream, cuMaskSize, cuMask);
|
||||
|
||||
if (cuMask == nullptr) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
int deviceId = hip::getCurrentDevice()->deviceId();
|
||||
auto* deviceHandle = g_devices[deviceId]->devices()[0];
|
||||
const auto& info = deviceHandle->info();
|
||||
|
||||
// find the minimum cuMaskSize required to present the CU mask bit-array in a patch of 32 bits
|
||||
// and return error if the cuMaskSize argument is less than cuMaskSizeRequired
|
||||
uint32_t cuMaskSizeRequired = info.maxComputeUnits_ / 32 +
|
||||
((info.maxComputeUnits_ % 32) ? 1 : 0);
|
||||
|
||||
if (cuMaskSize < cuMaskSizeRequired) {
|
||||
HIP_RETURN(hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
// make a default CU mask bit-array where all CUs are active
|
||||
// this default mask will be returned when there is no
|
||||
// custom or global CU mask defined
|
||||
std::vector<uint32_t> defaultCUMask;
|
||||
uint32_t temp = 0;
|
||||
uint32_t bit_index = 0;
|
||||
for (uint32_t i = 0; i < info.maxComputeUnits_; i++) {
|
||||
temp |= 1UL << bit_index;
|
||||
if (bit_index >= 32) {
|
||||
defaultCUMask.push_back(temp);
|
||||
temp = 0;
|
||||
bit_index = 0;
|
||||
temp |= 1UL << bit_index;
|
||||
}
|
||||
bit_index += 1;
|
||||
}
|
||||
if (bit_index != 0) {
|
||||
defaultCUMask.push_back(temp);
|
||||
}
|
||||
|
||||
// if the stream is null then either return globalCUMask_ (if it is defined)
|
||||
// or return defaultCUMask
|
||||
if (stream == nullptr) {
|
||||
if (info.globalCUMask_.size() != 0) {
|
||||
std::copy(info.globalCUMask_.begin(), info.globalCUMask_.end(), cuMask);
|
||||
} else {
|
||||
std::copy(defaultCUMask.begin(), defaultCUMask.end(), cuMask);
|
||||
}
|
||||
} else {
|
||||
// if the stream is not null then get the stream's CU mask and return one of the below cases
|
||||
// case1 if globalCUMask_ is defined then return the AND of globalCUMask_ and stream's CU mask
|
||||
// case2 if globalCUMask_ is not defined then retuen AND of defaultCUMask and stream's CU mask
|
||||
// in both cases above if stream's CU mask is empty then either globalCUMask_ (for case1)
|
||||
// or defaultCUMask(for case2) will be returned
|
||||
std::vector<uint32_t> streamCUMask;
|
||||
streamCUMask = reinterpret_cast<hip::Stream*>(stream)->GetCUMask();
|
||||
std::vector<uint32_t> mask = {};
|
||||
if (info.globalCUMask_.size() != 0) {
|
||||
for (uint32_t i = 0; i < std::min(streamCUMask.size(), info.globalCUMask_.size()); i++) {
|
||||
mask.push_back(streamCUMask[i] & info.globalCUMask_[i]);
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < std::min(streamCUMask.size(), defaultCUMask.size()); i++) {
|
||||
mask.push_back(streamCUMask[i] & defaultCUMask[i]);
|
||||
}
|
||||
// check to make sure after ANDing streamCUMask (custom-defined) with global CU mask,
|
||||
//we have non-zero mask, oterwise just return either globalCUMask_ or defaultCUMask
|
||||
bool zeroCUMask = true;
|
||||
for (auto m : mask) {
|
||||
if (m != 0) {
|
||||
zeroCUMask = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (zeroCUMask) {
|
||||
mask = (info.globalCUMask_.size() != 0) ? info.globalCUMask_ : defaultCUMask;
|
||||
}
|
||||
std::copy(mask.begin(), mask.end(), cuMask);
|
||||
}
|
||||
}
|
||||
HIP_RETURN(hipSuccess);
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include "hip_internal.hpp"
|
||||
#include "platform/command_utils.hpp"
|
||||
|
||||
hipError_t ihipStreamOperation(hipStream_t stream, cl_command_type cmdType, void* ptr,
|
||||
int64_t value, uint64_t mask, unsigned int flags, size_t sizeBytes) {
|
||||
size_t offset = 0;
|
||||
unsigned int outFlags = 0;
|
||||
|
||||
amd::Memory* memory = getMemoryObject(ptr, offset);
|
||||
if (!memory) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
// NOTE: 'mask' is only used in Wait operation, 'sizeBytes' is only used in Write operation
|
||||
// 'flags' for now used only for Wait, but in future there will usecases for Write too.
|
||||
|
||||
if (cmdType == ROCCLR_COMMAND_STREAM_WAIT_VALUE) {
|
||||
// Wait is only supported on SignalMemory objects
|
||||
if (!(memory->getMemFlags() & ROCCLR_MEM_HSA_SIGNAL_MEMORY)) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
switch (flags) {
|
||||
case hipStreamWaitValueGte:
|
||||
outFlags = ROCCLR_STREAM_WAIT_VALUE_GTE;
|
||||
break;
|
||||
case hipStreamWaitValueEq:
|
||||
outFlags = ROCCLR_STREAM_WAIT_VALUE_EQ;
|
||||
break;
|
||||
case hipStreamWaitValueAnd:
|
||||
outFlags = ROCCLR_STREAM_WAIT_VALUE_AND;
|
||||
break;
|
||||
case hipStreamWaitValueNor:
|
||||
outFlags = ROCCLR_STREAM_WAIT_VALUE_NOR;
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
break;
|
||||
}
|
||||
} else if (cmdType != ROCCLR_COMMAND_STREAM_WRITE_VALUE) {
|
||||
return hipErrorInvalidValue;
|
||||
}
|
||||
|
||||
amd::HostQueue* queue = hip::getQueue(stream);
|
||||
amd::Command::EventWaitList waitList;
|
||||
|
||||
amd::StreamOperationCommand* command =
|
||||
new amd::StreamOperationCommand(*queue, cmdType, waitList, *memory->asBuffer(),
|
||||
value, mask, outFlags, offset, sizeBytes);
|
||||
|
||||
if (command == nullptr) {
|
||||
return hipErrorOutOfMemory;
|
||||
}
|
||||
command->enqueue();
|
||||
command->release();
|
||||
return hipSuccess;
|
||||
}
|
||||
|
||||
hipError_t hipStreamWaitValue32(hipStream_t stream, void* ptr, int32_t value, unsigned int flags,
|
||||
uint32_t mask) {
|
||||
HIP_INIT_API(hipStreamWaitValue32, stream, ptr, value, mask, flags);
|
||||
// NOTE: ptr corresponds to a HSA Signal memeory which is 64 bits.
|
||||
// 32 bit value and mask are converted to 64-bit values.
|
||||
HIP_RETURN_DURATION(ihipStreamOperation(
|
||||
stream,
|
||||
ROCCLR_COMMAND_STREAM_WAIT_VALUE,
|
||||
ptr,
|
||||
value,
|
||||
mask,
|
||||
flags,
|
||||
0)); // sizeBytes un-used for wait, set it to 0
|
||||
}
|
||||
|
||||
hipError_t hipStreamWaitValue64(hipStream_t stream, void* ptr, int64_t value, unsigned int flags,
|
||||
uint64_t mask) {
|
||||
HIP_INIT_API(hipStreamWaitValue64, stream, ptr, value, mask, flags);
|
||||
HIP_RETURN_DURATION(ihipStreamOperation(
|
||||
stream,
|
||||
ROCCLR_COMMAND_STREAM_WAIT_VALUE,
|
||||
ptr,
|
||||
value,
|
||||
mask,
|
||||
flags,
|
||||
0)); // sizeBytes un-used for wait, set it to 0
|
||||
}
|
||||
|
||||
hipError_t hipStreamWriteValue32(hipStream_t stream, void* ptr, int32_t value, unsigned int flags) {
|
||||
HIP_INIT_API(hipStreamWriteValue32, stream, ptr, value, flags);
|
||||
HIP_RETURN_DURATION(ihipStreamOperation(
|
||||
stream,
|
||||
ROCCLR_COMMAND_STREAM_WRITE_VALUE,
|
||||
ptr,
|
||||
value,
|
||||
0, // mask un-used set it to 0
|
||||
0, // flags un-used for now set it to 0
|
||||
4));
|
||||
}
|
||||
|
||||
hipError_t hipStreamWriteValue64(hipStream_t stream, void* ptr, int64_t value, unsigned int flags) {
|
||||
HIP_INIT_API(hipStreamWriteValue64, stream, ptr, value, flags);
|
||||
HIP_RETURN_DURATION(ihipStreamOperation(
|
||||
stream,
|
||||
ROCCLR_COMMAND_STREAM_WRITE_VALUE,
|
||||
ptr,
|
||||
value,
|
||||
0, // mask un-used set it to 0
|
||||
0, // flags un-used for now set it to 0
|
||||
8));
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
#include "hip_internal.hpp"
|
||||
#include <hip/amd_detail/amd_hip_surface_types.h>
|
||||
|
||||
hipError_t hipCreateSurfaceObject(hipSurfaceObject_t* pSurfObject,
|
||||
const hipResourceDesc* pResDesc) {
|
||||
HIP_INIT_API(hipCreateSurfaceObject, pSurfObject, pResDesc);
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
|
||||
hipError_t hipDestroySurfaceObject(hipSurfaceObject_t surfaceObject) {
|
||||
HIP_INIT_API(hipDestroySurfaceObject, surfaceObject);
|
||||
|
||||
HIP_RETURN(hipErrorNotSupported);
|
||||
}
|
||||
Executable
+1303
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,65 @@
|
||||
/* Copyright (c) 2015-present Advanced Micro Devices, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef HIPRTC_SRC_HIP_INTERNAL_H
|
||||
#define HIPRTC_SRC_HIP_INTERNAL_H
|
||||
|
||||
#include "hip_internal.hpp"
|
||||
|
||||
#if __linux__
|
||||
#include <cstdlib>
|
||||
|
||||
#if HIPRTC_USE_CXXABI
|
||||
#include <cxxabi.h>
|
||||
|
||||
#define DEMANGLE abi::__cxa_demangle
|
||||
|
||||
#else
|
||||
extern "C" char * __cxa_demangle(const char *mangled_name, char *output_buffer,
|
||||
size_t *length, int *status);
|
||||
|
||||
#define DEMANGLE __cxa_demangle
|
||||
#endif //HIPRTC_USE_CXXABI
|
||||
|
||||
#elif defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
#include <DbgHelp.h>
|
||||
|
||||
#define UNDECORATED_SIZE 4096
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
// This macro should be called at the beginning of every HIP RTC API.
|
||||
#define HIPRTC_INIT_API(...) \
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API, "[%zx] %s ( %s )", std::this_thread::get_id(), __func__, ToString( __VA_ARGS__ ).c_str()); \
|
||||
amd::Thread* thread = amd::Thread::current(); \
|
||||
if (!VDI_CHECK_THREAD(thread)) { \
|
||||
HIPRTC_RETURN(HIPRTC_ERROR_INTERNAL_ERROR); \
|
||||
} \
|
||||
HIP_INIT();
|
||||
|
||||
#define HIPRTC_RETURN(ret) \
|
||||
hiprtc::g_lastRtcError = ret; \
|
||||
ClPrint(amd::LOG_INFO, amd::LOG_API, "[%zx] %s: Returned %s", std::this_thread::get_id(), __func__, \
|
||||
hiprtcGetErrorString(hiprtc::g_lastRtcError)); \
|
||||
return hiprtc::g_lastRtcError;
|
||||
|
||||
|
||||
#endif // HIPRTC_SRC_HIP_INTERNAL_H
|
||||
Loaded 100 of 119 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user