Files
rocm-systems/projects/clr/rocclr/runtime/device/device.hpp
T
foreman 4a59ff1a4e P4 to Git Change 1624807 by gandryey@gera-w8 on 2018/10/26 18:35:39
SWDEV-167970 - Ethereum mining (EthDcrMiner64.exe) App crashed while running Claymore Mining over VI,AI ,CI ASIC families
	- Fix a regression after CL#1608975. Use amdil complib instance to query the binary options. The logic in the abstraction layer attempts to validate the binary options and for some reason Ethereum binary isn't compatible with the HSAIL complib instance. It's a workaround for now, since the app doesn't allow debugger and printf debugging is quite time consuming.

Affected files ...

... //depot/stg/opencl/drivers/opencl/runtime/device/device.hpp#322 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpudevice.hpp#169 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/program.cpp#97 edit


[ROCm/clr commit: e8ca159b62]
2018-10-26 18:44:00 -04:00

1385 строки
47 KiB
C++

//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef DEVICE_HPP_
#define DEVICE_HPP_
#include "top.hpp"
#include "thread/thread.hpp"
#include "thread/monitor.hpp"
#include "platform/context.hpp"
#include "platform/object.hpp"
#include "platform/memory.hpp"
#include "utils/util.hpp"
#include "amdocl/cl_kernel.h"
#include "elf/elf.hpp"
#include "appprofile.hpp"
#include "devprogram.hpp"
#include "devkernel.hpp"
#if defined(WITH_LIGHTNING_COMPILER)
#include "caching/cache.hpp"
#include "driver/AmdCompiler.h"
#endif // defined(WITH_LIGHTNING_COMPILER)
#include "acl.h"
#include "hwdebug.hpp"
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <utility>
namespace amd {
class Command;
class CommandQueue;
class ReadMemoryCommand;
class WriteMemoryCommand;
class FillMemoryCommand;
class CopyMemoryCommand;
class CopyMemoryP2PCommand;
class MapMemoryCommand;
class UnmapMemoryCommand;
class MigrateMemObjectsCommand;
class NDRangeKernelCommand;
class NativeFnCommand;
class FlushCommand;
class FinishCommand;
class AcquireExtObjectsCommand;
class ReleaseExtObjectsCommand;
class PerfCounterCommand;
class ReleaseObjectCommand;
class StallQueueCommand;
class Marker;
class ThreadTraceCommand;
class ThreadTraceMemObjectsCommand;
class SignalCommand;
class MakeBuffersResidentCommand;
class SvmFreeMemoryCommand;
class SvmCopyMemoryCommand;
class SvmFillMemoryCommand;
class SvmMapMemoryCommand;
class SvmUnmapMemoryCommand;
class TransferBufferFileCommand;
class HwDebugManager;
class Device;
class CacheCompilation;
struct KernelParameterDescriptor;
struct Coord3D;
namespace option {
class Options;
} // option
}
enum OclExtensions {
ClKhrFp64 = 0,
ClAmdFp64,
ClKhrSelectFpRoundingMode,
ClKhrGlobalInt32BaseAtomics,
ClKhrGlobalInt32ExtendedAtomics,
ClKhrLocalInt32BaseAtomics,
ClKhrLocalInt32ExtendedAtomics,
ClKhrInt64BaseAtomics,
ClKhrInt64ExtendedAtomics,
ClKhr3DImageWrites,
ClKhrByteAddressableStore,
ClKhrFp16,
ClKhrGlSharing,
ClKhrGLDepthImages,
ClExtDeviceFission,
ClAmdDeviceAttributeQuery,
ClAmdVec3,
ClAmdPrintf,
ClAmdMediaOps,
ClAmdMediaOps2,
ClAmdPopcnt,
#if defined(_WIN32)
ClKhrD3d10Sharing,
ClKhrD3d11Sharing,
ClKhrD3d9Sharing,
#endif
ClKhrImage2dFromBuffer,
ClAmdSemaphore,
ClAMDBusAddressableMemory,
ClAMDC11Atomics,
ClKhrSpir,
ClKhrSubGroups,
ClKhrGlEvent,
ClKhrDepthImages,
ClKhrMipMapImage,
ClKhrMipMapImageWrites,
ClKhrIlProgram,
ClAMDLiquidFlash,
ClAmdCopyBufferP2P,
ClAmdAssemblyProgram,
#if defined(_WIN32)
ClAmdPlanarYuv,
#endif
ClExtTotal
};
static const char* OclExtensionsString[] = {"cl_khr_fp64 ",
"cl_amd_fp64 ",
"cl_khr_select_fprounding_mode ",
"cl_khr_global_int32_base_atomics ",
"cl_khr_global_int32_extended_atomics ",
"cl_khr_local_int32_base_atomics ",
"cl_khr_local_int32_extended_atomics ",
"cl_khr_int64_base_atomics ",
"cl_khr_int64_extended_atomics ",
"cl_khr_3d_image_writes ",
"cl_khr_byte_addressable_store ",
"cl_khr_fp16 ",
"cl_khr_gl_sharing ",
"cl_khr_gl_depth_images ",
"cl_ext_device_fission ",
"cl_amd_device_attribute_query ",
"cl_amd_vec3 ",
"cl_amd_printf ",
"cl_amd_media_ops ",
"cl_amd_media_ops2 ",
"cl_amd_popcnt ",
#if defined(_WIN32)
"cl_khr_d3d10_sharing ",
"cl_khr_d3d11_sharing ",
"cl_khr_dx9_media_sharing ",
#endif
"cl_khr_image2d_from_buffer ",
"",
"cl_amd_bus_addressable_memory ",
"cl_amd_c11_atomics ",
"cl_khr_spir ",
"cl_khr_subgroups ",
"cl_khr_gl_event ",
"cl_khr_depth_images ",
"cl_khr_mipmap_image ",
"cl_khr_mipmap_image_writes ",
"",
"cl_amd_liquid_flash ",
"cl_amd_copy_buffer_p2p ",
"cl_amd_assembly_program ",
#if defined(_WIN32)
"cl_amd_planar_yuv",
#endif
NULL};
static constexpr int AmdVendor = 0x1002;
namespace device {
class ClBinary;
class BlitManager;
class Program;
class Kernel;
//! Physical device properties.
struct Info : public amd::EmbeddedObject {
//! The OpenCL device type.
cl_device_type type_;
//! A unique device vendor identifier.
cl_uint vendorId_;
//! The number of parallel compute cores on the compute device.
cl_uint maxComputeUnits_;
//! Maximum dimensions that specify the global and local work-item IDs
// used by the data-parallel execution model.
cl_uint maxWorkItemDimensions_;
//! Maximum number of work-items that can be specified in each dimension
// to clEnqueueNDRangeKernel.
size_t maxWorkItemSizes_[3];
//! Maximum number of work-items in a work-group executing a kernel
// using the data-parallel execution model.
size_t maxWorkGroupSize_;
//! Preferred number of work-items in a work-group executing a kernel
// using the data-parallel execution model.
size_t preferredWorkGroupSize_;
//! Number of shader engines in physical GPU
size_t numberOfShaderEngines;
//! cl_uint Preferred native vector width size for built-in scalar types
// that can be put into vectors.
cl_uint preferredVectorWidthChar_;
cl_uint preferredVectorWidthShort_;
cl_uint preferredVectorWidthInt_;
cl_uint preferredVectorWidthLong_;
cl_uint preferredVectorWidthFloat_;
cl_uint preferredVectorWidthDouble_;
cl_uint preferredVectorWidthHalf_;
//! Returns the native ISA vector width. The vector width is defined as the
// number of scalar elements that can be stored in the vector.
cl_uint nativeVectorWidthChar_;
cl_uint nativeVectorWidthShort_;
cl_uint nativeVectorWidthInt_;
cl_uint nativeVectorWidthLong_;
cl_uint nativeVectorWidthFloat_;
cl_uint nativeVectorWidthDouble_;
cl_uint nativeVectorWidthHalf_;
//! Maximum configured engine clock frequency of the device in MHz.
cl_uint maxEngineClockFrequency_;
//! Maximum configured memory clock frequency of the device in MHz.
cl_uint maxMemoryClockFrequency_;
//! Memory bus width in bits.
cl_uint vramBusBitWidth_;
//! Size of L2 Cache in bytes.
cl_uint l2CacheSize_;
//! Timestamp frequency in Hz.
cl_uint timeStampFrequency_;
//! Describes the address spaces supported by the device.
cl_uint addressBits_;
//! Max number of simultaneous image objects that can be read by a
// kernel.
cl_uint maxReadImageArgs_;
//! Max number of simultaneous image objects that can be written to
// by a kernel.
cl_uint maxWriteImageArgs_;
//! Max number of simultaneous image objects that can be read/written to
// by a kernel.
cl_uint maxReadWriteImageArgs_;
//! Max size of memory object allocation in bytes.
cl_ulong maxMemAllocSize_;
//! Max width of 2D image in pixels.
size_t image2DMaxWidth_;
//! Max height of 2D image in pixels.
size_t image2DMaxHeight_;
//! Max width of 3D image in pixels.
size_t image3DMaxWidth_;
//! Max height of 3D image in pixels.
size_t image3DMaxHeight_;
//! Max depth of 3D image in pixels.
size_t image3DMaxDepth_;
//! Describes whether images are supported
cl_bool imageSupport_;
//! Max size in bytes of the arguments that can be passed to a kernel.
size_t maxParameterSize_;
//! Maximum number of samplers that can be used in a kernel.
cl_uint maxSamplers_;
//! Describes the alignment in bits of the base address of any
// allocated memory object.
cl_uint memBaseAddrAlign_;
//! The smallest alignment in bytes which can be used for any data type.
cl_uint minDataTypeAlignSize_;
//! Describes single precision floating point capability of the device.
cl_device_fp_config halfFPConfig_;
cl_device_fp_config singleFPConfig_;
cl_device_fp_config doubleFPConfig_;
//! Type of global memory cache supported.
cl_device_mem_cache_type globalMemCacheType_;
//! Size of global memory cache line in bytes.
cl_uint globalMemCacheLineSize_;
//! Size of global memory cache in bytes.
cl_ulong globalMemCacheSize_;
//! Size of global device memory in bytes.
cl_ulong globalMemSize_;
//! Max size in bytes of a constant buffer allocation.
cl_ulong maxConstantBufferSize_;
//! Preferred size in bytes of a constant buffer allocation.
cl_ulong preferredConstantBufferSize_;
//! Max number of arguments declared
cl_uint maxConstantArgs_;
//! This is used to determine the type of local memory that is available
cl_device_local_mem_type localMemType_;
//! Size of local memory arena in bytes.
cl_ulong localMemSize_;
//! If enabled, implies that all the memories, caches, registers etc. in
// the device implement error correction.
cl_bool errorCorrectionSupport_;
//! CL_TRUE if the device and the host have a unified memory subsystem and
// is CL_FALSE otherwise.
cl_bool hostUnifiedMemory_;
//! Describes the resolution of device timer.
size_t profilingTimerResolution_;
//! Timer starting point offset to Epoch.
cl_ulong profilingTimerOffset_;
//! CL_TRUE if device is a little endian device.
cl_bool littleEndian_;
//! If enabled, implies that commands can be submitted to command-queues
// created on this device.
cl_bool available_;
//! if the implementation does not have a compiler available to compile
// the program source.
cl_bool compilerAvailable_;
//! Describes the execution capabilities of the device.
cl_device_exec_capabilities executionCapabilities_;
//! Describes the SVM capabilities of the device.
cl_device_svm_capabilities svmCapabilities_;
//! Preferred alignment for OpenCL fine-grained SVM atomic types.
cl_uint preferredPlatformAtomicAlignment_;
//! Preferred alignment for OpenCL global atomic types.
cl_uint preferredGlobalAtomicAlignment_;
//! Preferred alignment for OpenCL local atomic types.
cl_uint preferredLocalAtomicAlignment_;
//! Describes the command-queue properties supported of the host queue.
cl_command_queue_properties queueProperties_;
//! The platform associated with this device
cl_platform_id platform_;
//! Device name string
char name_[0x40];
//! Vendor name string
char vendor_[0x20];
//! OpenCL software driver version string in the form major.minor
char driverVersion_[0x20];
//! Returns the profile name supported by the device.
const char* profile_;
//! Returns the OpenCL version supported by the device.
const char* version_;
//! The highest OpenCL C version supported by the compiler for this device.
const char* oclcVersion_;
//! Returns a space separated list of extension names.
const char* extensions_;
//! Returns if device linker is available
cl_bool linkerAvailable_;
//! Returns the list of built-in kernels, supported by the device
const char* builtInKernels_;
//! Returns max number of pixels for a 1D image created from a buffer object
size_t imageMaxBufferSize_;
//! Returns max number of images in a 1D or 2D image array
size_t imageMaxArraySize_;
//! Returns CL_TRUE if the devices preference is for the user to be
//! responsible for synchronization
cl_bool preferredInteropUserSync_;
//! Returns maximum size of the internal buffer that holds the output
//! of printf calls from a kernel
size_t printfBufferSize_;
//! Indicates maximum number of supported global atomic counters
cl_uint maxAtomicCounters_;
//! Returns the topology for the device
cl_device_topology_amd deviceTopology_;
//! Semaphore information
cl_uint maxSemaphores_;
cl_uint maxSemaphoreSize_;
//! Returns the SKU board name for the device
char boardName_[128];
//! Number of SIMD (Single Instruction Multiple Data) units per compute unit
//! that execute in parallel. All work items from the same work group must be
//! executed by SIMDs in the same compute unit.
cl_uint simdPerCU_;
cl_uint cuPerShaderArray_; //!< Number of CUs per shader array
//! The maximum number of work items from the same work group that can be
//! executed by a SIMD in parallel
cl_uint simdWidth_;
//! The number of instructions that a SIMD can execute in parallel
cl_uint simdInstructionWidth_;
//! The number of workitems per wavefront
cl_uint wavefrontWidth_;
//! Available number of SGPRs
cl_uint availableSGPRs_;
//! Number of global memory channels
cl_uint globalMemChannels_;
//! Number of banks in each global memory channel
cl_uint globalMemChannelBanks_;
//! Width in bytes of each of global memory bank
cl_uint globalMemChannelBankWidth_;
//! Local memory size per CU
cl_uint localMemSizePerCU_;
//! Number of banks of local memory
cl_uint localMemBanks_;
//! The core engine GFXIP version
cl_uint gfxipVersion_;
//! Number of available async queues
cl_uint numAsyncQueues_;
//! Number of available real time queues
cl_uint numRTQueues_;
//! Number of available real time compute units
cl_uint numRTCUs_;
//! Thread trace enable
cl_bool threadTraceEnable_;
//! Image pitch alignment for image2d_from_buffer
cl_uint imagePitchAlignment_;
//! Image base address alignment for image2d_from_buffer
cl_uint imageBaseAddressAlignment_;
//! Describes whether buffers from images are supported
cl_bool bufferFromImageSupport_;
//! Returns the supported SPIR versions for the device
const char* spirVersions_;
//! OpenCL20 device info fields:
//! The max number of pipe objects that can be passed as arguments to a kernel
cl_uint maxPipeArgs_;
//! The max number of reservations that can be active for a pipe per work-item in a kernel
cl_uint maxPipeActiveReservations_;
//! The max size of pipe packet in bytes
cl_uint maxPipePacketSize_;
//! The command-queue properties supported of the device queue.
cl_command_queue_properties queueOnDeviceProperties_;
//! The preferred size of the device queue in bytes
cl_uint queueOnDevicePreferredSize_;
//! The max size of the device queue in bytes
cl_uint queueOnDeviceMaxSize_;
//! The maximum number of device queues
cl_uint maxOnDeviceQueues_;
//! The maximum number of events in use on a device queue
cl_uint maxOnDeviceEvents_;
//! The maximum size of global scope variables
size_t maxGlobalVariableSize_;
size_t globalVariablePreferredTotalSize_;
//! Driver store location
char driverStore_[200];
//! Device ID
uint32_t pcieDeviceId_;
//! Revision ID
uint32_t pcieRevisionId_;
};
//! Device settings
class Settings : public amd::HeapObject {
public:
uint64_t extensions_; //!< Supported OCL extensions
union {
struct {
uint apuSystem_ : 1; //!< Device is APU system with shared memory
uint partialDispatch_ : 1; //!< Enables partial dispatch
uint supportRA_ : 1; //!< Support RA channel order format
uint waitCommand_ : 1; //!< Enables a wait for every submitted command
uint customHostAllocator_ : 1; //!< True if device has custom host allocator
// that replaces generic OS allocation routines
uint supportDepthsRGB_ : 1; //!< Support DEPTH and sRGB channel order format
uint enableHwDebug_ : 1; //!< Enable HW debug support
uint reportFMAF_ : 1; //!< Report FP_FAST_FMAF define in CL program
uint reportFMA_ : 1; //!< Report FP_FAST_FMA define in CL program
uint singleFpDenorm_ : 1; //!< Support Single FP Denorm
uint gfx10Hsail_ : 1 ; //!< GFX10 HSAIL path
uint useLightning_ : 1; //!< Enable LC path for this device
uint reserved_ : 20;
};
uint value_;
};
uint commandQueues_; //!< Field value for maximum number
//!< concurrent Virtual GPUs for each backend
//! Default constructor
Settings();
//! Check the specified extension
bool checkExtension(uint name) const {
return (extensions_ & (static_cast<uint64_t>(1) << name)) ? true : false;
}
//! Enable the specified extension
void enableExtension(uint name) { extensions_ |= static_cast<uint64_t>(1) << name; }
private:
//! Disable copy constructor
Settings(const Settings&);
//! Disable assignment
Settings& operator=(const Settings&);
};
//! Device-independent cache memory, base class for the device-specific
//! memories. One Memory instance refers to one or more of these.
class Memory : public amd::HeapObject {
public:
//! Resource map flags
enum CpuMapFlags {
CpuReadWrite = 0x00000000, //!< Lock for CPU read/Write
CpuReadOnly = 0x00000001, //!< Lock for CPU read only operation
CpuWriteOnly = 0x00000002, //!< Lock for CPU write only operation
};
union SyncFlags {
struct {
uint skipParent_ : 1; //!< Skip parent synchronization
uint skipViews_ : 1; //!< Skip views synchronization
uint skipEntire_ : 1; //!< Skip entire synchronization
};
uint value_;
SyncFlags() : value_(0) {}
};
struct WriteMapInfo : public amd::HeapObject {
amd::Coord3D origin_; //!< Origin of the map location
amd::Coord3D region_; //!< Mapped region
amd::Image* baseMip_; //!< The base mip level for images
union {
struct {
uint32_t count_ : 8; //!< The same map region counter
uint32_t unmapWrite_ : 1; //!< Unmap write operation
uint32_t unmapRead_ : 1; //!< Unmap read operation
uint32_t entire_ : 1; //!< Process the entire memory
};
uint32_t flags_;
};
//! Returns the state of entire map
bool isEntire() const { return (entire_) ? true : false; }
//! Returns the state of map write flag
bool isUnmapWrite() const { return (unmapWrite_) ? true : false; }
//! Returns the state of map read flag
bool isUnmapRead() const { return (unmapRead_) ? true : false; }
WriteMapInfo() : origin_(0, 0, 0), region_(0, 0, 0), baseMip_(NULL), flags_(0) {}
};
//! Constructor (from an amd::Memory object).
Memory(amd::Memory& owner)
: flags_(0), owner_(&owner), version_(0), mapMemory_(NULL), indirectMapCount_(0) {
size_ = owner.getSize();
}
//! Constructor (no owner), always eager allocation.
Memory(size_t size)
: flags_(0), owner_(NULL), version_(0), mapMemory_(NULL), indirectMapCount_(0), size_(size) {}
enum GLResourceOP {
GLDecompressResource = 0, // orders the GL driver to decompress any depth-stencil or MSAA
// resource to be sampled by a CL kernel.
GLInvalidateFBO // orders the GL driver to invalidate any FBO the resource may be bound to,
// since the resource internal state changed.
};
//! Default destructor for the device memory object
virtual ~Memory(){};
//! Releases virtual objects associated with this memory
void releaseVirtual();
//! Read the size
size_t size() const { return size_; }
//! Gets the owner Memory instance
amd::Memory* owner() const { return owner_; }
//! Immediate blocking write from device cache to owners's backing store.
//! Marks owner as "current" by resetting the last writer to NULL.
virtual void syncHostFromCache(SyncFlags syncFlags = SyncFlags()) {}
//! Allocate memory for API-level maps
virtual void* allocMapTarget(const amd::Coord3D& origin, //!< The map location in memory
const amd::Coord3D& region, //!< The map region in memory
uint mapFlags, //!< Map flags
size_t* rowPitch = NULL, //!< Row pitch for the mapped memory
size_t* slicePitch = NULL //!< Slice for the mapped memory
) {
return NULL;
}
virtual bool pinSystemMemory(void* hostPtr, //!< System memory address
size_t size //!< Size of allocated system memory
) {
return true;
}
//! Releases indirect map surface
virtual void releaseIndirectMap() {}
//! decompress any MSAA/depth-stencil interop surfaces.
//! notify GL to invalidate any surfaces touched by a CL kernel
virtual bool processGLResource(GLResourceOP operation) { return false; }
//! Map the device memory to CPU visible
virtual void* cpuMap(VirtualDevice& vDev, //!< Virtual device for map operaiton
uint flags = 0, //!< flags for the map operation
// Optimization for multilayer map/unmap
uint startLayer = 0, //!< Start layer for multilayer map
uint numLayers = 0, //!< End layer for multilayer map
size_t* rowPitch = NULL, //!< Row pitch for the device memory
size_t* slicePitch = NULL //!< Slice pitch for the device memory
) {
amd::Image* image = owner()->asImage();
if (image != NULL) {
*rowPitch = image->getRowPitch();
*slicePitch = image->getSlicePitch();
}
// Default behavior uses preallocated host mem for CPU
return owner()->getHostMem();
}
//! Unmap the device memory
virtual void cpuUnmap(VirtualDevice& vDev //!< Virtual device for unmap operaiton
) {}
//! Saves map info for this object
//! @note: It's not a thread safe operation, the app must implement
//! synchronization for the multiple write maps if necessary
void saveMapInfo(const void* mapAddress, //!< Map cpu address
const amd::Coord3D origin, //!< Origin of the map location
const amd::Coord3D region, //!< Mapped region
uint mapFlags, //!< Map flags
bool entire, //!< True if the enitre memory was mapped
amd::Image* baseMip = nullptr //!< The base mip level for map
);
const WriteMapInfo* writeMapInfo(const void* mapAddress) const {
// Unmap must be serialized.
amd::ScopedLock lock(owner()->lockMemoryOps());
auto it = writeMapInfo_.find(mapAddress);
if (it == writeMapInfo_.end()) {
if (writeMapInfo_.size() == 0) {
LogError("Unmap is a NOP!");
return nullptr;
}
LogWarning("Unknown unmap signature!");
// Get the first map info
it = writeMapInfo_.begin();
}
return &it->second;
}
//! Clear memory object as mapped read only
void clearUnmapInfo(const void* mapAddress) {
// Unmap must be serialized.
amd::ScopedLock lock(owner()->lockMemoryOps());
auto it = writeMapInfo_.find(mapAddress);
if (it == writeMapInfo_.end()) {
// Get the first map info
it = writeMapInfo_.begin();
}
if (--it->second.count_ == 0) {
writeMapInfo_.erase(it);
}
}
//! Returns the state of memory direct access flag
bool isHostMemDirectAccess() const { return (flags_ & HostMemoryDirectAccess) ? true : false; }
//! Returns the state of host memory registration flag
bool isHostMemoryRegistered() const { return (flags_ & HostMemoryRegistered) ? true : false; }
//! Returns the state of CPU uncached access
bool isCpuUncached() const { return (flags_ & MemoryCpuUncached) ? true : false; }
virtual uint64_t virtualAddress() const { return 0; }
protected:
enum Flags {
HostMemoryDirectAccess = 0x00000001, //!< GPU has direct access to the host memory
MapResourceAlloced = 0x00000002, //!< Map resource was allocated
PinnedMemoryAlloced = 0x00000004, //!< An extra pinned resource was allocated
SubMemoryObject = 0x00000008, //!< Memory is sub-memory
HostMemoryRegistered = 0x00000010, //!< Host memory was registered
MemoryCpuUncached = 0x00000020 //!< Memory is uncached on CPU access(slow read)
};
uint flags_; //!< Memory object flags
amd::Memory* owner_; //!< The Memory instance that we cache,
//!< or NULL if we're device-private workspace.
volatile size_t version_; //!< The version we're currently shadowing
//! NB, the map data below is for an API-level map (from clEnqueueMapBuffer),
//! not a physical map. When a memory object does not use USE_HOST_PTR we
//! can use a remote resource and DMA, avoiding the additional CPU memcpy.
amd::Memory* mapMemory_; //!< Memory used as map target buffer
volatile size_t indirectMapCount_; //!< Number of maps
std::unordered_map<const void*, WriteMapInfo> writeMapInfo_; //!< Saved write map info for partial unmap
//! Increment map count
void incIndMapCount() { ++indirectMapCount_; }
//! Decrement map count
virtual void decIndMapCount() {}
size_t size_; //!< Memory size
private:
//! Disable default copy constructor
Memory& operator=(const Memory&) = delete;
//! Disable operator=
Memory(const Memory&) = delete;
};
class Sampler : public amd::HeapObject {
public:
//! Constructor
Sampler() : hwSrd_(0) {}
//! Default destructor for the device memory object
virtual ~Sampler(){};
//! Returns device specific HW state for the sampler
uint64_t hwSrd() const { return hwSrd_; }
protected:
uint64_t hwSrd_; //!< Device specific HW state for the sampler
private:
//! Disable default copy constructor
Sampler& operator=(const Sampler&);
//! Disable operator=
Sampler(const Sampler&);
};
class ClBinary : public amd::HeapObject {
public:
enum BinaryImageFormat {
BIF_VERSION2 = 0, //!< Binary Image Format version 2.0 (ELF)
BIF_VERSION3 //!< Binary Image Format version 3.0 (ELF)
};
//! Constructor
ClBinary(const amd::Device& dev, BinaryImageFormat bifVer = BIF_VERSION3);
//! Destructor
virtual ~ClBinary();
void init(amd::option::Options* optionsObj, bool amdilRequired = false);
/** called only in loading image routines,
never called in storing routines */
bool setBinary(const char* theBinary, size_t theBinarySize, bool allocated = false);
//! setin elfIn_
bool setElfIn();
void resetElfIn();
//! set out elf
bool setElfOut(unsigned char eclass, const char* outFile);
void resetElfOut();
//! Set elf header information
virtual bool setElfTarget();
// class used in for loading images in new format
amd::OclElf* elfIn() { return elfIn_; }
// classes used storing and loading images in new format
amd::OclElf* elfOut() { return elfOut_; }
void elfOut(amd::OclElf* v) { elfOut_ = v; }
//! Create and save ELF binary image
bool createElfBinary(bool doencrypt, Program::type_t type);
// save BIF binary image
void saveBIFBinary(const char* binaryIn, size_t size);
bool decryptElf(const char* binaryIn, size_t size, char** decryptBin, size_t* decryptSize,
int* encryptCode);
//! Returns the binary pair for the abstraction layer
Program::binary_t data() const;
//! Loads llvmir binary from OCL binary file
bool loadLlvmBinary(
std::string& llvmBinary, //!< LLVMIR binary code
amd::OclElf::oclElfSections& elfSectionType //!< LLVMIR binary is in SPIR format
) const;
//! Loads compile options from OCL binary file
bool loadCompileOptions(std::string& compileOptions //!< return the compile options loaded
) const;
//! Loads link options from OCL binary file
bool loadLinkOptions(std::string& linkOptions //!< return the link options loaded
) const;
//! Store compile options into OCL binary file
void storeCompileOptions(const std::string& compileOptions //!< the compile options to be stored
);
//! Store link options into OCL binary file
void storeLinkOptions(const std::string& linkOptions //!< the link options to be stored
);
//! Check if the binary is recompilable
bool isRecompilable(std::string& llvmBinary, amd::OclElf::oclElfPlatform thePlatform);
void saveOrigBinary(const char* origBinary, size_t origSize) {
origBinary_ = origBinary;
origSize_ = origSize;
}
void restoreOrigBinary() {
if (origBinary_ != NULL) {
(void)setBinary(origBinary_, origSize_, false);
}
}
//! Set Binary flags
void setFlags(int encryptCode);
bool saveSOURCE() { return ((flags_ & BinarySourceMask) == BinarySaveSource); }
bool saveLLVMIR() { return ((flags_ & BinaryLlvmirMask) == BinarySaveLlvmir); }
bool saveAMDIL() { return ((flags_ & BinaryAmdilMask) == BinarySaveAmdil); }
bool saveISA() { return ((flags_ & BinaryIsaMask) == BinarySaveIsa); }
bool saveAS() { return ((flags_ & BinaryASMask) == BinarySaveAS); }
// Return the encrypt code for this input binary ( "> 0" means encrypted)
int getEncryptCode() { return encryptCode_; }
// Returns TRUE of binary file is SPIR
bool isSPIR() const;
// Returns TRUE of binary file is SPIRV
bool isSPIRV() const;
protected:
enum Flags {
BinaryAllocated = 0x1, //!< Binary was created
// Source control
BinaryNoSaveSource = 0x0, // 0: default
BinaryRemoveSource = 0x2, // for encrypted binary
BinarySaveSource = 0x4,
BinarySourceMask = 0x6,
// LLVMIR control
BinarySaveLlvmir = 0x0, // 0: default
BinaryRemoveLlvmir = 0x8, // for encrypted binary
BinaryNoSaveLlvmir = 0x10,
BinaryLlvmirMask = 0x18,
// AMDIL control
BinarySaveAmdil = 0x0, // 0: default
BinaryRemoveAmdil = 0x20, // for encrypted binary
BinaryNoSaveAmdil = 0x40,
BinaryAmdilMask = 0x60,
// ISA control
BinarySaveIsa = 0x0, // 0: default
BinaryRemoveIsa = 0x80, // for encrypted binary
BinaryNoSaveIsa = 0x100,
BinaryIsaMask = 0x180,
// AS control
BinaryNoSaveAS = 0x0, // 0: default
BinaryRemoveAS = 0x200, // for encrypted binary
BinarySaveAS = 0x400,
BinaryASMask = 0x600
};
//! Returns TRUE if binary file was allocated
bool isBinaryAllocated() const { return (flags_ & BinaryAllocated) ? true : false; }
//! Returns BIF symbol name by symbolID,
//! returns empty string if not found or if BIF version is unsupported
std::string getBIFSymbol(unsigned int symbolID) const;
protected:
const amd::Device& dev_; //!< Device object
private:
//! Disable default copy constructor
ClBinary(const ClBinary&);
//! Disable default operator=
ClBinary& operator=(const ClBinary&);
//! Releases the binary data store
void release();
const char* binary_; //!< binary data
size_t size_; //!< binary size
uint flags_; //!< CL binary object flags
const char* origBinary_; //!< original binary data
size_t origSize_; //!< original binary size
int encryptCode_; //!< Encryption Code for input binary (0 for not encrypted)
protected:
amd::OclElf* elfIn_; //!< ELF object for input ELF binary
amd::OclElf* elfOut_; //!< ELF object for output ELF binary
BinaryImageFormat format_; //!< which binary image format to use
};
inline const Program::binary_t Program::binary() const {
if (clBinary() == NULL) {
return {(const void*)0, 0};
}
return clBinary()->data();
}
inline Program::binary_t Program::binary() {
if (clBinary() == NULL) {
return {(const void*)0, 0};
}
return clBinary()->data();
}
/*! \class PerfCounter
*
* \brief The device interface class for the performance counters
*/
class PerfCounter : public amd::HeapObject {
public:
//! Constructor for the device performance
PerfCounter() {}
//! Get the performance counter info
virtual uint64_t getInfo(uint64_t infoType) const = 0;
//! Destructor for PerfCounter class
virtual ~PerfCounter() {}
private:
//! Disable default copy constructor
PerfCounter(const PerfCounter&);
//! Disable default operator=
PerfCounter& operator=(const PerfCounter&);
};
/*! \class ThreadTrace
*
* \brief The device interface class for the performance counters
*/
class ThreadTrace : public amd::HeapObject {
public:
//! Constructor for the device performance
ThreadTrace() {}
//! Update ThreadTrace status to true/false if new buffer was binded/unbinded respectively
virtual void setNewBufferBinded(bool) = 0;
//! Get the performance counter info
virtual bool info(uint infoType, uint* info, uint infoSize) const = 0;
//! Destructor for PerfCounter class
virtual ~ThreadTrace() {}
private:
//! Disable default copy constructor
ThreadTrace(const ThreadTrace&);
//! Disable default operator=
ThreadTrace& operator=(const ThreadTrace&);
};
//! A device execution environment.
class VirtualDevice : public amd::HeapObject {
public:
//! Construct a new virtual device for the given physical device.
VirtualDevice(amd::Device& device) : device_(device), blitMgr_(NULL) {}
//! Destroy this virtual device.
virtual ~VirtualDevice() {}
//! Prepare this virtual device for destruction.
virtual bool terminate() = 0;
//! Return the physical device for this virtual device.
const amd::Device& device() const { return device_(); }
virtual void submitReadMemory(amd::ReadMemoryCommand& cmd) = 0;
virtual void submitWriteMemory(amd::WriteMemoryCommand& cmd) = 0;
virtual void submitCopyMemory(amd::CopyMemoryCommand& cmd) = 0;
virtual void submitCopyMemoryP2P(amd::CopyMemoryP2PCommand& cmd) = 0;
virtual void submitMapMemory(amd::MapMemoryCommand& cmd) = 0;
virtual void submitUnmapMemory(amd::UnmapMemoryCommand& cmd) = 0;
virtual void submitKernel(amd::NDRangeKernelCommand& command) = 0;
virtual void submitNativeFn(amd::NativeFnCommand& cmd) = 0;
virtual void submitMarker(amd::Marker& cmd) = 0;
virtual void submitFillMemory(amd::FillMemoryCommand& cmd) = 0;
virtual void submitMigrateMemObjects(amd::MigrateMemObjectsCommand& cmd) = 0;
virtual void submitAcquireExtObjects(amd::AcquireExtObjectsCommand& cmd) = 0;
virtual void submitReleaseExtObjects(amd::ReleaseExtObjectsCommand& cmd) = 0;
virtual void submitPerfCounter(amd::PerfCounterCommand& cmd) = 0;
virtual void submitThreadTraceMemObjects(amd::ThreadTraceMemObjectsCommand& cmd) = 0;
virtual void submitThreadTrace(amd::ThreadTraceCommand& cmd) = 0;
virtual void flush(amd::Command* list = NULL, bool wait = false) = 0;
virtual void submitSvmFreeMemory(amd::SvmFreeMemoryCommand& cmd) = 0;
virtual void submitSvmCopyMemory(amd::SvmCopyMemoryCommand& cmd) = 0;
virtual void submitSvmFillMemory(amd::SvmFillMemoryCommand& cmd) = 0;
virtual void submitSvmMapMemory(amd::SvmMapMemoryCommand& cmd) = 0;
virtual void submitSvmUnmapMemory(amd::SvmUnmapMemoryCommand& cmd) = 0;
/// Optional extensions
virtual void submitSignal(amd::SignalCommand& cmd) = 0;
virtual void submitMakeBuffersResident(amd::MakeBuffersResidentCommand& cmd) = 0;
virtual void submitTransferBufferFromFile(amd::TransferBufferFileCommand& cmd) {
ShouldNotReachHere();
}
//! Get the blit manager object
device::BlitManager& blitMgr() const { return *blitMgr_; }
private:
//! Disable default copy constructor
VirtualDevice& operator=(const VirtualDevice&);
//! Disable operator=
VirtualDevice(const VirtualDevice&);
//! The physical device that this virtual device utilizes
amd::SharedReference<amd::Device> device_;
protected:
device::BlitManager* blitMgr_; //!< Blit manager
};
} // namespace device
namespace amd {
//! MemoryObject map lookup class
class MemObjMap : public AllStatic {
public:
static size_t size(); //!< obtain the size of the container
static void AddMemObj(const void* k,
amd::Memory* v); //!< add the host mem pointer and buffer in the container
static void RemoveMemObj(const void* k); //!< Remove an entry of mem object from the container
static amd::Memory* FindMemObj(
const void* k); //!< find the mem object based on the input pointer
private:
static std::map<uintptr_t, amd::Memory*> MemObjMap_; //!< the mem object<->hostptr information container
static amd::Monitor AllocatedLock_; //!< amd monitor locker
};
/*! \addtogroup Runtime
* @{
*
* \addtogroup Device Device Abstraction
* @{
*/
class Device : public RuntimeObject {
protected:
typedef aclCompiler Compiler;
public:
typedef std::list<CommandQueue*> CommandQueues;
struct BlitProgram : public amd::HeapObject {
Program* program_; //!< GPU program obejct
Context* context_; //!< A dummy context
BlitProgram(Context* context) : program_(NULL), context_(context) {}
~BlitProgram();
//! Creates blit program for this device
bool create(Device* device, //!< Device object
const char* extraKernel = NULL, //!< Extra kernels from the device layer
const char* extraOptions = NULL //!< Extra compilation options
);
};
virtual Compiler* compiler() const = 0;
virtual Compiler* binCompiler() const { return compiler(); }
Device();
virtual ~Device();
//! Initializes abstraction layer device object
bool create();
uint retain() {
// Overwrite the RuntimeObject::retain().
// There is an issue in the old SHOC11_DeviceMemory test on TC
return 0u;
}
uint release() {
// Overwrite the RuntimeObject::release().
// There is an issue in the old SHOC11_DeviceMemory test on TC
return 0u;
}
//! Register a device as available
void registerDevice();
//! Initialize the device layer (enumerate known devices)
static bool init();
//! Shutdown the device layer
static void tearDown();
static std::vector<Device*> getDevices(cl_device_type type, //!< Device type
bool offlineDevices //!< Enable offline devices
);
static size_t numDevices(cl_device_type type, //!< Device type
bool offlineDevices //!< Enable offline devices
);
static bool getDeviceIDs(cl_device_type deviceType, //!< Device type
cl_uint numEntries, //!< Number of entries in the array
cl_device_id* devices, //!< Array of the device ID(s)
cl_uint* numDevices, //!< Number of available devices
bool offlineDevices //!< Report offline devices
);
const device::Info& info() const { return info_; }
//! Return svm support capability.
bool svmSupport() const {
return (info().svmCapabilities_ &
(CL_DEVICE_SVM_COARSE_GRAIN_BUFFER | CL_DEVICE_SVM_FINE_GRAIN_BUFFER |
CL_DEVICE_SVM_FINE_GRAIN_SYSTEM)) != 0
? true
: false;
}
//! check svm FGS support capability.
inline bool isFineGrainedSystem(bool FGSOPT = false) const {
return FGSOPT && (info().svmCapabilities_ & CL_DEVICE_SVM_FINE_GRAIN_SYSTEM) != 0 ? true
: false;
}
//! Return this device's type.
cl_device_type type() const { return info().type_ & ~(CL_DEVICE_TYPE_DEFAULT); }
//! Create a new virtual device environment.
virtual device::VirtualDevice* createVirtualDevice(CommandQueue* queue = NULL) = 0;
//! Create a program for device.
virtual device::Program* createProgram(option::Options* options = NULL) = 0;
//! Allocate a chunk of device memory as a cache for a CL memory object
virtual device::Memory* createMemory(Memory& owner) const = 0;
//! Allocate a device sampler object
virtual bool createSampler(const Sampler&, device::Sampler**) const = 0;
//! Allocates a view object from the device memory
virtual device::Memory* createView(
amd::Memory& owner, //!< Owner memory object
const device::Memory& parent //!< Parent device memory object for the view
) const = 0;
//! Return true if initialized external API interop, otherwise false
virtual bool bindExternalDevice(
uint flags, //!< Enum val. for ext.API type: GL, D3D10, etc.
void* const pDevice[], //!< D3D device do D3D, HDC/Display handle of X Window for GL
void* pContext, //!< HGLRC/GLXContext handle
bool validateOnly //! Only validate if the device can inter-operate with pDevice/pContext, do
//! not bind.
) = 0;
virtual bool unbindExternalDevice(
uint flags, //!< Enum val. for ext.API type: GL, D3D10, etc.
void* const pDevice[], //!< D3D device do D3D, HDC/Display handle of X Window for GL
void* pContext, //!< HGLRC/GLXContext handle
bool validateOnly //! Only validate if the device can inter-operate with pDevice/pContext, do
//! not bind.
) = 0;
//! resolves GL depth/msaa buffer
virtual bool resolveGLMemory(device::Memory*) const { return true; }
//! Gets free memory on a GPU device
virtual bool globalFreeMemory(size_t* freeMemory //!< Free memory information on a GPU device
) const = 0;
/**
* @return True if the device has its own custom host allocator to be used
* instead of the generic OS allocation routines
*/
bool customHostAllocator() const { return settings().customHostAllocator_ == 1; }
/**
* @copydoc amd::Context::hostAlloc
*/
virtual void* hostAlloc(size_t size, size_t alignment, bool atomics = false) const {
ShouldNotCallThis();
return NULL;
}
/**
* @copydoc amd::Context::hostFree
*/
virtual void hostFree(void* ptr, size_t size = 0) const { ShouldNotCallThis(); }
/**
* @copydoc amd::Context::svmAlloc
*/
virtual void* svmAlloc(Context& context, size_t size, size_t alignment, cl_svm_mem_flags flags,
void* svmPtr) const = 0;
/**
* @copydoc amd::Context::svmFree
*/
virtual void svmFree(void* ptr) const = 0;
//! Validate kernel
virtual bool validateKernel(const amd::Kernel& kernel, const device::VirtualDevice* vdev) {
return true;
};
//! Returns TRUE if the device is available for computations
bool isOnline() const { return online_; }
//! Returns device settings
const device::Settings& settings() const { return *settings_; }
//! Returns blit program info structure
BlitProgram* blitProgram() const { return blitProgram_; }
//! RTTI internal implementation
virtual ObjectType objectType() const { return ObjectTypeDevice; }
//! Returns app profile
static const AppProfile* appProfile() { return &appProfile_; }
//! Register a hardware debugger manager
HwDebugManager* hwDebugMgr() const { return hwDebugMgr_; }
//! Initialize the Hardware Debug Manager
virtual cl_int hwDebugManagerInit(amd::Context* context, uintptr_t messageStorage) {
return CL_SUCCESS;
}
//! Remove the Hardware Debug Manager
virtual void hwDebugManagerRemove() {}
//! Adds GPU memory to the VA cache list
void addVACache(device::Memory* memory) const;
//! Removes GPU memory from the VA cache list
void removeVACache(const device::Memory* memory) const;
//! Finds GPU memory from virtual address
device::Memory* findMemoryFromVA(const void* ptr, size_t* offset) const;
static std::vector<Device*>& devices() { return *devices_; }
// P2P devices that are accessible from the current device
std::vector<cl_device_id> p2pDevices_;
#if defined(WITH_LIGHTNING_COMPILER)
amd::CacheCompilation* cacheCompilation() const { return cacheCompilation_.get(); }
#endif
protected:
//! Enable the specified extension
char* getExtensionString();
device::Info info_; //!< Device info structure
device::Settings* settings_; //!< Device settings
bool online_; //!< The device in online
BlitProgram* blitProgram_; //!< Blit program info
static AppProfile appProfile_; //!< application profile
HwDebugManager* hwDebugMgr_; //!< Hardware Debug manager
#if defined(WITH_LIGHTNING_COMPILER)
//! Compilation with cache support
std::unique_ptr<amd::CacheCompilation> cacheCompilation_;
#endif
private:
bool IsTypeMatching(cl_device_type type, bool offlineDevices);
#if defined(WITH_HSA_DEVICE)
static AppProfile* rocAppProfile_;
#endif
static std::vector<Device*>* devices_; //!< All known devices
Monitor* vaCacheAccess_; //!< Lock to serialize VA caching access
std::map<uintptr_t, device::Memory*>* vaCacheMap_; //!< VA cache map
};
#if defined(WITH_LIGHTNING_COMPILER)
//! Compilation process with cache support.
class CacheCompilation : public amd::HeapObject {
public:
enum COMPILER_OPERATION { LINK_LLVM_BITCODES = 0, COMPILE_TO_LLVM, COMPILE_AND_LINK_EXEC };
//! Constructor
CacheCompilation(std::string targetStr, std::string postfix, bool enableCache, bool resetCache);
//! NB, the cacheOpt argument is used for specifying the operation
//! condition, normally would be the same as the options argument.
//! However, the cacheOpt argument should not include any option
//! that would be modified each time but not affect the operation,
//! e.g. output file name.
//! Link LLVM bitcode
bool linkLLVMBitcode(amd::opencl_driver::Compiler* C,
std::vector<amd::opencl_driver::Data*>& inputs,
amd::opencl_driver::Buffer* output, std::vector<std::string>& options,
std::string& buildLog);
//! Compile to LLVM bitcode
bool compileToLLVMBitcode(amd::opencl_driver::Compiler* C,
std::vector<amd::opencl_driver::Data*>& inputs,
amd::opencl_driver::Buffer* output, std::vector<std::string>& options,
std::string& buildLog);
//! Compile and link executable
bool compileAndLinkExecutable(amd::opencl_driver::Compiler* C,
std::vector<amd::opencl_driver::Data*>& inputs,
amd::opencl_driver::Buffer* output,
std::vector<std::string>& options, std::string& buildLog);
private:
StringCache codeCache_; //! Cached codes
const bool isCodeCacheEnabled_; //! Code cache enable
};
#endif // defined(WITH_LIGHTNING_COMPILER)
/*! @}
* @}
*/
} // namespace amd
#endif /*DEVICE_HPP_*/