initial commit

This commit is contained in:
foreman
2014-07-04 16:17:05 -04:00
parent dc4af184c7
commit 3694ab2ce8
351 changed files with 113713 additions and 1 deletions
@@ -0,0 +1,98 @@
//
// Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
//
#include "top.hpp"
#include "utils/debug.hpp"
#include "device/appprofile.hpp"
#include "device/gpu/gpuappprofile.hpp"
namespace gpu {
AppProfile::AppProfile():amd::AppProfile(),
enableHighPerformanceState_(IS_LINUX ? false : true),
reportAsOCL12Device_(false)
{
propertyDatatypeMap_.insert(DatatypeMap::value_type("HighPerfState",
DataType_Boolean));
boolPropertyMap_.insert(BoolMap::value_type("HighPerfState",
&enableHighPerformanceState_));
propertyDatatypeMap_.insert(DatatypeMap::value_type("OCL12Device",
DataType_Boolean));
boolPropertyMap_.insert(BoolMap::value_type("OCL12Device",
&reportAsOCL12Device_));
}
bool AppProfile::ParseApplicationProfile()
{
amd::ADL *adl = new amd::ADL;
if (!adl->init()) {
delete adl;
return false;
}
int result = ADL_ERR_NOT_INIT;
ADLApplicationProfile *pProfile = NULL;
//
// Apply blb configurations
//
result = adl->adl2ApplicationProfilesProfileOfApplicationx2Search(adl->adlContext(),
wsAppFileName_.c_str(),
NULL,
NULL,
L"OCL",
&pProfile);
delete adl;
if (pProfile == NULL) {
return false;
}
PropertyRecord *firstProperty = pProfile->record;
PropertyRecord *profileProperty = NULL;
uint32_t valueOffset = 0;
for (int index = 0; index < pProfile->iCount; index++) {
profileProperty = reinterpret_cast<PropertyRecord*>
((reinterpret_cast<char*>(firstProperty)) + valueOffset);
//
// Get property name
//
char* propertyName = profileProperty->strName;
DatatypeMap::const_iterator propertyDatatypeMapIt =
propertyDatatypeMap_.find(std::string(propertyName));
if (propertyDatatypeMapIt == propertyDatatypeMap_.end())
{
valueOffset += (sizeof(PropertyRecord) + profileProperty->iDataSize - 4);
continue; // unexpected name.
}
DataTypes dataType = propertyDatatypeMapIt->second;
switch(dataType) {
case DataType_Boolean:
{
unsigned char propertyValue = profileProperty->uData[0];
BoolMap::iterator boolPropertyMapIt =
boolPropertyMap_.find(std::string(propertyName));
if (boolPropertyMapIt != boolPropertyMap_.end()) {
*(boolPropertyMapIt->second) = propertyValue ? true : false;
}
}
break;
default:
break;
}
valueOffset += (sizeof(PropertyRecord) + profileProperty->iDataSize - 4);
}
free(pProfile);
pProfile = NULL;
return true;
}
}
@@ -0,0 +1,44 @@
//
// Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUAPPPROFILE_HPP_
#define GPUAPPPROFILE_HPP_
#include <string>
#include <map>
namespace gpu {
class AppProfile : public amd::AppProfile
{
public:
AppProfile();
//! return the value of enableHighPerformanceState_
bool enableHighPerformanceState() const {return enableHighPerformanceState_; }
bool reportAsOCL12Device() const {return reportAsOCL12Device_; }
protected:
//! parse application profile based on application file name
virtual bool ParseApplicationProfile();
private:
typedef enum DataTypesEnum
{
DataType_Unknown = 0,
DataType_Boolean,
} DataTypes;
typedef std::map<std::string, DataTypes> DatatypeMap;
typedef std::map<std::string, bool*> BoolMap;
DatatypeMap propertyDatatypeMap_;
BoolMap boolPropertyMap_;
bool enableHighPerformanceState_;
bool reportAsOCL12Device_;
};
}
#endif
+548
View File
@@ -0,0 +1,548 @@
//
// Copyright (c) 2009 Advanced Micro Devices, Inc. All rights reserved.
//
#include "device/gpu/gpubinary.hpp"
#include "device/gpu/gpuprogram.hpp"
#include "utils/options.hpp"
#include "os/os.hpp"
#include <string>
#include <sstream>
namespace {
enum {
NDX_KERNEL = 0,
NDX_METADATA = 1,
NDX_HEADER = 2,
NDX_AMDIL = 3,
NDX_LAST
};
typedef struct {
bool IsKernel; // whether the entry is for kernel
/*
SymInfo[NDX_KERNEL] : SymbolInfo for kernel isa (cal image)
SymInfo[NDX_METADATA] : SymbolInfo for kernel metadata
SymInfo[NDX_HEADER] : SymbolInfo for kernel header
SymInfo[NDX_AMDIL] : SymbolInfo for kernel's amdil
*/
amd::OclElf::SymbolInfo SymInfo[NDX_LAST];
} ElfSymbol_t;
}
namespace gpu {
bool
ClBinary::loadKernels(NullProgram& program, bool* hasRecompiled)
{
const char __OpenCL_[] = "__OpenCL_";
const char _kernel[] = "_kernel";
const char _data[] = "_metadata"; // metadata for kernel function
const char _fdata[] = "_fmetadata"; // metadata for non-kernel function
const char _header[] = "_header";
const char _amdil[] = "_amdil";
*hasRecompiled = false;
// TODO : jugu
// Target should be 15 bit maximum. Should check this somewhere.
uint32_t target = static_cast<uint32_t>(dev().calTarget());
uint16_t elf_target;
amd::OclElf::oclElfPlatform platform;
if (!elfIn()->getTarget(elf_target, platform)) {
LogError("The OCL binary image loading failed: incorrect format");
return false;
}
if (platform == amd::OclElf::COMPLIB_PLATFORM) {
// BIF 3.0
uint32_t flag;
aclTargetInfo tgtInfo = aclGetTargetInfo("amdil", dev().hwInfo()->targetName_, NULL);
if (!elfIn()->getFlags(flag)){
LogError("The OCL binary image loading failed: incorrect format");
return false;
}
if ((elf_target != EM_AMDIL) ||
(tgtInfo.chip_id != flag)) {
LogError("The OCL binary image loading failed: different target");
return false;
}
}
else {
if (((platform != amd::OclElf::CAL_PLATFORM) ||
((uint32_t)target != elf_target))) {
LogError("The OCL binary image loading failed: different target");
return false;
}
}
/* Using class so that dtor() can be invoked to do clean-up */
class TempWrapper {
public:
/*
functionNameMap[] maps from a function name (linkage name in the generated code)
to ElfSymbol_t, which is defined as above.
*/
std::map<std::string, ElfSymbol_t*> functionNameMap;
// Keep all kernel ILs if -use-debugil is present (gpu debugging)
std::map<std::string, std::string> kernelILs;
~TempWrapper () {
std::map<std::string, ElfSymbol_t*>::iterator
I, IB = functionNameMap.begin(), IE = functionNameMap.end();
for (I = IB; I != IE; ++I) {
delete [] (*I).second;
}
kernelILs.clear();
}
} tempObj;
/*
If usedebugil is true, we will load IL from .debugil section. We will ignore
_kernel, _amdil, _header in the binary.
*/
bool usedebugil = program.getCompilerOptions()->oVariables->UseDebugIL;
for (amd::Sym_Handle sym = elfIn()->nextSymbol(NULL);
sym != NULL;
sym = elfIn()->nextSymbol(sym)) {
amd::OclElf::SymbolInfo symInfo;
if (!elfIn()->getSymbolInfo(sym, &symInfo)) {
LogError("LoadKernelFromElf: getSymbolInfo() fails");
return false;
}
std::string elfSymName(symInfo.sym_name);
const size_t offset = sizeof(__OpenCL_) - 1;
if (elfSymName.compare(0, offset, __OpenCL_) != 0) {
continue;
}
// Assume this elfSymName is associated with a kernel name. The following code will adjust
// it if it isn't.
const size_t suffixPos = elfSymName.rfind('_');
bool isKernel = true; // assume it is a kernel
std::string FName = elfSymName.substr(0, suffixPos);
FName.append("_kernel"); // make the kernel's linkage name
ElfSymbol_t* elfsymbol = tempObj.functionNameMap[FName];
amd::OclElf::SymbolInfo* sinfo = (elfsymbol != NULL) ? &(elfsymbol->SymInfo[0]) : NULL;
// Add info for this elf symbol into tempobj's functionNameMap[]
int index = -1;
if (!usedebugil &&
(elfSymName.compare(suffixPos, sizeof(_kernel) - 1, _kernel) == 0)) {
index = NDX_KERNEL;
assert (((sinfo == NULL) || (sinfo[index].size == 0)) &&
"More than one kernel symbol for the same kernel");
}
else if (!usedebugil &&
(elfSymName.compare(suffixPos, sizeof(_header) - 1, _header) == 0)) {
index = NDX_HEADER;
assert (((sinfo == NULL) || (sinfo[index].size == 0)) &&
"More than one header symbol for a kernel");
}
else if (!usedebugil &&
(elfSymName.compare(suffixPos, sizeof(_amdil) - 1, _amdil) == 0)) {
index = NDX_AMDIL;
assert (((sinfo == NULL) || (sinfo[index].size == 0)) &&
"More than one amdil symbol for a kernel");
}
else if (elfSymName.compare(suffixPos, sizeof(_data) - 1, _data) == 0) {
index = NDX_METADATA;
assert (((sinfo == NULL) || (sinfo[index].size == 0)) &&
"More than one metadata symbol for the same kernel");
}
else if (elfSymName.compare(suffixPos, sizeof(_fdata) - 1, _fdata) == 0) {
index = NDX_METADATA;
isKernel = false;
FName = elfSymName.substr(offset, suffixPos - offset);
elfsymbol = tempObj.functionNameMap[FName];
sinfo = (elfsymbol != NULL) ? &(elfsymbol->SymInfo[0]) : NULL;
assert (((sinfo == NULL) || (sinfo[index].size == 0)) &&
"More than one metadata symbol for a non-kernel function");
}
if (index >= 0) {
if (elfsymbol == NULL) {
elfsymbol = new ElfSymbol_t();
sinfo = &(elfsymbol->SymInfo[0]);
::memset(sinfo, 0, NDX_LAST * sizeof(amd::OclElf::SymbolInfo));
tempObj.functionNameMap[FName] = elfsymbol;
elfsymbol->IsKernel = isKernel;
}
sinfo[index] = symInfo;
}
}
if (usedebugil) {
std::string programil;
char *section;
size_t sz;
if (elfIn_->getSection(amd::OclElf::ILDEBUG, &section, &sz)) {
// Get debugIL
programil.append(section, sz);
}
else {
LogError("LoadKernelFromElf(): reading .debugil failed");
return false;
}
// Append all function metadata to debugIL
std::map<std::string, ElfSymbol_t*>::iterator
I, IB = tempObj.functionNameMap.begin(), IE = tempObj.functionNameMap.end();
for (I = IB; I != IE; ++I) {
ElfSymbol_t* elfsymbol = (*I).second;
if (elfsymbol == NULL) {
// Not valid, skip
continue;
}
if ( (elfsymbol->SymInfo[NDX_METADATA].address != 0) &&
(elfsymbol->SymInfo[NDX_METADATA].size > 0) ) {
std::string mdString = std::string(elfsymbol->SymInfo[NDX_METADATA].address,
elfsymbol->SymInfo[NDX_METADATA].size);
assert ((mdString.find_first_of('\0') == std::string::npos) &&
"Metadata string has NULL inside !");
programil.append(mdString);
}
}
const char* ilKernelName =
program.getCompilerOptions()->oVariables->JustKernel;
if (!program.getAllKernelILs(tempObj.kernelILs, programil, ilKernelName)) {
LogError("LoadKernelFromElf(): MDParser failed generating kernel ILs");
return false;
}
// Now, patch the IL from debugIL into functionNameMap[]
std::map<std::string, std::string>::iterator
KI, KIB = tempObj.kernelILs.begin(), KIE = tempObj.kernelILs.end();
for (KI = KIB; KI != KIE; ++KI) {
const std::string& kn = (*KI).first;
const std::string& ilstr = (*KI).second;
ElfSymbol_t* elfsymbol = tempObj.functionNameMap[kn];
if (elfsymbol == NULL) {
elfsymbol = new ElfSymbol_t();
::memset(elfsymbol->SymInfo, 0, NDX_LAST * sizeof(amd::OclElf::SymbolInfo));
tempObj.functionNameMap[kn] = elfsymbol;
}
amd::OclElf::SymbolInfo* sinfo = &(elfsymbol->SymInfo[0]);
elfsymbol->IsKernel = true;
sinfo[NDX_AMDIL].address = const_cast<char*>(ilstr.data());
sinfo[NDX_AMDIL].size = ilstr.size();
// All the other fields in SymInfo is unused
}
}
bool recompiled = false;
bool hasKernels = false;
std::map<std::string, ElfSymbol_t*>::iterator
I, IB = tempObj.functionNameMap.begin(), IE = tempObj.functionNameMap.end();
for (I = IB; I != IE; ++I) {
ElfSymbol_t* elfsymbol = (*I).second;
if (elfsymbol == NULL) {
// Not valid, skip
continue;
}
else if (!elfsymbol->IsKernel) {
// Not a kernel. Add its metadata to the OCL binary in case recompilation happens
// and the new binary is needed.
if (saveAMDIL()&&
(elfsymbol->SymInfo[NDX_METADATA].size > 0)) {
std::string fmetadata = "__OpenCL_";
fmetadata.append((*I).first);
fmetadata.append("_fmetadata");
if (!elfOut()->addSymbol(amd::OclElf::RODATA, fmetadata.c_str(),
elfsymbol->SymInfo[NDX_METADATA].address,
elfsymbol->SymInfo[NDX_METADATA].size)) {
LogError ("AddSymbol() failed to add fmetadata");
return false;
}
}
continue;
}
amd::OclElf::SymbolInfo* sinfo = &(elfsymbol->SymInfo[0]);
std::string FName = (*I).first;
// For this kernel, get the demangled kernel name, which is used to identify each kernel.
const size_t name_sz = FName.size() - (sizeof(_kernel) - 1) - (sizeof(__OpenCL_) - 1);
std::string demangledKName = FName.substr(sizeof(__OpenCL_) - 1, name_sz);
// Check if the current entry is valid
if (((sinfo[NDX_HEADER].size <= 0) || (sinfo[NDX_KERNEL].size <= 0)) &&
(sinfo[NDX_AMDIL].size <= 0)) {
std::string tlog = "Warning: both IL and CAL Image are not available for kernel " +
demangledKName;
LogWarning (tlog.c_str());
continue;
}
hasKernels = true;
Kernel::InitData initData = {0};
std::string ilSource(sinfo[NDX_AMDIL].address, sinfo[NDX_AMDIL].size);
std::string metadata(sinfo[NDX_METADATA].address, sinfo[NDX_METADATA].size);
if ((sinfo[NDX_HEADER].size <= 0) || (sinfo[NDX_KERNEL].size <= 0)) {
// IL recompilation
// TODO: global data recompilation as well.
// 1) parse IL; 2) parse metadata to set up kernel header
size_t pos;
if (!program.findAllILFuncs(ilSource, pos)) {
program.freeAllILFuncs();
return false;
}
bool isFailed = false;
for (uint32_t i=0; i < program.funcs_.size(); ++i) {
ILFunc *func = program.funcs_[i];
ElfSymbol_t *sym = tempObj.functionNameMap[func->name_];
if (sym == NULL) {
// No metadata for this function.
continue;
}
assert ((func->metadata_.end_ == 0) && "ILFunc init failed");
amd::OclElf::SymbolInfo* si = &(sym->SymInfo[0]);
if (si[NDX_METADATA].size > 0) {
std::string meta(si[NDX_METADATA].address, si[NDX_METADATA].size);
if (!program.parseFuncMetadata(meta, 0, std::string::npos)) {
isFailed = true;
break;
}
if (func->metadata_.end_ != std::string::npos) {
assert( false && "ILFunc name and index does not match");
isFailed = true;
break;
}
// Accumulate all emulated local, region and private sizes,
// necessary for the kernel execution
initData.localSize_ += func->localSize_;
initData.privateSize_ += func->privateSize_;
// Accumulate all HW local, region and private sizes,
// necessary for the kernel execution
initData.hwLocalSize_ += func->hwLocalSize_;
initData.hwPrivateSize_ += func->hwPrivateSize_;
initData.flags_ |= func->flags_;
}
}
program.freeAllILFuncs();
if (isFailed) {
return false;
}
}
else {
KernelHeaderSymbol kHeader = {0};
::memcpy(&kHeader, sinfo[NDX_HEADER].address,
(sizeof(kHeader) < sinfo[NDX_HEADER].size)
? sizeof(kHeader)
: sinfo[NDX_HEADER].size);
if (kHeader.version_ > VERSION_CURRENT) {
LogError("LoadKernelFromElf: cannot handle the newer version of the binary");
return false;
}
// VERSION_0
initData.localSize_ = kHeader.localSize_;
initData.hwLocalSize_ = kHeader.hwLocalSize_;
initData.privateSize_ = kHeader.privateSize_;
initData.hwPrivateSize_ = kHeader.hwPrivateSize_;
initData.flags_ = kHeader.flags_;
}
bool created;
NullKernel* gpuKernel = program.createKernel(demangledKName, &initData, ilSource, metadata,
&created, sinfo[NDX_KERNEL].address, sinfo[NDX_KERNEL].size);
if (!created) {
std::string tlog = "Error: Creating kernel during loading OCL binary " +
demangledKName + " failed!";
LogError(tlog.c_str());
return false;
}
recompiled = recompiled || (sinfo[NDX_KERNEL].size == 0);
// Add the current kernel to the OCL binary in case recompilation happens and
// the new binary is needed.
if (!storeKernel(demangledKName, gpuKernel, &initData, metadata, ilSource)) {
return false;
}
}
*hasRecompiled = recompiled;
return hasKernels;
}
bool
ClBinary::storeKernel(
const std::string& name,
const NullKernel* nullKernel,
Kernel::InitData* initData,
const std::string& metadata,
const std::string& ilSource)
{
if (!saveISA() && !saveAMDIL()) {
return true;
}
// should we save kernel metadata only under saveAMDIL()?
bool kernelMetaStored = false;
if (saveAMDIL() && (ilSource.size() > 0)) {
// Save IL (this is the per-kernel IL)
std::string ilName = "__OpenCL_" + name + "_amdil";
if (!elfOut()->addSymbol(amd::OclElf::ILTEXT, ilName.c_str(),
ilSource.data(), ilSource.size())) {
LogError ("AddElfSymbol failed");
return false;
}
std::string metaName = "__OpenCL_" + name + "_metadata";
// Save metadata symbols in .rodata
if (!elfOut()->addSymbol(amd::OclElf::RODATA, metaName.c_str(),
metadata.data(), metadata.size())) {
LogError ("AddElfSymbol failed");
return false;
}
kernelMetaStored = true;
}
if (!saveISA()) {
return true;
}
size_t binarySize = (nullKernel != NULL) ? nullKernel->getCalBinarySize() : 0;
if (binarySize != 0) {
if (!kernelMetaStored) {
std::string metaName = "__OpenCL_" + name + "_metadata";
// Save metadata symbols in .rodata
if (!elfOut()->addSymbol(amd::OclElf::RODATA, metaName.c_str(),
metadata.data(), metadata.size())) {
LogError ("AddSymbol failed");
return false;
}
}
// Save kernel symbol that is associated with GPU ISA
std::string kernelName = "__OpenCL_" + name + "_kernel";
uint8_t* isacode = new uint8_t[binarySize];
if (!nullKernel->getCalBinary(
reinterpret_cast<void*>(isacode), binarySize)) {
LogError("Failed to read GPU kernel isa");
delete [] isacode;
return false;
}
if (!elfOut()->addSymbol(amd::OclElf::CAL, kernelName.c_str(),
isacode, binarySize)) {
LogError ("AddElfSymbol failed");
return false;
}
delete [] isacode;
// Save kernel header information into a pseudo symbol
// __OpenCL_<kernelName>_header
// for example, given a kernel foo, this pseudo symbol
// would be __OpenCL_foo_header
std::string headerName = "__OpenCL_" + name + "_header";
KernelHeaderSymbol kHeader;
// VERSION_0
kHeader.privateSize_ = initData->privateSize_;
kHeader.localSize_ = initData->localSize_;
kHeader.regionSize_ = 0;
kHeader.hwPrivateSize_ = initData->hwPrivateSize_;
kHeader.hwLocalSize_ = initData->hwLocalSize_;
kHeader.hwRegionSize_ = 0;
kHeader.flags_ = initData->flags_;
// VERSION_1
kHeader.version_ = VERSION_CURRENT;
if (!elfOut()->addSymbol(amd::OclElf::RODATA, headerName.c_str(),
&kHeader, sizeof(kHeader))) {
LogError("AddElfSymbol failed");
return false;
}
}
return true;
}
bool
ClBinary::loadGlobalData(Program& program)
{
const char __OpenCL_[] = "__OpenCL_";
const char _global[] = "_global";
for (amd::Sym_Handle sym = elfIn()->nextSymbol(NULL);
sym != NULL;
sym = elfIn()->nextSymbol(sym)) {
amd::OclElf::SymbolInfo symInfo;
if (!elfIn()->getSymbolInfo(sym, &symInfo)) {
LogError("LoadGlobalDataFromElf: getSymbolInfo() fails");
return false;
}
std::string globalName(symInfo.sym_name);
const size_t offset = sizeof(__OpenCL_) - 1;
if (globalName.compare(0, offset, __OpenCL_) != 0) {
continue;
}
const size_t suffixPos = globalName.rfind('_');
if (globalName.compare(suffixPos, sizeof(_global) - 1, _global) != 0) {
continue;
}
// Get index for this global
std::string indexString = globalName.substr(offset, suffixPos - offset);
uint index = ::atoi(indexString.c_str());
if (!program.allocGlobalData(symInfo.address, symInfo.size, index)) {
LogError("Couldn't load global data");
return false;
}
}
return true;
}
bool
ClBinary::storeGlobalData(const void* globalData, size_t dataSize, uint index)
{
// For each global, use "__OpenCL_<globalname>" as its name
// Since there is no name in amdil, just use "__OpenCL_<index>_global" for now.
std::stringstream glbName;
glbName << "__OpenCL_" << index << "_global";
if (!elfOut()->addSymbol(amd::OclElf::RODATA, glbName.str().c_str(),
globalData, dataSize)) {
LogError("addSymbol() failed");
return false;
}
return true;
}
bool
ClBinary::clearElfOut()
{
// Recreate libelf elf object
if (!elfOut()->Clear()) {
return false;
}
// Need to re-setup target
return setElfTarget();
}
} // namespace gpu
+143
View File
@@ -0,0 +1,143 @@
//
// Copyright (c) 2009 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUBINARY_HPP_
#define GPUBINARY_HPP_
#include "top.hpp"
#include "device/gpu/gpudevice.hpp"
#include "device/gpu/gpukernel.hpp"
namespace gpu {
class ClBinary : public device::ClBinary
{
public:
#pragma pack(push, 8)
// Kernel version in the ELF header symbol
enum KernelVersions {
VERSION_0 = 0,
VERSION_1,
VERSION_CURRENT = VERSION_1
};
/* This is the ELF header symbol */
struct KernelHeaderSymbol {
/* VERSION_0
Version 0 has 8 uint32_t (32 bytes), top 5 are used, the rest zero'ed.
In Version_0, KernelHeaderSymbol is the same as KernelHeader
*/
uint32_t privateSize_; //!< Emulated private memory size
uint32_t localSize_; //!< Emulated local memory size
uint32_t hwPrivateSize_; //!< HW private memory size
uint32_t hwLocalSize_; //!< HW local memory size
uint32_t flags_; //!< Kernel's flags
/* VERSION_1
VERSION_1 has 6 uint32_t.
*/
uint32_t version_; //!< Kernel's version
uint32_t regionSize_; //!< Region memory size
uint32_t hwRegionSize_; //!< HW region memory size
/* New entries can be added here, do not change the previous entries */
};
#pragma pack(pop)
//! Constructor
ClBinary(const NullDevice& dev)
: device::ClBinary(dev)
{}
//! Destructor
~ClBinary() {}
//! Creates and loads kernels from the OCL ELF binary file into the program
bool loadKernels(
NullProgram& program, //!< Program object with the binary
bool* hasRecompiled //!< Recompile amdil to isa.
);
//! Stores compiled kernel into the OCL ELF binary file
bool storeKernel(
const std::string& name, //!< Kernel's name
const NullKernel* nullKernel, //!< The kernel to add
Kernel::InitData* initData, //!< Kernel init data
const std::string& metadata, //!< Kernel's metadata
const std::string& ilSource //!< IL source text
);
//! Loads the program's global data
bool loadGlobalData(
Program& program //!< The program object for the global data load
);
//! Stores the program's global data
bool storeGlobalData(
const void* globalData, //!< The program global data
size_t dataSize, //!< The program global data size
uint index //!< The global data storage index
);
//! Set elf header information for GPU target
bool setElfTarget() {
uint32_t target = static_cast<uint32_t>(dev().calTarget());
assert (((0xFFFF8000 & target) == 0) && "ASIC target ID >= 2^15");
uint16_t elf_target = (uint16_t)(0x7FFF & target);
return elfOut()->setTarget(elf_target, amd::OclElf::CAL_PLATFORM);
}
//! Clear elf out.
bool clearElfOut();
private:
//! Disable default copy constructor
ClBinary(const ClBinary&);
//! Disable default operator=
ClBinary& operator=(const ClBinary&);
//! Returns the GPU device for this object
const NullDevice& dev() const { return static_cast<const NullDevice&>(dev_); }
};
class ClBinaryHsa : public device::ClBinary
{
public:
ClBinaryHsa(const Device& dev, BinaryImageFormat bifVer = BIF_VERSION3)
: device::ClBinary(dev, bifVer)
{}
//! Destructor
~ClBinaryHsa() {}
protected:
bool setElfTarget() {
uint32_t target = static_cast<uint32_t>(21);//dev().calTarget());
assert (((0xFFFF8000 & target) == 0) && "ASIC target ID >= 2^15");
uint16_t elf_target = (uint16_t)(0x7FFF & target);
return elfOut()->setTarget(elf_target, amd::OclElf::CAL_PLATFORM);
return true;
}
private:
//! Disable default copy constructor
ClBinaryHsa(const ClBinaryHsa&);
//! Disable default operator=
ClBinaryHsa& operator=(const ClBinaryHsa&);
//! Returns the HSA device for this object
const Device& dev() const { return static_cast<const Device&>(dev_); }
};
} // namespace gpu
#endif // GPUBINARY_HPP_
File diff suppressed because it is too large Load Diff
+453
View File
@@ -0,0 +1,453 @@
//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUBLIT_HPP_
#define GPUBLIT_HPP_
#include "top.hpp"
#include "platform/command.hpp"
#include "device/gpu/gpudefs.hpp"
#include "device/device.hpp"
#include "device/blit.hpp"
/*! \addtogroup GPU Blit Implementation
* @{
*/
//! GPU Blit Manager Implementation
namespace gpu {
class Device;
class Kernel;
class Resource;
class Memory;
class VirtualGPU;
//! DMA Blit Manager
class DmaBlitManager : public device::HostBlitManager
{
public:
//! Constructor
DmaBlitManager(
VirtualGPU& gpu, //!< Virtual GPU to be used for blits
Setup setup = Setup() //!< Specifies HW accelerated blits
);
//! Destructor
virtual ~DmaBlitManager() {}
//! Creates DmaBlitManager object
virtual bool create(amd::Device& device) { return true; }
//! Copies a buffer object to system memory
virtual bool readBuffer(
device::Memory& srcMemory, //!< Source memory object
void* dstHost, //!< Destination host memory
const amd::Coord3D& origin, //!< Source origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies a buffer object to system memory
virtual bool readBufferRect(
device::Memory& srcMemory, //!< Source memory object
void* dstHost, //!< Destinaiton host memory
const amd::BufferRect& bufRect, //!< Source rectangle
const amd::BufferRect& hostRect, //!< Destination rectangle
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies an image object to system memory
virtual bool readImage(
device::Memory& srcMemory, //!< Source memory object
void* dstHost, //!< Destination host memory
const amd::Coord3D& origin, //!< Source origin
const amd::Coord3D& size, //!< Size of the copy region
size_t rowPitch, //!< Row pitch for host memory
size_t slicePitch, //!< Slice pitch for host memory
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies system memory to a buffer object
virtual bool writeBuffer(
const void* srcHost, //!< Source host memory
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& origin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies system memory to a buffer object
virtual bool writeBufferRect(
const void* srcHost, //!< Source host memory
device::Memory& dstMemory, //!< Destination memory object
const amd::BufferRect& hostRect, //!< Destination rectangle
const amd::BufferRect& bufRect, //!< Source rectangle
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies system memory to an image object
virtual bool writeImage(
const void* srcHost, //!< Source host memory
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& origin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
size_t rowPitch, //!< Row pitch for host memory
size_t slicePitch, //!< Slice pitch for host memory
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies a buffer object to another buffer object
virtual bool copyBuffer(
device::Memory& srcMemory, //!< Source memory object
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& srcOrigin, //!< Source origin
const amd::Coord3D& dstOrigin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies a buffer object to another buffer object
virtual bool copyBufferRect(
device::Memory& srcMemory, //!< Source memory object
device::Memory& dstMemory, //!< Destination memory object
const amd::BufferRect& srcRect, //!< Source rectangle
const amd::BufferRect& dstRect, //!< Destination rectangle
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies an image object to a buffer object
virtual bool copyImageToBuffer(
device::Memory& srcMemory, //!< Source memory object
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& srcOrigin, //!< Source origin
const amd::Coord3D& dstOrigin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false, //!< Entire buffer will be updated
size_t rowPitch = 0, //!< Pitch for buffer
size_t slicePitch = 0 //!< Slice for buffer
) const;
//! Copies a buffer object to an image object
virtual bool copyBufferToImage(
device::Memory& srcMemory, //!< Source memory object
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& srcOrigin, //!< Source origin
const amd::Coord3D& dstOrigin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false, //!< Entire buffer will be updated
size_t rowPitch = 0, //!< Pitch for buffer
size_t slicePitch = 0 //!< Slice for buffer
) const;
//! Copies an image object to another image object
virtual bool copyImage(
device::Memory& srcMemory, //!< Source memory object
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& srcOrigin, //!< Source origin
const amd::Coord3D& dstOrigin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
protected:
const static uint MaxPinnedBuffers = 4;
//! Synchronizes the blit operations if necessary
inline void synchronize() const;
//! Returns the virtual GPU object
VirtualGPU& gpu() const { return static_cast<VirtualGPU&>(vDev_); }
//! Returns the GPU device object
const Device& dev() const { return static_cast<const Device&>(dev_); };
inline Memory& gpuMem(device::Memory& mem) const;
const size_t MinSizeForPinnedTransfer;
bool completeOperation_; //!< DMA blit manager must complete operation
private:
//! Disable copy constructor
DmaBlitManager(const DmaBlitManager&);
//! Disable operator=
DmaBlitManager& operator=(const DmaBlitManager&);
//! Reads video memory, using a staged buffer
bool readMemoryStaged(
Resource& srcMemory, //!< Source memory object
void* dstHost, //!< Destination host memory
Resource** xferBuf, //!< Staged buffer for read
size_t origin, //!< Original offset in the source memory
size_t& offset, //!< Offset for the current copy pointer
size_t& totalSize, //!< Total size for copy region
size_t xferSize //!< Transfer size
) const;
//! Write into video memory, using a staged buffer
bool writeMemoryStaged(
const void* srcHost, //!< Source host memory
Resource& dstMemory, //!< Destination memory object
Resource& xferBuf, //!< Staged buffer for write
size_t origin, //!< Original offset in the destination memory
size_t& offset, //!< Offset for the current copy pointer
size_t& totalSize, //!< Total size for the copy region
size_t xferSize //!< Transfer size
) const;
};
//! Kernel Blit Manager
class KernelBlitManager : public DmaBlitManager
{
public:
enum {
BlitCopyImage = 0,
BlitCopyImage1DA,
BlitCopyImageToBuffer,
BlitCopyBufferToImage,
BlitCopyBufferRect,
BlitCopyBufferRectAligned,
BlitCopyBuffer,
BlitCopyBufferAligned,
FillBuffer,
FillImage,
Scheduler,
BlitTotal
};
//! Constructor
KernelBlitManager(
VirtualGPU& gpu, //!< Virtual GPU to be used for blits
Setup setup = Setup() //!< Specifies HW accelerated blits
);
//! Destructor
virtual ~KernelBlitManager();
//! Creates DmaBlitManager object
virtual bool create(amd::Device& device);
//! Copies a buffer object to another buffer object
virtual bool copyBufferRect(
device::Memory& srcMemory, //!< Source memory object
device::Memory& dstMemory, //!< Destination memory object
const amd::BufferRect& srcRectIn, //!< Source rectangle
const amd::BufferRect& dstRectIn, //!< Destination rectangle
const amd::Coord3D& sizeIn, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies a buffer object to system memory
virtual bool readBuffer(
device::Memory& srcMemory, //!< Source memory object
void* dstHost, //!< Destination host memory
const amd::Coord3D& origin, //!< Source origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies a buffer object to system memory
virtual bool readBufferRect(
device::Memory& srcMemory, //!< Source memory object
void* dstHost, //!< Destinaiton host memory
const amd::BufferRect& bufRect, //!< Source rectangle
const amd::BufferRect& hostRect, //!< Destination rectangle
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies system memory to a buffer object
virtual bool writeBuffer(
const void* srcHost, //!< Source host memory
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& origin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies system memory to a buffer object
virtual bool writeBufferRect(
const void* srcHost, //!< Source host memory
device::Memory& dstMemory, //!< Destination memory object
const amd::BufferRect& hostRect, //!< Destination rectangle
const amd::BufferRect& bufRect, //!< Source rectangle
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies a buffer object to an image object
virtual bool copyBuffer(
device::Memory& srcMemory, //!< Source memory object
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& srcOrigin, //!< Source origin
const amd::Coord3D& dstOrigin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies a buffer object to an image object
virtual bool copyBufferToImage(
device::Memory& srcMemory, //!< Source memory object
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& srcOrigin, //!< Source origin
const amd::Coord3D& dstOrigin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false, //!< Entire buffer will be updated
size_t rowPitch = 0, //!< Pitch for buffer
size_t slicePitch = 0 //!< Slice for buffer
) const;
//! Copies an image object to a buffer object
virtual bool copyImageToBuffer(
device::Memory& srcMemory, //!< Source memory object
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& srcOrigin, //!< Source origin
const amd::Coord3D& dstOrigin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false, //!< Entire buffer will be updated
size_t rowPitch = 0, //!< Pitch for buffer
size_t slicePitch = 0 //!< Slice for buffer
) const;
//! Copies an image object to another image object
virtual bool copyImage(
device::Memory& srcMemory, //!< Source memory object
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& srcOrigin, //!< Source origin
const amd::Coord3D& dstOrigin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies an image object to system memory
virtual bool readImage(
device::Memory& srcMemory, //!< Source memory object
void* dstHost, //!< Destination host memory
const amd::Coord3D& origin, //!< Source origin
const amd::Coord3D& size, //!< Size of the copy region
size_t rowPitch, //!< Row pitch for host memory
size_t slicePitch, //!< Slice pitch for host memory
bool entire = false //!< Entire buffer will be updated
) const;
//! Copies system memory to an image object
virtual bool writeImage(
const void* srcHost, //!< Source host memory
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& origin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
size_t rowPitch, //!< Row pitch for host memory
size_t slicePitch, //!< Slice pitch for host memory
bool entire = false //!< Entire buffer will be updated
) const;
//! Fills a buffer memory with a pattern data
virtual bool fillBuffer(
device::Memory& memory, //!< Memory object to fill with pattern
const void* pattern, //!< Pattern data
size_t patternSize, //!< Pattern size
const amd::Coord3D& origin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Fills an image memory with a pattern data
virtual bool fillImage(
device::Memory& dstMemory, //!< Memory object to fill with pattern
const void* pattern, //!< Pattern data
const amd::Coord3D& origin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false //!< Entire buffer will be updated
) const;
//! Fills an image memory with a pattern data
virtual bool runScheduler(
device::Memory& vqueue, //!< Memory object for virtual queue
device::Memory& params, //!< Extra arguments for the scheduler
uint paramIdx, //!< Parameter index
uint numSlots //!< Number of slots in the queue
) const;
private:
static const size_t MaxXferBuffers = 2;
//! Copies a buffer object to an image object
bool copyBufferToImageKernel(
device::Memory& srcMemory, //!< Source memory object
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& srcOrigin, //!< Source origin
const amd::Coord3D& dstOrigin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false, //!< Entire buffer will be updated
size_t rowPitch = 0, //!< Pitch for buffer
size_t slicePitch = 0 //!< Slice for buffer
) const;
//! Copies an image object to a buffer object
bool copyImageToBufferKernel(
device::Memory& srcMemory, //!< Source memory object
device::Memory& dstMemory, //!< Destination memory object
const amd::Coord3D& srcOrigin, //!< Source origin
const amd::Coord3D& dstOrigin, //!< Destination origin
const amd::Coord3D& size, //!< Size of the copy region
bool entire = false, //!< Entire buffer will be updated
size_t rowPitch = 0, //!< Pitch for buffer
size_t slicePitch = 0 //!< Slice for buffer
) const;
//! Creates a program for all blit operations
bool createProgram(
Device& device //!< Device object
);
//! Pins host memory for GPU access
amd::Memory* pinHostMemory(
const void* hostMem, //!< Host memory pointer
size_t pinSize, //!< Host memory size
size_t& partial //!< Extra offset for memory alignment
) const;
//! Creates a view memory object
Memory* createView(
const Memory& parent, //!< Parent memory object
const CalFormat& format //!< The new format for a view
) const;
//! Disable copy constructor
KernelBlitManager(const KernelBlitManager&);
//! Disable operator=
KernelBlitManager& operator=(const KernelBlitManager&);
amd::Program* program_; //!< GPU program obejct
amd::Kernel* kernels_[BlitTotal]; //!< GPU kernels for blit
amd::Context* context_; //!< A dummy context
amd::Memory* constantBuffer_; //!< An internal CB for blits
amd::Memory* xferBuffers_[MaxXferBuffers]; //!< Transfer buffers for images
size_t xferBufferSize_; //!< Transfer buffer size
amd::Monitor* lockXferOps_; //!< Lock transfer operation
};
static const char* BlitName[KernelBlitManager::BlitTotal] = {
"copyImage",
"copyImage1DA",
"copyImageToBuffer",
"copyBufferToImage",
"copyBufferRect",
"copyBufferRectAligned",
"copyBuffer",
"copyBufferAligned",
"fillBuffer",
"fillImage",
"scheduler",
};
/*@}*/} // namespace gpu
#endif /*GPUBLIT_HPP_*/
+450
View File
@@ -0,0 +1,450 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include "os/os.hpp"
#include "device/gpu/gpudevice.hpp"
#include "device/gpu/gpuprogram.hpp"
#include "device/gpu/gpukernel.hpp"
#include "utils/options.hpp"
#include <cstdio>
//CLC_IN_PROCESS_CHANGE
extern int openclFrontEnd(const char* cmdline, std::string*, std::string* typeInfo = NULL);
namespace gpu {
static int programsCount = 0;
bool
NullProgram::compileImpl(const std::string& src,
const std::vector<const std::string*>& headers,
const char** headerIncludeNames,
amd::option::Options* options)
{
std::string sourceCode = src;
if (dev().settings().debugFlags_ & Settings::CheckForILSource) {
size_t inc = sourceCode.find("il_cs_", 0);
if (inc != std::string::npos) {
// CL program is an IL program
ilProgram_ = sourceCode;
return true;
}
}
std::string tempFolder = amd::Os::getTempPath();
std::string tempFileName = amd::Os::getTempFileName();
if (dev().settings().debugFlags_ & Settings::StubCLPrograms) {
std::stringstream fileName;
std::fstream stubRead;
// Dump the IL function
fileName << "program_" << programsCount++ << ".cl";
stubRead.open(fileName.str().c_str(), (std::fstream::in | std::fstream::binary));
// Check if we have OpenCL program
if (stubRead.is_open()) {
// Find the stream size
stubRead.seekg(0, std::fstream::end);
size_t size = stubRead.tellg();
stubRead.seekg(0, std::ios::beg);
char* data = new char[size];
stubRead.read(data, size);
stubRead.close();
sourceCode.assign(data, size);
delete[] data;
}
else {
std::fstream stubWrite;
stubWrite.open(fileName.str().c_str(),
(std::fstream::out | std::fstream::binary));
stubWrite << sourceCode;
stubWrite.close();
}
}
std::fstream f;
std::vector<std::string> headerFileNames(headers.size());
std::vector<std::string> newDirs;
for (size_t i = 0; i < headers.size(); ++i) {
std::string headerPath = tempFolder;
std::string headerIncludeName(headerIncludeNames[i]);
// replace / in path with current os's file separator
if ( amd::Os::fileSeparator() != '/') {
for (std::string::iterator it = headerIncludeName.begin(),
end = headerIncludeName.end();
it != end;
++it) {
if (*it == '/') *it = amd::Os::fileSeparator();
}
}
size_t pos = headerIncludeName.rfind(amd::Os::fileSeparator());
if (pos != std::string::npos) {
headerPath += amd::Os::fileSeparator();
headerPath += headerIncludeName.substr(0, pos);
headerIncludeName = headerIncludeName.substr(pos+1);
}
if (!amd::Os::pathExists(headerPath)) {
bool ret = amd::Os::createPath(headerPath);
assert(ret && "failed creating path!");
newDirs.push_back(headerPath);
}
std::string headerFullName
= headerPath + amd::Os::fileSeparator() + headerIncludeName;
headerFileNames[i] = headerFullName;
f.open(headerFullName.c_str(), std::fstream::out);
assert(!f.fail() && "failed creating header file!");
f.write(headers[i]->c_str(), headers[i]->length());
f.close();
}
acl_error err;
const aclTargetInfo& targInfo = info();
aclBinaryOptions binOpts = {0};
binOpts.struct_size = sizeof(binOpts);
binOpts.elfclass = targInfo.arch_id == aclAMDIL64 ? ELFCLASS64 : ELFCLASS32;
binOpts.bitness = ELFDATA2LSB;
binOpts.alloc = &::malloc;
binOpts.dealloc = &::free;
aclBinary* bin
= aclBinaryInit(sizeof(aclBinary), &targInfo, &binOpts, &err);
if (err != ACL_SUCCESS) {
LogWarning("aclBinaryInit failed");
return false;
}
if (ACL_SUCCESS != aclInsertSection(dev().compiler(), bin,
sourceCode.c_str(), sourceCode.size(), aclSOURCE)) {
LogWarning("aclInsertSection failed");
aclBinaryFini(bin);
return false;
}
// temporary solution to synchronize buildNo between runtime and complib
// until we move runtime inside complib
((amd::option::Options*)bin->options)->setBuildNo(options->getBuildNo());
std::stringstream opts;
std::string token;
opts << options->origOptionStr.c_str();
if (options->origOptionStr.find("-cl-std=CL") == std::string::npos) {
switch(dev().settings().oclVersion_) {
case OpenCL10: opts << " -cl-std=CL1.0"; break;
case OpenCL11: opts << " -cl-std=CL1.1"; break;
case OpenCL20: default:
case OpenCL12: opts << " -cl-std=CL1.2"; break;
}
}
// FIXME: Should we prefix everything with -Wf,?
std::istringstream iss(options->clcOptions);
while (getline(iss, token, ' ')) {
if (!token.empty()) {
// Check if this is a -D option
if (token.compare("-D") == 0) {
// It is, skip payload
getline(iss, token, ' ');
continue;
}
opts << " -Wf," << token;
}
}
if (!headers.empty()) {
opts << " -I" << tempFolder;
}
if (!dev().settings().imageSupport_) {
opts << " -fno-image-support";
}
if (dev().settings().reportFMAF_) {
opts << " -mfast-fmaf";
}
if (dev().settings().reportFMA_) {
opts << " -mfast-fma";
}
iss.clear();
iss.str(device().info().extensions_);
while (getline(iss, token, ' ')) {
if (!token.empty()) {
opts << " -D" << token << "=1";
}
}
std::string newOpt = opts.str();
size_t pos = newOpt.find("-fno-bin-llvmir");
while (pos != std::string::npos) {
newOpt.erase(pos, 15);
pos = newOpt.find("-fno-bin-llvmir");
}
err = aclCompile(dev().compiler(), bin, newOpt.c_str(),
ACL_TYPE_OPENCL, ACL_TYPE_LLVMIR_BINARY, NULL);
buildLog_ += aclGetCompilerLog(dev().compiler());
if (err != ACL_SUCCESS) {
LogWarning("aclCompile failed");
aclBinaryFini(bin);
return false;
}
size_t len = 0;
const void* ir = aclExtractSection(dev().compiler(), bin,
&len, aclLLVMIR, &err);
if (err != ACL_SUCCESS) {
LogWarning("aclExtractSection failed");
aclBinaryFini(bin);
return false;
}
llvmBinary_.assign(reinterpret_cast<const char*>(ir), len);
llvmBinaryIsSpir_ = false;
aclBinaryFini(bin);
for (size_t i = 0; i < headerFileNames.size(); ++i) {
amd::Os::unlink(headerFileNames[i].c_str());
}
for (size_t i = 0; i < newDirs.size(); ++i) {
amd::Os::removePath(newDirs[i]);
}
#ifdef _WIN32
amd::Os::unlink(tempFileName);
#endif
if (clBinary()->saveSOURCE()) {
clBinary()->elfOut()->addSection(
amd::OclElf::SOURCE, sourceCode.data(), sourceCode.size());
}
if (clBinary()->saveLLVMIR()) {
clBinary()->elfOut()->addSection(
amd::OclElf::LLVMIR, llvmBinary_.data(), llvmBinary_.size(), false);
// store the original compile options
clBinary()->storeCompileOptions(compileOptions_);
}
return true;
}
int
NullProgram::compileBinaryToIL(amd::option::Options* options)
{
acl_error err;
const aclTargetInfo& targInfo = info();
aclBinaryOptions binOpts = {0};
binOpts.struct_size = sizeof(binOpts);
binOpts.elfclass = targInfo.arch_id == aclAMDIL64 ? ELFCLASS64 : ELFCLASS32;
binOpts.bitness = ELFDATA2LSB;
binOpts.alloc = &::malloc;
binOpts.dealloc = &::free;
aclBinary* bin
= aclBinaryInit(sizeof(aclBinary), &targInfo, &binOpts, &err);
if (err != ACL_SUCCESS) {
LogWarning("aclBinaryInit failed");
return CL_BUILD_PROGRAM_FAILURE;
}
bool spirFlag = std::string::npos != options->clcOptions.find("--spir")
|| llvmBinaryIsSpir_;
if (ACL_SUCCESS != aclInsertSection(dev().compiler(), bin,
llvmBinary_.data(), llvmBinary_.size(),
spirFlag ? aclSPIR : aclLLVMIR)) {
LogWarning("aclInsertSection failed");
aclBinaryFini(bin);
return CL_BUILD_PROGRAM_FAILURE;
}
// pass kernel argument alignment info to compiler lib through option str
std::string optionStr = options->origOptionStr;
if (options->origOptionStr.find("kernel-arg-alignment")
== std::string::npos) {
char s[256];
sprintf(s, " -Wb,-kernel-arg-alignment=%d",
dev().info().memBaseAddrAlign_ / 8);
optionStr += s;
}
// temporary solution to synchronize buildNo between runtime and complib
// until we move runtime inside complib
((amd::option::Options*)bin->options)->setBuildNo(options->getBuildNo());
aclType type = ACL_TYPE_CG ;
// If option bin-bif30 is set, generate BIF 3.0 binary
if (options->oVariables->BinBIF30) {
type = ACL_TYPE_ISA;
}
err = aclCompile(dev().compiler(), bin, optionStr.c_str(),
spirFlag ? ACL_TYPE_SPIR_BINARY : ACL_TYPE_LLVMIR_BINARY,
type, NULL);
buildLog_ += aclGetCompilerLog(dev().compiler());
if (err != ACL_SUCCESS) {
LogWarning("aclCompile failed");
aclBinaryFini(bin);
return CL_BUILD_PROGRAM_FAILURE;
}
if (options->oVariables->BinBIF30) {
if (!createBIFBinary(bin)) {
aclBinaryFini(bin);
return CL_BUILD_PROGRAM_FAILURE;
}
}
size_t len = 0;
const void* amdil = aclExtractSection(dev().compiler(), bin,
&len, aclCODEGEN, &err);
if (err != ACL_SUCCESS) {
LogWarning("aclExtractSection failed");
aclBinaryFini(bin);
return CL_BUILD_PROGRAM_FAILURE;
}
ilProgram_.assign(reinterpret_cast<const char*>(amdil), len);
aclBinaryFini(bin);
return CL_SUCCESS;
}
bool
HSAILProgram::compileImpl(
const std::string& sourceCode,
const std::vector<const std::string*>& headers,
const char** headerIncludeNames,
amd::option::Options* options)
{
acl_error errorCode;
aclTargetInfo target;
std::string arch = "hsail";
if (dev().settings().use64BitPtr_) {
arch += "-64";
}
target = aclGetTargetInfo(arch.c_str(),
dev().info().name_, &errorCode);
// end if asic info is ready
// We dump the source code for each program (param: headers)
// into their filenames (headerIncludeNames) into the TEMP
// folder specific to the OS and add the include path while
// compiling
// Find the temp folder for the OS
std::string tempFolder = amd::Os::getTempPath();
std::string tempFileName = amd::Os::getTempFileName();
// Iterate through each source code and dump it into tmp
std::fstream f;
std::vector<std::string> headerFileNames(headers.size());
std::vector<std::string> newDirs;
for (size_t i = 0; i < headers.size(); ++i) {
std::string headerPath = tempFolder;
std::string headerIncludeName(headerIncludeNames[i]);
// replace / in path with current os's file separator
if (amd::Os::fileSeparator() != '/') {
for (std::string::iterator it = headerIncludeName.begin(),
end = headerIncludeName.end(); it != end; ++it) {
if (*it == '/') *it = amd::Os::fileSeparator();
}
}
size_t pos = headerIncludeName.rfind(amd::Os::fileSeparator());
if (pos != std::string::npos) {
headerPath += amd::Os::fileSeparator();
headerPath += headerIncludeName.substr(0, pos);
headerIncludeName = headerIncludeName.substr(pos+1);
}
if (!amd::Os::pathExists(headerPath)) {
bool ret = amd::Os::createPath(headerPath);
assert(ret && "failed creating path!");
newDirs.push_back(headerPath);
}
std::string headerFullName =
headerPath + amd::Os::fileSeparator() + headerIncludeName;
headerFileNames[i] = headerFullName;
f.open(headerFullName.c_str(), std::fstream::out);
// Should we allow asserts
assert(!f.fail() && "failed creating header file!");
f.write(headers[i]->c_str(), headers[i]->length());
f.close();
}
// Create Binary
binaryElf_ = aclBinaryInit(sizeof(aclBinary),
&target, &binOpts_, &errorCode);
if (errorCode != ACL_SUCCESS) {
buildLog_ += "Error: aclBinary init failure\n";
LogWarning("aclBinaryInit failed");
return false;
}
// Insert opencl into binary
errorCode = aclInsertSection(dev().hsaCompiler(), binaryElf_,
sourceCode.c_str(), strlen(sourceCode.c_str()), aclSOURCE);
if (errorCode != ACL_SUCCESS) {
buildLog_ += "Error: Inserting openCl Source to binary\n";
}
// Set the options for the compiler
// Set the include path for the temp folder that contains the includes
if (!headers.empty()) {
compileOptions_.append(" -I");
compileOptions_.append(tempFolder);
}
//Add only for CL2.0 and above
if (options->oVariables->CLStd[2] >= '2') {
std::stringstream opts;
opts << " -D" << "CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE="
<< device().info().maxGlobalVariableSize_;
compileOptions_.append(opts.str());
}
#if !defined(_LP64)
if (options->origOptionStr.find("-cl-std=CL2.0") != std::string::npos && !dev().settings().force32BitOcl20_) {
errorCode = ACL_UNSUPPORTED;
LogWarning("aclCompile failed");
return false;
}
#endif
// Compile source to IR
compileOptions_.append(hsailOptions());
errorCode = aclCompile(dev().hsaCompiler(), binaryElf_, compileOptions_.c_str(),
ACL_TYPE_OPENCL, ACL_TYPE_LLVMIR_BINARY, NULL);
buildLog_ += aclGetCompilerLog(dev().hsaCompiler());
if (errorCode != ACL_SUCCESS) {
LogWarning("aclCompile failed");
buildLog_ += "Error: Compiling CL to IR\n";
return false;
}
// Save the binary in the interface class
size_t size = 0;
void* mem = NULL;
aclWriteToMem(binaryElf_, &mem, &size);
setBinary(static_cast<char*>(mem), size);
// Save the binary inside the program
// The FSAILProgram will be responsible to free it during destruction
rawBinary_ = mem;
return true;
}
} // namespace gpu
+89
View File
@@ -0,0 +1,89 @@
//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//
#include "device/gpu/gpuconstbuf.hpp"
#include "device/gpu/gpuvirtual.hpp"
#include "device/gpu/gpudevice.hpp"
#include "device/gpu/gpusettings.hpp"
namespace gpu {
ConstBuffer::ConstBuffer(
VirtualGPU& gpu,
size_t size)
: Resource(const_cast<gpu::Device&>(gpu.dev()), size, CM_SURF_FMT_RGBA32F)
, gpu_(gpu)
, size_(size * VectorSize)
, wrtOffset_(0)
, lastWrtSize_(0)
, wrtAddress_(NULL)
{
}
ConstBuffer::~ConstBuffer()
{
if (wrtAddress_ != NULL) {
unmap(&gpu_);
}
amd::AlignedMemory::deallocate(sysMemCopy_);
}
bool
ConstBuffer::create()
{
// Create sysmem copy for the constant buffer
sysMemCopy_ = reinterpret_cast<address>(amd::AlignedMemory::allocate(size_, 256));
if (sysMemCopy_ == NULL) {
LogPrintfError("We couldn't allocate sysmem copy for constant buffer,\
size(%d)!", size_);
return false;
}
memset(sysMemCopy_, 0, size_);
if (!Resource::create(Resource::RemoteUSWC)) {
LogPrintfError("We couldn't create HW constant buffer, size(%d)!", size_);
return false;
}
// Constant buffer warm-up
warmUpRenames(gpu_);
wrtAddress_ = map(&gpu_, Resource::Discard);
if (wrtAddress_ == NULL) {
LogPrintfError("We couldn't map HW constant buffer, size(%d)!", size_);
return false;
}
return true;
}
bool
ConstBuffer::uploadDataToHw(size_t size)
{
static const size_t HwCbAlignment = 256;
// Align copy size on the vector's boundary
size_t count = amd::alignUp(size, VectorSize);
wrtOffset_ += lastWrtSize_;
// Check if CB has enough space for copy
if ((wrtOffset_ + count) > size_) {
if (wrtAddress_ != NULL) {
unmap(&gpu_);
}
wrtAddress_ = map(&gpu_, Resource::Discard);
wrtOffset_ = 0;
lastWrtSize_ = 0;
}
// Update memory with new CB data
memcpy((reinterpret_cast<char*>(wrtAddress_) + wrtOffset_), sysMemCopy_, count);
// Adjust the size by the HW CB buffer alignment
lastWrtSize_ = amd::alignUp(size, HwCbAlignment);
return true;
}
} // namespace gpu
+70
View File
@@ -0,0 +1,70 @@
//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUCONSTBUF_HPP_
#define GPUCONSTBUF_HPP_
#include "device/gpu/gpuresource.hpp"
//! \namespace gpu GPU Resource Implementation
namespace gpu {
//! Cconstant buffer
class ConstBuffer : public Resource
{
public:
//! Vector size of the constant buffer
static const size_t VectorSize = 16;
//! Constructor for the ConstBuffer class
ConstBuffer(
VirtualGPU& gpu, //!< Virtual GPU device object
size_t size //!< size of the constant buffer in vectors
);
//! Destructor for the ConstBuffer class
~ConstBuffer();
//! Creates the real HW constant buffer
bool create();
/*! \brief Uploads current constant buffer data from sysMemCopy_ to HW
*
* \return True if the data upload was succesful
*/
bool uploadDataToHw(
size_t size //!< real data size for upload
);
//! Returns a pointer to the system memory copy for CB
address sysMemCopy() const { return sysMemCopy_; }
//! Returns CB size
size_t size() const { return size_; }
//! Returns current write offset for the constant buffer
size_t wrtOffset() const { return wrtOffset_; }
//! Returns last write size for the constant buffer
size_t lastWrtSize() const { return lastWrtSize_; }
private:
//! Disable copy constructor
ConstBuffer(const ConstBuffer&);
//! Disable operator=
ConstBuffer& operator=(const ConstBuffer&);
VirtualGPU& gpu_; //!< Virtual GPU object
address sysMemCopy_; //!< System memory copy
size_t size_; //!< Constant buffer size
size_t wrtOffset_; //!< Current write offset
size_t lastWrtSize_; //!< Last write size
void* wrtAddress_; //!< Write address in CB
};
/*@}*/} // namespace gpu
#endif /*GPUCONSTBUF_HPP_*/
+87
View File
@@ -0,0 +1,87 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include "device/gpu/gpudefs.hpp"
#include "device/gpu/gpucounters.hpp"
#include "device/gpu/gpuvirtual.hpp"
namespace gpu {
CalCounterReference::~CalCounterReference() {
// The counter object is always associated with a particular queue,
// so we have to lock just this queue
amd::ScopedLock lock(gpu_.execution());
if (0 != counter_) {
gpu().destroyCounter(gslCounter());
}
}
bool
CalCounterReference::growResultArray(uint index) {
if (results_ != NULL) {
delete [] results_;
}
results_ = new uint64_t [index + 1];
if (results_ == NULL) {
return false;
}
return true;
}
PerfCounter::~PerfCounter()
{
if (calRef_ == NULL) {
return;
}
// Release the counter reference object
calRef_->release();
}
bool
PerfCounter::create(
CalCounterReference* calRef)
{
assert(&gpu() == &calRef->gpu());
calRef_ = calRef;
counter_ = calRef->gslCounter();
index_ = calRef->retain() - 2;
calRef->growResultArray(index_);
// Initialize the counter
gpu().configPerformanceCounter(gslCounter(),
info()->blockIndex_, info()->counterIndex_, info()->eventIndex_);
return true;
}
uint64_t
PerfCounter::getInfo(uint64_t infoType) const
{
switch (infoType) {
case CL_PERFCOUNTER_GPU_BLOCK_INDEX: {
// Return the GPU block index
return info()->blockIndex_;
}
case CL_PERFCOUNTER_GPU_COUNTER_INDEX: {
// Return the GPU counter index
return info()->counterIndex_;
}
case CL_PERFCOUNTER_GPU_EVENT_INDEX: {
// Return the GPU event index
return info()->eventIndex_;
}
case CL_PERFCOUNTER_DATA: {
gpu().getCounter(reinterpret_cast<uint64*>(calRef_->results()), gslCounter());
return calRef_->results()[index_];
}
default:
LogError("Wrong PerfCounter::getInfo parameter");
}
return 0;
}
} // namespace gpu
+140
View File
@@ -0,0 +1,140 @@
//
// Copyright (c) 2009 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUCOUNTERS_HPP_
#define GPUCOUNTERS_HPP_
#include "top.hpp"
#include "device/device.hpp"
#include "device/gpu/gpudevice.hpp"
namespace gpu {
class VirtualGPU;
class CalCounterReference : public amd::ReferenceCountedObject
{
public:
//! Default constructor
CalCounterReference(
VirtualGPU& gpu, //!< Virtual GPU device object
gslQueryObject gslCounter)
: gpu_(gpu)
, counter_(gslCounter)
, results_(NULL) {}
//! Get CAL counter
gslQueryObject gslCounter() const { return counter_; }
//! Returns the virtual GPU device
const VirtualGPU& gpu() const { return gpu_; }
//! Increases the results array for this CAL counter(container)
bool growResultArray(
uint maxIndex //!< the maximum HW counter index in the CAL counter
);
//! Returns the CAL counter results
uint64_t* results() const { return results_; }
protected:
//! Default destructor
~CalCounterReference();
private:
//! Disable copy constructor
CalCounterReference(const CalCounterReference&);
//! Disable operator=
CalCounterReference& operator=(const CalCounterReference&);
VirtualGPU& gpu_; //!< The virtual GPU device object
gslQueryObject counter_; //!< GSL object counter
uint64_t* results_; //!< CAL counter results
};
//! Performance counter implementation on GPU
class PerfCounter : public device::PerfCounter
{
public:
//! The performance counter info
struct Info : public amd::EmbeddedObject
{
uint blockIndex_; //!< Index of the block to configure
uint counterIndex_; //!< Index of the hardware counter
uint eventIndex_; //!< Event you wish to count with the counter
};
//! The PerfCounter flags
enum Flags
{
BeginIssued = 0x00000001,
EndIssued = 0x00000002,
ResultReady = 0x00000004
};
//! Constructor for the GPU PerfCounter object
PerfCounter(
const Device& device, //!< A GPU device object
const VirtualGPU& gpu, //!< Virtual GPU device object
cl_uint blockIndex, //!< HW block index
cl_uint counterIndex, //!< Counter index within the block
cl_uint eventIndex) //!< Event index for profiling
: gpuDevice_(device)
, gpu_(gpu)
, calRef_(NULL)
, flags_(0)
, counter_(0)
, index_(0)
{
info_.blockIndex_ = blockIndex;
info_.counterIndex_ = counterIndex;
info_.eventIndex_ = eventIndex;
}
//! Destructor for the GPU PerfCounter object
virtual ~PerfCounter();
//! Creates the current object
bool create(
CalCounterReference* calRef //!< Reference counter
);
//! Returns the specific information about the counter
uint64_t getInfo(
uint64_t infoType //!< The type of returned information
) const;
//! Returns the GPU device, associated with the current object
const Device& dev() const { return gpuDevice_; }
//! Returns the virtual GPU device
const VirtualGPU& gpu() const { return gpu_; }
//! Returns the CAL performance counter descriptor
const Info* info() const { return &info_; }
//! Returns the Info structure for performance counter
gslQueryObject gslCounter() const { return counter_; }
private:
//! Disable default copy constructor
PerfCounter(const PerfCounter&);
//! Disable default operator=
PerfCounter& operator=(const PerfCounter&);
const Device& gpuDevice_; //!< The backend device
const VirtualGPU& gpu_; //!< The virtual GPU device object
CalCounterReference* calRef_; //!< Reference counter
uint flags_; //!< The perfcounter object state
Info info_; //!< The info structure for perfcounter
gslQueryObject counter_; //!< GSL counter object
uint index_; //!< Counter index in the CAL container
};
} // namespace gpu
#endif // GPUCOUNTERS_HPP_
+450
View File
@@ -0,0 +1,450 @@
//
// Copyright (c) 2009 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUDEFS_HPP_
#define GPUDEFS_HPP_
#include "top.hpp"
#include "cal.h"
#include "calcl.h"
#include "gsl_types.h"
#include "gsl_config.h"
#include "gsl_vid_if.h"
#include "gsl_ctx.h"
#include "backend.h"
#include "GSLDevice.h"
#include "GSLContext.h"
extern bool getFuncInfoFromImage(CALimage image, CALfuncInfo *pFuncInfo);
/*! \addtogroup GPU
* @{
*/
//! GPU Device Implementation
namespace gpu {
//! Maximum number of the supported global atomic counters
const static uint MaxAtomicCounters = 8;
//! Maximum number of the supported samplers
const static uint MaxSamplers = 16;
//! Maximum number of supported read images
const static uint MaxReadImage = 128;
//! Maximum number of supported write images
const static uint MaxWriteImage = 8;
//! Maximum number of supported read/write images for OCL20
const static uint MaxReadWriteImage = 64;
//! Maximum number of supported constant arguments
const static uint MaxConstArguments = 8;
//! Maximum number of supported kernel UAV arguments
const static uint MaxUavArguments = 1024;
//! Maximum number of pixels for a 1D image created from a buffer
const static size_t MaxImageBufferSize = 65536;
//! Maximum number of pixels for a 1D image created from a buffer
const static size_t MaxImageArraySize = 2048;
//! Maximum number of supported constant buffers
const static uint MaxConstBuffers = MaxConstArguments + 8;
//! Maximum number of constant buffers for arguments
const static uint MaxConstBuffersArguments = 2;
//! Define offline CAL implementation
const static uint CalOfflineImpl = 0xffffffff;
//! Alignment restriciton for the pinned memory
const static size_t PinnedMemoryAlignment = 4 * Ki;
//! Reserved address space
const static cl_ulong ReservedAdressSpaceSize = static_cast<cl_ulong>(4) * Gi;
//! Defines all supported ASIC families
enum AsicFamilies {
Family7xx,
Family8xx,
FamilyTotal
};
struct AMDDeviceInfo {
uint machine_; //!< Machine target ID
const char* targetName_; //!< Target name
const char* machineTarget_; //!< Machine target
uint simdPerCU_; //!< Number of SIMDs per CU
uint simdWidth_; //!< Number of workitems processed per SIMD
uint simdInstructionWidth_; //!< Number of instructions processed per SIMD
uint memChannelBankWidth_; //!< Memory channel bank width
uint localMemSizePerCU_; //!< Local memory size per CU
uint localMemBanks_; //!< Number of banks of local memory
uint gfxipVersion_; //!< The core engine GFXIP version
};
static const AMDDeviceInfo DeviceInfo[] = {
// Machine targetName machineTarget
/* CAL_TARGET_600 */ { ED_ATI_CAL_MACHINE_R600_ISA, "", "", 0, 0, 0, 0, 0, 0, 0 },
/* CAL_TARGET_610 */ { ED_ATI_CAL_MACHINE_R610_ISA, "", "", 0, 0, 0, 0, 0, 0, 0 },
/* CAL_TARGET_630 */ { ED_ATI_CAL_MACHINE_R630_ISA, "", "", 0, 0, 0, 0, 0, 0, 0 },
/* CAL_TARGET_670 */ { ED_ATI_CAL_MACHINE_R670_ISA, "", "", 0, 0, 0, 0, 0, 0, 0 },
/* CAL_TARGET_7XX */ { ED_ATI_CAL_MACHINE_R770_ISA, "", "", 0, 0, 0, 0, 0, 0, 0 },
/* CAL_TARGET_770 */ { ED_ATI_CAL_MACHINE_R770_ISA, "", "", 0, 0, 0, 0, 0, 0, 0 },
/* CAL_TARGET_710 */ { ED_ATI_CAL_MACHINE_R710_ISA, "", "", 0, 0, 0, 0, 0, 0, 0 },
/* CAL_TARGET_730 */ { ED_ATI_CAL_MACHINE_R730_ISA, "", "", 0, 0, 0, 0, 0, 0, 0 },
/* CAL_TARGET_CYPRESS */ { ED_ATI_CAL_MACHINE_CYPRESS_ISA, "Cypress", "cypress", 1, 16, 5, 256, 32 * Ki, 32, 400 },
/* CAL_TARGET_JUNIPER */ { ED_ATI_CAL_MACHINE_JUNIPER_ISA, "Juniper", "juniper", 1, 16, 5, 256, 32 * Ki, 32, 400 },
/* CAL_TARGET_REDWOOD */ { ED_ATI_CAL_MACHINE_REDWOOD_ISA, "Redwood", "redwood", 1, 16, 5, 256, 32 * Ki, 16, 400 },
/* CAL_TARGET_CEDAR */ { ED_ATI_CAL_MACHINE_CEDAR_ISA, "Cedar", "cedar", 1, 8, 5, 256, 32 * Ki, 16, 400 },
/* CAL_TARGET_SUMO */ { ED_ATI_CAL_MACHINE_SUMO_ISA, "WinterPark", "redwood", 1, 16, 5, 256, 32 * Ki, 16, 400 },
/* CAL_TARGET_SUPERSUMO*/ { ED_ATI_CAL_MACHINE_SUPERSUMO_ISA, "BeaverCreek", "redwood", 1, 16, 5, 256, 32 * Ki, 16, 400 },
/* CAL_TARGET_WRESTLER*/ { ED_ATI_CAL_MACHINE_WRESTLER_ISA, "Loveland", "cedar", 1, 8, 5, 256, 32 * Ki, 16, 400 },
/* CAL_TARGET_CAYMAN */ { ED_ATI_CAL_MACHINE_CAYMAN_ISA, "Cayman", "cayman", 1, 16, 4, 256, 32 * Ki, 32, 500 },
/* CAL_TARGET_KAUAI */ { ED_ATI_CAL_MACHINE_KAUAI_ISA, "", "", 1, 16, 5, 256, 32 * Ki, 32, 400 },
/* CAL_TARGET_BARTS */ { ED_ATI_CAL_MACHINE_BARTS_ISA , "Barts", "barts", 1, 16, 5, 256, 32 * Ki, 32, 400 },
/* CAL_TARGET_TURKS */ { ED_ATI_CAL_MACHINE_TURKS_ISA , "Turks", "turks", 1, 16, 5, 256, 32 * Ki, 32, 400 },
/* CAL_TARGET_CAICOS */ { ED_ATI_CAL_MACHINE_CAICOS_ISA, "Caicos", "caicos", 1, 16, 5, 256, 32 * Ki, 32, 400 },
/* CAL_TARGET_TAHITI */ { ED_ATI_CAL_MACHINE_TAHITI_ISA, "Tahiti", "tahiti", 4, 16, 1, 256, 64 * Ki, 32, 600 },
/* CAL_TARGET_PITCAIRN */ { ED_ATI_CAL_MACHINE_PITCAIRN_ISA, "Pitcairn", "pitcairn", 4, 16, 1, 256, 64 * Ki, 32, 600 },
/* CAL_TARGET_CAPEVERDE */ { ED_ATI_CAL_MACHINE_CAPEVERDE_ISA, "Capeverde", "capeverde", 4, 16, 1, 256, 64 * Ki, 32, 600 },
/* CAL_TARGET_DEVASTATOR */ { ED_ATI_CAL_MACHINE_DEVASTATOR_ISA,"Devastator", "trinity", 1, 16, 4, 256, 32 * Ki, 32, 500 },
/* CAL_TARGET_SCRAPPER */ { ED_ATI_CAL_MACHINE_SCRAPPER_ISA, "Scrapper", "trinity", 1, 16, 4, 256, 32 * Ki, 32, 500 },
/* CAL_TARGET_OLAND */ { ED_ATI_CAL_MACHINE_OLAND_ISA, "Oland", "oland", 4, 16, 1, 256, 64 * Ki, 32, 600 },
/* CAL_TARGET_BONAIRE */ { ED_ATI_CAL_MACHINE_BONAIRE_ISA, "Bonaire", "bonaire", 4, 16, 1, 256, 64 * Ki, 32, 702 },
/* CAL_TARGET_SPECTRE */ { ED_ATI_CAL_MACHINE_SPECTRE_ISA, "Spectre", "spectre", 4, 16, 1, 256, 64 * Ki, 32, 701 },
/* CAL_TARGET_SPOOKY */ { ED_ATI_CAL_MACHINE_SPOOKY_ISA, "Spooky", "spooky", 4, 16, 1, 256, 64 * Ki, 32, 701 },
/* CAL_TARGET_KALINDI */ { ED_ATI_CAL_MACHINE_KALINDI_ISA, "Kalindi", "kalindi", 4, 16, 1, 256, 64 * Ki, 32, 702 },
/* CAL_TARGET_HAINAN */ { ED_ATI_CAL_MACHINE_HAINAN_ISA, "Hainan", "hainan", 4, 16, 1, 256, 64 * Ki, 32, 600 },
/* CAL_TARGET_HAWAII */ { ED_ATI_CAL_MACHINE_HAWAII_ISA, "Hawaii", "hawaii", 4, 16, 1, 256, 64 * Ki, 32, 702 },
/* CAL_TARGET_ICELAND */ { ED_ATI_CAL_MACHINE_ICELAND_ISA, "Iceland", "iceland", 4, 16, 1, 256, 64 * Ki, 32, 800 },
/* CAL_TARGET_TONGA */ { ED_ATI_CAL_MACHINE_TONGA_ISA, "Tonga", "tonga", 4, 16, 1, 256, 64 * Ki, 32, 800 },
/* CAL_TARGET_MULLINS */ { ED_ATI_CAL_MACHINE_GODAVARI_ISA, "Mullins", "mullins", 4, 16, 1, 256, 64 * Ki, 32, 702 },
/* CAL_TARGET_BERMUDA */ { ED_ATI_CAL_MACHINE_BERMUDA_ISA, "", "", 4, 16, 1, 256, 64 * Ki, 32, 800 },
/* CAL_TARGET_FIJI */ { ED_ATI_CAL_MACHINE_FIJI_ISA, "", "", 4, 16, 1, 256, 64 * Ki, 32, 800 },
/* CAL_TARGET_CARRIZO */ { ED_ATI_CAL_MACHINE_CARRIZO_ISA, "", "", 4, 16, 1, 256, 64 * Ki, 32, 800 },
};
// Supported OpenCL versions
enum OclVersion {
OpenCL10,
OpenCL11,
OpenCL12,
OpenCL20
};
struct CalFormat {
gslChannelOrder channelOrder_; //!< Texel/pixel GSL channel order
cmSurfFmt type_; //!< Texel/pixel CAL format
};
struct MemoryFormat {
cl_image_format clFormat_; //!< CL image format
CalFormat calFormat_; //!< CAL image format
};
static const MemoryFormat
MemoryFormatMap[] = {
// R
{ { CL_R, CL_UNORM_INT8 },
{ GSL_CHANNEL_ORDER_R, CM_SURF_FMT_INTENSITY8 } },
{ { CL_R, CL_UNORM_INT16 },
{ GSL_CHANNEL_ORDER_R, CM_SURF_FMT_R16 } },
{ { CL_R, CL_SNORM_INT8 },
{ GSL_CHANNEL_ORDER_R, CM_SURF_FMT_sR8 } },
{ { CL_R, CL_SNORM_INT16 },
{ GSL_CHANNEL_ORDER_R, CM_SURF_FMT_sU16 } },
{ { CL_R, CL_SIGNED_INT8 },
{ GSL_CHANNEL_ORDER_R, CM_SURF_FMT_sR8I } },
{ { CL_R, CL_SIGNED_INT16 },
{ GSL_CHANNEL_ORDER_R, CM_SURF_FMT_sR16I } },
{ { CL_R, CL_SIGNED_INT32},
{ GSL_CHANNEL_ORDER_R, CM_SURF_FMT_sR32I } },
{ { CL_R, CL_UNSIGNED_INT8 },
{ GSL_CHANNEL_ORDER_R, CM_SURF_FMT_R8I } },
{ { CL_R, CL_UNSIGNED_INT16 },
{ GSL_CHANNEL_ORDER_R, CM_SURF_FMT_R16I } },
{ { CL_R, CL_UNSIGNED_INT32},
{ GSL_CHANNEL_ORDER_R , CM_SURF_FMT_R32I } },
{ { CL_R, CL_HALF_FLOAT },
{ GSL_CHANNEL_ORDER_R, CM_SURF_FMT_R16F } },
{ { CL_R, CL_FLOAT },
{ GSL_CHANNEL_ORDER_R, CM_SURF_FMT_R32F } },
// A
{ { CL_A, CL_UNORM_INT8 },
{ GSL_CHANNEL_ORDER_A, CM_SURF_FMT_INTENSITY8 } },
{ { CL_A, CL_UNORM_INT16 },
{ GSL_CHANNEL_ORDER_A, CM_SURF_FMT_R16 } },
{ { CL_A, CL_SNORM_INT8 },
{ GSL_CHANNEL_ORDER_A, CM_SURF_FMT_sR8 } },
{ { CL_A, CL_SNORM_INT16 },
{ GSL_CHANNEL_ORDER_A, CM_SURF_FMT_sU16 } },
{ { CL_A, CL_SIGNED_INT8 },
{ GSL_CHANNEL_ORDER_A, CM_SURF_FMT_sR8I } },
{ { CL_A, CL_SIGNED_INT16 },
{ GSL_CHANNEL_ORDER_A, CM_SURF_FMT_sR16I } },
{ { CL_A, CL_SIGNED_INT32},
{ GSL_CHANNEL_ORDER_A, CM_SURF_FMT_sR32I } },
{ { CL_A, CL_UNSIGNED_INT8 },
{ GSL_CHANNEL_ORDER_A, CM_SURF_FMT_R8I } },
{ { CL_A, CL_UNSIGNED_INT16 },
{ GSL_CHANNEL_ORDER_A, CM_SURF_FMT_R16I } },
{ { CL_A, CL_UNSIGNED_INT32},
{ GSL_CHANNEL_ORDER_A , CM_SURF_FMT_R32I } },
{ { CL_A, CL_HALF_FLOAT },
{ GSL_CHANNEL_ORDER_A, CM_SURF_FMT_R16F } },
{ { CL_A, CL_FLOAT },
{ GSL_CHANNEL_ORDER_A, CM_SURF_FMT_R32F } },
// RG
{ { CL_RG, CL_UNORM_INT8 },
{ GSL_CHANNEL_ORDER_RG, CM_SURF_FMT_RG8 } },
{ { CL_RG, CL_UNORM_INT16 },
{ GSL_CHANNEL_ORDER_RG, CM_SURF_FMT_RG16 } },
{ { CL_RG, CL_SNORM_INT8 },
{ GSL_CHANNEL_ORDER_RG, CM_SURF_FMT_sRG8 } },
{ { CL_RG, CL_SNORM_INT16 },
{ GSL_CHANNEL_ORDER_RG, CM_SURF_FMT_sUV16 } },
{ { CL_RG, CL_SIGNED_INT8 },
{ GSL_CHANNEL_ORDER_RG, CM_SURF_FMT_sRG8I } },
{ { CL_RG, CL_SIGNED_INT16 },
{ GSL_CHANNEL_ORDER_RG, CM_SURF_FMT_sRG16I } },
{ { CL_RG, CL_SIGNED_INT32},
{ GSL_CHANNEL_ORDER_RG, CM_SURF_FMT_sRG32I } },
{ { CL_RG, CL_UNSIGNED_INT8 },
{ GSL_CHANNEL_ORDER_RG, CM_SURF_FMT_RG8I } },
{ { CL_RG, CL_UNSIGNED_INT16 },
{ GSL_CHANNEL_ORDER_RG, CM_SURF_FMT_RG16I } },
{ { CL_RG, CL_UNSIGNED_INT32},
{ GSL_CHANNEL_ORDER_RG , CM_SURF_FMT_RG32I } },
{ { CL_RG, CL_HALF_FLOAT },
{ GSL_CHANNEL_ORDER_RG, CM_SURF_FMT_RG16F } },
{ { CL_RG, CL_FLOAT },
{ GSL_CHANNEL_ORDER_RG, CM_SURF_FMT_RG32F } },
// RA
{ { CL_RA, CL_UNORM_INT8 },
{ GSL_CHANNEL_ORDER_RA, CM_SURF_FMT_RG8 } },
{ { CL_RA, CL_UNORM_INT16 },
{ GSL_CHANNEL_ORDER_RA, CM_SURF_FMT_RG16 } },
{ { CL_RA, CL_SNORM_INT8 },
{ GSL_CHANNEL_ORDER_RA, CM_SURF_FMT_sRG8 } },
{ { CL_RA, CL_SNORM_INT16 },
{ GSL_CHANNEL_ORDER_RA, CM_SURF_FMT_sUV16 } },
{ { CL_RA, CL_SIGNED_INT8 },
{ GSL_CHANNEL_ORDER_RA, CM_SURF_FMT_sRG8I } },
{ { CL_RA, CL_SIGNED_INT16 },
{ GSL_CHANNEL_ORDER_RA, CM_SURF_FMT_sRG16I } },
{ { CL_RA, CL_SIGNED_INT32},
{ GSL_CHANNEL_ORDER_RA, CM_SURF_FMT_sRG32I } },
{ { CL_RA, CL_UNSIGNED_INT8 },
{ GSL_CHANNEL_ORDER_RA, CM_SURF_FMT_RG8I } },
{ { CL_RA, CL_UNSIGNED_INT16 },
{ GSL_CHANNEL_ORDER_RA, CM_SURF_FMT_RG16I } },
{ { CL_RA, CL_UNSIGNED_INT32},
{ GSL_CHANNEL_ORDER_RA , CM_SURF_FMT_RG32I } },
{ { CL_RA, CL_HALF_FLOAT },
{ GSL_CHANNEL_ORDER_RA, CM_SURF_FMT_RG16F } },
{ { CL_RA, CL_FLOAT },
{ GSL_CHANNEL_ORDER_RA, CM_SURF_FMT_RG32F } },
// RGBA
{ { CL_RGBA, CL_UNORM_INT8 },
{ GSL_CHANNEL_ORDER_RGBA, CM_SURF_FMT_RGBA8 } },
{ { CL_RGBA, CL_UNORM_INT16 },
{ GSL_CHANNEL_ORDER_RGBA, CM_SURF_FMT_RGBA16 } },
{ { CL_RGBA, CL_SNORM_INT8 },
{ GSL_CHANNEL_ORDER_RGBA, CM_SURF_FMT_sRGBA8 } },
{ { CL_RGBA, CL_SNORM_INT16 },
{ GSL_CHANNEL_ORDER_RGBA, CM_SURF_FMT_sUVWQ16 } },
{ { CL_RGBA, CL_SIGNED_INT8 },
{ GSL_CHANNEL_ORDER_RGBA, CM_SURF_FMT_sRGBA8I } },
{ { CL_RGBA, CL_SIGNED_INT16 },
{ GSL_CHANNEL_ORDER_RGBA, CM_SURF_FMT_sRGBA16I } },
{ { CL_RGBA, CL_SIGNED_INT32},
{ GSL_CHANNEL_ORDER_RGBA, CM_SURF_FMT_sRGBA32I } },
{ { CL_RGBA, CL_UNSIGNED_INT8 },
{ GSL_CHANNEL_ORDER_RGBA, CM_SURF_FMT_RGBA8UI } },
{ { CL_RGBA, CL_UNSIGNED_INT16 },
{ GSL_CHANNEL_ORDER_RGBA, CM_SURF_FMT_RGBA16UI } },
{ { CL_RGBA, CL_UNSIGNED_INT32},
{ GSL_CHANNEL_ORDER_RGBA , CM_SURF_FMT_RGBA32UI } },
{ { CL_RGBA, CL_HALF_FLOAT },
{ GSL_CHANNEL_ORDER_RGBA, CM_SURF_FMT_RGBA16F } },
{ { CL_RGBA, CL_FLOAT },
{ GSL_CHANNEL_ORDER_RGBA, CM_SURF_FMT_RGBA32F } },
// ARGB
{ { CL_ARGB, CL_UNORM_INT8 },
{ GSL_CHANNEL_ORDER_ARGB, CM_SURF_FMT_RGBA8 } },
{ { CL_ARGB, CL_SNORM_INT8 },
{ GSL_CHANNEL_ORDER_ARGB, CM_SURF_FMT_sRGBA8 } },
{ { CL_ARGB, CL_SIGNED_INT8 },
{ GSL_CHANNEL_ORDER_ARGB, CM_SURF_FMT_sRGBA8I } },
{ { CL_ARGB, CL_UNSIGNED_INT8 },
{ GSL_CHANNEL_ORDER_ARGB, CM_SURF_FMT_RGBA8UI } },
// BGRA
{ { CL_BGRA, CL_UNORM_INT8 },
{ GSL_CHANNEL_ORDER_BGRA, CM_SURF_FMT_RGBA8 } },
{ { CL_BGRA, CL_SNORM_INT8 },
{ GSL_CHANNEL_ORDER_BGRA, CM_SURF_FMT_sRGBA8 } },
{ { CL_BGRA, CL_SIGNED_INT8 },
{ GSL_CHANNEL_ORDER_BGRA, CM_SURF_FMT_sRGBA8I } },
{ { CL_BGRA, CL_UNSIGNED_INT8 },
{ GSL_CHANNEL_ORDER_BGRA, CM_SURF_FMT_RGBA8UI } },
// LUMINANCE
{ {CL_LUMINANCE, CL_SNORM_INT8},
{ GSL_CHANNEL_ORDER_LUMINANCE,CM_SURF_FMT_sR8 } },
{ {CL_LUMINANCE, CL_SNORM_INT16},
{ GSL_CHANNEL_ORDER_LUMINANCE,CM_SURF_FMT_sU16 } },
{ {CL_LUMINANCE, CL_UNORM_INT8},
{ GSL_CHANNEL_ORDER_LUMINANCE,CM_SURF_FMT_INTENSITY8 } },
{ {CL_LUMINANCE, CL_UNORM_INT16},
{ GSL_CHANNEL_ORDER_LUMINANCE,CM_SURF_FMT_R16 } },
{ {CL_LUMINANCE, CL_HALF_FLOAT},
{ GSL_CHANNEL_ORDER_LUMINANCE,CM_SURF_FMT_R16F } },
{ {CL_LUMINANCE, CL_FLOAT},
{ GSL_CHANNEL_ORDER_LUMINANCE,CM_SURF_FMT_R32F } },
// INTENSITY
{ {CL_INTENSITY, CL_SNORM_INT8},
{ GSL_CHANNEL_ORDER_INTENSITY,CM_SURF_FMT_sR8 } },
{ {CL_INTENSITY, CL_SNORM_INT16},
{ GSL_CHANNEL_ORDER_INTENSITY,CM_SURF_FMT_sU16 } },
{ {CL_INTENSITY, CL_UNORM_INT8},
{ GSL_CHANNEL_ORDER_INTENSITY,CM_SURF_FMT_INTENSITY8 } },
{ {CL_INTENSITY, CL_UNORM_INT16},
{ GSL_CHANNEL_ORDER_INTENSITY,CM_SURF_FMT_R16 } },
{ {CL_INTENSITY, CL_HALF_FLOAT},
{ GSL_CHANNEL_ORDER_INTENSITY,CM_SURF_FMT_R16F } },
{ {CL_INTENSITY, CL_FLOAT},
{ GSL_CHANNEL_ORDER_INTENSITY,CM_SURF_FMT_R32F } },
// sRBGA
{ {CL_sRGBA ,CL_UNORM_INT8},
{ GSL_CHANNEL_ORDER_SRGBA, CM_SURF_FMT_RGBA8_SRGB } },
{ {CL_sRGBA ,CL_UNSIGNED_INT8}, // This is used only by blit kernel
{ GSL_CHANNEL_ORDER_SRGBA, CM_SURF_FMT_RGBA8UI } },
// sRBG
{ {CL_sRGB ,CL_UNORM_INT8},
{ GSL_CHANNEL_ORDER_SRGB, CM_SURF_FMT_RGBX8UI } },
{ {CL_sRGB ,CL_UNSIGNED_INT8}, // This is used only by blit kernel
{ GSL_CHANNEL_ORDER_SRGB, CM_SURF_FMT_RGBA8UI } },
// sRBGx
{ {CL_sRGBx ,CL_UNORM_INT8},
{ GSL_CHANNEL_ORDER_SRGBX, CM_SURF_FMT_RGBX8UI } },
{ {CL_sRGBx ,CL_UNSIGNED_INT8}, // This is used only by blit kernel
{ GSL_CHANNEL_ORDER_SRGBX, CM_SURF_FMT_RGBA8UI } },
// sBGRA
{ {CL_sBGRA ,CL_UNORM_INT8},
{ GSL_CHANNEL_ORDER_SBGRA, CM_SURF_FMT_RGBA8 } },
{ {CL_sBGRA ,CL_UNSIGNED_INT8}, // This is used only by blit kernel
{ GSL_CHANNEL_ORDER_SBGRA, CM_SURF_FMT_RGBA8UI } },
// DEPTH
{ {CL_DEPTH ,CL_FLOAT},
{GSL_CHANNEL_ORDER_REPLICATE_R ,CM_SURF_FMT_DEPTH32F}},
{ {CL_DEPTH ,CL_UNSIGNED_INT32}, // This is used only by blit kernel
{GSL_CHANNEL_ORDER_REPLICATE_R ,CM_SURF_FMT_R32I}},
{ {CL_DEPTH ,CL_UNORM_INT16},
{GSL_CHANNEL_ORDER_REPLICATE_R ,CM_SURF_FMT_DEPTH16}},
{ {CL_DEPTH ,CL_UNSIGNED_INT16}, // This is used only by blit kernel
{GSL_CHANNEL_ORDER_REPLICATE_R ,CM_SURF_FMT_R16I}},
{ {CL_DEPTH_STENCIL ,CL_UNORM_INT24},
{GSL_CHANNEL_ORDER_REPLICATE_R ,CM_SURF_FMT_DEPTH24_STEN8}},
{ {CL_DEPTH_STENCIL ,CL_FLOAT},
{GSL_CHANNEL_ORDER_REPLICATE_R ,CM_SURF_FMT_DEPTH32F_X24_STEN8}}
};
struct MemFormatStruct {
cmSurfFmt format_;
uint size_;
uint components_;
};
static const MemFormatStruct
MemoryFormatSize[] = {
{ CM_SURF_FMT_INTENSITY8, 1, 1 },/**< 1 component, normalized unsigned 8-bit integer value per component */
{ CM_SURF_FMT_RG8, 2, 2 }, /**< 2 component, normalized unsigned 8-bit integer value per component */
{ CM_SURF_FMT_RGBA8, 4, 4 }, /**< 4 component, normalized unsigned 8-bit integer value per component */
{ CM_SURF_FMT_RGBA8_SRGB, 4, 4 }, /**< 4 component, normalized unsigned 8-bit integer value per component */
{ CM_SURF_FMT_R16, 2, 1 }, /**< 1 component, normalized unsigned 16-bit integer value per component */
{ CM_SURF_FMT_RG16, 4, 2 }, /**< 2 component, normalized unsigned 16-bit integer value per component */
{ CM_SURF_FMT_RGBA16, 8, 4 }, /**< 4 component, normalized unsigned 16-bit integer value per component */
{ CM_SURF_FMT_sRGBA8, 4, 4 }, /**< 4 component, normalized signed 8-bit integer value per component */
{ CM_SURF_FMT_sU16, 2, 1 }, /**< 1 component, normalized signed 16-bit integer value per component */
{ CM_SURF_FMT_sUV16, 4, 2 }, /**< 2 component, normalized signed 16-bit integer value per component */
{ CM_SURF_FMT_sUVWQ16, 8, 4 }, /**< 4 component, normalized signed 16-bit integer value per component */
{ CM_SURF_FMT_R32F, 4, 1 }, /**< A 1 component, 32-bit float value per component */
{ CM_SURF_FMT_RG32F, 8, 2 }, /**< A 2 component, 32-bit float value per component */
{ CM_SURF_FMT_RGBA32F, 16, 4 }, /**< A 4 component, 32-bit float value per component */
{ CM_SURF_FMT_sR8, 1, 1 }, /**< 1 component, normalized signed 8-bit integer value per component */
{ CM_SURF_FMT_sRG8, 2, 2 }, /**< 2 component, normalized signed 8-bit integer value per component */
{ CM_SURF_FMT_R8I, 1, 1 }, /**< 1 component, unnormalized unsigned 8-bit integer value per component */
{ CM_SURF_FMT_RG8I, 2, 2 }, /**< 2 component, unnormalized unsigned 8-bit integer value per component */
{ CM_SURF_FMT_RGBA8UI, 4, 4 }, /**< 4 component, unnormalized unsigned 8-bit integer value per component */
{ CM_SURF_FMT_RGBX8UI, 4, 4 }, /**< 4 component, unnormalized unsigned 8-bit integer value per component */
{ CM_SURF_FMT_sR8I, 1, 1 }, /**< 1 component, unnormalized signed 8-bit integer value per component */
{ CM_SURF_FMT_sRG8I, 2, 2 }, /**< 2 component, unnormalized signed 8-bit integer value per component */
{ CM_SURF_FMT_sRGBA8I, 4, 4 }, /**< 4 component, unnormalized signed 8-bit integer value per component */
{ CM_SURF_FMT_R16I, 2, 1 }, /**< 1 component, unnormalized unsigned 16-bit integer value per component */
{ CM_SURF_FMT_RG16I, 4, 2 }, /**< 2 component, unnormalized unsigned 16-bit integer value per component */
{ CM_SURF_FMT_RGBA16UI, 8, 4 }, /**< 4 component, unnormalized unsigned 16-bit integer value per component */
{ CM_SURF_FMT_sR16I, 2, 1 }, /**< 1 component, unnormalized signed 16-bit integer value per component */
{ CM_SURF_FMT_sRG16I, 4, 2 }, /**< 2 component, unnormalized signed 16-bit integer value per component */
{ CM_SURF_FMT_sRGBA16I, 8, 4 }, /**< 4 component, unnormalized signed 16-bit integer value per component */
{ CM_SURF_FMT_R32I, 4, 1 }, /**< 1 component, unnormalized unsigned 32-bit integer value per component */
{ CM_SURF_FMT_RG32I, 8, 2 }, /**< 2 component, unnormalized unsigned 32-bit integer value per component */
{ CM_SURF_FMT_RGBA32UI, 16, 4 }, /**< 4 component, unnormalized unsigned 32-bit integer value per component */
{ CM_SURF_FMT_sR32I, 4, 1 }, /**< 1 component, unnormalized signed 32-bit integer value per component */
{ CM_SURF_FMT_sRG32I, 8, 2 }, /**< 2 component, unnormalized signed 32-bit integer value per component */
{ CM_SURF_FMT_sRGBA32I, 16, 4 }, /**< 4 component, unnormalized signed 32-bit integer value per component */
{ CM_SURF_FMT_R16F, 2, 1 }, /**< A 1 component, 16-bit float value per component */
{ CM_SURF_FMT_RG16F, 4, 2 }, /**< A 2 component, 16-bit float value per component */
{ CM_SURF_FMT_RGBA16F, 8, 4 }, /**< A 4 component, 16-bit float value per component */
{ CM_SURF_FMT_DEPTH32F, 4, 1 }, /**< A one component, 32 float value per component */
{ CM_SURF_FMT_DEPTH16 , 2, 1 }, /**< A one component, 16 unsigned int value per component */
{ CM_SURF_FMT_DEPTH24_STEN8 , 4 ,1}, /**< A one component, 32 float value per component */
{ CM_SURF_FMT_DEPTH32F_X24_STEN8 , 8 ,2} /**< depth + stencil, 64 bits per element packed as (@c XXXXXXXXXXXXXXXXXXXXXXXXSSSSSSSSDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD) */
};
__inline const MemFormatStruct&
memoryFormatSize(cmSurfFmt fmt)
{
for (uint i = 0; i < sizeof(MemoryFormatSize) / sizeof(MemFormatStruct); ++i) {
if (MemoryFormatSize[i].format_ == fmt) {
return MemoryFormatSize[i];
}
}
assert (!"Unknown GSL memory format!");
return MemoryFormatSize[0];
}
} // namespace gpu
#endif // GPUDEFS_HPP_
File diff suppressed because it is too large Load Diff
+626
View File
@@ -0,0 +1,626 @@
//
// Copyright (c) 2009 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPU_HPP_
#define GPU_HPP_
#include "top.hpp"
#include "device/device.hpp"
#include "platform/command.hpp"
#include "platform/program.hpp"
#include "platform/perfctr.hpp"
#include "platform/threadtrace.hpp"
#include "platform/memory.hpp"
#include "utils/concurrent.hpp"
#include "thread/thread.hpp"
#include "thread/monitor.hpp"
#include "device/gpu/gpuvirtual.hpp"
#include "device/gpu/gpumemory.hpp"
#include "device/gpu/gpudefs.hpp"
#include "device/gpu/gpusettings.hpp"
#include "device/gpu/gpuappprofile.hpp"
#include "acl.h"
#include "vaminterface.h"
/*! \addtogroup GPU
* @{
*/
//! GPU Device Implementation
namespace gpu {
//! A nil device object
class NullDevice : public amd::Device
{
protected:
static aclCompiler* compiler_;
static aclCompiler* hsaCompiler_;
public:
aclCompiler* compiler() const { return compiler_; }
aclCompiler* hsaCompiler() const { return hsaCompiler_; }
public:
static bool init(void);
//! Construct a new identifier
NullDevice();
//! Creates an offline device with the specified target
bool create(
CALtarget target //!< GPU device identifier
);
virtual cl_int createSubDevices(
device::CreateSubDevicesInfo& create_info,
cl_uint num_entries,
cl_device_id* devices,
cl_uint* num_devices) {
return CL_INVALID_VALUE;
}
//! Instantiate a new virtual device
virtual device::VirtualDevice* createVirtualDevice(
bool profiling,
bool interopQueue
#if cl_amd_open_video
, void* calVideoProperties = NULL
#endif // cl_amd_open_video
, uint deviceQueueSize = 0
) { return NULL; }
//! Compile the given source code.
virtual device::Program* createProgram(int oclVer = 120);
//! Just returns NULL for the dummy device
virtual device::Memory* createMemory(amd::Memory& owner) const { return NULL; }
//! Sampler object allocation
virtual bool createSampler(
const amd::Sampler& owner, //!< abstraction layer sampler object
device::Sampler** sampler //!< device sampler object
) const
{
ShouldNotReachHere();
return true;
}
//! Just returns NULL for the dummy device
virtual device::Memory* createView(
amd::Memory& owner, //!< Owner memory object
const device::Memory& parent //!< Parent device memory object for the view
) const { return NULL; }
//! Reallocates the provided buffer object
virtual bool reallocMemory(amd::Memory& owner) const { return true; }
//! Acquire external graphics API object in the host thread
//! Needed for OpenGL objects on CPU device
virtual bool bindExternalDevice(
intptr_t type, void* pDevice, void* pContext, bool validateOnly) { return true; }
virtual bool unbindExternalDevice(
intptr_t type, void* pDevice, void* pContext, bool validateOnly) { return true; }
//! Gets a pointer to a region of host-visible memory for use as the target
//! of a non-blocking map for a given memory object
virtual void* allocMapTarget(
amd::Memory& mem, //!< Abstraction layer memory object
const amd::Coord3D& origin, //!< The map location in memory
const amd::Coord3D& region, //!< The map region in memory
size_t* rowPitch = NULL, //!< Row pitch for the mapped memory
size_t* slicePitch = NULL //!< Slice for the mapped memory
) { return NULL; }
//! Releases non-blocking map target memory
virtual void freeMapTarget(amd::Memory& mem, void* target) {}
CALtarget calTarget() const { return calTarget_; }
const AMDDeviceInfo* hwInfo() const { return hwInfo_; }
//! Empty implementation on Null device
virtual bool globalFreeMemory(size_t* freeMemory) const { return false; }
//! Get GPU device settings
const gpu::Settings& settings() const
{ return reinterpret_cast<gpu::Settings&>(*settings_); }
virtual void* svmAlloc(amd::Context& context, size_t size, size_t alignment, cl_svm_mem_flags flags) const {return NULL;}
virtual void svmFree(void* ptr) const {return;}
protected:
CALtarget calTarget_; //!< GPU device identifier
const AMDDeviceInfo* hwInfo_; //!< Device HW info structure
};
//! Forward declarations
class Command;
class Device;
class GpuCommand;
class Heap;
class HeapBlock;
class Program;
class Kernel;
class Memory;
class Resource;
class VirtualDevice;
class PrintfDbg;
class ThreadTrace;
class Sampler : public device::Sampler
{
public:
//! Constructor
Sampler(const Device& dev): dev_(dev) {}
//! Default destructor for the device memory object
virtual ~Sampler();
//! Creates a device sampler from the OCL sampler state
bool create(
uint32_t oclSamplerState //!< OCL sampler state
);
const void* hwState() const { return hwState_; }
private:
//! Disable default copy constructor
Sampler& operator=(const Sampler&);
//! Disable operator=
Sampler(const Sampler&);
const Device& dev_; //!< Device object associated with the sampler
address hwState_; //!< GPU HW state (\todo legacy path)
};
//! A GPU device ordinal (physical GPU device)
class Device : public NullDevice, public CALGSLDevice
{
public:
//! Locks any access to the virtual GPUs
class ScopedLockVgpus : public amd::StackObject {
public:
//! Default constructor
ScopedLockVgpus(const Device& dev);
//! Destructor
~ScopedLockVgpus();
private:
const Device& dev_; //! Device object
};
//! Interop emulation flags
enum InteropEmulationFlags
{
D3D10Device = 0x00000001,
GLContext = 0x00000002,
};
class Engines : public amd::EmbeddedObject
{
public:
//! Default constructor
Engines() { memset(desc_, 0xff, sizeof(desc_)); }
//! Creates engine descriptor for this class
void create(uint num, gslEngineDescriptor* desc, uint maxNumComputeRings);
//! Gets engine type mask
uint getMask(gslEngineID id) const { return (1 << id); }
//! Gets a descriptor for the requested engines
uint getRequested(uint engines, gslEngineDescriptor* desc) const;
//! Returns the number of available compute rings
uint numComputeRings() const { return numComputeRings_; }
private:
uint numComputeRings_;
gslEngineDescriptor desc_[GSL_ENGINEID_MAX]; //!< Engine descriptor
};
//! Transfer buffers
class XferBuffers : public amd::HeapObject
{
public:
static const size_t MaxXferBufListSize = 8;
//! Default constructor
XferBuffers(const Device& device, Resource::MemoryType type, size_t bufSize)
: type_(type)
, bufSize_(bufSize)
, acquiredCnt_(0)
, gpuDevice_(device)
{}
//! Default destructor
~XferBuffers();
//! Creates the xfer buffers object
bool create();
//! Acquires an instance of the transfer buffers
Resource& acquire();
//! Releases transfer buffer
void release(
VirtualGPU& gpu, //!< Virual GPU object used with the buffer
Resource& buffer //!< Transfer buffer for release
);
//! Returns the buffer's size for transfer
size_t bufSize() const { return bufSize_; }
private:
//! Disable copy constructor
XferBuffers(const XferBuffers&);
//! Disable assignment operator
XferBuffers& operator=(const XferBuffers&);
//! Get device object
const Device& dev() const { return gpuDevice_; }
Resource::MemoryType type_; //!< The buffer's type
size_t bufSize_; //!< Staged buffer size
std::list<Resource*> freeBuffers_; //!< The list of free buffers
amd::Atomic<uint> acquiredCnt_; //!< The total number of acquired buffers
amd::Monitor lock_; //!< Stgaed buffer acquire/release lock
const Device& gpuDevice_; //!< GPU device object
};
//! Virtual address cache entry
struct VACacheEntry : public amd::HeapObject
{
void* startAddress_; //!< Start virtual address
void* endAddress_; //!< End virtual address
Memory* memory_; //!< GPU memory, associated with the range
//! Constructor
VACacheEntry(
void* startAddress, //!< Start virtual address
void* endAddress, //!< End virtual address
Memory* memory //!< GPU memory object
): startAddress_(startAddress), endAddress_(endAddress), memory_(memory) {}
private:
//! Disable default constructor
VACacheEntry();
};
struct ScratchBuffer : public amd::HeapObject
{
uint regNum_; //!< The number of used scratch registers
std::vector<Memory*> memObjs_; //!< Memory objects for scratch buffers
//! Default constructor
ScratchBuffer(uint numMems): regNum_(0), memObjs_(numMems) {}
//! Default constructor
~ScratchBuffer();
//! Destroys memory objects
void destroyMemory();
};
class SrdManager : public amd::HeapObject {
public:
SrdManager(const Device& dev, uint srdSize, uint bufSize)
: dev_(dev)
, numFlags_(bufSize / (srdSize * MaskBits))
, srdSize_(srdSize)
, bufSize_(bufSize) {}
~SrdManager();
//! Allocates a new SRD slot for a resource
uint64_t allocSrdSlot(address* cpuAddr);
//! Frees a SRD slot
void freeSrdSlot(uint64_t addr);
// Fills the resource list for VidMM KMD
void fillResourceList(std::vector<const Resource*>& memList);
private:
//! Disable copy constructor
SrdManager(const SrdManager&);
//! Disable assignment operator
SrdManager& operator=(const SrdManager&);
struct Chunk {
Memory* buf_;
uint* flags_;
Chunk(): buf_(NULL), flags_(NULL) {}
};
static const uint MaskBits = 32;
const Device& dev_; //!< GPU device for the chunk manager
amd::Monitor ml_; //!< Global lock for the SRD manager
std::vector<Chunk> pool_; //!< Pool of SRD buffers
uint numFlags_; //!< Total number of flags in array
uint srdSize_; //!< SRD size
uint bufSize_; //!< Buffer size that holds SRDs
};
//! Initialise the whole GPU device subsystem (CAL init, device enumeration, etc).
static bool init();
//! Shutdown the whole GPU device subsystem (CAL shutdown).
static void tearDown();
//! Construct a new physical GPU device
Device();
//! Initialise a device (i.e. all parts of the constructor that could
//! potentially fail)
bool create(
CALuint ordinal //!< GPU device ordinal index. Starts from 0
);
//! Destructor for the physical GPU device
virtual ~Device();
//! Reallocates current global heap
bool reallocHeap(
size_t size, //!< requested size for reallocation
bool remoteAlloc //!< allocate the new heap in remote memory
);
//! Instantiate a new virtual device
device::VirtualDevice* createVirtualDevice(
bool profiling,
bool interopQueue
#if cl_amd_open_video
, void* calVideoProperties = NULL
#endif // cl_amd_open_video
, uint deviceQueueSize = 0
);
//! Memory allocation
virtual device::Memory* createMemory(
amd::Memory& owner //!< abstraction layer memory object
) const;
//! Sampler object allocation
virtual bool createSampler(
const amd::Sampler& owner, //!< abstraction layer sampler object
device::Sampler** sampler //!< device sampler object
) const;
//! Reallocates the provided buffer object
virtual bool reallocMemory(
amd::Memory& owner //!< Buffer for reallocation
) const;
//! 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;
//! Create the device program.
virtual device::Program* createProgram(int oclVer = 120);
//! Attempt to bind with external graphics API's device/context
virtual bool bindExternalDevice(
intptr_t type,
void* pDevice,
void* pContext,
bool validateOnly);
//! Attempt to unbind with external graphics API's device/context
virtual bool unbindExternalDevice(
intptr_t type,
void* pDevice,
void* pContext,
bool validateOnly);
//! Validates kernel before execution
virtual bool validateKernel(
const amd::Kernel& kernel, //!< AMD kernel object
const device::VirtualDevice* vdev
);
//! Gets a pointer to a region of host-visible memory for use as the target
//! of a non-blocking map for a given memory object
virtual void* allocMapTarget(
amd::Memory& mem, //!< Abstraction layer memory object
const amd::Coord3D& origin, //!< The map location in memory
const amd::Coord3D& region, //!< The map region in memory
size_t* rowPitch = NULL, //!< Row pitch for the mapped memory
size_t* slicePitch = NULL //!< Slice for the mapped memory
);
//! Retrieves information about free memory on a GPU device
virtual bool globalFreeMemory(size_t* freeMemory) const;
//! Returns a GPU memory object from AMD memory object
gpu::Memory* getGpuMemory(
amd::Memory* mem //!< Pointer to AMD memory object
) const;
//! Gets the GPU resource associated with the global heap
const Resource& globalMem() const { return heap_->resource(); }
//! Gets the global heap object
const Heap* heap() const { return heap_; }
//! Allocates a heap block from the global heap
HeapBlock* allocHeapBlock(
size_t size //!< The heap block size for allocation
) const;
//! Gets the memory object for the dummy page
amd::Memory* dummyPage() const { return dummyPage_; }
amd::Monitor& lockAsyncOps() const { return *lockAsyncOps_; }
//! Returns the lock object for the virtual gpus list
amd::Monitor* vgpusAccess() const { return vgpusAccess_; }
//! Returns the number of virtual GPUs allocated on this device
uint numOfVgpus() const { return numOfVgpus_; }
uint numOfVgpus_; //!< The number of virtual GPUs (lock protected)
typedef std::vector<VirtualGPU*> VirtualGPUs;
//! Returns the list of all virtual GPUs running on this device
const VirtualGPUs vgpus() const { return vgpus_; }
VirtualGPUs vgpus_; //!< The list of all running virtual gpus (lock protected)
//! Scratch buffer allocation
gpu::Memory* createScratchBuffer(
size_t size //!< Size of buffer
) const;
//! Returns transfer buffer object
XferBuffers& xferWrite() const { return *xferWrite_; }
//! Returns transfer buffer object
XferBuffers& xferRead() const { return *xferRead_; }
//! Adds GPU memory to the VA cache list
void addVACache(Memory* memory) const;
//! Removes GPU memory from the VA cache list
void removeVACache(const Memory* memory) const;
//! Finds GPU memory from virtual address
Memory* findMemoryFromVA(const void* ptr, size_t* offset) const;
//! Finds an appropriate map target
amd::Memory* findMapTarget(size_t size) const;
//! Adds a map target to the cache
bool addMapTarget(amd::Memory* memory) const;
//! Returns resource cache object
ResourceCache& resourceCache() const { return *resourceCache_; }
//! Returns engines object
const Engines& engines() const { return engines_; }
//! Returns engines object
const device::BlitManager& xferMgr() const { return xferQueue_->blitMgr(); }
VirtualGPU* xferQueue() const { return xferQueue_; }
//! Retrieves the internal format from the OCL format
CalFormat getCalFormat(
const amd::Image::Format& format //! OCL image format
) const;
//! Retrieves the OCL format from the internal image format
amd::Image::Format getOclFormat(
const CalFormat& format //! Internal image format
) const;
const ScratchBuffer* scratch(uint idx) const { return scratch_[idx]; }
//! Destroys scratch buffer memory
void destroyScratchBuffers();
//! Initialize heap resources if uninitialized
bool initializeHeapResources();
//! Set GSL sampler to the specified state
void fillHwSampler(
uint32_t state, //!< Sampler's OpenCL state
void* hwState, //!< Sampler's HW state
uint32_t hwStateSize //!< Size of sampler's HW state
) const;
//! host memory alloc
virtual void* hostAlloc(size_t size, size_t alignment, bool atomics = false) const;
//! SVM allocation
virtual void* svmAlloc(amd::Context& context, size_t size, size_t alignment, cl_svm_mem_flags flags) const;
//! Free host SVM memory
void hostFree(void* ptr, size_t size) const;
//! SVM free
virtual void svmFree(void* ptr) const;
//! Returns SRD manger object
SrdManager& srds() const { return *srdManager_; }
private:
//! Disable copy constructor
Device(const Device&);
//! Disable assignment
Device& operator=(const Device&);
//! Sends the stall command to all queues
bool stallQueues();
//! Fills OpenCL device info structure
void fillDeviceInfo(
const CALdeviceattribs& calAttr, //!< CAL device attributes info
const CALdevicestatus& calStatus //!< CAL device status
#if cl_amd_open_video
,
const CALdeviceVideoAttribs& calVideoAttr //!< -"- video attrib. info
#endif //cl_amd_open_video
);
//! Buffer allocation from static heap (no VM mode only)
gpu::Memory* createBufferFromHeap(
amd::Memory& owner //!< Abstraction layer memory object
) const;
//! Buffer allocation
gpu::Memory* createBuffer(
amd::Memory& owner, //!< Abstraction layer memory object
bool directAccess, //!< Use direct host memory access
bool bufferAlloc //!< If TRUE, then don't use heap
) const;
//! Image allocation
gpu::Memory* createImage(
amd::Memory& owner, //!< Abstraction layer memory object
bool directAccess //!< Use direct host memory access
) const;
//! Allocates/reallocates the scratch buffer, according to the usage
bool allocScratch(
uint regNum, //!< Number of the scratch registers
const VirtualGPU* vgpu //!< Virtual GPU for the allocation
);
amd::Context* context_; //!< A dummy context for internal allocations
size_t heapSize_; //!< The global heap size
Heap* heap_; //!< GPU heap manager
amd::Memory* dummyPage_; //!< A dummy page for NULL pointer
amd::Monitor* lockAsyncOps_; //!< Lock to serialise all async ops on this device
amd::Monitor* lockAsyncOpsForInitHeap_; //!< Lock to serialise all async ops on initialization heap operation
amd::Monitor* vgpusAccess_; //!< Lock to serialise virtual gpu list access
XferBuffers* xferRead_; //!< Transfer buffers read
XferBuffers* xferWrite_; //!< Transfer buffers write
amd::Monitor* vaCacheAccess_; //!< Lock to serialize VA caching access
std::list<VACacheEntry*>* vaCacheList_; //!< VA cache list
std::vector<amd::Memory*>* mapCache_; //!< Map cache info structure
ResourceCache* resourceCache_; //!< CAL resource cache
Engines engines_; //!< Available engines on device
bool heapInitComplete_; //!< Keep track of initialization status of heap resources
VirtualGPU* xferQueue_; //!< Transfer queue
std::vector<ScratchBuffer*> scratch_; //!< Scratch buffers for kernels
SrdManager* srdManager_; //!< SRD manager object
static AppProfile appProfile_; //!< application profile
};
/*@}*/} // namespace gpu
#endif /*GPU_HPP_*/
+536
View File
@@ -0,0 +1,536 @@
//! Implementation of GPU device memory management
#include "top.hpp"
#include "thread/thread.hpp"
#include "thread/monitor.hpp"
#include "device/device.hpp"
#include "device/gpu/gpuheap.hpp"
#include "device/gpu/gpudevice.hpp"
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
//! Turn this on to enable sanity checks before and after every heap operation.
#if DEBUG
#define EXTRA_HEAP_CHECKS 1
#endif // DEBUG
namespace gpu {
// The GPU heap. Very simple implementation for now.
Heap::Heap(
Device& device)
: resource_(NULL)
, freeList_(NULL)
, busyList_(NULL)
, freeSize_(0)
, device_(device)
, granularity_(Heap::MinGranularity)
, lock_("GPU heap lock", true)
, virtualMode_(false)
, baseAddress_(0)
{
}
size_t
Heap::granularityB() const
{
return granularity_ * Heap::ElementSize;
}
bool
Heap::create(size_t totalSize, bool remoteAlloc)
{
Resource::MemoryType memType;
size_t maxHeight = device_.info().image2DMaxHeight_;
size_t sizeInElements;
size_t npages;
freeSize_ = totalSize;
sizeInElements = (totalSize + Heap::ElementSize - 1) / Heap::ElementSize;
// Calculate best granularity given the size and device characteristics
npages = amd::alignUp(sizeInElements, granularity_) / granularity_;
// Create a new GPU resource
resource_ = new Resource(device_, sizeInElements, Heap::ElementType);
if (resource_ == NULL) {
return false;
}
memType = (remoteAlloc) ? Resource::RemoteUSWC : Resource::Local;
if (!resource_->create(memType, NULL, true)) {
return false;
}
// Set up initial free list
freeList_ = new HeapBlock(this, npages * granularityB(), 0, NULL, NULL);
if (freeList_ == NULL) {
return false;
}
guarantee(isSane());
return true;
}
Heap::~Heap()
{
amd::ScopedLock k(lock_);
guarantee(isSane());
// Release all heap blocks
HeapBlock *walk, *next;
walk = busyList_;
while (walk) {
next = walk->next_;
walk->free();
walk = next;
}
walk = freeList_;
while (walk) {
next = walk->next_;
delete walk;
walk = next;
}
// Release resource
delete resource_;
}
HeapBlock*
Heap::alloc(size_t size)
{
amd::ScopedLock k(lock_);
HeapBlock* walk = freeList_;
HeapBlock* best = NULL;
guarantee(isSane());
// Round size
size = amd::alignUp(size, granularityB());
// Walk the free list looking for a suitable block (currently best-fit)
//! @todo:dgladdin: experiment with switching back to first-fit
while (walk) {
if ((walk->size_ > size) &&
(best == NULL || walk->size_ < best->size_)) {
best = walk;
}
else if (walk->size_ == size) {
// No need to split, just move to busy list
detachBlock(&freeList_, walk);
walk->inUse_ = true;
insertBlock(&busyList_, walk);
guarantee(isSane());
freeSize_ -= size;
return walk;
}
walk = walk->next_;
}
if (best != NULL) {
// Got one, but need to split it. Keep first part in free list,
// put second part into busy list.
HeapBlock *newblock = splitBlock(best, size);
newblock->inUse_ = true;
insertBlock(&busyList_, newblock);
guarantee(isSane());
freeSize_ -= size;
return newblock;
}
// No free block available
guarantee(isSane());
return NULL;
}
bool
Heap::copyTo(Heap* heap)
{
HeapBlock *walk;
walk = busyList_;
while (walk) {
if (walk->getMemory() != NULL) {
HeapBlock* hb = heap->alloc(walk->size_);
if (hb == NULL) {
return false;
}
hb->setMemory(walk->getMemory());
walk->destroyViewsMemory();
if (!walk->getMemory()->reallocate(hb, &(heap->resource()))) {
return false;
}
if (!walk->reallocateViews(hb,
static_cast<size_t>(hb->offset_ - walk->offset_))) {
return false;
}
}
walk = walk->next_;
}
return true;
}
void
Heap::free(HeapBlock* blk)
{
amd::ScopedLock k(lock_);
guarantee(isSane());
detachBlock(&busyList_, blk);
blk->inUse_ = false;
freeSize_ += blk->size_;
mergeBlock(&freeList_, blk);
guarantee(isSane());
}
void
Heap::detachBlock(HeapBlock** list, HeapBlock* blk)
{
// Sanity checks
guarantee(isSane());
if (*list == blk) {
*list = blk->next_;
}
if (blk->prev_) {
blk->prev_->next_ = blk->next_;
}
if (blk->next_) {
blk->next_->prev_ = blk->prev_;
}
// no heap sanity check as blk is now floating
}
void
Heap::insertBlock(HeapBlock** head, HeapBlock* blk)
{
if (NULL == *head) {
*head = blk;
blk->prev_ = NULL;
blk->next_ = NULL;
guarantee(isSane());
return;
}
// Find the place to insert it at
HeapBlock* walk = *head;
while (walk->next_ && walk->next_->offset_ < blk->offset_) {
walk = walk->next_;
}
// Insert it
if (walk == *head) {
if (walk->offset_ >= blk->offset_) {
*head = blk;
blk->prev_ = NULL;
blk->next_ = walk;
walk->prev_ = *head;
guarantee(isSane());
return;
}
}
blk->next_ = walk->next_;
blk->prev_ = walk;
if (walk->next_) {
walk->next_->prev_ = blk;
}
walk->next_ = blk;
guarantee(isSane());
}
HeapBlock*
Heap::splitBlock(HeapBlock* blk, size_t tailsize)
{
// Sanity checks
guarantee(isSane());
guarantee(blk->size_ > tailsize && "block too small to split as requested");
guarantee(!blk->inUse_ && "can't split in-use block");
// Create a new block
HeapBlock* nb = new HeapBlock(blk->owner_, tailsize,
blk->offset_ + blk->size_ - tailsize);
// Resize the old block
blk->size_ = blk->size_ - tailsize;
return nb; // no heap sanity check here as the new block hasn't been plugged in yet
}
//! Join two blocks, transferring the size of the second into the first and deleting
//! the second. Utility fn for mergeBlock()
static void
join2Blocks(HeapBlock* first, HeapBlock* second)
{
// Sanity checks
guarantee(first->size_ > 0 && "first block invalid");
guarantee(!first->inUse_ && "can't join an in-use block");
guarantee(second->size_ > 0 && "second block invalid");
guarantee(first->offset_ + first->size_ == second->offset_);
// Do the join
first->size_ = first->size_ + second->size_;
first->next_ = second->next_;
if (second->next_) {
second->next_->prev_ = first;
}
delete second;
}
//! Insert a block into a list, merging it with adjacent blocks if possible. Must be called
//! under a lock, cannot be used on in-use blocks or blocks with an associated resource alias.
void
Heap::mergeBlock(HeapBlock** head, HeapBlock* blk)
{
insertBlock(head, blk);
// Merge with successor if possible
if ((blk->next_ != NULL) &&
(blk->offset_ + blk->size_ == blk->next_->offset_)) {
join2Blocks(blk, blk->next_);
}
// Merge with predecessor if possible
if ((blk->prev_ != NULL) &&
(blk->prev_->offset_ + blk->prev_->size_ == blk->offset_)) {
join2Blocks(blk->prev_, blk);
}
guarantee(isSane());
}
//! Sanity check for both types of block (helper function for Heap::isSane())
static bool
isBlockSane(HeapBlock* b)
{
return (b->owner_ != NULL
&& (b->next_ == NULL || b->next_->prev_ == b)
&& (b->prev_ == NULL || b->prev_->next_ == b));
}
//! Sanity check for an individual free block (helper function for Heap::isSane())
static bool
isFreeBlockSane(HeapBlock* b)
{
if (isBlockSane(b) && !b->inUse_) {
return true;
} else {
return false;
}
}
//! Sanity check for an individual busy block (helper function for Heap::isSane())
static bool
isBusyBlockSane(HeapBlock* b)
{
if (isBlockSane(b) && b->inUse_) {
return true;
} else {
return false;
}
}
//! Sanity check for the heap.
bool
Heap::isSane() const
{
// If we got this far, everything is (probably) OK
#if EXTRA_HEAP_CHECKS
HeapBlock* walkFree = freeList_; // Free list position
HeapBlock* walkBusy = busyList_; // Busy list position
size_t offset = 0; // Current offset
// We can have zero lists if Heap allocation fails
if (walkFree == NULL && walkBusy == NULL) {
return true;
}
// Walk both lists in parallel
while (walkFree != NULL || walkBusy != NULL) {
if (walkFree != NULL && walkFree->offset_ == offset) {
if (!isFreeBlockSane(walkFree)) {
return false;
}
offset += walkFree->size_;
walkFree = walkFree->next_;
}
else if (walkBusy != NULL && walkBusy->offset_ == offset) {
if (!isBusyBlockSane(walkBusy)) {
return false;
}
offset += walkBusy->size_;
walkBusy = walkBusy->next_;
}
else {
return false;
}
}
#endif // EXTRA_HEAP_CHECKS
return true;
}
void
HeapBlock::destroyViewsMemory()
{
if ((parent_ != NULL) && (0 == views_.size())) {
memory_->free();
}
else if (views_.size() != 0) {
std::list<HeapBlock*>::const_iterator it;
for (it = views_.begin(); it != views_.end(); ++it) {
(*it)->destroyViewsMemory();
}
}
}
bool
HeapBlock::reallocateViews(HeapBlock* parent, size_t shift)
{
if (views_.size() != 0) {
std::list<HeapBlock*>::const_iterator it;
// Loop through all views and reallocate them
for (it = views_.begin(); it != views_.end(); ++it) {
// Get the view HeapBlock
HeapBlock* hb = (*it);
// Readjust the offset
hb->offset_ += shift;
// Add to the list if we have a new parent
if (parent != this) {
parent->addView(hb);
}
// Reallocate memory
hb->memory_->reallocate(hb, parent->getMemory());
// Process a view on view if available
if (!hb->reallocateViews(hb, shift)) {
return false;
}
}
// Destroy old list
if (parent != this) {
views_.clear();
}
}
return true;
}
//! Destructor. Frees the block if in use and does some final sanity checks.
HeapBlock::~HeapBlock()
{
if (NULL != owner_) {
if (inUse_) {
owner_->free(this);
}
}
else {
// View destruction
if (parent_ != NULL) {
assert(((parent_->getMemory() != NULL) && (parent_->getMemory()->owner() != NULL)));
amd::ScopedLock lock(parent_->getMemory()->owner()->lockMemoryOps());
parent_->removeView(this);
}
}
guarantee(size_ > 0 && "destructor called for zero-size heap block (destructor called twice?)");
size_ = 0; // Mark as invalid
if (views_.size() != 0) {
LogError("Can't destroy a resource if we still have views!");
}
}
void
HeapBlock::free()
{
if (NULL != owner_) {
owner_->free(this);
}
else {
// It's a view. Destroy the object
delete this;
}
}
VirtualHeap::VirtualHeap(
Device& device)
: Heap(device)
{
virtualMode_ = true;
}
bool
VirtualHeap::create(
size_t totalSize,
bool remoteAlloc)
{
// Create a new GPU resource
resource_ = new Resource(device_, 0, Heap::ElementType);
if (resource_ == NULL) {
return false;
}
if (!resource_->create(Resource::Heap)) {
return false;
}
if (!device_.settings().hsail_) {
baseAddress_ = resource_->gslResource()->getSurfaceAddress();
}
return true;
}
VirtualHeap::~VirtualHeap()
{
}
HeapBlock*
VirtualHeap::alloc(size_t size)
{
assert(false && "Dead branch!");
return NULL;
}
void
VirtualHeap::free(HeapBlock* blk)
{
assert(false && "Dead branch!");
}
bool
VirtualHeap::copyTo(Heap* heap)
{
assert(false && "Dead branch!");
return false;
}
bool
VirtualHeap::isSane(void) const
{
assert(false && "Dead branch!");
return true;
}
} // namespace gpu
+225
View File
@@ -0,0 +1,225 @@
//! Declarations for GPU memory management
#ifndef GPUHEAP_HPP_
#define GPUHEAP_HPP_
#include "top.hpp"
#include "thread/atomic.hpp"
#include "device/gpu/gpudefs.hpp"
/*! \addtogroup GPU
* @{
*/
//! GPU Device Implementation
namespace gpu {
class Device;
class Heap;
class Resource;
class Memory;
class VirtualGPU;
//! @todo:dgladdin: The heap list should be singly-linked
//! \brief A block on the GPU heap.
//!
//! Note that no code outside of the gpumemory.hpp/.cpp pair should touch this
//! class directly as it is not thread-safe. In general, this class should be
//! pretty much a struct and contain as little functionality as possible - just
//! a constructor, destructor.
//!
//! Any other methods - in particular, anything that talks to CAL - should be no
//! more than proxies for functionality implemented in Heap, as Heap is aware
//! of the lock state.
class HeapBlock : public amd::HeapObject
{
public:
//! Constructor
HeapBlock(
Heap* owner = NULL,
size_t size = 0,
size_t offset = 0,
HeapBlock* next=NULL,
HeapBlock* prev=NULL)
: owner_(owner)
, size_(size)
, offset_(offset)
, next_(next)
, prev_(prev)
, inUse_(false)
, parent_(NULL)
, memory_(NULL)
{}
//! Destructor does some sanity checks.
~HeapBlock();
//! Frees a heap block, returning its memory to the owning heap (proxy)
void free();
//! Sets the GPU memory object associated with the heap block
void setMemory(Memory* memory) { memory_ = memory; }
//! Gets the GPU memory object associated with the heap block
Memory* getMemory() const { return memory_; }
//! Adds a heapblock view to the list of views
void addView(HeapBlock* hb)
{ views_.push_back(hb); hb->parent_ = this; }
//! Removes a heapblock view from the list of views
void removeView(HeapBlock* hb) { views_.remove(hb); }
//! Destroys all views
void destroyViewsMemory();
//! Creates all new views
bool reallocateViews(
HeapBlock* parent, //!< Parent heap block
size_t shift //!< The new HeapBlock shift
);
//! Gets the offset
size_t offset() const { return offset_; }
Heap* owner_; //!< Heap that owns this block
size_t size_; //!< Size of the block in bytes
size_t offset_; //!< Offset of this block in the heap
HeapBlock* next_; //!< Next block on the list, or NULL
HeapBlock* prev_; //!< Previous block on the list, or NULL
bool inUse_; //!< true if the block is in use
HeapBlock* parent_; //!< The parent heap block for a view
private:
//! Disable copy constructor
HeapBlock(const HeapBlock&);
//! Disable assignment
HeapBlock& operator=(const HeapBlock&);
Memory* memory_; //!< Memory object associated with the heap block
std::list<HeapBlock*> views_; //!< The list of all allocated views
};
class Heap : public amd::HeapObject
{
public:
//! Minimal supported CAL granularity = 256 bytes / ElementSize
static const size_t MinGranularity = 64;
//! The size of a heap element in bytes
static const size_t ElementSize = 4;
//! The type of a heap element in bytes
static const cmSurfFmt ElementType = CM_SURF_FMT_R32I;
Heap(
Device& device //!< GPU device object
);
virtual bool create(
size_t totalSize, //!< total size of the allocated heap (bytes)
bool remoteAlloc //!< allocate the heap in remote memory
);
//! Heap destructor
virtual ~Heap();
/*!
* \brief Allocates memory from a heap (best-fit).
* We round up to 4k granularity for alignment.
*
* \return A pointer to allocated heap block object.
*/
virtual HeapBlock* alloc(
size_t size //! The allocation size
);
//! Release memory back to a heap.
virtual void free(HeapBlock* blk);
//! Copies this heap to another
virtual bool copyTo(Heap* heap);
//! Gets the GPU resource associated with the global heap
const Resource& resource() const { return *resource_; }
//! Read the page size (bytes)
size_t granularityB() const;
//! Read the total free space (bytes)
size_t freeSpace() const { return freeSize_; }
virtual bool isSane(void) const; //!< Checks heap sanity
//! Returns true if we have a virtual heap
bool isVirtual() const { return virtualMode_; }
//! Returns the base virtual address of the heap
uint64_t baseAddress() const { return baseAddress_; }
private:
//! Insert a block into a list. Must be called under a lock.
void insertBlock(HeapBlock** list, HeapBlock* node);
//! Merge a block into a list. Must be called under a lock.
void mergeBlock(HeapBlock** list, HeapBlock* node);
//! Remove a block from a list. Must be called under a lock.
void detachBlock(HeapBlock** list, HeapBlock* node);
//! Split a block into two pieces
HeapBlock* splitBlock(HeapBlock* node, size_t size);
protected:
Resource* resource_; //!< GPU resource referencing the heap memory
HeapBlock* freeList_; //!< Head block for free list
HeapBlock* busyList_; //!< Head block for busy list
size_t freeSize_; //!< total free size of the heap
Device& device_; //!< Device that owns this heap
size_t granularity_; //!< Size of an allocation page
amd::Monitor lock_; //!< Lock to serialise heap accesses
bool virtualMode_; //!< Virtual mode
uint64_t baseAddress_; //!< Virtual heap base address
};
class VirtualHeap : public Heap
{
public:
VirtualHeap(
Device& device //!< GPU device object
);
virtual bool create(
size_t totalSize, //!< total size of the allocated heap (bytes)
bool remoteAlloc //!< allocate the heap in remote memory
);
//! Heap destructor
virtual ~VirtualHeap();
/*!
* \brief Allocates memory from a heap (best-fit).
* We round up to 4k granularity for alignment.
*
* \return A pointer to allocated heap block object.
*/
virtual HeapBlock* alloc(
size_t size //! The allocation size
);
//! Release memory back to a heap.
virtual void free(HeapBlock* blk);
//! Copies this heap to another
virtual bool copyTo(Heap* heap);
virtual bool isSane(void) const; //!< Checks heap sanity
};
} // namespace gpu
#endif // GPUHEAP_HPP_
File diff suppressed because it is too large Load Diff
+960
View File
@@ -0,0 +1,960 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUKERNEL_HPP_
#define GPUKERNEL_HPP_
#include "device/device.hpp"
#include "utils/macros.hpp"
#include "platform/command.hpp"
#include "platform/program.hpp"
#include "platform/kernel.hpp"
#include "platform/sampler.hpp"
#include "device/gpu/gpudevice.hpp"
#include "device/gpu/gpuvirtual.hpp"
#include "sc-hsa/Interface/SCHSAInterface.h"
#include "device/gpu/gpuprintf.hpp"
#include "newcore.h"
//! \namespace gpu GPU Device Implementation
namespace gpu {
class VirtualGPU;
class Device;
class NullDevice;
class HSAILProgram;
struct HWSHADER_Helper
{
template <typename S, typename T>
static T Get(S base, T offset) {
return reinterpret_cast<T>(reinterpret_cast<intptr_t>(base)
+ reinterpret_cast<size_t>(offset));
}
};
#define HWSHADER_Get(shader, field) \
HWSHADER_Helper::Get((shader), (shader)->field)
template <typename D, typename S>
static void CalcPtr(D& dst, const S src, size_t structSize, size_t size) {
dst = reinterpret_cast<D>(reinterpret_cast<const intptr_t>(src)
+ structSize * size);
}
/*! \addtogroup GPU GPU Device Implementation
* @{
*/
/*! \brief Helper function for the std::string processing.
* Finds the name in the std::string
*
* \return True if we found the entry of the symbols
*/
bool expect(
const std::string& str, //!< The original std::string
size_t* pos, //!< Position to start
const std::string& sym //!< The sympols to expect
);
/*! \brief Helper function for the std::string processing.
* Gets a word from the std::string
*
* \return True if we successfully received a word
*/
bool getword(
const std::string& str, //!< The original std::string
size_t* pos, //!< Position to start
char* sym //!< Returned word
);
/*! \brief Helper function for the std::string processing.
* Loads numbers from the metadata
*
* \return True if we loaded a number
*/
bool getuint(
const std::string& str, //!< The original std::string
size_t* pos, //!< Position to start
uint* val //!< Returned number
);
/*! \brief Helper function for the std::string processing.
* Loads numbers from the metadata in HEX format
*
* \return True if we loaded a number
*/
bool getuintHex(
const std::string& str, //!< The original std::string
size_t* pos, //!< Position to start
uint* val //!< Returned number
);
/*! \brief Helper function for the std::string processing.
* Loads numbers from the metadata in HEX format
*
* \return True if we loaded a number
*/
bool getuint64Hex(
const std::string& str, //!< The original std::string
size_t* pos, //!< Position to start
uint64_t* val //!< Returned number
);
/*! \brief Helper function for the std::string processing.
* Converts unsigned integer to string
*
* \return None
*/
void intToStr(
size_t value, //!< Value for conversion
char* str, //!< Pointer to the converted string
size_t size //!< String size
);
//! Image constant data from ABI specification
struct ImageConstants : public amd::EmbeddedObject
{
uint32_t width_; //!< Image surface width
uint32_t height_; //!< Image surface height
uint32_t depth_; //!< Image surface depth (1 for 2D images)
uint32_t dataType_; //!< Image surface data type
float widthFloat_; //!< Image surface width
float heightFloat_; //!< Image surface height
float depthFloat_; //!< Image surface depth (1 for 2D images)
uint32_t channelOrder_; //!< Image surface texels channel order
};
//! Kernel arguments
struct KernelArg : public amd::HeapObject
{
public:
//! \enum Kernel argument type
enum ArgumentType
{
None = 0,
PointerGlobal,
Value,
Image,
PointerLocal,
PointerHwLocal,
PointerPrivate,
PointerHwPrivate,
PointerConst,
PointerHwConst,
Float,
Double,
Half,
Char,
UChar,
Short,
UShort,
Int,
UInt,
Long,
ULong,
Struct,
Union,
Opaque,
Event,
Image1D, //!< first image
Image2D,
Image1DB,
Image1DA,
Image2DA,
Image3D, //!< last image
Counter,
Sampler,
PrivateSize,
LocalSize,
HwPrivateSize,
HwLocalSize,
Grouping,
WrkgrpSize,
Wavefront,
PrivateFixed,
ErrorMessage,
WarningMessage,
PrintfFormatStr,
MetadataVersion,
UavId,
ABI64Bit,
GWS,
SWGWS,
Reflection,
ConstArg,
ConstBufId,
PrintfBufId,
GroupingHint,
VecTypeHint,
TotalTypes
};
// The compiler metadata fields
std::string name_; //!< parameters name
ArgumentType type_; //!< type of argument
union {
uint size_; //!< number of arguments (for values and pointers only)
uint location_; //!< sampler's location (for samplers only)
};
uint cbIdx_; //!< constant buffer index
uint cbPos_; //!< dword address in CB for the argument
std::string buf_; //!< buffer tag
uint index_; //!< buffer/image/sampler index
uint alignment_; //!< the required argument's alignment
ArgumentType dataType_; //!< data type of the argument
union {
struct {
uint uavBuf_ : 1; //!< UAV memory, no global heap
uint realloc_ : 1; //!< argument has to be reallocatedin the global heap
uint readOnly_ : 1; //!< Read only memory object
uint writeOnly_ : 1; //!< Write only memory object
uint readWrite_ : 1; //!< Read/Write memory object
};
uint value_;
} memory_;
std::string typeName_; //!< argument's type name
uint typeQualifier_; //!< argument's type qualifier
//! Default constructor for the kernel argument
KernelArg();
//! Copy constructor for the kernel argument
KernelArg(const KernelArg& data);
//! Overloads operator=
KernelArg& operator=(const KernelArg& data);
//! Destructor of the kernel argument
~KernelArg() { name_.clear(); }
/*! \brief Checks if this arguments requires a place in constant buffer
*
* \return True if we need CB
*/
bool isCbNeeded() const;
/*! \brief Retrieves the argument's size
*
* \return Size of the current argument
*/
size_t size(
bool gpuLayer //!< True if we want the argument's size for the GPU layer
) const;
/*! \brief Retrieves the argument's type for the abstraction layer
*
* \return The argument's type in the abstraction layer format
*/
clk_value_type_t type() const;
/*! \brief Retrieves the argument's address qualifier for the abstraction layer
*
* \return The argument's address qualifier in the abstraction layer format
*/
cl_kernel_arg_address_qualifier addressQualifier() const;
/*! \brief Retrieves the argument's access qualifier for the abstraction layer
*
* \return The argument's access qualifier in the abstraction layer format
*/
cl_kernel_arg_access_qualifier accessQualifier() const;
/*! \brief Retrieves the argument's type name for the abstraction layer
*
* \return The argument's type name
*/
const char* typeName() const { return typeName_.c_str(); }
/*! \brief Retrieves the argument's type qualifier for the abstraction layer
*
* \return The argument's type qualifier
*/
cl_kernel_arg_type_qualifier typeQualifier() const
{
switch (type_) {
case PointerConst:
case PointerHwConst:
return static_cast<cl_kernel_arg_type_qualifier>(typeQualifier_ |
CL_KERNEL_ARG_TYPE_CONST);
default:
return static_cast<cl_kernel_arg_type_qualifier>(typeQualifier_);
}
}
//! Special case for vectors with component size <= 16bit
const static uint VectorSizeLimit = 4;
size_t specialVector() const;
};
struct DataTypeConst
{
const char* tagName_; //!< data type's name
KernelArg::ArgumentType type_; //!< data type
};
//! Metadata description for parsing
struct MetaDataConst
{
const char* typeName_; //!< parameters name
KernelArg::ArgumentType type_; //!< type of argument
struct
{
uint size_ : 1; //!< number of arguments
uint name_ : 1; //!< argument's name
uint resType_: 1; //!< argument's type
uint cbIdx_ : 1; //!< resource index CB, sampler or image
uint cbPos_ : 1; //!< dword address in CB for the argument
uint buf_ : 1; //!< buffer tag
uint reserved: 26; //!< reserved
};
};
const uint DescTotal = 15;
const uint BasicTypeTotal = 14;
const uint ArgStateTotal = DescTotal + BasicTypeTotal;
//! The constant array that describes different metadata properties
extern const MetaDataConst ArgState[ArgStateTotal];
extern const DataTypeConst DataType[];
extern const uint DataTypeTotal;
// Forward declaration
class Program;
class NullProgram;
class CalImageReference : public amd::ReferenceCountedObject
{
public:
//! Default constructor
CalImageReference(CALimage calImage): image_(calImage) {}
//! Get CAL image
CALimage calImage() const { return image_; }
protected:
//! Default destructor
~CalImageReference();
private:
//! Disable copy constructor
CalImageReference(const CalImageReference&);
//! Disable operator=
CalImageReference& operator=(const CalImageReference&);
CALimage image_; //!< CAL kernel image
};
//! \class GPU NullKernel - Kernel for offline device
class NullKernel : public device::Kernel
{
public:
typedef std::vector<KernelArg*> arguments_t;
const static uint UavIdUndefined = 0xffff;
enum Flags {
LimitWorkgroup = 1 << 0, //!< Limits the workgroup size
PrintfOutput = 1 << 1, //!< Kernel has printf output
PrivateFixed = 1 << 2, //!< Kernel has printf output
ABI64bit = 1 << 3, //!< Kernel has 64 bit ABI
Unused0 = 1 << 4, //!< Unused
Unused1 = 1 << 5, //!< Unused
ImageEnable = 1 << 6, //!< Kernel uses images
ImageWrite = 1 << 7, //!< Kernel writes images
};
//! \enum Resource type for binding
enum ResourceType
{
Undefined = 0x00000000, //!< resource type will be detected
ConstantBuffer = 0x00000001, //!< resource is a constant buffer
GlobalBuffer = 0x00000002, //!< resource is a global buffer
GlobalBufferArena = 0x00000003, //!< resource is a global buffer
ArgumentHeapBuffer = 0x00000004, //!< resource is an argument buffer
ArgumentBuffer = 0x00000005, //!< resource is an argument buffer
ArgumentImageRead = 0x00000006, //!< resource is an argument image read
ArgumentImageWrite = 0x00000007, //!< resource is an argument image write
ArgumentConstBuffer = 0x00000008, //!< resource is an argument const buffer
ArgumentCounter = 0x00000009, //!< resource is a global counter
ArgumentUavID = 0x0000000a, //!< resource is a dummy ID read
ArgumentCbID = 0x0000000b, //!< resource is a constant buffer
ArgumentPrintfID = 0x0000000c, //!< resource is a printf buffer
};
//! GPU kernel constructor
NullKernel(
const std::string& name, //!< The kernel's name
const NullDevice& gpuNullDev, //!< GPU device object
const NullProgram& nullProg //!< Reference to the program
);
virtual ~NullKernel();
/*! \brief Creates a GPU kernel in CAL
*
* \return True if we successfully created a kernel in CAL
*/
bool create(
const std::string& code, //!< IL source code
const std::string& metadata, //!< the kernel metadata structure
const void* binaryCode = NULL, //!< binary machine code for CAL
size_t binarySize = 0 //!< the machine code size
);
//! Returns CAL function descriptor
CALimage calImage() const { return calRef_->calImage(); }
//! Returns TRUE if we successfully retrieved the binary from CAL
bool getCalBinary(
void* binary, //!< ISA binary code
size_t size //!< ISA binary size
) const;
//! Returns CAL image size
size_t getCalBinarySize() const;
//! Returns GPU device object, associated with this kernel
const NullDevice& nullDev() const { return gpuDev_; }
//! Returns GPU device object, associated with this kernel
const NullProgram& nullProg() const { return prog_; }
//! Returns the kernel's build log
const std::string& buildLog() const { return buildLog_; }
//! Returns the kernel's build error
const cl_int buildError() const { return buildError_; }
//! Returns the kernel's flags
uint flags() const { return flags_; }
//! Returns TRUE if ABI is for 64 bits
bool abi64Bit() const { return (flags_ & ABI64bit) ? true : false; }
//! Returns the total number of all arguments
size_t argSize() const { return arguments_.size(); }
//! Returns instruction count of the current kernel
uint instructionCnt() const { return instructionCnt_; }
protected:
//! Returns TRUE if memory should be reallocated, returns FALSE always for NullDevice
virtual bool isRealloc() const { return false; }
/*! \brief Parses the metadata structure for the kernel,
* provided by the OpenCL compiler
*
* \return True if we succefully parsed all arguments
*/
bool parseArguments(
const std::string& metaData, //!< the program for parsing
uint* uavRefCount //!< an array of reference counters for used UAVs
);
//! Returns the argument for the specified index
const KernelArg* argument(uint idx) const { return arguments_[idx]; }
//! Adds the kernel argument into the list
void addArgument(KernelArg* arg) { arguments_.push_back(arg); }
//! Returns the argument for the specified sampler's index
const KernelArg* sampler(uint idx) const { return intSamplers_[idx]; }
//! Returns the total number of all internal samplers
size_t samplerSize() const { return intSamplers_.size(); }
//! Adds the kernel sampler into the sampler's list
void addSampler(KernelArg* arg) { intSamplers_.push_back(arg); }
//! Returns UAV raw index for this kernel
uint uavRaw() const { return uavRaw_; }
//! Returns UAV arena index for this kernel
uint uavArena() const { return uavArena_; }
std::string buildLog_; //!< Kernel's build log
cl_int buildError_; //!< Kernel's build error
std::string ilSource_; //!< IL source code of this kernel
const NullDevice& gpuDev_; //!< GPU device object
const NullProgram& prog_; //!< Reference to the parent program
CalImageReference* calRef_; //!< CAL image reference for this kernel
bool internal_; //!< Runtime internal ker
uint flags_; //!< kernel object flags
arguments_t arguments_; //!< kernel arguments for the execution
arguments_t intSamplers_; //!< predefined intenal kernel samplers
size_t* cbSizes_; //!< real constant buffer sizes for this kernel
uint numCb_; //!< total number of constant buffers
uint uavRaw_; //!< UAV used for RAW access
uint uavArena_; //!< UAV used for arena access
bool rwAttributes_; //!< backend provides RW attributes for arguments
uint instructionCnt_;//!< Instruction count
uint cbId_; //!< UAV used for constant buffer access
uint printfId_; //!< UAV used for printf buffer access
private:
//! Disable copy constructor
NullKernel(const NullKernel&);
//! Disable operator=
NullKernel& operator=(const NullKernel&);
//! Creates a filename for ISA/IL dumps
std::string mkDumpName(
const char* extension //!< File extension to append
) const;
bool createMultiBinary(
uint* imageSize, //!< Multibinary image size
void** image, //!< Multibinary image
const void* isa //!< Kernel HW info
);
//! SI HW specific setup for kernels
bool siCreateHwInfo(
const void* shader, //!< HW info shader
AMUabiAddEncoding& encoding //!< ABI encoding structure
);
//! r800 HW specific setup for kernels
bool r800CreateHwInfo(
const void* shader, //!< HW info shader
AMUabiAddEncoding& encoding //!< ABI encoding structure
);
};
//! \class GPU kernel
class Kernel : public NullKernel
{
public:
struct InitData {
uint privateSize_; //!< Private ring initial size
uint localSize_; //!< Local ring initial size
uint hwPrivateSize_; //!< HW private ring initial size
uint hwLocalSize_; //!< HW local ring initial size
uint flags_; //!< Kernel initialization flags
};
//! GPU kernel constructor
Kernel(
const std::string& name, //!< The kernel's name
const Device& gpuDev, //!< GPU device object
const Program& prog, //!< Reference to the program
const InitData* initData_ //!< Initialization data
);
//! GPU kernel destructor
virtual ~Kernel();
/*! \brief Creates a GPU kernel in CAL
*
* \return True if we successfully created a kernel in CAL
*/
bool create(
const std::string& code, //!< IL source code
const std::string& metadata, //!< the kernel metadata structure
const void* binaryCode = NULL, //!< binary machine code for CAL
size_t binarySize = 0 //!< the machine code size
);
//! Validates memory argument
virtual bool validateMemory(
uint idx, //!< Argument's index
amd::Memory* amdMem //!< AMD memory object for validation
) const ;
//! Initializes the CAL program grid for the kernel execution
void setupProgramGrid(
VirtualGPU& gpu, //!< virtual GPU device object
size_t workDim, //!< work dimension
const amd::NDRange& glbWorkOffset, //!< global work offset
const amd::NDRange& gblWorkSize, //!< global work size
amd::NDRange& lclWorkSize, //!< local work size
const amd::NDRange& groupOffset, //!< group offsets
const amd::NDRange& glbWorkOffsetOrg,
const amd::NDRange& glbWorkSizeOrg //!< original global work size
) const;
/*! \brief Detects if runtime has to disable cache optimization and
* recompiles the kernel
*
* \return True if aliases were detected in the kernel arguments
*/
bool processMemObjects(
VirtualGPU& gpu, //!< Virtual GPU objects - queue
const amd::Kernel& kernel, //!< AMD kernel object for execution
const_address params, //!< pointer to the param's store
bool nativeMem //!< Native memory objects
) const;
/*! \brief Loads all kernel arguments, so we could run the kernel in HW.
* This includes CB update and resource binding
*
* \return True if we succefully loaded the arguments
*/
bool loadParameters(
VirtualGPU& gpu, //!< virtual GPU device object
const amd::Kernel& kernel, //!< AMD kernel object for execution
const_address params, //!< pointer to the param's store
bool nativeMem //!< Native memory objects
) const;
//! Binds the constant buffers associated with the kernel
bool bindConstantBuffers(VirtualGPU& gpu) const;
/*! \brief Runs the kernel on HW
*
* \return True if we succefully executed the kernel
*/
bool run(
VirtualGPU& gpu, //!< virtual GPU device object
GpuEvent* gpuEvent, //!< Pointer to the GPU event
bool lastRun //!< Last run in the split execution
) const;
//! Help function to debug the kernel output
void debug(
VirtualGPU& gpu //!< virtual GPU device object
) const;
//! Programs internal samplers defined inside the kernel
bool setInternalSamplers(
VirtualGPU& gpu //!< Virtual GPU device object
) const;
//! Returns TRUE if we successfully retrieved the binary from CAL
bool getCalBinary(
void* binary, //!< ISA binary code
size_t size //!< ISA binary size
) const;
//! Returns CAL image size
size_t getCalBinarySize() const;
//! Returns GPU device object, associated with this kernel
const Device& dev() const;
//! Returns GPU device object, associated with this kernel
const Program& prog() const;
//! Binds global HW constant buffers
bool bindGlobalHwCb(
VirtualGPU& gpu, //!< Virtual GPU device object
VirtualGPU::GslKernelDesc* desc //!< Kernel descriptor
) const;
protected:
//! Initializes the kernel parameters for the abstraction layer
bool initParameters();
/*! \brief Creates constant buffer resources, associated with the kernel
*
* \return TRUE if we succefully created constant buffers
*/
bool initConstBuffers();
//! Returns TRUE if memory should be reallocated, returns FALSE always for NullDevice
virtual bool isRealloc() const { return !dev().heap()->isVirtual(); }
private:
//! Disable copy constructor
Kernel(const Kernel&);
//! Disable operator=
Kernel& operator=(const Kernel&);
//! \enum Fixed Metadata offsets
enum MetadataOffsets
{
GlobalWorkitemOffset = 0,
LocalWorkitemOffset = 1,
GroupsOffset = 2,
PrivateRingOffset = 3,
LocalRingOffset = 4,
MathLibOffset = 5,
GlobalWorkOffsetOffset = 6,
GroupWorkOffsetOffset = 7,
GlobalDataStoreOffset = 8,
DebugOffset = 8,
NDRangeGlobalWorkOffsetOffset = 9,
// The total number of constants reserved for ABI
TotalABIVectors
};
/*! \brief Sets the kernel argument
*
* \return True if we succefully updated the arguments
*/
bool setArgument(
VirtualGPU& gpu, //!< Virtual GPU device object
uint idx, //!< the argument index
const void* param, //!< the arguments data
size_t size, //!< size of the provided data
bool nativeMem //!< Native memory objects
) const;
/*! \brief Initializes local and private buffer ranges
*
* \return True if we succefully initialized the ranges
*/
bool initLocalPrivateRanges(
VirtualGPU& gpu //!< Virtual GPU device object
) const;
//! Sets local and private buffer ranges
void setLocalPrivateRanges(
VirtualGPU& gpu //!< Virtual GPU device object
) const;
//! Sets the sampler's parameters for the image look-up
void setSampler(
VirtualGPU& gpu, //!< virtual GPU device object
uint32_t state, //!< sampler state
uint physUnit //!< sampler's number
) const;
/*! \brief Binds resource
*
* \return True if we succefully created constant buffers
*/
bool bindResource(
VirtualGPU& gpu, //!< virtual GPU device object
const Resource& resource, //!< resource for binding
uint paramIdx, //!< index of the parameter
ResourceType type, //!< resource type
uint physUnit, //!< PhysUnit
Memory* memory = NULL, //!< GPU layer memory object
size_t offset = 0
) const;
//! Unbinds all resources for the kernel
void unbindResources(
VirtualGPU& gpu, //!< virtual GPU device object
GpuEvent gpuEvent, //!< GPU event that will be associated with the resources
bool lastRun //!< last run in the split execution
) const;
//! Returns true if arena setup was successful
bool setupArenaAliases(
VirtualGPU& gpu, //!< Virtual GPU device object
const Resource& resource //!< Resource for aliases setup
) const;
//! Copies image constants to the constant buffer
void copyImageConstants(
const amd::Image* amdImage, //!< Abstraction layer image object
ImageConstants* imageData //!< Pointer in CB to the image constants
) const;
//! Finds local workgroup size
void findLocalWorkSize(
size_t workDim, //!< Work dimension
const amd::NDRange& gblWorkSize,//!< Global work size
amd::NDRange& lclWorkSize //!< Local work size
) const;
uint hwPrivateSize_; //!< initial HW private size
uint hwLocalSize_; //!< initial HW local size
//! @todo remove the blit kernel hack
bool blitKernelHack_; //!< No VM hack for kernel blit
};
enum HSAIL_ADDRESS_QUALIFIER{
HSAIL_ADDRESS_ERROR = 0,
HSAIL_ADDRESS_GLOBAL,
HSAIL_ADDRESS_LOCAL,
HSAIL_MAX_ADDRESS_QUALIFIERS
} ;
enum HSAIL_ARG_TYPE{
HSAIL_ARGTYPE_ERROR = 0,
HSAIL_ARGTYPE_POINTER,
HSAIL_ARGTYPE_VALUE,
HSAIL_ARGTYPE_IMAGE,
HSAIL_ARGTYPE_SAMPLER,
HSAIL_ARGTYPE_QUEUE,
HSAIL_ARGMAX_ARG_TYPES
};
enum HSAIL_DATA_TYPE{
HSAIL_DATATYPE_ERROR = 0,
HSAIL_DATATYPE_B1,
HSAIL_DATATYPE_B8,
HSAIL_DATATYPE_B16,
HSAIL_DATATYPE_B32,
HSAIL_DATATYPE_B64,
HSAIL_DATATYPE_S8,
HSAIL_DATATYPE_S16,
HSAIL_DATATYPE_S32,
HSAIL_DATATYPE_S64,
HSAIL_DATATYPE_U8,
HSAIL_DATATYPE_U16,
HSAIL_DATATYPE_U32,
HSAIL_DATATYPE_U64,
HSAIL_DATATYPE_F16,
HSAIL_DATATYPE_F32,
HSAIL_DATATYPE_F64,
HSAIL_DATATYPE_STRUCT,
HSAIL_DATATYPE_OPAQUE,
HSAIL_DATATYPE_MAX_TYPES
};
class HSAILKernel : public device::Kernel
{
public:
struct Argument
{
std::string name_; //!< Argument's name
std::string typeName_; //!< Argument's type name
uint size_; //!< Size in bytes
uint offset_; //!< Argument's offset
uint alignment_; //!< Argument's alignment
HSAIL_ARG_TYPE type_; //!< Type of the argument
HSAIL_ADDRESS_QUALIFIER addrQual_; //!< Address qualifier of the argument
HSAIL_DATA_TYPE dataType_; //!< The type of data
uint numElem_; //!< Number of elements
};
// Global offsets located in the first 3 elements
static const uint ExtraArguments = 6;
HSAILKernel(std::string name,
HSAILProgram* prog,
std::string compileOptions);
virtual ~HSAILKernel();
//! Initializes the metadata required for this kernel
bool init();
//! Returns true if memory is valid for execution
virtual bool validateMemory(uint idx, amd::Memory* amdMem) const;
//! Returns a pointer to the hsail argument
const Argument* argument(size_t i) const { return arguments_[i]; }
//! Returns the number of hsail arguments
size_t numArguments() const { return arguments_.size(); }
//! Returns GPU device object, associated with this kernel
const Device& dev() const;
//! Returns HSA program associated with this kernel
const HSAILProgram& prog() const;
//! Returns LDS size used in this kernel
uint32_t ldsSize() const
{ return cpuAqlCode_->workgroup_group_segment_byte_size; }
//! Returns pointer on CPU to AQL code info
const void* cpuAqlCode() const { return cpuAqlCode_; }
//! Returns memory object with AQL code
const gpu::Memory* gpuAqlCode() const { return code_; }
//! Returns the size of argument buffer
size_t argsBufferSize() const
{ return cpuAqlCode_->kernarg_segment_byte_size; }
//! Returns spill reg size per workitem
int spillSegSize() const
{ return cpuAqlCode_->workitem_private_segment_byte_size; }
//! Returns TRUE if kernel uses dynamic parallelism
bool dynamicParallelism() const
{ return (flags_.dynamicParallelism_) ? true : false; }
//! Finds local workgroup size
void findLocalWorkSize(
size_t workDim, //!< Work dimension
const amd::NDRange& gblWorkSize,//!< Global work size
amd::NDRange& lclWorkSize //!< Local work size
) const;
//! Returns AQL packet in CPU memory
//! if the kerenl arguments were successfully loaded, otherwise NULL
HsaAqlDispatchPacket* loadArguments(
VirtualGPU& gpu, //!< Running GPU context
const amd::Kernel& kernel, //!< AMD kernel object
const amd::NDRangeContainer& sizes, //!< NDrange container
const_address parameters, //!< Application arguments for the kernel
bool nativeMem, //!< Native memory objectes are passed
uint64_t vmDefQueue, //!< GPU VM default queue pointer
uint64_t* vmParentWrap, //!< GPU VM parent aql wrap object
std::vector<const Resource*>& memList //!< Memory list for GSL/VidMM handles
) const;
//! Returns pritnf info array
const std::vector<PrintfInfo>& printfInfo() const { return printf_; }
//! Returns the kernel index in the program
uint index() const { return index_; }
private:
//! Disable copy constructor
HSAILKernel(const HSAILKernel&);
//! Disable operator=
HSAILKernel& operator=(const HSAILKernel&);
//! Creates AQL kernel HW info
bool aqlCreateHWInfo(
const void* kernel, //!< Kernel's packed binary info and code
size_t kernelSize //!< Size of the kernel's packed binary
);
//! Initializes arguments_ and the abstraction layer kernel parameters
void initArgList(
const aclArgData* aclArg //!< List of ACL arguments
);
//! Initializes Hsail Argument metadata and info
void initHsailArgs(
const aclArgData* aclArg //!< List of ACL arguments
);
//! Initializes Hsail Printf metadata and info
void initPrintf(
const aclPrintfFmt* aclPrintf //!< List of ACL printfs
);
std::vector<Argument*> arguments_; //!< Vector list of HSAIL Arguments
std::string compileOptions_; //!< compile used for finalizing this kernel
amd_kernel_code_t* cpuAqlCode_; //!< AQL kernel code on CPU
const NullDevice& dev_; //!< GPU device object
const HSAILProgram& prog_; //!< Reference to the parent program
std::vector<PrintfInfo> printf_; //!< Format strings for GPU printf support
uint index_; //!< Kernel index in the program
gpu::Memory* code_; //!< Memory object with ISA code
char* hwMetaData_; //!< SI metadata
union Flags {
struct {
uint imageEna_: 1; //!< Kernel uses images
uint imageWriteEna_: 1; //!< Kernel uses image writes
uint dynamicParallelism_: 1; //!< Dynamic parallelism enabled
};
uint value_;
Flags(): value_(0) {}
} flags_;
};
/*@}*/} // namespace gpu
#endif /*GPUKERNEL_HPP_*/
File diff suppressed because it is too large Load Diff
+305
View File
@@ -0,0 +1,305 @@
//
// Copyright (c) 2009 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUMEMORY_HPP_
#define GPUMEMORY_HPP_
#include "top.hpp"
#include "thread/atomic.hpp"
#include "device/gpu/gpuresource.hpp"
#include "device/gpu/gpuheap.hpp"
#include "device/gpu/gpudevice.hpp"
#include <map>
/*! \addtogroup GPU
* @{
*/
namespace device {
class Memory;
}
//! GPU Device Implementation
namespace gpu {
class Device;
class Heap;
class Resource;
class Memory;
class VirtualGPU;
class HeapBlock;
//! GPU memory object.
// Wrapper that can contain a heap block or an interop buffer/image.
class Memory: public device::Memory, public Resource
{
public:
enum InteropType {
InteropNone = 0, //!< None interop memory
InteropHwEmulation = 1, //!< Uses HW emulaiton with calMemCopy
InteropDirectAccess = 2 //!< Uses direct access to the interop surface
};
//! Constructor (with owner)
Memory(
const Device& gpuDev,
amd::Memory& owner,
HeapBlock* hb,
size_t size = 0);
//! Constructor (nonfat version for local scratch mem use)
Memory(
const Device& gpuDev,
HeapBlock& hb);
//! Constructor (nonfat version for local scratch mem use without heap block)
Memory(
const Device& gpuDev,
size_t size);
//! Constructor memory for buffer (without global heap allocaton)
Memory(
const Device& gpuDev, //!< GPU device object
amd::Memory& owner, //!< Abstraction layer memory object
size_t width, //!< Memory width
cmSurfFmt format //!< CAL format
);
//! Constructor memory for buffer (without global heap allocaton)
Memory(
const Device& gpuDev, //!< GPU device object
size_t size, //!< Memory object size
size_t width, //!< Memory width
cmSurfFmt format //!< CAL format
);
//! Constructor memory for images (without global heap allocaton)
Memory(
const Device& gpuDev, //!< GPU device object
amd::Memory& owner, //!< Abstraction layer memory object
size_t width, //!< Allocated memory width
size_t height, //!< Allocated memory height
size_t depth, //!< Allocated memory depth
cmSurfFmt format, //!< Memory format
gslChannelOrder chOrder, //!< Channel order
cl_mem_object_type imageType //!< CL image type
);
//! Constructor memory for images (without global heap allocaton)
Memory(
const Device& gpuDev, //!< GPU device object
size_t size, //!< Memory object size
size_t width, //!< Allocated memory width
size_t height, //!< Allocated memory height
size_t depth, //!< Allocated memory depth
cmSurfFmt format, //!< Memory format
gslChannelOrder chOrder, //!< Channel order
cl_mem_object_type imageType //!< CL image type
);
//! Default destructor
~Memory();
//! Reallocates the memory object in the new heap block
bool reallocate(
HeapBlock* hb, //! The new heap block for this memory object
const Resource* parent //! Parent resource for view reallocaiton
);
//! Creates the interop memory
bool createInterop(
InteropType type //!< The interop type
);
//! Overloads the resource create method
virtual bool create(
Resource::MemoryType memType, //!< Memory type
Resource::CreateParams* params = NULL //!< Prameters for create
);
//! 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
size_t* rowPitch = NULL, //!< Row pitch for the mapped memory
size_t* slicePitch = NULL //!< Slice for the mapped memory
);
//! Pins system memory associated with this memory object
virtual bool pinSystemMemory(
void* hostPtr, //!< System memory address
size_t size //!< Size of allocated system memory
);
//! Releases indirect map surface
virtual void releaseIndirectMap() { decIndMapCount(); }
//! Map the device memory to CPU visible
virtual void* cpuMap(
device::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
);
//! Unmap the device memory
virtual void cpuUnmap(
device::VirtualDevice& vDev //!< Virtual device for unmap operaiton
);
//! Updates device memory from the owner's host allocation
void syncCacheFromHost(
VirtualGPU& gpu, //!< Virtual GPU device object
//! Synchronization flags
device::Memory::SyncFlags syncFlags = device::Memory::SyncFlags()
);
//! Updates the owner's host allocation from device memory
virtual void syncHostFromCache(
//! Synchronization flags
device::Memory::SyncFlags syncFlags = device::Memory::SyncFlags()
);
//! Creates a view from current resource
virtual Memory* createBufferView(
amd::Memory& subBufferOwner //!< The abstraction layer subbuf owner
);
//! Allocates host memory for synchronization with MGPU context
void mgpuCacheWriteBack();
//! Transfers objects data to the destination object
bool moveTo(Memory& dst);
//! Accessors for indirect map memory object
Memory* mapMemory() const;
//! Returns the interop memory for this memory object
Memory* interop() const { return interopMemory_; }
//! Gets interop type for this memory object
InteropType interopType() const { return interopType_; }
//! Sets interop type for this memory object
void setInteropType(InteropType type) { interopType_ = type; }
//! Returns the HeapBlock pointer
const HeapBlock* hb() const { return hb_; }
//! Set the owner
void setOwner(amd::Memory* owner) { owner_ = owner; }
// Decompress GL depth-stencil/MSAA resources for CL access
// Invalidates any FBOs the resource may be bound to, otherwise the GL driver may crash.
virtual bool processGLResource(GLResourceOP operation);
//! Returns the interop resource for this memory object
const Memory* parent() const { return parent_; }
protected:
//! Decrement map count
void decIndMapCount();
//! Initialize the object members
void init();
private:
//! Disable copy constructor
Memory(const Memory&);
//! Disable operator=
Memory& operator=(const Memory&);
InteropType interopType_; //!< Interop type
Memory* interopMemory_; //!< interop memory
HeapBlock* hb_; //!< Heap Block, or NULL if not in-heap memory
Memory* pinnedMemory_; //!< Memory used as pinned system memory
const Memory* parent_; //!< Parent memory object
};
class Buffer: public gpu::Memory
{
public:
//! Buffer constructor
Buffer(
const Device& gpuDev, //!< GPU device object
amd::Memory& owner, //!< Abstraction layer memory object
size_t size //!< Buffer size
)
: gpu::Memory(gpuDev, owner,
amd::alignUp(size, ElementSize) / ElementSize, ElementType)
{}
//! Creates a view from current resource
virtual Memory* createBufferView(
amd::Memory& subBufferOwner //!< The abstraction layer subbuf owner
) const;
private:
//! Disable copy constructor
Buffer(const Buffer&);
//! Disable operator=
Buffer& operator=(const Buffer&);
//! The size of buffer element in bytes
static const size_t ElementSize = 4;
//! The type of buffer element
static const cmSurfFmt ElementType = CM_SURF_FMT_R32I;
};
class Image: public gpu::Memory
{
public:
//! Image constructor
Image(
const Device& gpuDev, //!< GPU device object
amd::Memory& owner, //!< Abstraction layer memory object
size_t width, //!< Allocated memory width
size_t height, //!< Allocated memory height
size_t depth, //!< Allocated memory depth
cmSurfFmt format, //!< Memory format
gslChannelOrder chOrder, //!< Channel order
cl_mem_object_type imageType //!< CL image type
)
: gpu::Memory(gpuDev, owner, width, height, depth, format, chOrder, imageType)
{}
//! Image constructor
Image(
const Device& gpuDev, //!< GPU device object
size_t size, //!< Memory size
size_t width, //!< Allocated memory width
size_t height, //!< Allocated memory height
size_t depth, //!< Allocated memory depth
cmSurfFmt format, //!< Memory format
gslChannelOrder chOrder, //!< Channel order
cl_mem_object_type imageType //!< CL image type
)
: gpu::Memory(gpuDev, size, width, height, depth, format, chOrder, imageType)
{}
//! 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
size_t* rowPitch = NULL, //!< Row pitch for the mapped memory
size_t* slicePitch = NULL //!< Slice for the mapped memory
);
private:
//! Disable copy constructor
Image(const Image&);
//! Disable operator=
Image& operator=(const Image&);
};
} // namespace gpu
#endif // GPUMEMORY_HPP_
+722
View File
@@ -0,0 +1,722 @@
//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//
#include "top.hpp"
#include "os/os.hpp"
#include "device/device.hpp"
#include "device/gpu/gpudefs.hpp"
#include "device/gpu/gpumemory.hpp"
#include "device/gpu/gpukernel.hpp"
#include "device/gpu/gpuprogram.hpp"
#include "device/gpu/gpuprintf.hpp"
#include <cstdio>
#include <math.h>
namespace gpu {
PrintfDbg::PrintfDbg(Device& device, FILE* file)
: dbgBuffer_(NULL)
, dbgFile_(file)
, gpuDevice_(device)
, wiDbgSize_(0)
, initCntValue_(device, 1, CM_SURF_FMT_R32I)
{
}
PrintfDbg::~PrintfDbg()
{
delete dbgBuffer_;
}
bool
PrintfDbg::create()
{
// Create a resource for the init count value
if (initCntValue_.create(Resource::Remote)) {
uint32_t* value = reinterpret_cast<uint32_t*>(initCntValue_.map(NULL));
// The counter starts from 1
if (NULL != value) {
*value = 1;
}
else {
return false;
}
initCntValue_.unmap(NULL);
return true;
}
return false;
}
bool
PrintfDbg::init(
VirtualGPU& gpu,
bool printfEnabled,
const amd::NDRange& size)
{
// Set up debug output buffer (if printf active)
if (printfEnabled) {
if (!allocate()) {
return false;
}
// Make sure that the size isn't bigger than the reported max
if (size.product() <= dev().settings().maxWorkGroupSize_) {
size_t wiDbgSizeTmp;
// Calculate the debug buffer size per workitem
wiDbgSizeTmp = std::min(dbgBuffer_->size() / size.product(),
dev().xferRead().bufSize());
// Make sure the size is DWORD aligned
wiDbgSizeTmp = amd::alignDown(wiDbgSizeTmp, sizeof(uint32_t));
// If the new size is different, then clear the initial values
if (wiDbgSize_ != wiDbgSizeTmp) {
wiDbgSize_ = wiDbgSizeTmp;
if (!clearWorkitems(gpu, 0, size.product())) {
wiDbgSize_ = 0;
return false;
}
}
}
}
return true;
}
bool
PrintfDbg::output(
VirtualGPU& gpu,
bool printfEnabled,
const amd::NDRange& size,
const std::vector<PrintfInfo>& printfInfo)
{
// Are we expected to generate debug output?
if (printfEnabled) {
uint32_t* workitemData;
size_t i, j, k, z;
bool realloc = false;
// Wait for kernel execution
gpu.waitAllEngines();
size_t zdim = 1;
size_t ydim = 1;
size_t xdim = 1;
switch (size.dimensions()) {
case 3:
zdim = size[2];
// Fall through ...
case 2:
ydim = size[1];
// Fall through ...
case 1:
xdim = size[0];
// Fall through ...
default:
break;
}
for (k = 0; k < zdim; ++k) {
for (j = 0; j < ydim; ++j) {
for (i = 0; i < xdim; ++i) {
size_t idx = (xdim * (ydim * k + j) + i);
workitemData = mapWorkitem(gpu, idx, &realloc);
if (NULL != workitemData) {
uint32_t wp = workitemData[0]; // write pointer (i.e. first unwritten element)
// Walk through each PrintfDbg entry
for (z = 1; (z < (wiDbgSize() / sizeof(uint32_t))) && (z < wp); ) {
if (printfInfo.size() < workitemData[z]) {
LogError("The format string wasn't reported");
return false;
}
// Get the PrintfDbg info
const PrintfInfo& info = printfInfo[workitemData[z++]];
// There's something in this buffer
outputDbgBuffer(info, workitemData, z);
}
}
unmapWorkitem(gpu, workitemData);
}
}
}
// Reallocate debug buffer if necessary
if (!allocate(realloc)) {
return false;
}
}
return true;
}
uint64_t
PrintfDbg::bufOffset() const
{
return dbgBuffer_->hbOffset();
}
bool
PrintfDbg::allocate(bool realloc)
{
if (NULL == dbgBuffer_) {
dbgBuffer_ = dev().createScratchBuffer(dev().info().printfBufferSize_);
}
else if (realloc) {
LogWarning("Debug buffer reallocation!");
// Double the buffer size if it's not big enough
size_t size = dbgBuffer_->size();
delete dbgBuffer_;
dbgBuffer_ = dev().createScratchBuffer(size << 1);
}
return (NULL != dbgBuffer_) ? true : false;
}
bool
PrintfDbg::checkFloat(const std::string& fmt) const
{
switch (fmt[fmt.size() - 1]) {
case 'e':
case 'E':
case 'f':
case 'g':
case 'G':
case 'a':
return true;
break;
default:
break;
}
return false;
}
bool
PrintfDbg::checkString(const std::string& fmt) const
{
if (fmt[fmt.size() - 1] == 's')
return true;
return false;
}
int
PrintfDbg::checkVectorSpecifier(
const std::string& fmt,
size_t startPos,
size_t& curPos) const
{
int vectorSize = 0;
size_t pos = curPos;
size_t size = curPos - startPos;
if (size >= 3) {
size = 0;
//no modifiers
if (fmt[curPos - 3] == 'v') {
size = 2;
}
//the modifiers are "h" or "l"
else if (fmt[curPos - 4] == 'v') {
size = 3;
}
//the modifier is "hh"
else if ((curPos >= 5) && (fmt[curPos - 5] == 'v')) {
size = 4;
}
if (size > 0) {
curPos = size;
pos -= curPos;
// Get vector size
vectorSize = fmt[pos++] - '0';
// PrintfDbg supports only 2, 3, 4, 8 and 16 wide vectors
switch (vectorSize) {
case 1:
if ((fmt[pos++] - '0') == 6) {
vectorSize = 16;
}
else {
vectorSize = 0;
}
break;
case 2:
case 3:
case 4:
case 8:
break;
default:
vectorSize = 0;
break;
}
}
}
return vectorSize;
}
static const size_t ConstStr = 0xffffffff;
static const char Separator[] = ",\0";
size_t
PrintfDbg::outputArgument(
const std::string& fmt,
bool printFloat,
size_t size,
const uint32_t* argument) const
{
// Serialize the output to the screen
amd::ScopedLock k(dev().lockAsyncOps());
size_t copiedBytes = size;
// Print the string argument, using standard PrintfDbg()
if (checkString(fmt.c_str())) {
//copiedBytes should be as number of printed chars
copiedBytes = 0;
//(null) should be printed
if (*argument == 0) {
amd::Os::printf(fmt.data(),0);
//copiedBytes = strlen("(null)")
copiedBytes = 6;
}
else {
const unsigned char* argumentStr = reinterpret_cast<const unsigned char*>(argument);
amd::Os::printf(fmt.data(),argumentStr);
//copiedBytes = strlen(argumentStr)
while (argumentStr[copiedBytes++] != 0);
}
}
// Print the argument(except for string ), using standard PrintfDbg()
else {
bool hlModifier = (strstr(fmt.c_str(),"hl") != NULL);
std::string hlFmt;
if (hlModifier) {
hlFmt = fmt;
hlFmt.erase(hlFmt.find_first_of("hl"),2);
}
switch (size) {
case 0: {
const char* str = reinterpret_cast<const char*>(argument);
amd::Os::printf(fmt.data(), str);
// Find the string length
while (str[copiedBytes++] != 0);
}
break;
case 1:
amd::Os::printf(fmt.data(), *(reinterpret_cast<const unsigned char*>(argument)));
break;
case 2:
case 4:
if (printFloat) {
static const char* fSpecifiers = "eEfgGa";
std::string fmtF = fmt;
size_t posS = fmtF.find_first_of("%");
size_t posE = fmtF.find_first_of(fSpecifiers);
if (posS != std::string::npos &&posE != std::string::npos) {
fmtF.replace(posS+1,posE-posS,"s");
}
float fArg = *(reinterpret_cast<const float*>(argument));
float fSign = copysign(1.0,fArg);
if (isinf(fArg)&&!isnan(fArg)) {
if(fSign < 0) {
amd::Os::printf(fmtF.data(),"-infinity");
}
else {
amd::Os::printf(fmtF.data(),"infinity");
}
}
else if (isnan(fArg)) {
if(fSign < 0) {
amd::Os::printf(fmtF.data(),"-nan");
}
else {
amd::Os::printf(fmtF.data(),"nan");
}
}
else if (hlModifier) {
amd::Os::printf(hlFmt.data(),fArg);
}
else {
amd::Os::printf(fmt.data(),fArg);
}
}
else {
bool hhModifier = (strstr(fmt.c_str(),"hh") != NULL);
if (hhModifier) {
//current implementation of printf in gcc 4.5.2 runtime libraries, doesn`t recognize "hh" modifier ==>
//argument should be explicitly converted to unsigned char (uchar) before printing and
//fmt should be updated not to contain "hh" modifier
std::string hhFmt = fmt;
hhFmt.erase(hhFmt.find_first_of("h"),2);
amd::Os::printf(hhFmt.data(), *(reinterpret_cast<const unsigned char*>(argument)));
}
else if (hlModifier) {
amd::Os::printf(hlFmt.data(), *argument);
}
else {
amd::Os::printf(fmt.data(), *argument);
}
}
break;
case 8:
if (printFloat) {
if (hlModifier) {
amd::Os::printf(hlFmt.data(), *(reinterpret_cast<const double*>(argument)));
}
else {
amd::Os::printf(fmt.data(), *(reinterpret_cast<const double*>(argument)));
}
}
else {
std::string out = fmt;
// Use 'll' for 64 bit printf
out.insert((out.size() - 1), 1, 'l');
amd::Os::printf(out.data(), *(reinterpret_cast<const uint64_t*>(argument)));
}
break;
case ConstStr: {
const char* str = reinterpret_cast<const char*>(argument);
amd::Os::printf(fmt.data(), str);
}
break;
default:
amd::Os::printf("Error: Unsupported data size for PrintfDbg. %d bytes",
static_cast<int>(size));
return 0;
}
}
fflush(stdout);
return copiedBytes;
}
void
PrintfDbg::outputDbgBuffer(const PrintfInfo& info, const uint32_t* workitemData, size_t& i) const
{
static const char* specifiers = "cdieEfgGaosuxXp";
static const char* modifiers = "hl";
static const char* special = "%n";
static const std::string sepStr = "%s";
const uint32_t* s = workitemData;
size_t pos = 0;
// Find the format string
std::string str = info.fmtString_;
std::string fmt;
size_t posStart, posEnd;
// Print all arguments
// Note: the following code walks through all arguments, provided by the kernel and
// finds the corresponding specifier in the format string.
// Then it splits the original string into substrings with a single specifier and
// uses standard PrintfDbg() to print each argument
for (uint j = 0; j < info.arguments_.size(); ++j) {
do {
posStart = str.find_first_of("%", pos);
if (posStart != std::string::npos) {
posStart++;
// Erase all spaces after %
while (str[posStart] == ' ') {
str.erase(posStart, 1);
}
size_t tmp = str.find_first_of(special, posStart);
size_t tmp2 = str.find_first_of(specifiers, posStart);
// Special cases. Special symbol is located before any specifier
if (tmp < tmp2) {
posEnd = posStart + 1;
fmt = str.substr(pos, posEnd - pos);
fmt.erase(posStart - pos - 1, 1);
pos = posStart = posEnd;
outputArgument(sepStr, false, ConstStr,
reinterpret_cast<const uint32_t*>(fmt.data()));
continue;
}
break;
}
else if (pos < str.length()) {
outputArgument(sepStr, false, ConstStr,reinterpret_cast<const uint32_t*>((str.substr(pos)).data()));
}
}
while (posStart != std::string::npos);
if (posStart != std::string::npos) {
bool printFloat = false;
int vectorSize = 0;
size_t length;
size_t idPos = 0;
// Search for PrintfDbg specifier in the format string.
// It will be a split point for the output
posEnd = str.find_first_of(specifiers, posStart);
if (posEnd == std::string::npos) {
pos = posStart = posEnd;
break;
}
posEnd++;
size_t curPos = posEnd;
vectorSize = checkVectorSpecifier(str, posStart, curPos);
// Get substring from the last position to the current specifier
fmt = str.substr(pos, posEnd - pos);
// Readjust the string pointer if PrintfDbg outputs a vector
if (vectorSize != 0) {
size_t posVecSpec = fmt.length()-(curPos + 1);
size_t posVecMod = fmt.find_first_of(modifiers,posVecSpec + 1);
size_t posMod = str.find_first_of(modifiers,posStart);
if(posMod < posEnd){
fmt = fmt.erase(posVecSpec, posVecMod - posVecSpec);
}
else{
fmt = fmt.erase(posVecSpec, curPos);
}
idPos = posStart - pos - 1;
}
pos = posStart = posEnd;
// Find out if the argument is a float
printFloat = checkFloat(fmt);
// Is it a scalar value?
if (vectorSize == 0) {
length = outputArgument(fmt, printFloat, info.arguments_[j], &s[i]);
if (0 == length) {
return;
}
i += amd::alignUp(length, sizeof(uint32_t)) / sizeof(uint32_t);
}
else {
size_t elemSize;
size_t k = i * sizeof(uint32_t);
std::string elementStr = fmt.substr(idPos, fmt.size());
if (vectorSize == 3) {
// 3-component vector's size is defined as 4 * size of each scalar component
elemSize = info.arguments_[j] / 4;
}
else {
elemSize = info.arguments_[j] / vectorSize;
}
// Print first element with full string
if (0 == outputArgument(fmt, printFloat, elemSize, &s[i])) {
return;
}
// Print other elemnts with separator if available
for (int e = 1; e < vectorSize; ++e) {
const char* t = reinterpret_cast<const char*>(s);
// Output the vector separator
outputArgument(sepStr, false, ConstStr,
reinterpret_cast<const uint32_t*>(Separator));
// Output the next element
outputArgument(elementStr, printFloat, elemSize,
reinterpret_cast<const uint32_t*>(&t[k + e * elemSize]));
}
i += (amd::alignUp(info.arguments_[j], sizeof(uint32_t)))
/ sizeof(uint32_t);
}
}
else {
amd::Os::printf("Error: The arguments don't match the printf format string. printf(%s)",
info.fmtString_.data());
return;
}
}
if (pos != std::string::npos) {
fmt = str.substr(pos, str.size() - pos);
outputArgument(sepStr, false, ConstStr,
reinterpret_cast<const uint32_t*>(fmt.data()));
}
}
bool
PrintfDbg::clearWorkitems(VirtualGPU& gpu, size_t idxStart, size_t number) const
{
// Go through all locations for every thread and copy 1
for (uint i = idxStart; i < idxStart + number; ++i) {
amd::Coord3D dst(i * wiDbgSize(), 0, 0);
amd::Coord3D size(sizeof(uint32_t), 0, 0);
// Copy 1 into the corresponding location in the debug buffer
if (!initCntValue_.partialMemCopyTo(
gpu, amd::Coord3D(0, 0, 0), dst, size, *dbgBuffer_)) {
return false;
}
}
return true;
}
uint32_t*
PrintfDbg::mapWorkitem(VirtualGPU& gpu, size_t idx, bool* realloc)
{
uint32_t wiSize = 0;
amd::Coord3D src(idx * wiDbgSize(), 0, 0);
xferBufRead_ = &(dev().xferRead().acquire());
// Copy workitem size from the corresponding location in the debug buffer
if (!dbgBuffer_->partialMemCopyTo(gpu,
src, amd::Coord3D(0, 0, 0), amd::Coord3D(sizeof(uint32_t), 0, 0),
*xferBufRead_)) {
return NULL;
}
// Get memory pointer to the satged buffer
uint32_t* workitem = reinterpret_cast<uint32_t*>(xferBufRead_->map(&gpu));
if (NULL == workitem) {
return NULL;
}
// Copy size value
wiSize = *workitem;
xferBufRead_->unmap(&gpu);
// Check if the cuurent workitem almost reached the size limit
if ((wiDbgSize() - static_cast<size_t>(wiSize)) < 3) {
*realloc = true;
}
// If the current workitem had any output then get the data
if ((wiSize > 1) && (wiSize <= wiDbgSize())) {
amd::Coord3D size(wiSize * sizeof(uint32_t), 0, 0);
// Copy the current workitem output data to the staged buffer
if (!dbgBuffer_->partialMemCopyTo(
gpu, src, amd::Coord3D(0, 0, 0), size, *xferBufRead_) ||
// Clear the write pointer back to index 1 for the current workitem
!clearWorkitems(gpu, idx, 1)) {
LogError("Reading the workitem data failed!");
return NULL;
}
// Get a pointer to the workitem data
uint32_t* workitem = reinterpret_cast<uint32_t*>
(xferBufRead_->map(&gpu));
return workitem;
}
return NULL;
}
void
PrintfDbg::unmapWorkitem(VirtualGPU& gpu , const uint32_t* workitemData) const
{
if (NULL != workitemData) {
xferBufRead_->unmap(&gpu);
}
dev().xferRead().release(gpu, *xferBufRead_);
}
bool
PrintfDbgHSA::init(
VirtualGPU& gpu,
bool printfEnabled)
{
// Set up debug output buffer (if printf active)
if (printfEnabled) {
if (!allocate()) {
return false;
}
// The first two DWORDs in the printf buffer are as follows:
// First DWORD = Offset to where next information is to
// be written, initialized to 0
// Second DWORD = Number of bytes available for printf data
// = buffer size 2*sizeof(uint32_t)
const uint8_t initSize = 2*sizeof(uint32_t);
uint8_t sysMem[initSize];
memset(sysMem, 0, initSize);
uint32_t dbgBufferSize = dbgBuffer_->size() - initSize;
memcpy(&sysMem[4], &dbgBufferSize, sizeof(dbgBufferSize));
// Copy offset and number of bytes available for printf data
// into the corresponding location in the debug buffer
dbgBuffer_->writeRawData(gpu, initSize, sysMem, true);
}
return true;
}
bool
PrintfDbgHSA::output(
VirtualGPU& gpu,
bool printfEnabled,
const std::vector<PrintfInfo>& printfInfo)
{
if (printfEnabled) {
uint32_t offsetSize = 0;
xferBufRead_ = &(dev().xferRead().acquire());
// Copy offset from the first DWORD in the debug buffer
if (!dbgBuffer_->partialMemCopyTo(gpu,
amd::Coord3D(0, 0, 0), amd::Coord3D(0, 0, 0),
amd::Coord3D(sizeof(uint32_t), 0, 0),*xferBufRead_)) {
return false;
}
// Get memory pointer to the satged buffer
uint32_t* dbgBufferPtr = reinterpret_cast<uint32_t*>(xferBufRead_->map(&gpu));
if (NULL == dbgBufferPtr) {
return false;
}
offsetSize = *dbgBufferPtr;
xferBufRead_->unmap(&gpu);
if (offsetSize == 0) {
LogError("\n The printf buffer is empty!");
return false;
}
// Copy the buffer data (i.e., the printfID followed by the
//argument data for each printf call in th kernel) to the staged buffer
if (!dbgBuffer_->partialMemCopyTo(gpu,
amd::Coord3D(2*sizeof(uint32_t), 0, 0), amd::Coord3D(0, 0, 0),
offsetSize,*xferBufRead_)) {
return false;
}
// Get a pointer to the buffer data
dbgBufferPtr = reinterpret_cast<uint32_t*>(xferBufRead_->map(&gpu));
if (NULL == dbgBufferPtr) {
return false;
}
std::vector<uint>::const_iterator ita;
uint sb = 0;
uint sbt = 0;
size_t idx = 1;
// parse the debug buffer
while (sbt < offsetSize) {
assert(((*dbgBufferPtr) < printfInfo.size()) &&
"Cound't find the reported PrintfID!");
const PrintfInfo& info = printfInfo[(*dbgBufferPtr)];
sb += sizeof(uint32_t);
for (ita = info.arguments_.begin();
ita != info.arguments_.end(); ++ita){
sb += *ita;
}
// There's something in the debug buffer
outputDbgBuffer(info, dbgBufferPtr, idx);
sbt += sb;
dbgBufferPtr += sb/sizeof(uint32_t);
sb = 0;
}
xferBufRead_->unmap(&gpu);
dev().xferRead().release(gpu, *xferBufRead_);
}
return true;
}
} // namespace gpu
+193
View File
@@ -0,0 +1,193 @@
//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUPRINTFDBG_HPP_
#define GPUPRINTFDBG_HPP_
/*! \addtogroup GPU GPU Device Implementation
* @{
*/
#ifndef isinf
#ifdef _MSC_VER
#define isinf(X) (!_finite(X) && !_isnan(X))
#endif //_MSC_VER
#endif //isinf
#ifndef isnan
#ifdef _MSC_VER
#define isnan(X) (_isnan(X))
#endif //_MSC_VER
#endif //isnan
#ifndef copysign
#ifdef _MSC_VER
#define copysign(X,Y) (_copysign(X,Y))
#endif //_MSC_VER
#endif //copysign
//! GPU Device Implementation
namespace gpu {
//! Printf info structure
struct PrintfInfo
{
std::string fmtString_; //!< formated string for printf
std::vector<uint> arguments_; //!< passed arguments to the printf() call
};
class Kernel;
class VirtualGPU;
class Memory;
class PrintfDbg : public amd::HeapObject
{
public:
//! Debug buffer size per workitem
static const uint WorkitemDebugSize = 4096;
//! Default constructor
PrintfDbg(
Device& device,
FILE* file = NULL
);
//! Destructor
~PrintfDbg();
//! Creates the PrintfDbg object
bool create();
//! Initializes the debug buffer before kernel's execution
bool init(
VirtualGPU& gpu, //!< Virtual GPU object
bool printfEnabled, //!< checks for printf
const amd::NDRange& size //!< Kernel's workload
);
//! Prints the kernel's debug informaiton from the buffer
bool output(
VirtualGPU& gpu, //!< Virtual GPU object
bool printfEnabled, //!< checks for printf
const amd::NDRange& size, //!< Kernel's workload
const std::vector<PrintfInfo>& printfInfo //!< printf info
);
//! Returns the debug buffer offset
uint64_t bufOffset() const;
//! Debug buffer size per workitem
size_t wiDbgSize() const { return wiDbgSize_; }
//! Returns debug buffer object
Memory* dbgBuffer() const { return dbgBuffer_; }
protected:
Memory* dbgBuffer_; //!< Buffer to hold debug output
FILE* dbgFile_; //!< Debug file
Device& gpuDevice_; //!< GPU device object
Resource* xferBufRead_; //!< Transfer buffer for the dump read
//! Gets GPU device object
Device& dev() const { return gpuDevice_; }
//! Allocates the debug buffer
bool allocate(
bool realloc = false //!< If TRUE then reallocate the debug memory
);
//! Returns TRUE if a float value has to be printed
bool checkFloat(
const std::string& fmt //!< Format string
) const;
//! Returns TRUE if a string value has to be printed
bool checkString(
const std::string& fmt //!< Format string
) const;
//! Finds the specifier in the format string
int checkVectorSpecifier(
const std::string& fmt, //!< Format string
size_t startPos, //!< Start position for processing
size_t& curPos //!< End position for processing
) const;
//! Outputs an argument
size_t outputArgument(
const std::string& fmt, //!< Format strint
bool printFloat, //!< Argument is a float value
size_t size, //!< Argument's size
const uint32_t* argument //!< Argument's location
) const;
//! Displays the PrintfDbg
void outputDbgBuffer(
const PrintfInfo& info, //!< printf info
const uint32_t* workitemData, //!< The PrintfDbg dump buffer
size_t& i //!< index to the data in the buffer
) const;
private:
//! Disable copy constructor
PrintfDbg(const PrintfDbg&);
//! Disable assignment
PrintfDbg& operator=(const PrintfDbg&);
//! Returns the pointer to the workitem data block
bool clearWorkitems(
VirtualGPU& gpu, //!< Virtual GPU object
size_t idxStart, //!< Workitem global index start
size_t number //!< Number of workitems to clear
) const;
//! Returns the pointer to the workitem data block
uint32_t* mapWorkitem(
VirtualGPU& gpu, //!< Virtual GPU object
size_t idx, //!< Workitem global index
bool* realloc //!< Returns TRUE if workitem reached the buffer limit
);
//! Unamp the staged buffer
void unmapWorkitem(
VirtualGPU& gpu, //!< Virtual GPU object
const uint32_t* workitemData //!< The PrintfDbg dump buffer
) const;
size_t wiDbgSize_; //!< Workitem debug size
Resource initCntValue_; //!< Initialized count value
};
class PrintfDbgHSA : public PrintfDbg
{
public:
//! Default constructor
PrintfDbgHSA(
Device& device,
FILE* file = NULL
): PrintfDbg(device, file) { }
//! Initializes the debug buffer before kernel's execution
bool init(
VirtualGPU& gpu, //!< Virtual GPU object
bool printfEnabled //!< checks for printf
);
//! Prints the kernel's debug informaiton from the buffer
bool output(
VirtualGPU& gpu, //!< Virtual GPU object
bool printfEnabled, //!< checks for printf
const std::vector<PrintfInfo>& printfInfo //!< printf info
);
private:
//! Disable copy constructor
PrintfDbgHSA(const PrintfDbgHSA&);
//! Disable assignment
PrintfDbgHSA& operator=(const PrintfDbgHSA&);
};
/*@}*/} // namespace gpu
#endif /*GPUPRINTFDBG_HPP_*/
File diff suppressed because it is too large Load Diff
+494
View File
@@ -0,0 +1,494 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUPROGRAM_HPP_
#define GPUPROGRAM_HPP_
#include "device/gpu/gpukernel.hpp"
#include "device/gpu/gpubinary.hpp"
namespace amd {
namespace option {
class Options;
} // option
} // amd
//! \namespace gpu GPU Device Implementation
namespace gpu {
/*! \addtogroup GPU GPU Device Implementation
* @{
*/
//! \struct ILFunc for the opencl program processing
struct ILFunc : public amd::HeapObject
{
public:
//! \struct CodeRange for the code ranges
struct SourceRange : public amd::EmbeddedObject
{
size_t begin_; //!< start code position
size_t end_; //!< end code position
};
//! \enum IL function state
enum State
{
Unknown = 0x00000000, //! unknown function
Regular = 0x00000001, //! regular function from the program
Kernel = 0x00000002 //! kernel function from the program
};
//! Default constructor
ILFunc()
: name_("")
, index_(0)
, state_(Unknown)
, privateSize_(0)
, localSize_(0)
, hwPrivateSize_(0)
, hwLocalSize_(0)
, flags_(0)
{
code_.begin_ = code_.end_ = 0;
metadata_.begin_ = metadata_.end_ = 0;
}
//! Copy constructor
ILFunc(const ILFunc& func) { *this = func; }
//! Destructor
~ILFunc() {}
//! Overloads operator=
ILFunc& operator=(const ILFunc& func)
{
name_ = func.name_;
index_ = func.index_;
code_ = func.code_;
metadata_ = func.metadata_;
state_ = func.state_;
privateSize_ = func.privateSize_;
localSize_ = func.localSize_;
hwPrivateSize_ = func.hwPrivateSize_;
hwLocalSize_ = func.hwLocalSize_;
flags_ = func.flags_;
// Note: we don't copy calls_ and macros_
return *this;
}
std::string name_; //!< kernel's name
uint index_; //!< kernel's index
SourceRange code_; //!< the entire function range in the source
SourceRange metadata_; //!< the metadata range
State state_; //!< the function is real, and not intrinsic
uint privateSize_; //!< private ring allocation by the function
uint localSize_; //!< local ring allocation by the function
uint hwPrivateSize_; //!< HW private ring allocation by the function
uint hwLocalSize_; //!< HW local ring allocation by the function
uint flags_; //!< The IL func flags/properties
std::vector<const ILFunc*> calls_; //! Functions called from the current
std::vector<uint> macros_; //! Macros, used in the IL function
};
//! \class empty program
class NullProgram : public device::Program
{
friend class ClBinary;
public:
//! Default constructor
NullProgram(NullDevice& nullDev) : device::Program(nullDev) , patch_(0) {}
//! Default destructor
~NullProgram();
// Initialize Binary for GPU
virtual bool initClBinary();
// Release Binary for GPU
virtual void releaseClBinary();
//! Returns global constant buffers
const std::vector<uint>& glbCb() const { return glbCb_; }
protected:
//! pre-compile setup for GPU
virtual bool initBuild(amd::option::Options* options);
//! post-compile setup for GPU
virtual bool finiBuild(bool isBuildGood);
/*! \brief Compiles GPU CL program to LLVM binary (compiler frontend)
*
* \return True if we successefully compiled a GPU program
*/
virtual bool compileImpl(
const std::string& sourceCode, //!< the program's source code
const std::vector<const std::string*>& headers, //!< header souce codes
const char** headerIncludeNames,//!< include names of headers
amd::option::Options* options //!< compile options's object
);
/*! \brief Compiles LLVM binary to IL code (compiler backend: link+opt+codegen)
*
* \return The build error code
*/
int compileBinaryToIL(
amd::option::Options* options //!< options for compilation
);
/*! \brief Links the compiled IL program with HW
*
* \return True if we successefully linked a GPU program
*/
virtual bool linkImpl(
amd::option::Options* options = NULL //!< options object
);
virtual bool linkImpl(
const std::vector<device::Program*>& inputPrograms,
amd::option::Options* options = NULL, //!< options object
bool createLibrary = false
);
virtual bool createBinary(amd::option::Options* options);
/*! \brief Parses the GPU program and finds all available kernels
*
* \return True if we successefully parsed the GPU program
*/
bool parseKernels(
const std::string& source //! the program's source code
);
/*! \brief Parse all functions in the program
*
* \return True if we successefully parsed all functions
*/
bool parseAllILFuncs(
const std::string& source //! the program's source code
);
/*! \brief Parse a function's metadata given as source[posBegin:posEnd-1]
*
* \return True if we successefully parsed the given metadata
*/
bool parseFuncMetadata(
const std::string& source, //! string that contains metadata
size_t posBegin, //! begin of metadata in 'source'
size_t posEnd //! end of metadata in 'source'
);
/*! \brief Finds functions with the given start and end string in the
* program
*
* \return True if we successefully found all functions
*/
bool findILFuncs(
const std::string& source, //! the program's source code
const std::string& func_start, //! the start string of a function
const std::string& func_end, //! the end string of a function
size_t& lastFuncPos //! pos to the end of the last func in 'source'
);
/*! \brief Finds all functions in the program
*
* \return True if we successefully found all functions
*/
bool findAllILFuncs(
const std::string& source, //! the program's source code
size_t& lastFuncPos //! pos to the end of the last func in 'source'
);
/*! \brief Finds function, corresponded to the provided unique index
*
* \return Pointer to the ILFunc structure
*/
ILFunc* findILFunc(
uint index //! the function unique index
);
//! Destroys all objects, associated with the IL functions
void freeAllILFuncs();
/*! \brief Finds if a provided function is called from the base function
*
* \return True if a function is used from the base one
*/
bool isCalled(
const ILFunc* base, //!< The base function
const ILFunc* func //!< Function to check for usage
);
//! Patches the "main" function with the call to the current kernel
void patchMain(
std::string& kernel, //! The current kernel's code for compilation
uint index //! Index of the current kernel in the program
);
//! Adds the IL function object into the list of functions
void addFunc(ILFunc* func) { funcs_.push_back(func); }
//! Empty implementation, since we don't have real HW
virtual bool allocGlobalData(
const void* globalData, //!< Pointer to the global data
size_t dataSize, //!< The global data size
uint index //!< Index for the global data store (0 - global heap)
) { glbCb_.push_back(index); return true; }
//! Load binary for offline device.
virtual bool loadBinary(bool *hasRecompiled);
//! Create NullKernel for compiling to isa.
virtual NullKernel* createKernel(
const std::string& name, //!< The kernel's name
const Kernel::InitData* initData, //!< Initialization data
const std::string& code, //!< IL source code
const std::string& metadata, //!< the kernel metadata structure
bool* created, //!< True if the object was created
const void* binaryCode = NULL, //!< binary machine code for CAL
size_t binarySize = 0 //!< the machine code size
);
ClBinary* clBinary() {
return static_cast<ClBinary*>(device::Program::clBinary());
}
const ClBinary* clBinary() const {
return static_cast<const ClBinary*>(device::Program::clBinary());
}
/*! Get all per-kernel IL from programIL, where programIL is the IL for the
* whole compilation unit.
*/
bool getAllKernelILs(std::map<std::string, std::string>& allKernelILs,
std::string& programIL, const char* ilKernelName);
protected:
std::vector<PrintfInfo> printf_; //!< Format strings for GPU printf support
std::vector<uint> glbCb_; //!< Global constant buffers
virtual bool isElf(const char* bin) const {
return amd::isElfMagic(bin);
}
virtual const aclTargetInfo & info(const char * str = "");
private:
//! Disable default copy constructor
NullProgram(const NullProgram&);
//! Disable operator=
NullProgram& operator=(const NullProgram&);
//! Initializes the global data store
bool initGlobalData(
const std::string& source, //!< the program's source code
size_t start //!< start position for the global data search
);
//! Return a typecasted GPU device
gpu::NullDevice& dev()
{ return const_cast<gpu::NullDevice&>(
static_cast<const gpu::NullDevice&>(device())); }
size_t patch_; //!< Patch call position in the source code.
std::vector<ILFunc*> funcs_; //!< list of all functions.
std::string ilProgram_; //!< IL program after compilation
};
//! \class GPU program
class Program : public NullProgram
{
public:
//! GPU program constructor
Program(Device& gpuDev)
: NullProgram(gpuDev)
, glbData_(NULL)
{}
//! GPU program destructor
~Program();
//! Get the global data store for this program
gpu::Memory* glbData() const { return glbData_; }
//! Returns TRUE if we successfully allocated the global data store
//! in video memory
bool allocGlobalData(
const void* globalData, //!< Pointer to the global data
size_t dataSize, //!< The global data size
uint index //!< Index for the global data store (0 - global heap)
);
//! Returns TRUE if we could
virtual bool loadBinary(bool* hasRecompiled);
//! Creates the GPU kernel (return base type)
virtual NullKernel* createKernel(
const std::string& name, //!< The kernel's name
const Kernel::InitData* initData, //!< Initialization data
const std::string& code, //!< IL source code
const std::string& metadata, //!< the kernel metadata structure
bool* created, //!< True if the object was created
const void* binaryCode = NULL, //!< binary machine code for CAL
size_t binarySize = 0 //!< the machine code size
);
typedef std::map<uint, gpu::Memory*> HwConstBuffers;
//! Global HW constant buffers
const HwConstBuffers& glbHwCb() const { return constBufs_; }
//! Returns pritnf info array
const std::vector<PrintfInfo>& printfInfo() const { return printf_; }
//! Return a typecasted GPU device
gpu::Device& dev()
{ return const_cast<gpu::Device&>(
static_cast<const gpu::Device&>(device())); }
protected:
private:
//! Disable copy constructor
Program(const Program&);
//! Disable operator=
Program& operator=(const Program&);
HwConstBuffers constBufs_; //!< Constant buffers for the global store
gpu::Memory* glbData_; //!< Global data store
};
//! \class HSAIL program
class HSAILProgram : public device::Program
{
friend class ClBinary;
public:
//! Default constructor
HSAILProgram(Device& device);
//! Default destructor
~HSAILProgram();
//! Returns the aclBinary associated with the progrm
aclBinary* binaryElf() const {
return static_cast<aclBinary*>(binaryElf_); }
void setGlobalStore(Memory* mem) { globalStore_ = mem; }
const Memory* globalStore() const { return globalStore_; }
//! Return a typecasted GPU device
gpu::Device& dev()
{ return const_cast<gpu::Device&>(
static_cast<const gpu::Device&>(device())); }
//! Returns GPU kernel table
const Memory* kernelTable() const { return kernels_; }
//! Adds all kernels to the mem handle lists
void fillResListWithKernels(std::vector<const Resource*>& memList) const;
//! Returns the maximum number of scratch regs used in the program
uint maxScratchRegs() const { return maxScratchRegs_; }
//! Add internal static sampler
void addSampler(Sampler* sampler) { staticSamplers_.push_back(sampler); }
protected:
//! pre-compile setup for GPU
virtual bool initBuild(amd::option::Options* options);
//! post-compile setup for GPU
virtual bool finiBuild(bool isBuildGood);
/*! \brief Compiles GPU CL program to LLVM binary (compiler frontend)
*
* \return True if we successefully compiled a GPU program
*/
virtual bool compileImpl(
const std::string& sourceCode, //!< the program's source code
const std::vector<const std::string*>& headers,
const char** headerIncludeNames,
amd::option::Options* options //!< compile options's object
);
aclType getNextCompilationStageFromBinary();
/*! \brief Compiles LLVM binary to FSAIL code (compiler backend: link+opt+codegen)
*
* \return The build error code
*/
int compileBinaryToFSAIL(
amd::option::Options* options //!< options for compilation
);
virtual bool linkImpl(amd::option::Options* options);
//! Link the device programs.
virtual bool linkImpl (const std::vector<device::Program*>& inputPrograms,
amd::option::Options* options,
bool createLibrary);
virtual bool createBinary(amd::option::Options* options);
//! Initialize Binary
virtual bool initClBinary();
//! Release the Binary
virtual void releaseClBinary();
virtual const aclTargetInfo & info(const char * str = "") {
return info_;
}
virtual bool isElf(const char* bin) const {
return amd::isElfMagic(bin);
//return false;
}
//! Returns the binary
// This should ensure that the binary is updated with all the kernels
// ClBinary& clBinary() { return binary_; }
ClBinary* clBinary() {
return static_cast<ClBinary*>(device::Program::clBinary());
}
const ClBinary* clBinary() const {
return static_cast<const ClBinary*>(device::Program::clBinary());
}
private:
//! Disable default copy constructor
HSAILProgram(const HSAILProgram&);
//! Disable operator=
HSAILProgram& operator=(const HSAILProgram&);
//! Returns all the options to be appended while passing to the
//compiler library
std::string hsailOptions();
//! Allocate kernel table
bool allocKernelTable();
std::string openCLSource_; //!< Original OpenCL source
std::string HSAILProgram_; //!< FSAIL program after compilation
std::string llvmBinary_; //!< LLVM IR binary code
aclBinary* binaryElf_; //!< Binary for the new compiler library
void* rawBinary_; //!< Pointer to the raw binary
aclBinaryOptions binOpts_; //!< Binary options to create aclBinary
Memory* globalStore_; //!< Global memory for the program
Memory* kernels_; //!< Table with kernel object pointers
uint maxScratchRegs_; //!< Maximum number of scratch regs used in the program by individual kernel
std::list<Sampler*> staticSamplers_; //!< List od internal static samplers
};
/*@}*/} // namespace gpu
#endif /*GPUPROGRAM_HPP_*/
File diff suppressed because it is too large Load Diff
+508
View File
@@ -0,0 +1,508 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPURESOURCE_HPP_
#define GPURESOURCE_HPP_
#include "platform/command.hpp"
#include "platform/program.hpp"
#include "device/gpu/gpudefs.hpp"
//! \namespace gpu GPU Resource Implementation
namespace gpu {
class Device;
class VirtualGPU;
/*! \addtogroup GPU GPU Resource Implementation
* @{
*/
class GslResourceReference : public amd::ReferenceCountedObject
{
public:
//! Default constructor
GslResourceReference(
const Device& gpuDev, //!< GPU device object
gslMemObject gslResource, //!< CAL resource
gslMemObject gslResOriginal = NULL //!< Original CAL resource
);
//! Get CAL resource
gslMemObject gslResource() const { return resource_; }
//! Original CAL resource
gslMemObject gslOriginal() const { return (resOriginal_ == 0) ? resource_ : resOriginal_; }
const Device& device_; //!< GPU device
gslMemObject resource_; //!< GSL resource object
gslMemObject resOriginal_; //!< Original resource object, NULL if no channel order
void* cpuAddress_; //!< CPU address of this memory
protected:
//! Default destructor
~GslResourceReference();
private:
//! Disable copy constructor
GslResourceReference(const GslResourceReference&);
//! Disable operator=
GslResourceReference& operator=(const GslResourceReference&);
};
//! GPU resource
class Resource : public amd::HeapObject
{
public:
enum InteropType {
InteropTypeless = 0,
InteropVertexBuffer,
InteropIndexBuffer,
InteropRenderBuffer,
InteropTexture,
InteropTextureViewLevel,
InteropTextureViewCube,
InteropSurface
};
struct CreateParams : public amd::StackObject {
amd::Memory* owner_; //!< Resource's owner
VirtualGPU* gpu_; //!< Resource won't be shared between multiple queues
CreateParams(): owner_(NULL), gpu_(NULL) {}
};
struct PinnedParams : public CreateParams {
const amd::HostMemoryReference* hostMemRef_;//!< System memory pointer for pinning
size_t size_; //!< System memory size
};
struct ViewParams : public CreateParams {
size_t offset_; //!< Alias resource offset
size_t size_; //!< Alias resource size
const Resource* resource_; //!< Parent resource for the view creation
const void* memory_;
};
struct ImageViewParams : public CreateParams {
size_t level_; //!< Image mip level for a new view
size_t layer_; //!< Image layer for a new view
const Resource* resource_; //!< Parent resource for the view creation
const void* memory_;
};
struct ImageBufferParams : public CreateParams {
const Resource* resource_; //!< Parent resource for the image creation
const void* memory_;
};
struct OGLInteropParams : public CreateParams {
InteropType type_; //!< OGL resource type
CALuint handle_; //!< OGL resource handle
uint mipLevel_; //!< Texture mip level
uint layer_; //!< Texture layer
void* glPlatformContext_;
void* glDeviceContext_;
uint flags_;
};
#ifdef _WIN32
struct D3DInteropParams : public CreateParams {
InteropType type_; //!< D3D resource type
void* iDirect3D_; //!< D3D resource interface object
HANDLE handle_; //!< D3D resource handle
uint mipLevel_; //!< Texture mip level
int layer_; //!< Texture layer
uint misc; //!< miscellaneous cases
};
#endif // _WIN32
//! Resource memory
enum MemoryType
{
Empty = 0x0, //!< resource is empty
Local, //!< resource in local memory
Persistent, //!< resource in persistent memory
Remote, //!< resource in nonlocal memory
RemoteUSWC, //!< resource in nonlocal memory
Pinned, //!< resource in pinned system memory
View, //!< resource is an alias
OGLInterop, //!< resource is an OGL memory object
D3D10Interop, //!< resource is a D3D10 memory object
D3D11Interop, //!< resource is a D3D11 memory object
Heap, //!< resource is a heap
ImageView, //!< resource is a view to some image
ImageBuffer, //!< resource is an image view of a buffer
BusAddressable, //!< resource is a bus addressable memory
ExternalPhysical, //!< resource is an external physical memory
D3D9Interop, //!< resource is a D3D9 memory object
Scratch //!< resource is scratch memory
};
//! Resource map flags
enum MapFlags
{
Discard = 0x00000001, //!< discard lock
NoOverwrite = 0x00000002, //!< lock with no overwrite
ReadOnly = 0x00000004, //!< lock for read only operation
WriteOnly = 0x00000008, //!< lock for write only operation
NoWait = 0x00000010, //!< lock with no wait
};
//! CAL resource descriptor
struct CalResourceDesc : public amd::HeapObject
{
MemoryType type_; //!< Memory type
size_t width_; //!< CAL resource width
size_t height_; //!< CAL resource height
size_t depth_; //!< CAL resource depth
cmSurfFmt format_; //!< GSL resource format
CALuint flags_; //!< CAL resource flags, used in creation
size_t pitch_; //!< CAL resource pitch, valid if locked
CALuint slice_; //!< CAL resource slice, valid if locked
gslChannelOrder channelOrder_; //!< GSL resource channel order
gslMemObjectAttribType dimension_; //!< GSL resource dimension
cl_mem_object_type imageType_; //!< CL image type
union {
struct {
uint dimSize_ : 2; //!< Dimension size
uint cardMemory_ : 1; //!< GSL resource is in video memory
uint imageArray_ : 1; //!< GSL resource is an array of images
uint buffer_ : 1; //!< GSL resource is a buffer
uint tiled_ : 1; //!< GSL resource is tiled
uint SVMRes_ : 1; //!< SVM flag to the cal resource
};
uint state_;
};
};
//! Constructor of 1D Resource object
Resource(
const Device& gpuDev, //!< GPU device object
size_t width, //!< resource width
cmSurfFmt format //!< resource format
);
//! Constructor of Image Resource object
Resource(
const Device& gpuDev, //!< GPU device object
size_t width, //!< resource width
size_t height, //!< resource height
size_t depth, //!< resource depth
cmSurfFmt format, //!< resource format
gslChannelOrder chOrder, //!< resource channel order
cl_mem_object_type imageType //!< CL image type
);
//! Destructor of the resource
virtual ~Resource();
/*! \brief Creates a CAL object, associated with the resource
*
* \return True if we succesfully created a CAL resource
*/
virtual bool create(
MemoryType memType, //!< memory type
CreateParams* params = 0, //!< special parameters for resource allocation
bool heap = false //!< Global heap allocation for not VM mode
);
/*! \brief Reallocates a CAL object, associated with the resource
*
* \return True if we succesfully reallocated a CAL resource
*/
bool reallocate(
CreateParams* params = 0 //!< special parameters for resource allocation
);
/*! \brief Copies a subregion of memory from one resource to another
*
* This is a general copy from anything to anything (as long as it fits).
* All positions and sizes are given in bytes. Note, however, that only
* a subset of this general interface is currently implemented.
*
* \return true if successful
*/
bool partialMemCopyTo(
VirtualGPU& gpu, //!< Virtual GPU device object
const amd::Coord3D& srcOrigin, //!< Origin of the source region
const amd::Coord3D& dstOrigin, //!< Origin of the destination region
const amd::Coord3D& size, //!< Size of the region to copy
Resource& dstResource, //!< Destination resource
bool enableRectCopy = false, //!< Rectangular DMA support
bool flushDMA = false //!< Flush DMA if requested
) const;
/*! \brief Copies size/4 DWORD of memory to a surface
*
* This is a raw copy to any surface using a CP packet.
* Size needs to be atleast a DWORD or multiple
*
*/
void writeRawData(
VirtualGPU& gpu, //!< Virtual GPU device object
size_t size, //!< Size in bytes of data to be copied(multiple of DWORDS)
const void* data, //!< Data to be copied
bool waitForEvent //!< Wait for event complete
) const;
//! Returns the offset in GPU memory for aliases
size_t offset() const { return offset_; }
//! Returns the offset in GPU heap
uint64_t hbOffset() const { return hbOffset_; }
//! Returns the pinned memory offset
uint64_t pinOffset() const { return pinOffset_; }
//! Returns the size in GPU heap
uint64_t hbSize() const { return hbSize_; }
//! Returns the GPU device that owns this resource
const Device& dev() const { return gpuDevice_; }
//! Returns the CAL descriptor for resource
const CalResourceDesc* cal() const { return &cal_; }
//! Returns the CAL resource handle
gslMemObject gslResource() const { return gslRef_->gslResource(); }
//! Returns global memory offset
uint64_t vmAddress() const { return gslResource()->getSurfaceAddress(); }
//! Checks if persistent memory can have a direct map
bool isPersistentDirectMap() const;
/*! \brief Locks the resource and returns a physical pointer
*
* \note This operation stalls HW pipeline!
*
* \return Pointer to the physical memory
*/
void* map(
VirtualGPU* gpu, //!< Virtual GPU device object
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
);
//! Unlocks the resource if it was locked
void unmap(
VirtualGPU* gpu //!< Virtual GPU device object
);
//! Marks the resource as busy
void setBusy(
VirtualGPU& gpu, //!< Virtual GPU device object
GpuEvent calEvent //!< CAL event
) const;
//! Wait for the resource
void wait(
VirtualGPU& gpu, //!< Virtual GPU device object
bool waitOnBusyEngine = false//!< Wait only if engine has changed
) const;
//! Performs host write to the resource GPU memory
bool hostWrite(
VirtualGPU* gpu, //!< Virtual GPU device object
const void* hostPtr, //!< Host pointer to the SRC data
const amd::Coord3D& origin, //!< Offsets for the update
const amd::Coord3D& size, //!< The number of bytes to write
uint flags = 0, //!< Map flags
size_t rowPitch = 0, //!< Raw data row pitch
size_t slicePitch = 0 //!< Raw data slice pitch
);
//! Performs host read from the resource GPU memory
bool hostRead(
VirtualGPU* gpu, //!< Virtual GPU device object
void* hostPtr, //!< Host pointer to the DST data
const amd::Coord3D& origin, //!< Offsets for the update
const amd::Coord3D& size, //!< The number of bytes to write
size_t rowPitch = 0, //!< Raw data row pitch
size_t slicePitch = 0 //!< Raw data slice pitch
);
//! Warms up the rename list for this resource
void warmUpRenames(VirtualGPU& gpu);
//! Gets the resource element size
size_t elementSize() const { return elementSize_; }
//! Get the mapped address of this resource
address data() const { return reinterpret_cast<address>(address_); }
//! Frees all allocated CAL memories and resources,
//! associated with this objects. And also destroys all rename structures
//! Note: doesn't destroy the object itself
void free();
//! Return memory type
MemoryType memoryType() const { return cal_.type_; }
//! Retunrs true if memory type matches specified
bool isMemoryType(MemoryType memType) const;
//! Returns TRUE if resource was allocated as cacheable
bool isCacheable() const
{ return (isMemoryType(Remote) || isMemoryType(Pinned)) ? true : false; }
//! Returns alias memory object
Resource* getAliasUAVBuffer(cmSurfFmt newFormat);
bool gslGLAcquire() ;
bool gslGLRelease() ;
//! Returns HW state for the resource (used for images only)
const void* hwState() const { return hwState_; }
//! Returns CPU HW SRD for the resource (used for images only)
uint64_t hwSrd() const { return hwSrd_; }
protected:
size_t elementSize_; //!< Size of a single element in bytes
private:
//! Disable copy constructor
Resource(const Resource&);
//! Disable operator=
Resource& operator=(const Resource&);
typedef std::vector<GslResourceReference*> RenameList;
//! Rename current resource
bool rename(
VirtualGPU& gpu, //!< Virtual GPU device object
bool force = false //!< Force renaming
);
//! Sets the rename as active
void setActiveRename(
VirtualGPU& gpu, //!< Virtual GPU device object
GslResourceReference* rename //!< new active rename
);
//! Gets the active rename
bool getActiveRename(
VirtualGPU& gpu, //!< Virtual GPU device object
GslResourceReference** rename //!< Saved active rename
);
/*! \brief Locks the resource with layers and returns a physical pointer
*
* \return Pointer to the physical memory
*/
void* mapLayers(
VirtualGPU* gpu, //!< Virtual GPU device object
CALuint flags = 0 //!< flags for the map operation
);
//! Unlocks the resource with layers if it was locked
void unmapLayers(
VirtualGPU* gpu //!< Virtual GPU device object
);
//! Calls GSL to map a resource
bool gslMap(
void** ptr, //!< Pointer to virtual address
size_t* pitch, //!< Pitch value for the image
gslMapAccessType flags, //!< Map flags
gslMemObject resource //!< GSL memory object
) const;
//! Uses GSL to unmap a resource
bool gslUnmap(
gslMemObject resource //!< GSL memory object
) const;
//! Fress all GSL resources associated with OCL resource
void gslFree() const;
const Device& gpuDevice_; //!< GPU device
CalResourceDesc cal_; //!< CAL descriptor for this resource
amd::Atomic<int> mapCount_; //!< Total number of maps
void* address_; //!< Physical address of this resource
size_t offset_; //!< Resource offset
size_t curRename_; //!< Current active rename in the list
RenameList renames_; //!< Rename resource list
GslResourceReference* gslRef_; //!< GSL resource reference
const Resource* viewOwner_; //!< GPU resource, which owns this view
uint64_t hbOffset_; //!< Offset in the heap (virtual or real)
uint64_t hbSize_; //!< Memory size
uint64_t pinOffset_; //!< Pinned memory offset
Resource* byteView_; //!< Byte view memory object
Resource* shortView_; //!< Short view memory object
gslMemObject glInterop_; //!< Original GL interop object
void* glInteropMbRes_;//!< Mb Res handle
CALResGLBufferType glType_; //!< GL interop type
void* glPlatformContext_;
void* glDeviceContext_;
// Optimization for multilayer map/unmap
uint startLayer_; //!< Start layer for map/unmapLayer
uint numLayers_; //!< Number of layers for map/unmapLayer
CALuint mapFlags_; //!< Map flags for map/umapLayer
//! @note: This field is necessary for the thread safe release only
VirtualGPU* gpu_; //!< Resource will be used only on this queue
uint32_t* hwState_; //!< HW state for image object
uint64_t hwSrd_; //!< GPU pointer to HW SRD
};
class ResourceCache : public amd::HeapObject
{
public:
//! Default constructor
ResourceCache(size_t cacheSizeLimit)
: lockCacheOps_("CAL resource cache", true)
, cacheSize_(0)
, cacheSizeLimit_(cacheSizeLimit)
{}
//! Default destructor
~ResourceCache();
//! Adds a CAL resource to the cache
bool addCalResource(
Resource::CalResourceDesc* desc, //!< CAL resource descriptor - cache key
GslResourceReference* ref //!< CAL resource reference
);
//! Finds a CAL resource from the cache
GslResourceReference* findCalResource(
Resource::CalResourceDesc* desc //!< CAL resource descriptor - cache key
);
//! Destroys cache
bool free(size_t minCacheEntries = 0);
private:
//! Disable copy constructor
ResourceCache(const ResourceCache&);
//! Disable operator=
ResourceCache& operator=(const ResourceCache&);
//! Gets resource size in bytes
size_t getResourceSize(Resource::CalResourceDesc* desc);
//! Removes one last entry from the cache
void removeLast();
amd::Monitor lockCacheOps_; //!< Lock to serialise cache access
size_t cacheSize_; //!< Current cache size in bytes
size_t cacheSizeLimit_; //!< Cache size limit in bytes
//! CAL resource cache
std::list<std::pair<Resource::CalResourceDesc*, GslResourceReference*> > resCache_;
};
/*@}*/} // namespace gpu
#endif /*GPURESOURCE_HPP_*/
+73
View File
@@ -0,0 +1,73 @@
//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUSCHED_HPP_
#define GPUSCHED_HPP_
#include "newcore.h"
namespace gpu {
//! AmdAqlWrap slot state
enum AqlWrapState {
AQL_WRAP_FREE = 0,
AQL_WRAP_RESERVED,
AQL_WRAP_READY,
AQL_WRAP_MARKER,
AQL_WRAP_BUSY,
AQL_WRAP_DONE
};
struct AmdVQueueHeader {
uint32_t aql_slot_num; //!< [LRO/SRO] The total number of the AQL slots (multiple of 64).
uint32_t event_slot_num; //!< [LRO] The number of kernel events in the events buffer
uint64_t event_slot_mask; //!< [LRO] A pointer to the allocation bitmask array for the events
uint64_t event_slots; //!< [LRO] Pointer to a buffer for the events.
// Array of event_slot_num entries of AmdEvent
uint64_t aql_slot_mask; //!< [LRO/SRO]A pointer to the allocation bitmask for aql_warp slots
uint32_t command_counter; //!< [LRW] The global counter for the submitted commands into the queue
uint32_t wait_size; //!< [LRO] The wait list size (in clk_event_t)
uint32_t arg_size; //!< [LRO] The size of argument buffer (in bytes)
uint32_t reserved0; //!< For the future usage
uint64_t kernel_table; //!< [LRO] Pointer to an array with all kernel objects (ulong for each entry)
uint32_t reserved[2]; //!< For the future usage
};
struct AmdAqlWrap {
uint32_t state; //!< [LRW/SRW] The current state of the AQL wrapper: FREE, RESERVED, READY,
// MARKER, BUSY and DONE. The block could be returned back to a free state.
uint32_t enqueue_flags; //!< [LWO/SRO] Contains the flags for the kernel execution start
uint32_t command_id; //!< [LWO/SRO] The unique command ID
uint32_t child_counter; //!< [LRW/SRW] Counter that determine the launches of child kernels.
// Its incremented on the
// start and decremented on the finish. The parent kernel can be considered as
// done when the value is 0 and the state is DONE
uint64_t completion; //!< [LWO/SRO] CL event for the current execution (clk_event_t)
uint64_t parent_wrap; //!< [LWO/SRO] Pointer to the parent AQL wrapper (AmdAqlWrap*)
uint64_t wait_list; //!< [LRO/SRO] Pointer to an array of clk_event_t objects (64 bytes default)
uint32_t wait_num; //!< [LWO/SRO] The number of cl_event_wait objects
uint32_t reserved[5]; //!< For the future usage
HsaAqlDispatchPacket aql; //!< [LWO/SRO] AQL packet 64 bytes AQL packet
};
struct AmdEvent {
uint32_t state; //!< [LRO/SRW] Event state: START, END, COMPLETE
uint32_t counter; //!< [LRW] Event retain/release counter. 0 means the event is free
uint64_t timer[3]; //!< [LRO/SWO] Timer values for profiling for each state
};
struct SchedulerParam {
uint32_t signal; //!< Signal to stop the child queue(address must be 16 bytes aligned)
uint32_t eng_clk; //!< Engine clock in Mhz
uint64_t hw_queue; //!< Address to HW queue
uint64_t hsa_queue; //!< Address to HSA dummy queue
uint32_t launch; //!< Launch semaphore for the scheduler threads
uint32_t scratchSize; //!< Scratch buffer size
uint64_t scratch; //!< GPU address to the scratch buffer
uint32_t numMaxWaves; //!< The max number of possible waves
uint32_t reserved; //!< reserved
};
} // namespace gpu
#endif
+467
View File
@@ -0,0 +1,467 @@
//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//
namespace gpu {
#define SCHEDULER_KERNEL(...) #__VA_ARGS__
const char* SchedulerSourceCode = SCHEDULER_KERNEL(
\n
//! AmdAqlWrap slot state
enum AqlWrapState {
AQL_WRAP_FREE = 0,
AQL_WRAP_RESERVED,
AQL_WRAP_READY,
AQL_WRAP_MARKER,
AQL_WRAP_BUSY,
AQL_WRAP_DONE
};
//! Profiling states
enum ProfilingState {
PROFILING_COMMAND_START = 0,
PROFILING_COMMAND_END,
PROFILING_COMMAND_COMPLETE
};
typedef struct _HsaAqlDispatchPacket {
uint mix;
ushort workgroup_size[3];
ushort reserved2;
uint grid_size[3];
uint private_segment_size_bytes;
uint group_segment_size_bytes;
ulong kernel_object_address;
ulong kernel_arg_address;
ulong reserved3;
ulong completion_signal;
} HsaAqlDispatchPacket;
typedef struct _AmdVQueueHeader {
uint aql_slot_num; //!< [LRO/SRO] The total number of the AQL slots (multiple of 64).
uint event_slot_num; //!< [LRO] The number of kernel events in the events buffer
ulong event_slot_mask; //!< [LRO] A pointer to the allocation bitmask array for the events
ulong event_slots; //!< [LRO] Pointer to a buffer for the events.
// Array of event_slot_num entries of AmdEvent
ulong aql_slot_mask; //!< [LRO/SRO]A pointer to the allocation bitmask for aql_warp slots
uint command_counter; //!< [LRW] The global counter for the submitted commands into the queue
uint wait_size; //!< [LRO] The wait list size (in clk_event_t)
uint arg_size; //!< [LRO] The size of argument buffer (in bytes)
uint reserved0; //!< For the future usage
ulong kernel_table; //!< [LRO] Pointer to an array with all kernel objects (ulong for each entry)
uint reserved[2]; //!< For the future usage
} AmdVQueueHeader;
typedef struct _AmdAqlWrap {
uint state; //!< [LRW/SRW] The current state of the AQL wrapper: FREE, RESERVED, READY,
// MARKER, BUSY and DONE. The block could be returned back to a free state.
uint enqueue_flags; //!< [LWO/SRO] Contains the flags for the kernel execution start
// (kernel_enqueue_flags_t)
// CLK_ENQUEUE_FLAGS_NO_WAIT we just start processing
// CLK_ENQUEUE_FLAGS_WAIT_KERNEL check if parent_wrap->state is done and then start processing
// CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP - currently == WAIT_KERNEL
uint command_id; //!< [LWO/SRO] The unique command ID
uint child_counter; //!< [LRW/SRW] Counter that determine the launches of child kernels.
// Its incremented on the
// start and decremented on the finish. The parent kernel can be considered as
// done when the value is 0 and the state is DONE
ulong completion; //!< [LWO/SRO] CL event for the current execution (clk_event_t)
ulong parent_wrap; //!< [LWO/SRO] Pointer to the parent AQL wrapper (AmdAqlWrap*)
ulong wait_list; //!< [LRO/SRO] Pointer to an array of clk_event_t objects (64 bytes default)
uint wait_num; //!< [LWO/SRO] The number of cl_event_wait objects
uint reserved[5]; //!< For the future usage
HsaAqlDispatchPacket aql; //!< [LWO/SRO] AQL packet 64 bytes AQL packet
} AmdAqlWrap;
typedef struct _AmdEvent {
uint state; //!< [LRO/SRW] Event state: START, END, COMPLETE
uint counter; //!< [LRW] Event retain/release counter. 0 means the event is free
ulong timer[3]; //!< [LRO/SWO] Timer values for profiling for each state
} AmdEvent;
typedef struct _SchedulerParam {
uint signal; //!< Signal to stop the child queue
uint eng_clk; //!< Engine clock in Mhz
ulong hw_queue; //!< Address to HW queue
ulong hsa_queue; //!< Address to HSA dummy queue
uint launch; //!< Child launch status
uint scratchSize; //!< Scratch buffer size
ulong scratch; //!< GPU address to the scratch buffer
uint numMaxWaves; //!< Num max waves on the asic
uint reserved; //!< Reserved
} SchedulerParam;
typedef struct _HwDispatch {
uint startExe; // REWIND execution
uint condExe0; // 0xC0032200 -- TYPE 3, COND_EXEC
uint condExe1; // 0x00000204 ----
uint condExe2; // 0x00000000 ----
uint condExe3; // 0x00000000 ----
uint condExe4; // 0x00000000 ----
uint packet0; // 0xC0067602 -- TYPE 3, SET_SH_REG, TYPE:COMPUTE (6 values)
uint offset0; // 0x00000204 ---- OFFSET
uint startX; // 0x00000000 ---- COMPUTE_START_X: START = 0x0
uint startY; // 0x00000000 ---- COMPUTE_START_Y: START = 0x0
uint startZ; // 0x00000000 ---- COMPUTE_START_Z: START = 0x0
uint wrkGrpSizeX; // 0x00000000 ---- COMPUTE_NUM_THREAD_X: NUM_THREAD_FULL = 0x0, NUM_THREAD_PARTIAL = 0x0
uint wrkGrpSizeY; // 0x00000000 ---- COMPUTE_NUM_THREAD_Y: NUM_THREAD_FULL = 0x0, NUM_THREAD_PARTIAL = 0x0
uint wrkGrpSizeZ; // 0x00000000 ---- COMPUTE_NUM_THREAD_Z: NUM_THREAD_FULL = 0x0, NUM_THREAD_PARTIAL = 0x0
uint packet1; // 0xC0027602 -- TYPE 3, SET_SH_REG, TYPE:COMPUTE (2 values)
uint offset1; // 0x0000020C ---- OFFSET
uint isaLo; // 0x00000000 ---- COMPUTE_PGM_LO: DATA = 0x0
uint isaHi; // 0x00000000 ---- COMPUTE_PGM_HI: DATA = 0x0, INST_ATC__CI__VI = 0x0
uint packet2; // 0xC0027602 -- TYPE 3, SET_SH_REG, TYPE:COMPUTE (2 values)
uint offset2; // 0x00000212 ---- OFFSET
uint resource1; // 0x00000000 ---- COMPUTE_PGM_RSRC1: VGPRS = 0x0, SGPRS = 0x0, PRIORITY = 0x0, FLOAT_MODE = 0x0, PRIV = 0x0, DX10_CLAMP = 0x0, DEBUG_MODE = 0x0, IEEE_MODE = 0x0, BULKY__CI__VI = 0x0, CDBG_USER__CI__VI = 0x0
uint resource2; // 0x00000000 ---- COMPUTE_PGM_RSRC2: SCRATCH_EN = 0x0, USER_SGPR = 0x0, TRAP_PRESENT = 0x0, TGID_X_EN = 0x0, TGID_Y_EN = 0x0, TGID_Z_EN = 0x0, TG_SIZE_EN = 0x0, TIDIG_COMP_CNT = 0x0, EXCP_EN_MSB__CI__VI = 0x0, LDS_SIZE = 0x0, EXCP_EN = 0x0
uint packet3; // 0xC0067602 -- TYPE 3, SET_SH_REG, TYPE:COMPUTE (6 values)
uint offset3; // 0x00000215 ---- OFFSET
uint pad31; // 0x00000000 ---- COMPUTE_RESOURCE_LIMITS: WAVES_PER_SH = 0x0, TG_PER_CU = 0x0, LOCK_THRESHOLD = 0x0, SIMD_DEST_CNTL = 0x0, FORCE_SIMD_DIST__CI__VI = 0x0, CU_GROUP_COUNT__CI__VI = 0x0
uint pad32; // 0xFFFFFFFF ---- COMPUTE_STATIC_THREAD_MGMT_SE0: SH0_CU_EN = 0xFFFF, SH1_CU_EN = 0xFFFF
uint pad33; // 0xFFFFFFFF ---- COMPUTE_STATIC_THREAD_MGMT_SE1: SH0_CU_EN = 0xFFFF, SH1_CU_EN = 0xFFFF
uint ringSize; // 0x00000000 ---- COMPUTE_TMPRING_SIZE: WAVES = 0x0, WAVESIZE = 0x0
uint pad34; // 0xFFFFFFFF ---- COMPUTE_STATIC_THREAD_MGMT_SE2__CI__VI: SH0_CU_EN = 0xFFFF, SH1_CU_EN = 0xFFFF
uint pad35; // 0xFFFFFFFF ---- COMPUTE_STATIC_THREAD_MGMT_SE3__CI__VI: SH0_CU_EN = 0xFFFF, SH1_CU_EN = 0xFFFF
uint user0; // 0xC0047602 -- TYPE 3, SET_SH_REG, TYPE:COMPUTE (4 values)
uint offsUser0; // 0x00000240 ---- OFFSET
uint scratchLo; // 0x00000000 ---- COMPUTE_USER_DATA_0: DATA = 0x0
uint scratchHi; // 0x80000000 ---- COMPUTE_USER_DATA_1: DATA = 0x80000000
uint scratchSize; // 0x00000000 ---- COMPUTE_USER_DATA_2: DATA = 0x0
uint padUser; // 0x00EA7FAC ---- COMPUTE_USER_DATA_3: DATA = 0xEA7FAC
uint user1; // 0xC0027602 -- TYPE 3, SET_SH_REG, TYPE:COMPUTE (2 values)
uint offsUser1; // 0x00000244 ---- OFFSET
uint aqlPtrLo; // 0x00000000 ---- COMPUTE_USER_DATA_4: DATA = 0x0
uint aqlPtrHi; // 0x00000000 ---- COMPUTE_USER_DATA_5: DATA = 0x0
uint user2; // 0xC0027602 -- TYPE 3, SET_SH_REG, TYPE:COMPUTE (2 values)
uint offsUser2; // 0x00000246 ---- OFFSET
uint hsaQueueLo; // 0x00000000 ---- COMPUTE_USER_DATA_6: DATA = 0x0
uint hsaQueueHi; // 0x00000000 ---- COMPUTE_USER_DATA_7: DATA = 0x0
uint user3; // 0xC0027602 -- TYPE 3, SET_SH_REG, TYPE:COMPUTE (2 values)
uint offsUser3; // 0x00000246 ---- OFFSET
uint argsLo; // 0x00000000 ---- COMPUTE_USER_DATA_8: DATA = 0x0
uint argsHi; // 0x00000000 ---- COMPUTE_USER_DATA_9: DATA = 0x0
uint copyData; // 0xC0044000 -- TYPE 3, COPY_DATA
uint copyDataFlags; // 0x00000405 ---- srcSel 0x5, destSel 0x4, countSel 0x0, wrConfirm 0x0, engineSel 0x0
uint scratchAddrLo; // 0x000201C4 ---- srcAddressLo
uint scratchAddrHi; // 0x00000000 ---- srcAddressHi
uint shPrivateLo; // 0x00002580 ---- dstAddressLo
uint shPrivateHi; // 0x00000000 ---- dstAddressHi
uint user4; // 0xC0027602 -- TYPE 3, SET_SH_REG, TYPE:COMPUTE (2 values)
uint offsUser4; // 0x00000248 ---- OFFSET
uint privOffs; // 0x00000000 ---- COMPUTE_USER_DATA_10: DATA = 0x0
uint privSize; // 0x00000030 ---- COMPUTE_USER_DATA_11: DATA = 0x30
uint packet4; // 0xC0031502 -- TYPE 3, DISPATCH_DIRECT, TYPE:COMPUTE
uint glbSizeX; // 0x00000000
uint glbSizeY; // 0x00000000
uint glbSizeZ; // 0x00000000
uint padd41; // 0x00000021
} HwDispatch;
const uint ResumeExecution = 0x80000000; // 0x81000000
const uint StallExecution = 0x00000000; // 0x01000000
const uint WavefrontSize = 64;
const uint MaxWaveSize = 0x400;
void dispatch(
volatile __global HwDispatch* dispatch,
__global HsaAqlDispatchPacket* aqlPkt,
uint scratchSize,
uint numMaxWaves,
ulong scratch,
ulong hsaQueue)
{
const uint UsrRegOffset = 0x240;
const uint Pm4Nop = 0xC0001002;
const uint Pm4UserRegs = 0xC0007602;
const uint Pm4CopyReg = 0xC0044000;
// Wait for CP idle isn't necessary if CP waits for child
// while (atomic_and(&dispatch->startExe, 0xffffffff) != StallExecution) {}
uint usrRegCnt = 0;
dispatch->wrkGrpSizeX = aqlPkt->workgroup_size[0];
dispatch->wrkGrpSizeY = aqlPkt->workgroup_size[1];
dispatch->wrkGrpSizeZ = aqlPkt->workgroup_size[2];
// ISA address
__global uchar* kernelObj = (__global uchar*)aqlPkt->kernel_object_address;
ulong isa = aqlPkt->kernel_object_address + *((__global uint*)(kernelObj + 0x10));
dispatch->isaLo = (uint)(isa >> 8);
dispatch->isaHi = (uint)(isa >> 40);
// Program PGM resource registers
dispatch->resource1 = *((__global uint*)(kernelObj + 0x30));
dispatch->resource2 = *((__global uint*)(kernelObj + 0x34));
uint flags = *((__global uint*)(kernelObj + 0x38));
uint privateSize = *((__global uint*)(kernelObj + 0x50));
uint ldsSize = aqlPkt->group_segment_size_bytes +
*((__global uint*)(kernelObj + 0x54));
// Align up the LDS blocks 128 * 4(in DWORDs)
uint ldsBlocks = (ldsSize + 511) >> 9;
dispatch->resource2 |= (ldsBlocks << 15);
// Workaround for compiler bug
dispatch->scratchLo = (flags & 1);
// privSegEna = (flags & 1);
if (flags & 0x1) {
uint waveSize = privateSize * WavefrontSize;
// 256 DWRODs is the minimum for SQ
waveSize = max(MaxWaveSize, waveSize);
uint numWaves = scratchSize / waveSize;
numWaves = min(numWaves, numMaxWaves);
dispatch->ringSize = numWaves;
dispatch->ringSize |= (waveSize >> 10) << 12;
dispatch->user0 = Pm4UserRegs | (4 << 16);
dispatch->scratchLo = (uint)scratch;
dispatch->scratchHi = ((uint)(scratch >> 32)) | 0x80000000; // Enables swizzle
dispatch->scratchSize = scratchSize;
usrRegCnt += 4;
}
else {
dispatch->ringSize = 0;
dispatch->user0 = Pm4Nop | (4 << 16);
}
// dispatchEna = (flags & 0x2);
dispatch->user1 = (flags & 0x2) ? (Pm4UserRegs | (2 << 16)) : (Pm4Nop | (2 << 16));
dispatch->offsUser1 = UsrRegOffset + usrRegCnt;
usrRegCnt += (flags & 0x2) ? 2 : 0;
ulong gpuAqlPtr = (ulong)aqlPkt;
dispatch->aqlPtrLo = (uint)gpuAqlPtr;
dispatch->aqlPtrHi = (uint)(gpuAqlPtr >> 32);
// queuePtr = (flags & 0x4);
if (flags & 0x4) {
dispatch->user2 = Pm4UserRegs | (2 << 16);
dispatch->offsUser2 = UsrRegOffset + usrRegCnt;
usrRegCnt += 2;
dispatch->hsaQueueLo = (uint)hsaQueue;
dispatch->hsaQueueHi = (uint)(hsaQueue >> 32);
}
else {
dispatch->user2 = Pm4Nop | (2 << 16);
}
// kernelArgEna = (flags & 0x8);
dispatch->user3 = (flags & 0x8) ? (Pm4UserRegs | (2 << 16)) : (Pm4Nop | (2 << 16));
dispatch->offsUser3 = UsrRegOffset + usrRegCnt;
usrRegCnt += (flags & 0x8) ? 2 : 0;
dispatch->argsLo = (uint)aqlPkt->kernel_arg_address;
dispatch->argsHi = (uint)(aqlPkt->kernel_arg_address >> 32);
// flatScratchEna = (flags & 0x20);
if (flags & 0x20) {
dispatch->copyData = Pm4CopyReg;
dispatch->scratchAddrLo = (uint)(scratch >> 16);
dispatch->offsUser4 = UsrRegOffset + usrRegCnt;
dispatch->privSize = privateSize;
}
else {
dispatch->copyData = Pm4Nop | (8 << 16);
}
dispatch->glbSizeX = aqlPkt->grid_size[0];
dispatch->glbSizeY = aqlPkt->grid_size[1];
dispatch->glbSizeZ = aqlPkt->grid_size[2];
barrier(CLK_GLOBAL_MEM_FENCE);
// Resume the execution
dispatch->startExe = ResumeExecution;
}
bool
checkWaitEvents(__global AmdEvent* events, uint numEvents)
{
for (uint i = 0; i < numEvents; ++i) {
if (atomic_and(&events[i].state, 0xffffffff) != CL_COMPLETE) {
return false;
}
}
return true;
}
// release slot in a bitmask controlled resource i is the slot number
static inline void
release_slot(__global uint * restrict mask, uint i)
{
/* uint b = ~(1UL << (i & 0x1f)); */
uint b = ~amd_bfm(1U, i);
__global atomic_uint *p = (__global atomic_uint *)(mask + (i >> 5));
uint vv;
uint v = atomic_load_explicit(p, memory_order_acquire, memory_scope_device);
for (;;) {
vv = v & b;
if (atomic_compare_exchange_strong_explicit(p, &v, vv,
memory_order_acq_rel, memory_order_acquire, memory_scope_device)) {
break;
}
}
}
static inline uint
min_command(uint slot_num, __global AmdAqlWrap* wraps)
{
uint minCommand = 0xffffffff;
for (uint idx = 0; idx < slot_num; ++idx) {
__global AmdAqlWrap* disp = (__global AmdAqlWrap*)&wraps[idx];
uint slotState = atomic_load_explicit((__global atomic_uint*)(&disp->state),
memory_order_acquire, memory_scope_device);
if ((slotState != AQL_WRAP_FREE) && (slotState != AQL_WRAP_RESERVED)) {
minCommand = min(disp->command_id, minCommand);
}
}
return minCommand;
}
extern ulong __hsail_get_clock(); // Declaration is required
__kernel void
scheduler(
__global AmdVQueueHeader* queue,
__global SchedulerParam* params,
uint paramIdx)
{
__global SchedulerParam* param = &params[paramIdx];
volatile __global HwDispatch* hwDisp =
(volatile __global HwDispatch*)param->hw_queue;
__global uint* signal = (__global uint*)(&param->signal);
__global AmdAqlWrap* wraps = (__global AmdAqlWrap*)&queue[1];
__global uint* amask = (__global uint *)queue->aql_slot_mask;
uint launch = 0;
uint loop;
do {
uint mask = atomic_load_explicit((__global atomic_uint*)(&amask[get_group_id(0)]),
memory_order_acquire, memory_scope_device);
if (mask != 0) {
int baseIdx = get_group_id(0) * 32;
for (int idx = baseIdx + 31 - clz(mask); (idx >= baseIdx) && (launch == 0); --idx) {
__global AmdAqlWrap* disp = (__global AmdAqlWrap*)&wraps[idx];
uint slotState = atomic_load_explicit((__global atomic_uint*)(&disp->state),
memory_order_acquire, memory_scope_device);
__global AmdAqlWrap* parent = (__global AmdAqlWrap*)(disp->parent_wrap);
__global AmdEvent* event = (__global AmdEvent*)(disp->completion);
// Check if the current slot is ready for processing
if (slotState == AQL_WRAP_READY) {
if (launch == 0) {
launch = atomic_load_explicit((__global atomic_uint*)&param->launch,
memory_order_acquire, memory_scope_device);
}
if (launch == 0) {
// Attempt to find a new disaptch if nothing was launched yet
uint parentState = atomic_load_explicit(
(__global atomic_uint*)(&parent->state),
memory_order_acquire, memory_scope_device);
// Check the launch flags
if (((disp->enqueue_flags == CLK_ENQUEUE_FLAGS_WAIT_KERNEL) ||
(disp->enqueue_flags == CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP)) &&
(parentState != AQL_WRAP_DONE)) {
continue;
}
// Check if the command has any the wait events
if (disp->wait_num != 0) {
// Check if the wait list is COMPLETE
launch = checkWaitEvents(
(__global AmdEvent*)(disp->wait_list), disp->wait_num);
}
else {
launch = 1;
}
uint tmp = 0;
if (atomic_compare_exchange_strong_explicit(
(__global atomic_uint*)&param->launch, &tmp, launch,
memory_order_acq_rel, memory_order_acq_rel, memory_scope_device)) {
if (event != 0) {
event->timer[PROFILING_COMMAND_START] =
(__hsail_get_clock() * 1000) / (ulong)param->eng_clk;
}
// Launch child kernel ....
dispatch(hwDisp, &disp->aql, param->scratchSize, param->numMaxWaves,
param->scratch, param->hsa_queue);
disp->state = AQL_WRAP_BUSY;
break;
}
}
}
else if (slotState == AQL_WRAP_MARKER) {
bool complete = false;
if (disp->wait_num == 0) {
uint minCommand = min_command(queue->aql_slot_num, wraps);
if (disp->command_id == minCommand) {
complete = true;
}
}
else {
// Check if the wait list is COMPLETE
if (checkWaitEvents(
(__global AmdEvent*)(disp->wait_list), disp->wait_num)) {
complete = true;
}
}
if (complete) {
// Decrement the child execution counter on the parent
atomic_fetch_sub_explicit(
(__global atomic_uint*)&parent->child_counter,
1, memory_order_acq_rel, memory_scope_device);
event->state = CL_COMPLETE;
disp->state = AQL_WRAP_FREE;
release_slot(amask, idx);
}
}
else if (slotState == AQL_WRAP_DONE) {
// Was CL_EVENT requested?
if (event != 0) {
// The current dispatch doesn't have any outstanding children
if (disp->child_counter == 0) {
event->state = CL_COMPLETE;
event->timer[PROFILING_COMMAND_END] =
event->timer[PROFILING_COMMAND_COMPLETE] =
(__hsail_get_clock() * 1000) / (ulong)param->eng_clk;
}
else {
event->timer[PROFILING_COMMAND_END] =
(__hsail_get_clock() * 1000) / (ulong)param->eng_clk;
}
}
// The current dispatch doesn't have any outstanding children
if (disp->child_counter == 0) {
// Decrement the child execution counter on the parent
atomic_fetch_sub_explicit(
(__global atomic_uint*)&parent->child_counter,
1, memory_order_acq_rel, memory_scope_device);
disp->state = AQL_WRAP_FREE;
release_slot(amask, idx);
}
}
else if (slotState == AQL_WRAP_BUSY) {
disp->state = AQL_WRAP_DONE;
}
}
}
barrier(CLK_GLOBAL_MEM_FENCE);
launch = atomic_load_explicit((__global atomic_uint*)&param->launch,
memory_order_acquire, memory_scope_device);
loop = atomic_load_explicit((__global atomic_uint*)signal,
memory_order_acquire, memory_scope_device);
} while ((launch == 0) && (loop == 1));
if (loop == 0) {
atomic_or(&hwDisp->startExe, ResumeExecution);
}
}
\n
\n
);
} // namespace gpu
+479
View File
@@ -0,0 +1,479 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include "device/gpu/gpukernel.hpp"
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <ctime>
#include "acl.h"
#define R900_BUILD 1
#include "SCShadersR800.h"
#include "r8xx_r9xx_merged__offset.h"
#include "r8xx_r9xx_merged__typedef.h"
namespace gpu {
#define NUM_R800_CS_INFOS (0x22+SC_R800_MAX_UAV+ \
3+ /* globalReturnBuffer flag plus numUavs and numGlobalReturnBuffers */ \
1+ /* extendedCaching flag */ \
3+ /* globalReturnBuffer sizes for dword, shorts and bytes */ \
3*SC_R800_MAX_UAV+ /* offsetmap, cached and uncached fetch consts */ \
2*SC_R800_MAX_UAV+ /* 64- and 128-bit cached fetch consts */ \
2*R800_GLOBAL_RTN_BUF_LAST /* global return buffer fetch consts and type */ )
struct Options {
uint numClauseTemps_;
uint numGPRs_;
uint numThreads_;
uint numStackEntries_;
uint ldsSize_;
Options(CALtarget target) {
numClauseTemps_ = 4;
switch (target) {
case CAL_TARGET_DEVASTATOR:
case CAL_TARGET_SCRAPPER:
case CAL_TARGET_CAYMAN:
case CAL_TARGET_KAUAI:
numClauseTemps_ = 0;
numStackEntries_ = 512;
numThreads_ = 248;
break;
case CAL_TARGET_SUPERSUMO:
case CAL_TARGET_TURKS:
case CAL_TARGET_REDWOOD:
numStackEntries_ = 256;
numThreads_ = 248;
break;
case CAL_TARGET_WRESTLER:
case CAL_TARGET_SUMO:
case CAL_TARGET_CAICOS:
case CAL_TARGET_CEDAR:
numStackEntries_ = 256;
numThreads_ = 192;
break;
case CAL_TARGET_CYPRESS:
case CAL_TARGET_BARTS:
case CAL_TARGET_JUNIPER:
numStackEntries_ = 512;
numThreads_ = 248;
break;
default:
numStackEntries_ = 512;
numThreads_ = 248;
LogError("Unknown ASIC type");
}
numGPRs_ = 256 - 2 * numClauseTemps_;
ldsSize_ = 32*1024;
}
private:
Options();
Options(const Options&);
Options& operator=(const Options&);
};
static const uint UncachedFetchConst[SC_R800_MAX_UAV] =
{ 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 173 };
static const uint CachedFetchConst[SC_R800_MAX_UAV] =
{ 144, 145, 146, 148, 149, 150, 151, 152, 0, 0, 0, 153 };
static const uint GlobalReturnFetchConst[R800_GLOBAL_RTN_BUF_LAST] =
{ 165, 166, 167, 168, 169, 170, 171, 172 };
static const uint GlobalReturnBufferType[R800_GLOBAL_RTN_BUF_LAST] =
{ AMU_ABI_UAV_FORMAT_TYPELESS, AMU_ABI_UAV_FORMAT_FLOAT,
AMU_ABI_UAV_FORMAT_UNORM, AMU_ABI_UAV_FORMAT_SNORM, AMU_ABI_UAV_FORMAT_UINT,
AMU_ABI_UAV_FORMAT_SINT, AMU_ABI_UAV_FORMAT_SHORT, AMU_ABI_UAV_FORMAT_BYTE };
static const uint CachedFetchConst64[SC_R800_MAX_UAV] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174 };
static const uint CachedFetchConst128[SC_R800_MAX_UAV] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175 };
bool
NullKernel::r800CreateHwInfo(const void* shader, AMUabiAddEncoding& encoding)
{
CALProgramInfoEntry* newInfos;
const Options options(nullDev().calTarget());
uint i = 0;
uint numShaderEngines = 1;
if ((nullDev().calTarget() == CAL_TARGET_CAYMAN) ||
(nullDev().calTarget() == CAL_TARGET_CYPRESS) ||
(nullDev().calTarget() == CAL_TARGET_BARTS)) {
numShaderEngines = 2;
}
uint infoCount = NUM_R800_CS_INFOS;
SC_R800CSHWSHADER* cShader = (SC_R800CSHWSHADER *)shader;
if (cShader->u32NumThreadPerGroup == 0) {
return false;
}
newInfos = new CALProgramInfoEntry[infoCount];
encoding.progInfos = newInfos;
if (encoding.progInfos == 0) {
infoCount = 0;
return false;
}
memset(newInfos, 0, infoCount * sizeof(CALProgramInfoEntry));
newInfos[i].address = mmSQ_PGM_START_LS;
newInfos[i].value = 0x0;
i++;
newInfos[i].address = mmSQ_PGM_RESOURCES_LS;
cShader->sqPgmResourcesCs.bits.UNCACHED_FIRST_INST = 1;
cShader->sqPgmResourcesCs.bits.PRIME_CACHE_ENABLE = 1;
cShader->sqPgmResourcesCs.bits.PRIME_CACHE_ON_CONST = 0;
newInfos[i].value = cShader->sqPgmResourcesCs.u32All;
i++;
newInfos[i].address = mmSQ_PGM_RESOURCES_2_LS;
newInfos[i].value = cShader->sqPgmResources2Cs.u32All;
i++;
newInfos[i].address = mmSPI_THREAD_GROUPING;
regSPI_THREAD_GROUPING spi_thread_grouping;
spi_thread_grouping.u32All = 0;
spi_thread_grouping.bits.PS_GROUPING = 0;
spi_thread_grouping.bits.VS_GROUPING = 0;
spi_thread_grouping.bits.ES_GROUPING = 0;
spi_thread_grouping.bits.GS_GROUPING = 0;
// dyn_gpr_mgmt if CS_GROUPING = 1.
spi_thread_grouping.bits.CS_GROUPING = 0;
newInfos[i].value = spi_thread_grouping.u32All;
i++;
const unsigned int numSharedGPR = cShader->u32NumSharedGprTotal;
newInfos[i].address = mmSQ_DYN_GPR_CNTL_PS_FLUSH_REQ;
regSQ_DYN_GPR_CNTL_PS_FLUSH_REQ sq_dyn_gpr_cntl_ps_flush_req;
sq_dyn_gpr_cntl_ps_flush_req.u32All = 0;
sq_dyn_gpr_cntl_ps_flush_req.bits.RING0_OFFSET = numSharedGPR;
newInfos[i].value = sq_dyn_gpr_cntl_ps_flush_req.u32All;
i++;
const unsigned int numClauseTemps = options.numClauseTemps_;
const unsigned int MaxNumGPRsAvail = options.numGPRs_;
newInfos[i].address = mmSQ_GPR_RESOURCE_MGMT_1;
regSQ_GPR_RESOURCE_MGMT_1 sq_gpr_resource_mgmt_1;
sq_gpr_resource_mgmt_1.u32All = 0;
sq_gpr_resource_mgmt_1.bits.NUM_CLAUSE_TEMP_GPRS = numClauseTemps;
newInfos[i].value = sq_gpr_resource_mgmt_1.u32All;
i++;
newInfos[i].address = mmSQ_GPR_RESOURCE_MGMT_3__EG;
regSQ_GPR_RESOURCE_MGMT_3__EG sq_gpr_resource_mgmt_3;
sq_gpr_resource_mgmt_3.u32All = 0;
{
const unsigned int numWavefrontPerSIMD = 1 ; // ?? cShader->u32NumWavefrontPerSIMD;
if ((cShader->u32NumSharedGprUser != cShader->u32NumSharedGprTotal)) // cShader->bIsMaxNumWavePerSIMD)
{
// if running with a barrier, need to limit the number of wavefronts on a SIMD.
// force max wavefronts run on a simd by adjusting the num_es_gprs pool that all es programs can
// allocate from. (# of gprs the program uses * numWavefrontsPerSIMD)
sq_gpr_resource_mgmt_3.bits.NUM_LS_GPRS = cShader->sqPgmResourcesCs.bits.NUM_GPRS * numWavefrontPerSIMD;
}
else
{
sq_gpr_resource_mgmt_3.bits.NUM_LS_GPRS = MaxNumGPRsAvail - numSharedGPR;
}
}
newInfos[i].value = sq_gpr_resource_mgmt_3.u32All;
i++;
newInfos[i].address = mmSPI_GPR_MGMT;
regSPI_GPR_MGMT spi_gpr_mgmt;
spi_gpr_mgmt.u32All = 0;
{
const unsigned int numWavefrontPerSIMD = 1 ; // ?? cShader->u32NumWavefrontPerSIMD;
if ((cShader->u32NumSharedGprUser != cShader->u32NumSharedGprTotal)) // cShader->bIsMaxNumWavePerSIMD)
{
// if running with a barrier, need to limit the number of wavefronts on a SIMD.
// force max wavefronts run on a simd by adjusting the num_es_gprs pool that all es programs can
// allocate from. (# of gprs the program uses * numWavefrontsPerSIMD)
spi_gpr_mgmt.bits.NUM_LS_GPRS = (cShader->sqPgmResourcesCs.bits.NUM_GPRS * numWavefrontPerSIMD) >> 3;
}
else
{
spi_gpr_mgmt.bits.NUM_LS_GPRS = (MaxNumGPRsAvail - numSharedGPR) >> 3;
}
}
newInfos[i].value = spi_gpr_mgmt.u32All;
i++;
newInfos[i].address = mmSPI_WAVE_MGMT_1;
regSPI_WAVE_MGMT_1 spi_wave_mgmt_1;
spi_wave_mgmt_1.u32All = 0;
newInfos[i].value = spi_wave_mgmt_1.u32All;
i++;
newInfos[i].address = mmSPI_WAVE_MGMT_2;
regSPI_WAVE_MGMT_2 spi_wave_mgmt_2;
spi_wave_mgmt_2.u32All = 0;
spi_wave_mgmt_2.bits.NUM_CS_WAVES_ONE_RING = (options.numThreads_) >> 3;
newInfos[i].value = spi_wave_mgmt_2.u32All;
i++;
newInfos[i].address = mmSQ_THREAD_RESOURCE_MGMT__EG;
regSQ_THREAD_RESOURCE_MGMT__EG sq_thread_resource_mgmt;
sq_thread_resource_mgmt.u32All = 0;
sq_thread_resource_mgmt.bits.NUM_PS_THREADS = 0;
sq_thread_resource_mgmt.bits.NUM_VS_THREADS = 0;
sq_thread_resource_mgmt.bits.NUM_GS_THREADS = 0;
sq_thread_resource_mgmt.bits.NUM_ES_THREADS = 0;
newInfos[i].value = sq_thread_resource_mgmt.u32All;
i++;
newInfos[i].address = mmSQ_THREAD_RESOURCE_MGMT_2__EG;
regSQ_THREAD_RESOURCE_MGMT_2__EG sq_thread_resource_mgmt_2;
sq_thread_resource_mgmt_2.u32All = 0;
sq_thread_resource_mgmt_2.bits.NUM_HS_THREADS = 0;
sq_thread_resource_mgmt_2.bits.NUM_LS_THREADS = options.numThreads_;
newInfos[i].value = sq_thread_resource_mgmt_2.u32All;
i++;
regSPI_COMPUTE_INPUT_CNTL spi_dompute_input_cntl;
spi_dompute_input_cntl.u32All = 0;
spi_dompute_input_cntl.bits.DISABLE_INDEX_PACK = 1;
spi_dompute_input_cntl.bits.TID_IN_GROUP_ENA = 1;
spi_dompute_input_cntl.bits.TGID_ENA = 1;
newInfos[i].address = mmSPI_COMPUTE_INPUT_CNTL;
newInfos[i].value = spi_dompute_input_cntl.u32All;
i++;
newInfos[i].address = mmSQ_LDS_ALLOC;
newInfos[i].value = cShader->sqLdsAllocCs.u32All;
i++;
//This is information passed from SC to GSL, there is no valid address, so make up one.
newInfos[i].address = AMU_ABI_CS_MAX_SCRATCH_REGS;
newInfos[i].value = cShader->MaxScratchRegsNeeded;
i++;
newInfos[i].address = AMU_ABI_CS_NUM_SHARED_GPR_USER;
newInfos[i].value = cShader->u32NumSharedGprUser;
i++;
newInfos[i].address = AMU_ABI_CS_NUM_SHARED_GPR_TOTAL;
newInfos[i].value = cShader->u32NumSharedGprTotal;
i++;
newInfos[i].address = AMU_ABI_NUM_THREAD_PER_GROUP;
newInfos[i].value = cShader->u32NumThreadPerGroup;
i++;
newInfos[i].address = AMU_ABI_NUM_THREAD_PER_GROUP_X;
newInfos[i].value = cShader->u32NumThreadPerGroup_x;
i++;
newInfos[i].address = AMU_ABI_NUM_THREAD_PER_GROUP_Y;
newInfos[i].value = cShader->u32NumThreadPerGroup_y;
i++;
newInfos[i].address = AMU_ABI_NUM_THREAD_PER_GROUP_Z;
newInfos[i].value = cShader->u32NumThreadPerGroup_z;
i++;
newInfos[i].address = AMU_ABI_TOTAL_NUM_THREAD_GROUP;
newInfos[i].value = cShader->u32TotalNumThreadGroup;
i++;
newInfos[i].address = AMU_ABI_NUM_WAVEFRONT_PER_SIMD;
newInfos[i].value = 1;
i++;
newInfos[i].address = AMU_ABI_IS_MAX_NUM_WAVE_PER_SIMD;
newInfos[i].value = 0; // ??
i++;
newInfos[i].address = AMU_ABI_SET_BUFFER_FOR_NUM_GROUP;
newInfos[i].value = cShader->bSetBufferForNumGroup;
i++;
newInfos[i].address = AMU_ABI_RAT_OP_IS_USED;
newInfos[i].value = cShader->u32RatOpIsUsed;
i++;
newInfos[i].address = AMU_ABI_RAT_ATOMIC_OP_IS_USED;
newInfos[i].value = cShader->u32RatAtomicOpIsUsed;
i++;
newInfos[i].address = AMU_ABI_WAVEFRONT_SIZE;
newInfos[i].value = nullDev().hwInfo()->simdWidth_ * 4;
i++;
newInfos[i].address = AMU_ABI_NUM_GPR_AVAIL;
newInfos[i].value = options.numGPRs_;
i++;
newInfos[i].address = AMU_ABI_NUM_GPR_USED;
newInfos[i].value = cShader->sqPgmResourcesCs.bits.NUM_GPRS;
i++;
newInfos[i].address = AMU_ABI_LDS_SIZE_AVAIL;
newInfos[i].value = options.ldsSize_;
i++;
newInfos[i].address = AMU_ABI_LDS_SIZE_USED;
newInfos[i].value = cShader->sqLdsAllocCs.bits.SIZE;
i++;
newInfos[i].address = AMU_ABI_STACK_SIZE_AVAIL;
newInfos[i].value = options.numStackEntries_;
i++;
newInfos[i].address = AMU_ABI_STACK_SIZE_USED;
newInfos[i].value = cShader->sqPgmResourcesCs.bits.STACK_SIZE;
i++;
for (unsigned int j = 0;j <SC_R800_MAX_UAV; j++)
{
unsigned int bufferSize = cShader->scUavRtnBufInfoTbl[j].stride;
bufferSize *= 4; // convert from DWORDS to bytes
//
// multiply by the maximum number of threads in flight at one time
//
// 256 waves * 64 threads/wave * 2 shader engines (for 870)
//
bufferSize *= nullDev().hwInfo()->simdWidth_ * 4; // threads/wave
bufferSize *= 256 * 4; // maximum number of waves
bufferSize *= numShaderEngines;
newInfos[i].address = AMU_ABI_SET_BUFFER_FOR_UAV_RET_BUFFER0 + j;
newInfos[i].value = bufferSize;
i++;
}
newInfos[i].address = AMU_ABI_GLOBAL_RETURN_BUFFER;
newInfos[i].value = true;
i++;
// Always use extended caching with global return buffer
newInfos[i].address = AMU_ABI_EXTENDED_CACHING;
newInfos[i].value = true;
i++;
newInfos[i].address = AMU_ABI_NUM_GLOBAL_UAV;
newInfos[i].value = SC_R800_MAX_UAV;
i++;
newInfos[i].address = AMU_ABI_NUM_GLOBAL_RETURN_BUFFER;
newInfos[i].value = R800_GLOBAL_RTN_BUF_LAST;
i++;
{
unsigned int bufferSize = cShader->u32GlobalRtnBufSlot;
bufferSize *= 4; // convert from DWORDS to bytes
//
// multiply by the maximum number of threads in flight at one time
//
// 256 waves * 64 threads/wave * 2 shader engines (for 870)
//
bufferSize *= nullDev().hwInfo()->simdWidth_ * 4; // threads/wave
bufferSize *= 256 * 4; // maximum number of waves
bufferSize *= numShaderEngines;
newInfos[i].address = AMU_ABI_GLOBAL_RETURN_BUFFER_SIZE;
newInfos[i].value = bufferSize;
i++;
}
{
unsigned int bufferSize = cShader->u32GlobalRtnBufSlotShort;
bufferSize *= 4; // convert from DWORDS to bytes
//
// multiply by the maximum number of threads in flight at one time
//
// 256 waves * 64 threads/wave * 2 shader engines (for 870)
//
bufferSize *= nullDev().hwInfo()->simdWidth_ * 4; // threads/wave
bufferSize *= 256 * 4; // maximum number of waves
bufferSize *= numShaderEngines;
newInfos[i].address = AMU_ABI_GLOBAL_RETURN_BUFFER_SIZE_SHORT;
newInfos[i].value = bufferSize;
i++;
}
{
unsigned int bufferSize = cShader->u32GlobalRtnBufSlotByte;
bufferSize *= 4; // convert from DWORDS to bytes
//
// multiply by the maximum number of threads in flight at one time
//
// 256 waves * 64 threads/wave * 2 shader engines (for 870)
//
bufferSize *= nullDev().hwInfo()->simdWidth_ * 4; // threads/wave
bufferSize *= 256 * 4; // maximum number of waves
bufferSize *= numShaderEngines;
newInfos[i].address = AMU_ABI_GLOBAL_RETURN_BUFFER_SIZE_BYTE;
newInfos[i].value = bufferSize;
i++;
}
for (unsigned int j = 0; j < SC_R800_MAX_UAV; j++)
{
newInfos[i].address = AMU_ABI_OFFSET_TO_UAV0+j;
newInfos[i].value = j;
i++;
}
for (unsigned int j = 0; j < SC_R800_MAX_UAV; j++)
{
// Set up UAV->fetch constant mapping for uncached
newInfos[i].address = AMU_ABI_UNCACHED_FETCH_CONST_UAV0+j;
newInfos[i].value = UncachedFetchConst[j];
i++;
}
for (unsigned int j = 0; j < SC_R800_MAX_UAV; j++)
{
newInfos[i].address = AMU_ABI_CACHED_FETCH_CONST_UAV0+j;
newInfos[i].value = CachedFetchConst[j];
i++;
}
for (unsigned int j = 0; j < R800_GLOBAL_RTN_BUF_LAST; j++)
{
newInfos[i].address = AMU_ABI_GLOBAL_RETURN_FETCH_CONST0+j;
newInfos[i].value = GlobalReturnFetchConst[j];
i++;
}
for (unsigned int j = 0; j < R800_GLOBAL_RTN_BUF_LAST; j++)
{
newInfos[i].address = AMU_ABI_GLOBAL_RETURN_BUFFER_TYPE0+j;
newInfos[i].value = GlobalReturnBufferType[j];
i++;
}
for (unsigned int j = 0; j < SC_R800_MAX_UAV; j++)
{
newInfos[i].address = AMU_ABI_CACHED_FETCH_CONST64_UAV0+j;
newInfos[i].value = CachedFetchConst64[j];
i++;
}
for (unsigned int j = 0; j < SC_R800_MAX_UAV; j++)
{
newInfos[i].address = AMU_ABI_CACHED_FETCH_CONST128_UAV0+j;
newInfos[i].value = CachedFetchConst128[j];
i++;
}
assert(i == infoCount);
encoding.progInfosCount = infoCount;
encoding.uavMask.mask[0] = cShader->u32RatOpIsUsed;
encoding.textData = HWSHADER_Get(cShader, hShaderMemHandle);
encoding.textSize = cShader->CodeLenInByte;
instructionCnt_ = encoding.textSize / sizeof(uint32_t);
encoding.scratchRegisterCount = cShader->MaxScratchRegsNeeded;
uint bufferSize = 0;
bufferSize = cShader->u32GlobalRtnBufSlot +
cShader->u32GlobalRtnBufSlotShort + cShader->u32GlobalRtnBufSlotByte;
bufferSize *= 4; // convert from DWORDS to bytes
//
// multiply by the maximum number of threads in flight at one time
//
// 256 waves * 64 threads/wave * 2 shader engines (for 870)
//
bufferSize *= nullDev().hwInfo()->simdWidth_ * 4; // threads/wave
bufferSize *= 256 * 4; // maximum number of waves
bufferSize *= numShaderEngines;
encoding.UAVReturnBufferTotalSize = bufferSize;
return true;
}
} // namespace gpu
+203
View File
@@ -0,0 +1,203 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include "device/gpu/gpudefs.hpp"
#include "device/gpu/gpuprogram.hpp"
#include "device/gpu/gpukernel.hpp"
#include "acl.h"
#include "SCShadersSi.h"
#include "si_ci_merged_offset.h"
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <ctime>
namespace gpu {
bool
NullKernel::siCreateHwInfo(const void* shader, AMUabiAddEncoding& encoding)
{
static const uint NumSiCsInfos = (70 + 5 + 1 + 32 + 6);
CALProgramInfoEntry* newInfos;
uint i = 0;
uint infoCount = NumSiCsInfos;
const SC_SI_HWSHADER_CS* cShader = reinterpret_cast<const SC_SI_HWSHADER_CS*>(shader);
newInfos = new CALProgramInfoEntry[infoCount];
encoding.progInfos = newInfos;
if (encoding.progInfos == 0) {
infoCount = 0;
return false;
}
newInfos[i].address = AMU_ABI_USER_ELEMENT_COUNT;
newInfos[i].value = cShader->common.userElementCount;
i++;
for (unsigned int j = 0; j < cShader->common.userElementCount; j++) {
newInfos[i].address = AMU_ABI_USER_ELEMENTS_0_DWORD0 + 4*j;
newInfos[i].value = HWSHADER_Get(cShader, common.pUserElements)[j].dataClass;
i++;
newInfos[i].address = AMU_ABI_USER_ELEMENTS_0_DWORD1 + 4*j;
newInfos[i].value = HWSHADER_Get(cShader, common.pUserElements)[j].apiSlot;
i++;
newInfos[i].address = AMU_ABI_USER_ELEMENTS_0_DWORD2 + 4*j;
newInfos[i].value = HWSHADER_Get(cShader, common.pUserElements)[j].startUserReg;
i++;
newInfos[i].address = AMU_ABI_USER_ELEMENTS_0_DWORD3 + 4*j;
newInfos[i].value = HWSHADER_Get(cShader, common.pUserElements)[j].userRegCount;
i++;
}
newInfos[i].address = AMU_ABI_SI_NUM_VGPRS;
newInfos[i].value = cShader->common.numVgprs;
i++;
newInfos[i].address = AMU_ABI_SI_NUM_SGPRS;
newInfos[i].value = cShader->common.numSgprs;
i++;
newInfos[i].address = AMU_ABI_SI_NUM_SGPRS_AVAIL;
newInfos[i].value = 104-2; //512;//options.NumSGPRsAvailable;
i++;
newInfos[i].address = AMU_ABI_SI_NUM_VGPRS_AVAIL;
newInfos[i].value = 256;//options.NumVGPRsAvailable;
i++;
newInfos[i].address = AMU_ABI_SI_FLOAT_MODE;
newInfos[i].value = cShader->common.floatMode;
i++;
newInfos[i].address = AMU_ABI_SI_IEEE_MODE;
newInfos[i].value = cShader->common.bIeeeMode;
i++;
newInfos[i].address = AMU_ABI_SI_SCRATCH_SIZE;
newInfos[i].value = cShader->common.scratchSize;;
i++;
newInfos[i].address = mmCOMPUTE_PGM_RSRC2;
newInfos[i].value = cShader->computePgmRsrc2.u32All;
i++;
newInfos[i].address = AMU_ABI_NUM_THREAD_PER_GROUP_X;
newInfos[i].value = cShader->numThreadX;
i++;
newInfos[i].address = AMU_ABI_NUM_THREAD_PER_GROUP_Y;
newInfos[i].value = cShader->numThreadY;
i++;
newInfos[i].address = AMU_ABI_NUM_THREAD_PER_GROUP_Z;
newInfos[i].value = cShader->numThreadZ;
i++;
newInfos[i].address = AMU_ABI_ORDERED_APPEND_ENABLE;
newInfos[i].value = cShader->bOrderedAppendEnable;
i++;
newInfos[i].address = AMU_ABI_RAT_OP_IS_USED;
newInfos[i].value = cShader->common.uavResourceUsage[0];
i++;
for (unsigned int j = 0; j < ((SC_MAX_UAV + 31) / 32); j++) {
newInfos[i].address = AMU_ABI_UAV_RESOURCE_MASK_0 + j;
newInfos[i].value = cShader->common.uavResourceUsage[j];
i++;
}
newInfos[i].address = AMU_ABI_NUM_WAVEFRONT_PER_SIMD; // Setting the same as for scWrapR800Info
newInfos[i].value = 1;
i++;
newInfos[i].address = AMU_ABI_WAVEFRONT_SIZE;
newInfos[i].value = nullDev().hwInfo()->simdWidth_ * 4; //options.WavefrontSize;
i++;
newInfos[i].address = AMU_ABI_LDS_SIZE_AVAIL;
newInfos[i].value = 32*1024; //options.LDSSize;
i++;
newInfos[i].address = AMU_ABI_LDS_SIZE_USED;
newInfos[i].value = 64 * 4 * cShader->computePgmRsrc2.bits.LDS_SIZE;
i++;
infoCount = i;
assert((i + 4 * (16 - cShader->common.userElementCount)) == NumSiCsInfos);
encoding.progInfosCount = infoCount;
CALUavMask uavMask;
memcpy(uavMask.mask, cShader->common.uavResourceUsage, sizeof(CALUavMask));
encoding.uavMask = uavMask;
encoding.textData = HWSHADER_Get(cShader, common.hShaderMemHandle);
encoding.textSize = cShader->common.codeLenInByte;
instructionCnt_ = encoding.textSize / sizeof(uint32_t);
encoding.scratchRegisterCount = cShader->common.scratchSize;
encoding.UAVReturnBufferTotalSize = 0;
return true;
}
bool
HSAILKernel::aqlCreateHWInfo(const void* shader, size_t shaderSize)
{
// Copy the shader_isa into a buffer
hwMetaData_ = new char[shaderSize];
if (hwMetaData_ == NULL) {
return false;
}
memcpy(hwMetaData_, shader, shaderSize);
SC_SI_HWSHADER_CS* siMetaData = reinterpret_cast<SC_SI_HWSHADER_CS*>(hwMetaData_);
// Code to patch the pointers in the shader object.
// Must be preferably done in the compiler library
size_t offset = siMetaData->common.uSizeInBytes;
if (siMetaData->common.u32PvtDataSizeInBytes > 0) {
siMetaData->common.pPvtData =
reinterpret_cast<SC_BYTE *>(
reinterpret_cast<char *>(siMetaData) + offset);
offset += siMetaData->common.u32PvtDataSizeInBytes;
}
if (siMetaData->common.codeLenInByte > 0) {
siMetaData->common.hShaderMemHandle =
reinterpret_cast<char *>(siMetaData) + offset;
offset += siMetaData->common.codeLenInByte;
}
char* headerBaseAddress =
reinterpret_cast<char*>(siMetaData->common.hShaderMemHandle);
hsa_ext_code_descriptor_t* hcd =
reinterpret_cast<hsa_ext_code_descriptor_t*>(headerBaseAddress);
amd_kernel_code_t* akc = reinterpret_cast<amd_kernel_code_t*>(
headerBaseAddress + hcd->code.handle);
address codeStartAddress = reinterpret_cast<address>(akc);
address codeEndAddress = reinterpret_cast<address>(hcd) + siMetaData->common.codeLenInByte;
uint64_t codeSize = codeEndAddress - codeStartAddress;
code_ = new gpu::Memory(dev(), amd::alignUp(codeSize, gpu::ConstBuffer::VectorSize));
// Initialize kernel ISA code
if ((code_ != NULL) && code_->create(Resource::Local)) {
address cpuCodePtr = static_cast<address>(code_->map(NULL, Resource::WriteOnly));
// Copy only amd_kernel_code_t
memcpy(cpuCodePtr, codeStartAddress, codeSize);
code_->unmap(NULL);
}
else {
LogError("Failed to allocate ISA code!");
return false;
}
cpuAqlCode_ = akc;
assert((akc->workitem_private_segment_byte_size & 3) == 0 &&
"Scratch must be DWORD aligned");
workGroupInfo_.scratchRegs_ =
akc->workitem_private_segment_byte_size / sizeof(uint);
workGroupInfo_.availableSGPRs_ = dev().gslCtx()->getNumSGPRsAvailable();
workGroupInfo_.availableVGPRs_ = dev().gslCtx()->getNumVGPRsAvailable();
workGroupInfo_.preferredSizeMultiple_ = dev().getAttribs().wavefrontSize;
workGroupInfo_.privateMemSize_ = akc->workitem_private_segment_byte_size;
workGroupInfo_.localMemSize_ =
workGroupInfo_.usedLDSSize_ = akc->workgroup_group_segment_byte_size;
workGroupInfo_.usedSGPRs_ = akc->wavefront_sgpr_count;
workGroupInfo_.usedStackSize_ = 0;
workGroupInfo_.usedVGPRs_ = akc->workitem_vgpr_count;
workGroupInfo_.wavefrontPerSIMD_ = dev().getAttribs().wavefrontSize;
return true;
}
} // namespace gpu
+483
View File
@@ -0,0 +1,483 @@
//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//
#include "top.hpp"
#include "os/os.hpp"
#include "device/device.hpp"
#include "device/gpu/gpudefs.hpp"
#include "device/gpu/gpusettings.hpp"
#include <algorithm>
namespace gpu {
Settings::Settings()
{
// Initialize the GPU device default settings
oclVersion_ = OpenCL12;
debugFlags_ = 0;
singleHeap_ = false;
syncObject_ = GPU_USE_SYNC_OBJECTS;
remoteAlloc_ = REMOTE_ALLOC;
stagedXferRead_ = true;
stagedXferWrite_ = true;
stagedXferSize_ = GPU_STAGING_BUFFER_SIZE * Ki;
// We will enable staged read/write if we use local memory
disablePersistent_ = false;
// By Default persistent writes will be disabled.
stagingWritePersistent_ = GPU_STAGING_WRITE_PERSISTENT;
maxRenames_ = 32;
maxRenameSize_ = 4 * Mi;
// The global heap settings
heapSize_ = GPU_INITIAL_HEAP_SIZE * Mi;
heapSizeGrowth_ = GPU_HEAP_GROWTH_INCREMENT * Mi;
useAliases_ = false;
imageSupport_ = false;
hwLDSSize_ = 0;
// Set this to true when we drop the flag
doublePrecision_ = ::CL_KHR_FP64;
// Fill workgroup info size
// @todo: revisit the 256 limitation on workgroup size
maxWorkGroupSize_ = 256;
hostMemDirectAccess_ = HostMemDisable;
libSelector_ = amd::LibraryUndefined;
#if cl_amd_open_video
// By default Open Video extension is not yet supported
openVideo_ = false;
#endif // cl_amd_open_video
// Enable workload split by default (for 24 bit arithmetic or timeout)
workloadSplitSize_ = 1 << GPU_WORKLOAD_SPLIT;
// By default use host blit
blitEngine_ = BlitEngineHost;
const static size_t MaxPinnedXferSize = 32;
pinnedXferSize_ = std::min(GPU_PINNED_XFER_SIZE, MaxPinnedXferSize) * Mi;
pinnedMinXferSize_ = std::min(GPU_PINNED_MIN_XFER_SIZE * Ki, pinnedXferSize_);
// Disable FP_FAST_FMA defines by default
reportFMAF_ = false;
reportFMA_ = false;
// Disable async memory transfers by default
asyncMemCopy_ = false;
// GPU device by default
apuSystem_ = false;
// Save resource cache size
resourceCacheSize_ = GPU_RESOURCE_CACHE_SIZE * Mi;
// Disable 64 bit pointers support by default
use64BitPtr_ = false;
// Max alloc size is 16GB
maxAllocSize_ = 16 * static_cast<uint64_t>(Gi);
// Disable memory dependency tracking by default
numMemDependencies_ = 0;
// By default cache isn't present
cacheLineSize_ = 0;
cacheSize_ = 0;
// Initialize transfer buffer size to 1MB by default
xferBufSize_ = 1024 * Ki;
// Use image DMA if requested
imageDMA_ = GPU_IMAGE_DMA;
// Disable ASIC specific features by default
siPlus_ = false;
ciPlus_ = false;
viPlus_ = false;
// Number of compute rings.
numComputeRings_ = 0;
// Rectangular Linear DRMDMA
rectLinearDMA_ = false;
minWorkloadTime_ = 1; // 0.1 ms
maxWorkloadTime_ = 5000; // 500 ms
// Preallocates address space
preallocAddrSpace_ = GPU_PREALLOC_ADDR_SPACE;
// Controls tiled images in persistent
//!@note IOL for Linux doesn't setup tiling aperture in CMM/QS
linearPersistentImage_ = false;
useSingleScratch_ = GPU_USE_SINGLE_SCRATCH;
// SDMA profiling is disabled by default
sdmaProfiling_ = false;
// Device enqueuing settings
numDeviceEvents_ = 1024;
numWaitEvents_ = 8;
// Disable HSAIL by default
hsail_ = false;
// Don't support platform atomics by default.
svmAtomics_ = false;
// Use direct SRD by default
hsailDirectSRD_ = GPU_DIRECT_SRD;
}
bool
Settings::create(
const CALdeviceattribs& calAttr
#if cl_amd_open_video
, const CALdeviceVideoAttribs& calVideoAttr
#endif // cl_amd_open_video
, bool reportAsOCL12Device
)
{
CALuint target = calAttr.target;
uint32_t osVer = 0x0;
// Disable thread trace by default for all devices
threadTraceEnable_ = false;
if (calAttr.doublePrecision) {
// Report FP_FAST_FMA define if double precision HW
reportFMA_ = true;
// FMA is 1/4 speed on Pitcairn, Cape Verde, Devastator and Scrapper
// Bonaire, Kalindi, Spectre and Spooky so disable
// FP_FMA_FMAF for those parts in switch below
reportFMAF_ = true;
}
// Update GPU specific settings and info structure if we have any
switch (target) {
case CAL_TARGET_SUMO:
case CAL_TARGET_SUPERSUMO:
case CAL_TARGET_WRESTLER:
// Treat these like Evergreen parts as far as capabilities go
// Fall through ...
case CAL_TARGET_DEVASTATOR:
case CAL_TARGET_SCRAPPER:
apuSystem_ = true;
reportFMAF_ = false;
// For the system that has APU and Win 8, the work load needs to be smaller
// This is because KMD doesn't have workaround for TDR in Win 8
// This is needed only for EG/NI because EG/NI is using graphics ring
#if defined(_WIN32)
{
OSVERSIONINFOEX versionInfo = { 0 };
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
versionInfo.dwMajorVersion = 6;
versionInfo.dwMinorVersion = 2;
DWORDLONG conditionMask = 0;
VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
if (VerifyVersionInfo(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask)) {
maxWorkloadTime_ = 500; // 50 ms
}
}
#endif // defined(_WIN32)
// Add the caps for Trinity here ...
// Fall through ...
case CAL_TARGET_CAYMAN:
// Add the caps for Cayman here ...
case CAL_TARGET_KAUAI:
case CAL_TARGET_BARTS:
case CAL_TARGET_TURKS:
case CAL_TARGET_CAICOS:
// Treat these like Evergreen parts as far as capabilities go
// Fall through ...
case CAL_TARGET_CYPRESS:
case CAL_TARGET_JUNIPER:
case CAL_TARGET_REDWOOD:
case CAL_TARGET_CEDAR:
// UAV arena is a pre-SI specific HW feature
useAliases_ = true;
if (CAL_TARGET_CEDAR == target) {
// Workaround for SC spill bugs.
maxWorkGroupSize_ = 128;
}
// Get the link library
libSelector_ = amd::GPU_Library_Evergreen;
// Max alloc size
maxAllocSize_ = 512 * Mi;
if ((target == CAL_TARGET_CAYMAN) ||
(target == CAL_TARGET_DEVASTATOR) ||
(target == CAL_TARGET_SCRAPPER)) {
rectLinearDMA_ = true;
}
// Disable KHR_FP64 for Trinity in the mainline
if ((target == CAL_TARGET_DEVASTATOR) ||
(target == CAL_TARGET_SCRAPPER)) {
doublePrecision_ &= !IS_MAINLINE || !flagIsDefault(CL_KHR_FP64);
}
if (target == CAL_TARGET_CYPRESS) {
// Float FMA is slower than "multiply + add" because we combine
// "multiply + add" into mad. MAD is 25% faster than FMA on Cypress,
// assuming perfect VLIW packing.
reportFMAF_ = false;
}
enableExtension(ClAmdImage2dFromBufferReadOnly);
break;
case CAL_TARGET_ICELAND:
case CAL_TARGET_TONGA:
case CAL_TARGET_BERMUDA:
case CAL_TARGET_FIJI:
case CAL_TARGET_CARRIZO:
// Disable tiling aperture on VI+
linearPersistentImage_ = true;
viPlus_ = true;
// Fall through to CI ...
case CAL_TARGET_KALINDI:
case CAL_TARGET_SPECTRE:
case CAL_TARGET_SPOOKY:
case CAL_TARGET_GODAVARI:
if (!viPlus_) {
// APU systems for CI
apuSystem_ = true;
}
// Fall through ...
case CAL_TARGET_BONAIRE:
case CAL_TARGET_HAWAII:
ciPlus_ = true;
sdmaProfiling_ = true;
hsail_ = GPU_HSAIL_ENABLE;
// Fall through to SI ...
case CAL_TARGET_PITCAIRN:
case CAL_TARGET_CAPEVERDE:
case CAL_TARGET_OLAND:
case CAL_TARGET_HAINAN:
reportFMAF_ = false;
if (target == CAL_TARGET_HAWAII) {
reportFMAF_ = true;
}
// Fall through ...
case CAL_TARGET_TAHITI:
siPlus_ = true;
// Cache line size is 64 bytes
cacheLineSize_ = 64;
// L1 cache size is 16KB
cacheSize_ = 16 * Ki;
if (ciPlus_) {
libSelector_ = amd::GPU_Library_CI;
#if defined(_LP64)
oclVersion_ = reportAsOCL12Device ? OpenCL12 : XCONCAT(OpenCL,XCONCAT(OPENCL_MAJOR,OPENCL_MINOR));
#endif
if (GPU_FORCE_OCL20_32BIT) {
force32BitOcl20_ = true;
oclVersion_ = reportAsOCL12Device ? OpenCL12 : XCONCAT(OpenCL,XCONCAT(OPENCL_MAJOR,OPENCL_MINOR));
}
if (hsail_) {
oclVersion_ = OpenCL12;
}
numComputeRings_ = 8;
}
else {
numComputeRings_ = 2;
libSelector_ = amd::GPU_Library_SI;
}
// This needs to be cleaned once 64bit addressing is stable
if (oclVersion_ < OpenCL20) {
use64BitPtr_ = flagIsDefault(GPU_FORCE_64BIT_PTR) ? LP64_SWITCH(false,
calAttr.isWorkstation || hsail_) : GPU_FORCE_64BIT_PTR;
}
else {
if (GPU_FORCE_64BIT_PTR || LP64_SWITCH(false, (hsail_
|| (oclVersion_ >= OpenCL20)))) {
use64BitPtr_ = true;
}
}
if (oclVersion_ >= OpenCL20) {
supportDepthsRGB_ = true;
}
if (use64BitPtr_) {
maxAllocSize_ = 4048 * Mi;
}
else {
maxAllocSize_ = 3ULL * Gi;
}
supportRA_ = false;
partialDispatch_ = GPU_PARTIAL_DISPATCH;
numMemDependencies_ = GPU_NUM_MEM_DEPENDENCY;
//! @todo HSAIL doesn't support 64 bit atomic on 32 bit!
if (LP64_SWITCH(!hsail_, true)) {
enableExtension(ClKhrInt64BaseAtomics);
enableExtension(ClKhrInt64ExtendedAtomics);
}
enableExtension(ClKhrImage2dFromBuffer);
rectLinearDMA_ = true;
if (AMD_DEPTH_MSAA_INTEROP) {
enableExtension(ClKhrGLDepthImages);
depthMSAAInterop_ = true;
}
if (AMD_THREAD_TRACE_ENABLE) {
threadTraceEnable_ = true;
}
// Disable non-aliased(multiUAV) optimization
assumeAliases_ = true;
break;
default:
assert(0 && "Unknown ASIC type!");
return false;
}
// Enable atomics support
enableExtension(ClKhrGlobalInt32BaseAtomics);
enableExtension(ClKhrGlobalInt32ExtendedAtomics);
enableExtension(ClKhrLocalInt32BaseAtomics);
enableExtension(ClKhrLocalInt32ExtendedAtomics);
enableExtension(ClKhrByteAddressableStore);
enableExtension(ClKhrGlSharing);
enableExtension(ClKhrGlEvent);
enableExtension(ClAmdMediaOps);
enableExtension(ClAmdMediaOps2);
enableExtension(ClAmdPopcnt);
#if defined(_WIN32)
enableExtension(ClKhrD3d9Sharing);
enableExtension(ClKhrD3d10Sharing);
enableExtension(ClKhrD3d11Sharing);
#endif // _WIN32
enableExtension(ClKhr3DImageWrites);
enableExtension(ClAmdVec3);
enableExtension(ClAmdPrintf);
enableExtension(ClExtAtomicCounters32);
hwLDSSize_ = 32 * Ki;
imageSupport_ = true;
singleHeap_ = true;
customSvmAllocator_ = true;
// Use kernels for blit if appropriate
blitEngine_ = BlitEngineKernel;
#if cl_amd_open_video
// Enable OpenVideo by default if CAL supports it
if (calVideoAttr.max_decode_sessions > 0) {
openVideo_ = true;
if (GPU_OPEN_VIDEO)
enableExtension(ClAmdOpenVideo);
}
#endif // cl_amd_open_video
hostMemDirectAccess_ |= HostMemBuffer;
// HW doesn't support untiled image writes
// hostMemDirectAccess_ |= HostMemImage;
asyncMemCopy_ = true;
// Make sure device actually supports double precision
doublePrecision_ = (calAttr.doublePrecision) ? doublePrecision_ : false;
if (doublePrecision_) {
// Enable KHR double precision extension
enableExtension(ClKhrFp64);
}
if (calAttr.doublePrecision) {
// Enable AMD double precision extension
doublePrecision_ = true;
enableExtension(ClAmdFp64);
}
if (calAttr.totalSDIHeap > 0) {
//Enable bus addressable memory extension
enableExtension(ClAMDBusAddressableMemory);
}
if (calAttr.longIdleDetect) {
// KMD is unable to detect if we map the visible memory for CPU access, so
// accessing persistent staged buffer may fail if LongIdleDetct is enabled.
disablePersistent_ = true;
}
if (calAttr.priSupport) {
svmAtomics_ = true;
}
// Enable some platform extensions
enableExtension(ClAmdDeviceAttributeQuery);
enableExtension(ClKhrSpir);
// Enable some OpenCL 2.0 extensions
if (oclVersion_ >= OpenCL20) {
enableExtension(ClKhrSubGroups);
}
// Override current device settings
override();
return true;
}
void
Settings::override()
{
// Limit reported workgroup size
if (GPU_MAX_WORKGROUP_SIZE != 0) {
maxWorkGroupSize_ = GPU_MAX_WORKGROUP_SIZE;
}
// Override blit engine type
if (GPU_BLIT_ENGINE_TYPE != BlitEngineDefault) {
blitEngine_ = GPU_BLIT_ENGINE_TYPE;
}
if (!flagIsDefault(DEBUG_GPU_FLAGS)) {
debugFlags_ = DEBUG_GPU_FLAGS;
}
// Check async memory transfer
if (!flagIsDefault(GPU_ASYNC_MEM_COPY)) {
asyncMemCopy_ = GPU_ASYNC_MEM_COPY;
}
if (!flagIsDefault(DEBUG_GPU_FLAGS)) {
debugFlags_ = DEBUG_GPU_FLAGS;
}
if (!flagIsDefault(GPU_XFER_BUFFER_SIZE)) {
xferBufSize_ = GPU_XFER_BUFFER_SIZE * Ki;
}
if (!flagIsDefault(GPU_USE_SYNC_OBJECTS)) {
syncObject_ = GPU_USE_SYNC_OBJECTS;
}
if (!flagIsDefault(GPU_NUM_COMPUTE_RINGS)) {
numComputeRings_ = GPU_NUM_COMPUTE_RINGS;
}
if (!flagIsDefault(GPU_ASSUME_ALIASES)) {
assumeAliases_ = GPU_ASSUME_ALIASES;
}
}
} // namespace gpu
+134
View File
@@ -0,0 +1,134 @@
//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUSETTINGS_HPP_
#define GPUSETTINGS_HPP_
#include "top.hpp"
#include "library.hpp"
/*! \addtogroup GPU GPU Resource Implementation
* @{
*/
//! GPU Device Implementation
namespace gpu {
//! Device settings
class Settings : public device::Settings
{
public:
//! Debug GPU flags
enum DebugGpuFlags
{
CheckForILSource = 0x00000001,
StubCLPrograms = 0x00000002, //!< Enables OpenCL programs stubbing
LockGlobalMemory = 0x00000004,
};
enum BlitEngineType
{
BlitEngineDefault = 0x00000000,
BlitEngineHost = 0x00000001,
BlitEngineCAL = 0x00000002,
BlitEngineKernel = 0x00000003,
};
enum HostMemFlags
{
HostMemDisable = 0x00000000,
HostMemBuffer = 0x00000001,
HostMemImage = 0x00000002,
};
union {
struct {
uint singleHeap_: 1; //!< Device will use a preallocated heap
uint remoteAlloc_: 1; //!< Allocate remote memory for the heap
uint stagedXferRead_: 1; //!< Uses a staged buffer read
uint stagedXferWrite_: 1; //!< Uses a staged buffer write
uint disablePersistent_: 1; //!< Disables using persistent memory for staging
uint useAliases_: 1; //!< Enables global heap aliases in HW
uint imageSupport_: 1; //!< Report images support
uint doublePrecision_: 1; //!< Enables double precision support
uint openVideo_: 1; //!< Open Video interop support
uint reportFMAF_: 1; //!< Report FP_FAST_FMAF define in CL program
uint reportFMA_: 1; //!< Report FP_FAST_FMA define in CL program
uint use64BitPtr_: 1; //!< Use 64bit pointers on GPU
uint force32BitOcl20_: 1; //!< Force 32bit apps to take CLANG/HSAIL path on GPU
uint imageDMA_: 1; //!< Enable direct image DMA transfers
uint syncObject_: 1; //!< Enable syncobject
uint siPlus_: 1; //!< SI and post SI features
uint ciPlus_: 1; //!< CI and post CI features
uint viPlus_: 1; //!< VI and post VI features
uint rectLinearDMA_: 1; //!< Rectangular linear DRMDMA support
uint threadTraceEnable_: 1; //!< Thread trace enable
uint preallocAddrSpace_: 1; //!< Preallocates address space
uint linearPersistentImage_: 1; //!< Allocates linear images in persistent
uint useSingleScratch_: 1; //!< Allocates single scratch per device
uint sdmaProfiling_: 1; //!< Enables SDMA profiling
uint hsail_: 1; //!< Enables HSAIL compilation
uint stagingWritePersistent_: 1; //!< Enables persistent writes
uint svmAtomics_: 1; //!< SVM device atomics
uint apuSystem_: 1; //!< Device is APU system with shared memory
uint asyncMemCopy_: 1; //!< Use async memory transfers
uint hsailDirectSRD_: 1; //!< Controls direct SRD for HSAIL
uint reserved_: 2;
};
uint value_;
};
uint oclVersion_; //!< Reported OpenCL version support
uint debugFlags_; //!< Debug GPU flags
size_t stagedXferSize_; //!< Staged buffer size
uint maxRenames_; //!< Maximum number of possible renames
uint maxRenameSize_; //!< Maximum size for all renames
size_t heapSize_; //!< The global heap size
size_t heapSizeGrowth_; //!< The global heap size growth
uint hwLDSSize_; //!< HW local data store size
uint maxWorkGroupSize_; //!< Requested workgroup size for this device
uint hostMemDirectAccess_; //!< Enables direct access to the host memory
amd::LibrarySelector libSelector_; //!< Select linking libraries for compiler
uint workloadSplitSize_; //!< Workload split size
uint minWorkloadTime_; //!< Minimal workload time in 0.1 ms
uint maxWorkloadTime_; //!< Maximum workload time in 0.1 ms
uint blitEngine_; //!< Blit engine type
size_t pinnedXferSize_; //!< Pinned buffer size for transfer
size_t pinnedMinXferSize_; //!< Minimal buffer size for pinned transfer
size_t resourceCacheSize_; //!< Resource cache size in MB
uint64_t maxAllocSize_; //!< Maximum single allocation size
size_t numMemDependencies_;//!< The array size for memory dependencies tracking
uint cacheLineSize_; //!< Cache line size in bytes
uint cacheSize_; //!< L1 cache size in bytes
size_t xferBufSize_; //!< Transfer buffer size for image copy optimization
uint numComputeRings_; //!< 0 - disabled, 1 , 2,.. - the number of compute rings
uint numDeviceEvents_; //!< The number of device events
uint numWaitEvents_; //!< The number of wait events for device enqueue
//! Default constructor
Settings();
//! Creates settings
bool create(
const CALdeviceattribs& calAttr //!< CAL attributes structure
#if cl_amd_open_video
, const CALdeviceVideoAttribs& calVideoAttr //!< CAL video attributes
#endif // cl_amd_open_video
, bool reportAsOCL12Device = false //!< Report As OpenCL1.2 Device
);
private:
//! Disable copy constructor
Settings(const Settings&);
//! Disable assignment
Settings& operator=(const Settings&);
//! Overrides current settings based on registry/environment
void override();
};
/*@}*/} // namespace gpu
#endif /*GPUSETTINGS_HPP_*/
@@ -0,0 +1,66 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include "device/gpu/gputhreadtrace.hpp"
#include "device/gpu/gpuvirtual.hpp"
namespace gpu {
CalThreadTraceReference::~CalThreadTraceReference() {
// The thread trace object is always associated with a particular queue,
// so we have to lock just this queue
amd::ScopedLock lock(gpu_.execution());
if (0 != threadTrace_) {
//gpu().destroyThreadTrace(gslThreadTrace());
}
}
ThreadTrace::~ThreadTrace()
{
if (calRef_ == NULL) {
return;
}
for(uint i = 0; i < amdThreadTraceMemObjsNum_;++i) {
gpu().DestroyThreadTraceBuffer(threadTraceBufferObjs_[i],i);
}
// Release the thread trace reference object
//calRef_->release();
}
bool
ThreadTrace::create(CalThreadTraceReference* calRef)
{
assert(&gpu() == &calRef->gpu());
calRef_ = calRef;
threadTrace_ = calRef->gslThreadTrace();
return true;
}
bool
ThreadTrace::info(uint infoType, uint* info,uint infoSize) const
{
switch (infoType) {
case CL_THREAD_TRACE_BUFFERS_SIZE: {
if (infoSize < amdThreadTraceMemObjsNum_) {
LogError("The amount of buffers should be equal to the amount of Shader Engines");
return false;
}
else {
*info = gpu().getThreadTraceQueryRes(gslThreadTrace());
}
break;
}
default:
LogError("Wrong ThreadTrace::getInfo parameter");
return false;
}
return true;
}
} // namespace gpu
@@ -0,0 +1,137 @@
//
// Copyright (c) 2009 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPU_THREAD_TRACE_HPP_
#define GPU_THREAD_TRACE_HPP_
#include "top.hpp"
#include "device/device.hpp"
#include "device/gpu/gpudevice.hpp"
#include <vector>
namespace gpu {
class VirtualGPU;
class CalThreadTraceReference : public amd::ReferenceCountedObject
{
public:
//! Default constructor
CalThreadTraceReference(
VirtualGPU& gpu, //!< Virtual GPU device object
gslQueryObject gslThreadTrace) //!< GSL query thread trace object
: gpu_(gpu)
, threadTrace_(gslThreadTrace){}
//! Get GSL thread race object
gslQueryObject gslThreadTrace() const { return threadTrace_; }
//! Returns the virtual GPU device
const VirtualGPU& gpu() const { return gpu_; }
protected:
//! Default destructor
~CalThreadTraceReference();
private:
//! Disable copy constructor
CalThreadTraceReference(const CalThreadTraceReference&);
//! Disable operator=
CalThreadTraceReference& operator=(const CalThreadTraceReference&);
VirtualGPU& gpu_; //!< The virtual GPU device object
gslQueryObject threadTrace_; //!< GSL thread trace query object
};
//! ThreadTrace implementation on GPU
class ThreadTrace : public device::ThreadTrace
{
public:
//! Destructor for the GPU ThreadTrace object
virtual ~ThreadTrace();
//! Creates the current object
bool create(
CalThreadTraceReference* calRef //!< Reference ThreadTrace
);
//! Returns the GPU device, associated with the current object
const Device& dev() const { return gpuDevice_; }
//! Returns the virtual GPU device
const VirtualGPU& gpu() const { return gpu_; }
//! Constructor for the GPU ThreadTrace object
ThreadTrace(
Device& device, //!< A GPU device object
VirtualGPU& gpu, //!< Virtual GPU device object
uint amdThreadTraceMemObjsNum)
: gpuDevice_(device)
, gpu_(gpu)
, calRef_(NULL)
, index_(0)
, amdThreadTraceMemObjsNum_(amdThreadTraceMemObjsNum)
{
threadTraceBufferObjs_ = new gslShaderTraceBufferObject[amdThreadTraceMemObjsNum];
for (uint i = 0; i < amdThreadTraceMemObjsNum;++i) {
threadTraceBufferObjs_[i] = gpu.CreateThreadTraceBuffer();
}
}
//! Returns the specific information about the thread trace object
bool info(
uint infoType, //!< The type of returned information
uint* info, //!< The returned information
uint infoSize //!< The size of returned information
) const;
//! Set the ThreadTrace memory buffer size
void setMemBufferSizeTT(uint memBufferSizeTT) { memBufferSizeTT_ = memBufferSizeTT;}
//! Set isNewBufferBinded_ to true/false if new buffer was binded/unbinded respectively
void setNewBufferBinded(bool isNewBufferBinded) { isNewBufferBinded_ = isNewBufferBinded; }
//! Attach gslMemObject to the TreadTrace buffer
void attachMemToThreadTraceBuffer();
void setMemObj(size_t memObjSize,std::vector<amd::Memory*> memObj)
{
memObj_ = memObj;
memBufferSizeTT_ = memObjSize;
}
//! Get GSL thread trace object
gslQueryObject gslThreadTrace() const { return threadTrace_; }
//! Get GSL Thread Trace Buffer objects
gslShaderTraceBufferObject* getThreadTraceBufferObjects() {return threadTraceBufferObjs_;}
private:
//! Disable default copy constructor
ThreadTrace(const ThreadTrace&);
//! Disable default operator=
ThreadTrace& operator=(const ThreadTrace&);
//! Retrieve gslMemoryObject
gslMemObject getCurrentGslMemObject(amd::Memory* );
const Device& gpuDevice_; //!< The backend device
VirtualGPU& gpu_; //!< The virtual GPU device object
CalThreadTraceReference* calRef_; //!< Reference ThreadTrace
gslShaderTraceBufferObject* threadTraceBufferObjs_; //!< The buffer object for Thread Trace recording
uint index_; //!< ThreadTrace index in the CAL container
uint memBufferSizeTT_; //!< ThreadTrace memory buffer size
std::vector<amd::Memory*> memObj_; //!< ThreadTrace memory object
gslQueryObject threadTrace_; //!< GSL thread trace query object
uint amdThreadTraceMemObjsNum_; //!< ThreadTrace memory object`s number (should be equal to the SE number)
bool isNewBufferBinded_; //!< The indicator if new buffer was binded to the ThreadTrace object
bool isBufferOnSubmit_; //!< The indicator if "new buffer on submit" mode is used
};
} // namespace gpu
#endif // GPU_THREAD_TRACE_HPP_
+119
View File
@@ -0,0 +1,119 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include "os/os.hpp"
#include "platform/perfctr.hpp"
#include "device/gpu/gpudefs.hpp"
#include "device/gpu/gputimestamp.hpp"
#include "device/gpu/gpuvirtual.hpp"
#include "device/gpu/gpucounters.hpp"
namespace gpu {
TimeStamp::TimeStamp(
const VirtualGPU& gpu,
gslMemObject gslMem,
uint memOffset,
address cpuAddr)
: gpu_(gpu)
, gslMem_(gslMem)
, memOffset_(memOffset)
{
values_ = reinterpret_cast<volatile uint64_t*>(cpuAddr + memOffset);
}
TimeStamp::~TimeStamp()
{
}
void
TimeStamp::begin(bool sdma)
{
if (!flags_.beginIssued_) {
gpu().writeTimer(sdma, gslMem_,
memOffset_ + CommandStartTime * sizeof(uint64_t));
flags_.beginIssued_ = true;
}
}
void
TimeStamp::end(bool sdma)
{
CondLog(!flags_.beginIssued_, "We didn't issue a begin operation!");
gpu().writeTimer(sdma, gslMem_,
memOffset_ + CommandEndTime * sizeof(uint64_t));
flags_.endIssued_ = true;
flags_.sdma_ = sdma;
}
inline void
SetValue(uint64_t* time, uint64_t val, double nanos)
{
*time = static_cast<uint64_t>(static_cast<double>(val) * nanos);
}
void
TimeStamp::value(uint64_t* startTime, uint64_t* endTime)
{
CondLog(!flags_.endIssued_, "We didn't send the counter end operation!");
const double NanoSecondsPerTick = gpu_.dev().getAttribs().nanoSecondsPerTick;
SetValue(startTime, values_[CommandStartTime], NanoSecondsPerTick);
SetValue(endTime, values_[CommandEndTime], NanoSecondsPerTick);
}
TimeStampCache::~TimeStampCache()
{
// Release all time stamp objects from the cache
for (uint i = 0; i < freedTS_.size(); ++i) {
delete freedTS_[i];
}
freedTS_.clear();
// Release all memory objects
for (uint i = 0; i < tsBuf_.size(); ++i) {
tsBuf_[i]->unmap(&gpu_);
delete tsBuf_[i];
}
tsBuf_.clear();
}
TimeStamp*
TimeStampCache::allocTimeStamp()
{
TimeStamp* ts = NULL;
if (0 != freedTS_.size()) {
ts = freedTS_.back();
freedTS_.pop_back();
}
if (NULL == ts) {
if ((tsBufCpu_ == NULL) || ((tsOffset_ + TimerSlotSize) > TimerBufSize)) {
Memory* buf = new Memory(gpu_.dev(), TimerBufSize);
if (buf == NULL || !buf->create(Resource::Remote)) {
return NULL;
}
tsBufCpu_ = reinterpret_cast<address>(buf->map(&gpu_));
memset(tsBufCpu_, 0, TimerBufSize);
tsOffset_ = 0;
tsBuf_.push_back(buf);
}
// Allocate a TimeStamp object
ts = new TimeStamp(gpu_, tsBuf_[(tsBuf_.size() - 1)]->gslResource(),
tsOffset_, tsBufCpu_);
// Create a timestamp
if (ts == NULL) {
return NULL;
}
tsOffset_ += TimerSlotSize;
}
// Set this timestamp into DRM profile mode if it was requested
ts->clearStates();
return ts;
}
} // namespace gpu
+132
View File
@@ -0,0 +1,132 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUTIMESTAMP_HPP_
#define GPUTIMESTAMP_HPP_
#include "device/gpu/gpudefs.hpp"
#include "device/gpu/gpuresource.hpp"
/*! \addtogroup GPU GPU Resource Implementation
* @{
*/
//! GPU Device Implementation
namespace gpu {
class Device;
class VirtualGPU;
class Memory;
class TimeStamp : public amd::HeapObject
{
public:
//! Enums for the timestamp information
//! \note *4 is the limitaiton of SDMA HW
//! (address has to be aligned by 256 bit)
enum TimeStampValue {
CommandStartTime = 0,
CommandEndTime = 4,
CommandTotal = 8
};
//! The TimeStamp object flags
union Flags
{
struct
{
uint32_t beginIssued_ : 1;
uint32_t endIssued_ : 1;
uint32_t sdma_ : 1;
};
uint32_t value_;
Flags(): value_(0) {}
};
//! Default constructor
TimeStamp(
const VirtualGPU& gpu, //!< Virtual GPU
gslMemObject gslMem, //!< Buffer with the timer values
uint memOffset, //!< Offset in the buffer for the current TS
address cpuAddr //!< CPU pointer for the values in memory
);
//! Default destructor
~TimeStamp();
//! Starts the timestamp
void begin(bool sdma = false);
//! Ends the timestamp
void end(bool sdma = false);
//! Returns the timestamp result in nano seconds
void value(uint64_t* startTime, uint64_t* endTime);
//! Clear all TimeStamp states
void clearStates()
{ flags_.value_ = 0;
values_[CommandStartTime] = 0;
values_[CommandEndTime] = 0;
}
//! Timer commands were submitted to HW
bool isValid() const { return (flags_.endIssued_) ? true : false; }
private:
//! Disable copy constructor
TimeStamp(const TimeStamp&);
//! Disable operator=
TimeStamp& operator=(const TimeStamp&);
//! Returns the GPU device object
const VirtualGPU& gpu() const { return gpu_; }
const VirtualGPU& gpu_; //!< Virtual GPU
Flags flags_; //!< The time stamp state
gslMemObject gslMem_; //!< Buffer with the timer values
uint memOffset_; //!< Offset in the buffer for the current timer
volatile uint64_t* values_; //!< CPU pointer to the timer values
};
class TimeStampCache : public amd::HeapObject
{
public:
//! Default constructor
TimeStampCache(
VirtualGPU& gpu //!< Virtual GPU object
)
: gpu_(gpu)
, tsBufCpu_(NULL)
, tsOffset_(0) {}
//! Default destructor
~TimeStampCache();
//! Gets a time stamp object. It will find a freed object or allocate a new one
TimeStamp* allocTimeStamp();
//! Frees a time stamp object
void freeTimeStamp(TimeStamp* ts) { freedTS_.push_back(ts); }
private:
static const uint TimerSlotSize = TimeStamp::CommandTotal * sizeof(uint64_t);
static const uint TimerBufSize = TimerSlotSize * 4096;
//! Disable copy constructor
TimeStampCache(const TimeStampCache&);
//! Disable operator=
TimeStampCache& operator=(const TimeStampCache&);
std::vector<TimeStamp*> freedTS_; //!< Array of freed time stamp objects
VirtualGPU& gpu_; //!< Virtual GPU
std::vector<Memory*> tsBuf_; //!< Array of memory objects with the timer value
address tsBufCpu_; //!< CPU pointer for current TS memory
uint tsOffset_; //!< Active offset in the current mem object
};
/*@}*/} // namespace gpu
#endif /*GPUTIMESTAMP_HPP_*/
File diff suppressed because it is too large Load Diff
+538
View File
@@ -0,0 +1,538 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef GPUVIRTUAL_HPP_
#define GPUVIRTUAL_HPP_
#include "device/gpu/gpudefs.hpp"
#include "device/gpu/gpuconstbuf.hpp"
#include "device/gpu/gpuprintf.hpp"
#include "device/gpu/gputimestamp.hpp"
#include "device/gpu/gpusched.hpp"
#include "device/blit.hpp"
/*! \addtogroup GPU GPU Resource Implementation
* @{
*/
//! GPU Device Implementation
namespace gpu {
class Device;
class Kernel;
class Resource;
class Memory;
class CalCounterReference;
class VirtualGPU;
class Program;
class BlitManager;
class ThreadTrace;
//! Virtual GPU
class VirtualGPU : public device::VirtualDevice, public CALGSLContext
{
public:
struct CommandBatch : public amd::HeapObject
{
amd::Command* head_; //!< Command batch head
GpuEvent events_[AllEngines]; //!< Last known GPU events
TimeStamp* lastTS_; //!< TS associated with command batch
//! Constructor
CommandBatch(
amd::Command* head, //!< Command batch head
const GpuEvent* events, //!< HW events on all engines
TimeStamp* lastTS //!< Last TS in command batch
): head_(head), lastTS_(lastTS)
{
memcpy(&events_, events, AllEngines * sizeof(GpuEvent));
}
};
//! The virtual GPU states
union State
{
struct
{
uint boundGlobal_ : 1; //!< Global buffer was bound
uint profiling_ : 1; //!< Profiling is enabled
uint forceWait_ : 1; //!< Forces wait in flush()
uint boundCb_ : 1; //!< Constant buffer was bound
uint boundPrintf_ : 1; //!< Printf buffer was bound
uint hsailKernel_ : 1; //!< True if HSAIL kernel was used
};
uint value_;
State(): value_(0) {}
};
//! CAL descriptor for the GPU virtual device
struct CalVirtualDesc : public amd::EmbeddedObject
{
ProgramGrid progGrid_; //!< CAL program grid
uint memCount_; //!< Memory objects count
GpuEvent events_[AllEngines]; //!< Last known GPU events
uint iterations_; //!< Number of iterations for the execution
TimeStamp* lastTS_; //!< Last timestamp executed on Virtual GPU
gslMemObject constBuffers_[MaxConstBuffers];//!< Constant buffer names
gslMemObject uavs_[MaxUavArguments]; //!< UAV bindings
gslMemObject readImages_[MaxReadImage]; //!< Read images
uint32_t samplersState_[MaxSamplers]; //!< State of all samplers
};
typedef std::vector<ConstBuffer*> constbufs_t;
//! \note Legacy pre SI UAV Arena support
static const uint UavArena = MaxWriteImage; //!< 0-7 reserved for images
//! GSL descriptor for the GPU kernel, specific to the virtual device
struct GslKernelDesc : public amd::HeapObject
{
CALimage image_; //!< CAL image for the program
gslProgramObject func_; //!< GSL program object
gslMemObject intCb_; //!< Internal constant buffer
CALUavMask uavMask_; //!< UAV mask, unclear if necessary
CALfuncInfo funcInfo_; //!< CAL function info
};
struct ResourceSlot
{
union State
{
struct
{
uint bound_ : 1; //!< Resource is bound
uint constant_ : 1; //!< Resource is a constant
};
uint value_;
State(): value_(0) {}
};
State state_; //!< slot's state
Memory* memory_; //!< GPU memory object
ResourceSlot(): memory_(NULL) {}
//! Copy constructor for the kernel argument
ResourceSlot(const ResourceSlot& data) { *this = data; }
//! Overloads operator=
ResourceSlot& operator=(const ResourceSlot& data)
{
state_.value_ = data.state_.value_;
memory_ = data.memory_;
return *this;
}
};
class MemoryDependency : public amd::EmbeddedObject
{
public:
//! Default constructor
MemoryDependency()
: memObjectsInQueue_(NULL)
, numMemObjectsInQueue_(0)
, maxMemObjectsInQueue_(0) {}
~MemoryDependency() { delete [] memObjectsInQueue_; }
//! Creates memory dependecy structure
bool create(size_t numMemObj);
//! Notify the tracker about new kernel
void newKernel() { endMemObjectsInQueue_ = numMemObjectsInQueue_; }
//! Validates memory object on dependency
void validate(VirtualGPU& gpu, const Memory* memory, bool readOnly);
//! Clear memory dependency
void clear(bool all = true);
private:
struct MemoryState {
uint64_t start_; //! Busy memory start address
uint64_t end_; //! Busy memory end address
bool readOnly_; //! Current GPU state in the queue
};
MemoryState* memObjectsInQueue_; //!< Memory object state in the queue
size_t endMemObjectsInQueue_; //!< End of mem objects in the queue
size_t numMemObjectsInQueue_; //!< Number of mem objects in the queue
size_t maxMemObjectsInQueue_; //!< Maximum number of mem objects in the queue
};
class DmaFlushMgmt : public amd::EmbeddedObject
{
public:
DmaFlushMgmt(const Device& dev);
// Resets DMA command buffer workload
void resetCbWorkload(const Device& dev);
// Finds split size for the current dispatch
void findSplitSize(
const Device& dev, //!< GPU device object
uint64_t threads, //!< Total number of execution threads
uint instructions //!< Number of ALU instructions
);
// Returns TRUE if DMA command buffer is ready for a flush
bool isCbReady(
VirtualGPU& gpu, //!< Virtual GPU object
uint64_t threads, //!< Total number of execution threads
uint instructions //!< Number of ALU instructions
);
// Returns dispatch split size
uint dispatchSplitSize() const { return dispatchSplitSize_; }
private:
uint64_t maxDispatchWorkload_; //!< Maximum number of operations for a single dispatch
uint64_t maxCbWorkload_; //!< Maximum number of operations for DMA command buffer
uint64_t cbWorkload_; //!< Current number of operations in DMA command buffer
uint aluCnt_; //!< All ALUs on the chip
uint dispatchSplitSize_; //!< Dispath split size in elements
};
typedef std::vector<ResourceSlot> ResourceSlots;
public:
VirtualGPU(Device& device);
bool create(
bool profiling
#if cl_amd_open_video
, void* calVideoProperties
#endif // cl_amd_open_video
, uint deviceQueueSize = 0
);
~VirtualGPU();
void submitReadMemory(amd::ReadMemoryCommand& vcmd);
void submitWriteMemory(amd::WriteMemoryCommand& vcmd);
void submitCopyMemory(amd::CopyMemoryCommand& vcmd);
void submitMapMemory(amd::MapMemoryCommand& vcmd);
void submitUnmapMemory(amd::UnmapMemoryCommand& vcmd);
void submitKernel(amd::NDRangeKernelCommand& vcmd);
bool submitKernelInternal(
const amd::NDRangeContainer& sizes, //!< Workload sizes
const amd::Kernel& kernel, //!< Kernel for execution
const_address parameters, //!< Parameters for the kernel
bool nativeMem = true //!< Native memory objects
);
bool submitKernelInternalHSA(
const amd::NDRangeContainer& sizes, //!< Workload sizes
const amd::Kernel& kernel, //!< Kernel for execution
const_address parameters, //!< Parameters for the kernel
bool nativeMem = true //!< Native memory objects
);
void submitNativeFn(amd::NativeFnCommand& vcmd);
void submitFillMemory(amd::FillMemoryCommand& vcmd);
void submitMigrateMemObjects(amd::MigrateMemObjectsCommand& cmd);
void submitMarker(amd::Marker& vcmd);
void submitAcquireExtObjects(amd::AcquireExtObjectsCommand& vcmd);
void submitReleaseExtObjects(amd::ReleaseExtObjectsCommand& vcmd);
void submitPerfCounter(amd::PerfCounterCommand& vcmd);
void submitThreadTraceMemObjects(amd::ThreadTraceMemObjectsCommand& cmd);
void submitThreadTrace(amd::ThreadTraceCommand& vcmd);
#if cl_amd_open_video
void submitRunVideoProgram(amd::RunVideoProgramCommand& vcmd);
void submitSetVideoSession(amd::SetVideoSessionCommand& cmd);
#endif // cl_amd_open_video
void submitSignal(amd::SignalCommand & vcmd);
void submitMakeBuffersResident(amd::MakeBuffersResidentCommand & vcmd);
virtual void submitSvmFreeMemory(amd::SvmFreeMemoryCommand& cmd);
virtual void submitSvmCopyMemory(amd::SvmCopyMemoryCommand& cmd);
virtual void submitSvmFillMemory(amd::SvmFillMemoryCommand& cmd);
virtual void submitSvmMapMemory(amd::SvmMapMemoryCommand& cmd);
virtual void submitSvmUnmapMemory(amd::SvmUnmapMemoryCommand& cmd);
void releaseMemory(gslMemObject gslResource, bool wait = true);
void releaseKernel(CALimage calImage);
void flush(amd::Command* list = NULL, bool wait = false);
bool terminate() { return true; }
//! Returns GPU device object associated with this kernel
const Device& dev() const { return gpuDevice_; }
//! Returns CAL descriptor of the virtual device
const CalVirtualDesc* cal() const { return &cal_; }
//! Returns active kernel descriptor for this virtual device
const GslKernelDesc* gslKernelDesc() const { return activeKernelDesc_; }
//! Returns a GPU event, associated with GPU memory
GpuEvent* getGpuEvent(
const Resource* resource //!< GPU resource object
) { return &gpuEvents_[resource->gslResource()]; }
//! Assigns a GPU event, associated with GPU memory
void assignGpuEvent(
const Resource* resource, //!< GPU resource object
GpuEvent gpuEvent
) { gpuEvents_[resource->gslResource()] = gpuEvent; }
//! Set the kernel as active
bool setActiveKernelDesc(
const amd::NDRangeContainer& sizes, //!< kernel execution work sizes
const Kernel* kernel //!< GPU kernel object
);
//! Set the last known GPU event
void setGpuEvent(
GpuEvent gpuEvent, //!< GPU event for tracking
bool flush = false //!< TRUE if flush is required
);
//! Flush DMA buffer on the specified engine
void flushDMA(
uint engineID //!< Engine ID for DMA flush
);
//! Wait for all engines on this Virtual GPU
//! Returns TRUE if CPU didn't wait for GPU
bool waitAllEngines(
CommandBatch* cb = NULL //!< Command batch
);
//! Waits for the latest GPU event with a lock to prevent multiple entries
void waitEventLock(
CommandBatch* cb //!< Command batch
);
//! Returns a resource associated with the constant buffer
const ConstBuffer* cb(uint idx) const { return constBufs_[idx]; }
//! Adds CAL objects into the constant buffer vector
void addConstBuffer(ConstBuffer* cb) { constBufs_.push_back(cb); }
constbufs_t constBufs_; //!< constant buffers
//! Returns a resource associated with the constant buffer
ConstBuffer* numGrpCb() const { return numGrpCb_; }
//! Start the command profiling
void profilingBegin(
amd::Command& command, //!< Command queue object
bool drmProfiling = false //!< Measure DRM time
);
//! End the command profiling
void profilingEnd(amd::Command& command);
//! Collect the profiling results
bool profilingCollectResults(
CommandBatch* cb, //!< Command batch
const amd::Event* waitingEvent //!< Waiting event
);
//! Adds a memory handle into the GSL memory array for Virtual Heap
bool addVmMemory(
const Resource* resource //!< GPU resource object
);
//! Adds a stage write buffer into a list
void addXferWrite(Resource& resource);
//! Adds a pinned memory object into a map
void addPinnedMem(amd::Memory* mem);
//! Release pinned memory objects
void releasePinnedMem();
//! Returns gsl memory object for VM
const gslMemObject* vmMems() const { return vmMems_; }
//! Returns the monitor object for execution access by VirtualGPU
amd::Monitor& execution() { return execution_; }
//! Returns the virtual gpu unique index
uint index() const { return index_; }
//! Get the PrintfDbg object
PrintfDbg& printfDbg() const { return *printfDbg_; }
//! Get the PrintfDbgHSA object
PrintfDbgHSA& printfDbgHSA() const { return *printfDbgHSA_; }
//! Enables synchronized transfers
void enableSyncedBlit() const;
//! Checks if profiling is enabled
bool profiling() const { return state_.profiling_; }
//! Returns memory dependency class
MemoryDependency& memoryDependency() { return memoryDependency_; }
//! Returns hsaQueueMem_
const Memory* hsaQueueMem() const { return hsaQueueMem_;}
//! Returns DMA flush management structure
const DmaFlushMgmt& dmaFlushMgmt() const { return dmaFlushMgmt_; }
//! Releases GSL memory objects allocated on this queue
void releaseMemObjects();
//! Returns the HW ring used on this virtual device
uint hwRing() const { return hwRing_; }
//! Returns current timestamp object for profiling
TimeStamp* currTs() const { return cal_.lastTS_; }
//! Returns virtual queue object for device enqueuing
Memory* vQueue() const { return virtualQueue_; }
//! Update virtual queue header
void writeVQueueHeader(VirtualGPU& hostQ, uint64_t kernelTable);
EngineType engineID_; //!< Engine ID for this VirtualGPU
ResourceSlots slots_; //!< Resource slots for kernel arguments
State state_; //!< virtual GPU current state
CalVirtualDesc cal_; //!< CAL virtual device descriptor
protected:
virtual void profileEvent(EngineType engine, bool type) const;
//! Creates buffer object from image
amd::Memory* createBufferFromImage(
amd::Memory& amdImage //! The parent image object(untiled images only)
) const;
private:
typedef std::map<CALimage, GslKernelDesc*> GslKernels;
typedef std::map<gslMemObject, GpuEvent> GpuEvents;
//! Finds total amount of necessary iterations
inline void findIterations(
const amd::NDRangeContainer& sizes, //!< Original workload sizes
const amd::NDRange& local, //!< Local workgroup size
amd::NDRange& groups, //!< Calculated workgroup sizes
amd::NDRange& remainder, //!< Calculated remainder sizes
size_t& extra //!< Amount of extra executions for remainder
);
//! Setups workloads for the current iteration
inline void setupIteration(
uint iteration, //!< Current iteration
const amd::NDRangeContainer& sizes, //!< Original workload sizes
Kernel& gpuKernel, //!< GPU kernel
amd::NDRange& global, //!< Global size for the current iteration
amd::NDRange& offsets, //!< Offsets for the current iteration
amd::NDRange& local, //!< Local sizes for the current iteration
amd::NDRange& groups, //!< Group sizes for the current iteration
amd::NDRange& groupOffset, //!< Group offsets for the current iteration
amd::NDRange& divider, //!< Group divider
amd::NDRange& remainder, //!< Remain workload
size_t extra //!< Extra groups
);
//! Allocates constant buffers
bool allocConstantBuffers();
//! Allocates CAL kernel descriptor of the virtual device
GslKernelDesc* allocKernelDesc(
const Kernel* kernel, //!< Kernel object
CALimage calImage); //!< CAL image
//! Frees CAL kernel descriptor of the virtual device
void freeKernelDesc(GslKernelDesc* desc);
bool gslOpen(uint nEngines, gslEngineDescriptor *engines);
void gslDestroy();
//! Releases stage write buffers
void releaseXferWrite();
//! Allocate hsaQueueMem_
bool allocHsaQueueMem();
//! Awaits a command batch with a waiting event
bool awaitCompletion(
CommandBatch* cb, //!< Command batch for to wait
const amd::Event* waitingEvent = NULL //!< A waiting event
);
//! Validates the scratch buffer memory for a specified kernel
void validateScratchBuffer(
const Kernel* kernel //!< Kernel for validaiton
);
//! Detects memory dependency for HSAIL kernels and flushes caches
void processMemObjectsHSA(
const amd::Kernel& kernel, //!< AMD kernel object for execution
const_address params, //!< Pointer to the param's store
bool nativeMem //!< Native memory objects
);
//! Common function for fill memory used by both svm Fill and non-svm fill
bool fillMemory(
cl_command_type type, //!< the command type
amd::Memory* amdMemory, //!< memory object to fill
const void* pattern, //!< pattern to fill the memory
size_t patternSize, //!< pattern size
const amd::Coord3D& origin, //!< memory origin
const amd::Coord3D& size //!< memory size for filling
);
bool copyMemory(
cl_command_type type, //!< the command type
amd::Memory& srcMem, //!< source memory object
amd::Memory& dstMem, //!< destination memory object
bool entire, //!< flag of entire memory copy
const amd::Coord3D& srcOrigin, //!< source memory origin
const amd::Coord3D& dstOrigin, //!< destination memory object
const amd::Coord3D& size, //!< copy size
const amd::BufferRect& srcRect, //!< region of source for copy
const amd::BufferRect& dstRect //!< region of destination for copy
);
//! Returns TRUE if virtual queue was successfully allocatted
bool createVirtualQueue(
uint deviceQueueSize //!< Device queue size
);
GslKernels gslKernels_; //!< GSL kernel descriptors
GslKernelDesc* activeKernelDesc_; //!< active GSL kernel descriptors
GpuEvents gpuEvents_; //!< GPU events
Device& gpuDevice_; //!< physical GPU device
amd::Monitor execution_; //!< Lock to serialise access to all device objects
uint index_; //!< The virtual device unique index
PrintfDbg* printfDbg_; //!< GPU printf implemenation
PrintfDbgHSA* printfDbgHSA_; //!< HSAIL printf implemenation
TimeStampCache* tsCache_; //!< TimeStamp cache
MemoryDependency memoryDependency_; //!< Memory dependency class
gslMemObject* vmMems_; //!< Array of GSL memories for VM mode
uint numVmMems_; //!< Number of entries in VM mem array
DmaFlushMgmt dmaFlushMgmt_; //!< DMA flush management
std::list<Resource*> xferWriteBuffers_; //!< Stage write buffers
std::list<amd::Memory*> pinnedMems_;//!< Pinned memory list
typedef std::list<CommandBatch*> CommandBatchList;
CommandBatchList cbList_; //!< List of command batches
ConstBuffer* numGrpCb_; //!< Constant buffer for 8xx workaround
uint scratchRegNum_; //!< Number of scratch registers used in this queue
uint hwRing_; //!< HW ring used on this virtual device
uint64_t readjustTimeGPU_; //!< Readjust time between GPU and CPU timestamps
TimeStamp* currTs_; //!< current timestamp for command
AmdVQueueHeader* vqHeader_; //!< Sysmem copy for virtual queue header
Memory* virtualQueue_; //!< Virtual device queue
Memory* schedParams_; //!< The scheduler parameters
uint schedParamIdx_; //!< Index in the scheduler parameters buffer
Memory* hsaQueueMem_; //!< Memory for the amd_queue_t object
};
/*@}*/} // namespace gpu
#endif /*GPUVIRTUAL_HPP_*/
@@ -0,0 +1,2 @@
OPENCL_DEPTH = $(CAL_DEPTH)/../../../..
include $(OPENCL_DEPTH)/runtime/runtimedefs
@@ -0,0 +1 @@
include $(OPENCL_DEPTH)/runtime/runtimerules
@@ -0,0 +1,304 @@
/**
* @file cal.h
* @brief CAL Interface Header
* @version 1.00.0 Beta
*/
/* ============================================================
Copyright (c) 2007 Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use of this material is permitted under the following
conditions:
Redistributions must retain the above copyright notice and all terms of this
license.
In no event shall anyone redistributing or accessing or using this material
commence or participate in any arbitration or legal action relating to this
material against Advanced Micro Devices, Inc. or any copyright holders or
contributors. The foregoing shall survive any expiration or termination of
this license or any agreement or access or use related to this material.
ANY BREACH OF ANY TERM OF THIS LICENSE SHALL RESULT IN THE IMMEDIATE REVOCATION
OF ALL RIGHTS TO REDISTRIBUTE, ACCESS OR USE THIS MATERIAL.
THIS MATERIAL IS PROVIDED BY ADVANCED MICRO DEVICES, INC. AND ANY COPYRIGHT
HOLDERS AND CONTRIBUTORS "AS IS" IN ITS CURRENT CONDITION AND WITHOUT ANY
REPRESENTATIONS, GUARANTEE, OR WARRANTY OF ANY KIND OR IN ANY WAY RELATED TO
SUPPORT, INDEMNITY, ERROR FREE OR UNINTERRUPTED OPERATION, OR THAT IT IS FREE
FROM DEFECTS OR VIRUSES. ALL OBLIGATIONS ARE HEREBY DISCLAIMED - WHETHER
EXPRESS, IMPLIED, OR STATUTORY - INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
ACCURACY, COMPLETENESS, OPERABILITY, QUALITY OF SERVICE, OR NON-INFRINGEMENT.
IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. OR ANY COPYRIGHT HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, REVENUE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED OR BASED ON ANY THEORY OF LIABILITY
ARISING IN ANY WAY RELATED TO THIS MATERIAL, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE. THE ENTIRE AND AGGREGATE LIABILITY OF ADVANCED MICRO DEVICES,
INC. AND ANY COPYRIGHT HOLDERS AND CONTRIBUTORS SHALL NOT EXCEED TEN DOLLARS
(US $10.00). ANYONE REDISTRIBUTING OR ACCESSING OR USING THIS MATERIAL ACCEPTS
THIS ALLOCATION OF RISK AND AGREES TO RELEASE ADVANCED MICRO DEVICES, INC. AND
ANY COPYRIGHT HOLDERS AND CONTRIBUTORS FROM ANY AND ALL LIABILITIES,
OBLIGATIONS, CLAIMS, OR DEMANDS IN EXCESS OF TEN DOLLARS (US $10.00). THE
FOREGOING ARE ESSENTIAL TERMS OF THIS LICENSE AND, IF ANY OF THESE TERMS ARE
CONSTRUED AS UNENFORCEABLE, FAIL IN ESSENTIAL PURPOSE, OR BECOME VOID OR
DETRIMENTAL TO ADVANCED MICRO DEVICES, INC. OR ANY COPYRIGHT HOLDERS OR
CONTRIBUTORS FOR ANY REASON, THEN ALL RIGHTS TO REDISTRIBUTE, ACCESS OR USE
THIS MATERIAL SHALL TERMINATE IMMEDIATELY. MOREOVER, THE FOREGOING SHALL
SURVIVE ANY EXPIRATION OR TERMINATION OF THIS LICENSE OR ANY AGREEMENT OR
ACCESS OR USE RELATED TO THIS MATERIAL.
NOTICE IS HEREBY PROVIDED, AND BY REDISTRIBUTING OR ACCESSING OR USING THIS
MATERIAL SUCH NOTICE IS ACKNOWLEDGED, THAT THIS MATERIAL MAY BE SUBJECT TO
RESTRICTIONS UNDER THE LAWS AND REGULATIONS OF THE UNITED STATES OR OTHER
COUNTRIES, WHICH INCLUDE BUT ARE NOT LIMITED TO, U.S. EXPORT CONTROL LAWS SUCH
AS THE EXPORT ADMINISTRATION REGULATIONS AND NATIONAL SECURITY CONTROLS AS
DEFINED THEREUNDER, AS WELL AS STATE DEPARTMENT CONTROLS UNDER THE U.S.
MUNITIONS LIST. THIS MATERIAL MAY NOT BE USED, RELEASED, TRANSFERRED, IMPORTED,
EXPORTED AND/OR RE-EXPORTED IN ANY MANNER PROHIBITED UNDER ANY APPLICABLE LAWS,
INCLUDING U.S. EXPORT CONTROL LAWS REGARDING SPECIFICALLY DESIGNATED PERSONS,
COUNTRIES AND NATIONALS OF COUNTRIES SUBJECT TO NATIONAL SECURITY CONTROLS.
MOREOVER, THE FOREGOING SHALL SURVIVE ANY EXPIRATION OR TERMINATION OF ANY
LICENSE OR AGREEMENT OR ACCESS OR USE RELATED TO THIS MATERIAL.
NOTICE REGARDING THE U.S. GOVERNMENT AND DOD AGENCIES: This material is
provided with "RESTRICTED RIGHTS" and/or "LIMITED RIGHTS" as applicable to
computer software and technical data, respectively. Use, duplication,
distribution or disclosure by the U.S. Government and/or DOD agencies is
subject to the full extent of restrictions in all applicable regulations,
including those found at FAR52.227 and DFARS252.227 et seq. and any successor
regulations thereof. Use of this material by the U.S. Government and/or DOD
agencies is acknowledgment of the proprietary rights of any copyright holders
and contributors, including those of Advanced Micro Devices, Inc., as well as
the provisions of FAR52.227-14 through 23 regarding privately developed and/or
commercial computer software.
This license forms the entire agreement regarding the subject matter hereof and
supersedes all proposals and prior discussions and writings between the parties
with respect thereto. This license does not affect any ownership, rights, title,
or interest in, or relating to, this material. No terms of this license can be
modified or waived, and no breach of this license can be excused, unless done
so in a writing signed by all affected parties. Each term of this license is
separately enforceable. If any term of this license is determined to be or
becomes unenforceable or illegal, such term shall be reformed to the minimum
extent necessary in order for this license to remain in effect in accordance
with its terms as modified by such reformation. This license shall be governed
by and construed in accordance with the laws of the State of Texas without
regard to rules on conflicts of law of any state or jurisdiction or the United
Nations Convention on the International Sale of Goods. All disputes arising out
of this license shall be subject to the jurisdiction of the federal and state
courts in Austin, Texas, and all defenses are hereby waived concerning personal
jurisdiction and venue of these courts.
============================================================ */
#ifndef __CAL_H__
#define __CAL_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef void CALvoid; /**< void type */
typedef char CALchar; /**< ASCII character */
typedef signed char CALbyte; /**< 1 byte signed integer value */
typedef unsigned char CALubyte; /**< 1 byte unsigned integer value */
typedef signed short CALshort; /**< 2 byte signed integer value */
typedef unsigned short CALushort; /**< 2 byte unsigned integer value */
typedef signed int CALint; /**< 4 byte signed integer value */
typedef unsigned int CALuint; /**< 4 byte unsigned intger value */
typedef float CALfloat; /**< 32-bit IEEE floating point value */
typedef double CALdouble; /**< 64-bit IEEE floating point value */
typedef signed long CALlong; /**< long value */
typedef unsigned long CALulong; /**< unsigned long value */
#if defined(_MSC_VER)
typedef signed __int64 CALint64; /**< 8 byte signed integer value */
typedef unsigned __int64 CALuint64; /**< 8 byte unsigned integer value */
#elif defined(__GNUC__)
typedef signed long long CALint64; /**< 8 byte signed integer value */
typedef unsigned long long CALuint64; /**< 8 byte unsigned integer value */
#else
#error "Unsupported compiler type."
#endif
/** Boolean type */
typedef enum CALbooleanEnum {
CAL_FALSE = 0, /**< Boolean false value */
CAL_TRUE = 1 /**< Boolean true value */
} CALboolean;
/** Device Kernel ISA */
typedef enum CALtargetEnum {
CAL_TARGET_600, /**< R600 GPU ISA */
CAL_TARGET_610, /**< RV610 GPU ISA */
CAL_TARGET_630, /**< RV630 GPU ISA */
CAL_TARGET_670, /**< RV670 GPU ISA */
CAL_TARGET_7XX, /**< R700 class GPU ISA */
CAL_TARGET_770, /**< RV770 GPU ISA */
CAL_TARGET_710, /**< RV710 GPU ISA */
CAL_TARGET_730, /**< RV730 GPU ISA */
CAL_TARGET_CYPRESS, /**< CYPRESS GPU ISA */
CAL_TARGET_JUNIPER, /**< JUNIPER GPU ISA */
CAL_TARGET_REDWOOD, /**< REDWOOD GPU ISA */
CAL_TARGET_CEDAR, /**< CEDAR GPU ISA */
//##BEGIN_PRIVATE##
CAL_TARGET_SUMO, /**< SUMO GPU ISA */
CAL_TARGET_SUPERSUMO, /**< SUPERSUMO GPU ISA */
CAL_TARGET_WRESTLER, /**< WRESTLER GPU ISA */
CAL_TARGET_CAYMAN, /**< CAYMAN GPU ISA */
CAL_TARGET_KAUAI, /**< KAUAI GPU ISA */
CAL_TARGET_BARTS , /**< BARTS GPU ISA */
CAL_TARGET_TURKS , /**< TURKS GPU ISA */
CAL_TARGET_CAICOS, /**< CAICOS GPU ISA */
CAL_TARGET_TAHITI, /**< TAHITI GPU ISA*/
CAL_TARGET_PITCAIRN, /**< PITCAIRN GPU ISA*/
CAL_TARGET_CAPEVERDE, /**< CAPE VERDE GPU ISA*/
CAL_TARGET_DEVASTATOR, /**< DEVASTATOR GPU ISA*/
CAL_TARGET_SCRAPPER, /**< SCRAPPER GPU ISA*/
CAL_TARGET_OLAND, /**< OLAND GPU ISA*/
CAL_TARGET_BONAIRE, /**< BONAIRE GPU ISA*/
CAL_TARGET_SPECTRE, /**< KAVERI1 GPU ISA*/
CAL_TARGET_SPOOKY, /**< KAVERI2 GPU ISA*/
CAL_TARGET_KALINDI, /**< KALINDI GPU ISA*/
CAL_TARGET_HAINAN, /**< HAINAN GPU ISA*/
CAL_TARGET_HAWAII, /**< HAWAII GPU ISA*/
CAL_TARGET_ICELAND, /**< ICELAND GPU ISA*/
CAL_TARGET_TONGA, /**< TONGA GPU ISA*/
CAL_TARGET_GODAVARI, /**< MULLINS GPU ISA*/
CAL_TARGET_BERMUDA, /**< BERMUDA GPU ISA*/
CAL_TARGET_FIJI, /**< FIJI GPU ISA*/
CAL_TARGET_CARRIZO, /**< CARRIZO GPU ISA*/
CAL_TARGET_LAST = CAL_TARGET_CARRIZO, /**< last */
//##END_PRIVATE##
} CALtarget;
/** CAL image container */
typedef struct CALimageRec* CALimage;
#define CAL_ASIC_INFO_MAX_LEN 128
/** CAL computational domain */
typedef struct CALdomainRec {
CALuint x; /**< x origin of domain */
CALuint y; /**< y origin of domain */
CALuint width; /**< width of domain */
CALuint height; /**< height of domain */
} CALdomain;
/** CAL device attributes */
typedef struct CALdeviceattribsRec {
CALuint struct_size; /**< Client filled out size of CALdeviceattribs struct */
CALtarget target; /**< Asic identifier */
CALuint localRAM; /**< Amount of local GPU RAM in megabytes */
CALuint uncachedRemoteRAM; /**< Amount of uncached remote GPU memory in megabytes */
CALuint cachedRemoteRAM; /**< Amount of cached remote GPU memory in megabytes */
CALuint engineClock; /**< GPU device clock rate in megahertz */
CALuint memoryClock; /**< GPU memory clock rate in megahertz */
CALuint wavefrontSize; /**< Wavefront size */
CALuint numberOfSIMD; /**< Number of SIMDs */
bool doublePrecision; /**< double precision supported */
bool localDataShare; /**< local data share supported */
bool globalDataShare; /**< global data share supported */
bool globalGPR; /**< global GPR supported */
bool computeShader; /**< compute shader supported */
bool memExport; /**< memexport supported */
CALuint pitch_alignment; /**< Required alignment for calCreateRes allocations (in data elements) */
CALuint surface_alignment; /**< Required start address alignment for calCreateRes allocations (in bytes) */
CALuint numberOfUAVs; /**< Number of UAVs */
bool bUAVMemExport; /**< Hw only supports mem export to simulate 1 UAV */
CALuint numberOfShaderEngines; /**< Number of shader engines */
CALuint targetRevision; /**< Asic family revision */
CALuint totalVisibleHeap; /**< Amount of visible local GPU RAM in megabytes */
CALuint totalInvisibleHeap; /**< Amount of invisible local GPU RAM in megabytes */
CALuint totalDirectHeap; /**< Amount of direct GPU memory in megabytes */
CALuint totalCoherentHeap; /**< Amount of coherent GPU memory in megabytes */
CALuint totalRemoteSharedHeap; /**< Amount of remote Shared GPU memory in megabytes */
CALuint totalCachedRemoteSharedHeap; /**< Amount of cached remote Shared GPU memory in megabytes */
CALuint totalSDIHeap; /**< Amount of SDI memory allocated in CCC */
CALuint pciTopologyInformation; /**< PCI topology information contains: bus, device and function number. */
CALchar boardName[CAL_ASIC_INFO_MAX_LEN]; /**< Actual ASIC board name and not the internal name. */
bool vectorBufferInstructionAddr64; /**< Vector buffer instructions support ADDR64 mode */
bool memRandomAccessTargetInstructions; /**< hw/sc supports memory RAT (Random Access Target) instructions e.g. mem0.x_z_ supported */
CALuint memBusWidth; /**< Memory busw width */
CALuint numMemBanks; /**< Number of memory banks */
CALuint counterFreq; /**< Ref clock counter frequency */
double nanoSecondsPerTick; /**< Nano seconds per GPU tick */
bool longIdleDetect; /**< Whether LongIdleDetect enabled */
bool priSupport; /**< IOMMUv2 ATS/PRI support */
CALuint64 vaStart; /**< VA start address */
CALuint64 vaEnd; /**< VA end address */
bool isWorkstation; /**< Whether Device is a Workstation/Server part */
} CALdeviceattribs;
/** CAL device status */
typedef struct CALdevicestatusRec {
CALuint struct_size; /**< Client filled out size of CALdevicestatus struct */
CALuint availLocalRAM; /**< Amount of available local GPU RAM in megabytes */
CALuint availUncachedRemoteRAM; /**< Amount of available uncached remote GPU memory in megabytes */
CALuint availCachedRemoteRAM; /**< Amount of available cached remote GPU memory in megabytes */
CALuint availVisibleHeap; /**< Amount of available visible local GPU RAM in megabytes */
CALuint availInvisibleHeap; /**< Amount of available invisible local GPU RAM in megabytes */
CALuint availDirectHeap; /**< Amount of available direct GPU memory in megabytes */
CALuint availCoherentHeap; /**< Amount of available coherent GPU memory in megabytes */
CALuint availRemoteSharedHeap; /**< Amount of available remote Shared GPU memory in megabytes */
CALuint availCachedRemoteSharedHeap; /**< Amount of available cached remote Shared GPU memory in megabytes */
CALuint largestBlockVisibleHeap; /**< Largest block available visible local GPU RAM in megabytes */
CALuint largestBlockInvisibleHeap; /**< Largest block available invisible local GPU RAM in megabytes */
CALuint largestBlockRemoteHeap; /**< Largest block available remote GPU memory in megabytes */
CALuint largestBlockCachedRemoteHeap; /**< Largest block available cached remote GPU memory in megabytes */
CALuint largestBlockDirectHeap; /**< Largest block available direct GPU memory in megabytes */
CALuint largestBlockCoherentHeap; /**< Largest block available coherent GPU memory in megabytes */
CALuint largestBlockRemoteSharedHeap; /**< Largest block available remote Shared GPU memory in megabytes */
CALuint largestBlockCachedRemoteSharedHeap; /**< Largest block available cached remote Shared GPU memory in megabytes */
} CALdevicestatus;
/** CAL resource allocation flags **/
typedef enum CALresallocflagsEnum {
CAL_RESALLOC_GLOBAL_BUFFER = 1, /**< used for global import/export buffer */
} CALresallocflags;
/** CAL function information **/
typedef struct CALfuncInfoRec
{
CALuint maxScratchRegsNeeded; /**< Maximum number of scratch regs needed */
CALuint numSharedGPRUser; /**< Number of shared GPRs */
CALuint numSharedGPRTotal; /**< Number of shared GPRs including ones used by SC */
bool eCsSetupMode; /**< Slow mode */
CALuint numThreadPerGroup; /**< Flattend umber of threads per group */
CALuint numThreadPerGroupX; /**< x dimension of numThreadPerGroup */
CALuint numThreadPerGroupY; /**< y dimension of numThreadPerGroup */
CALuint numThreadPerGroupZ; /**< z dimension of numThreadPerGroup */
CALuint totalNumThreadGroup; /**< Total number of thread groups */
CALuint numWavefrontPerSIMD; /**< Number of wavefronts per SIMD */
bool isMaxNumWavePerSIMD; /**< Is this the max num active wavefronts per SIMD */
bool setBufferForNumGroup; /**< Need to set up buffer for info on number of thread groups? */
CALuint wavefrontSize; /**< number of threads per wavefront. */
CALuint numGPRsAvailable; /**< number of GPRs available to the program */
CALuint numGPRsUsed; /**< number of GPRs used by the program */
CALuint LDSSizeAvailable; /**< LDS size available to the program */
CALuint LDSSizeUsed; /**< LDS size used by the program */
CALuint stackSizeAvailable; /**< stack size availabe to the program */
CALuint stackSizeUsed; /**< stack size use by the program */
CALuint numSGPRsAvailable; /**< number of SGPRs available to the program */
CALuint numSGPRsUsed; /**< number of SGPRs used by the program */
CALuint numVGPRsAvailable; /**< number of VGPRs available to the program */
CALuint numVGPRsUsed; /**< number of VGPRs used by the program */
} CALfuncInfo;
#ifdef __cplusplus
} /* extern "C" { */
#endif
#endif /* __CAL_H__ */
@@ -0,0 +1,660 @@
/**
* @file calcl.h
* @brief CAL Compiler Interface Header
* @version 1.00.0 Beta
*/
/* ============================================================
Copyright (c) 2007 Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use of this material is permitted under the following
conditions:
Redistributions must retain the above copyright notice and all terms of this
license.
In no event shall anyone redistributing or accessing or using this material
commence or participate in any arbitration or legal action relating to this
material against Advanced Micro Devices, Inc. or any copyright holders or
contributors. The foregoing shall survive any expiration or termination of
this license or any agreement or access or use related to this material.
ANY BREACH OF ANY TERM OF THIS LICENSE SHALL RESULT IN THE IMMEDIATE REVOCATION
OF ALL RIGHTS TO REDISTRIBUTE, ACCESS OR USE THIS MATERIAL.
THIS MATERIAL IS PROVIDED BY ADVANCED MICRO DEVICES, INC. AND ANY COPYRIGHT
HOLDERS AND CONTRIBUTORS "AS IS" IN ITS CURRENT CONDITION AND WITHOUT ANY
REPRESENTATIONS, GUARANTEE, OR WARRANTY OF ANY KIND OR IN ANY WAY RELATED TO
SUPPORT, INDEMNITY, ERROR FREE OR UNINTERRUPTED OPERATION, OR THAT IT IS FREE
FROM DEFECTS OR VIRUSES. ALL OBLIGATIONS ARE HEREBY DISCLAIMED - WHETHER
EXPRESS, IMPLIED, OR STATUTORY - INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
ACCURACY, COMPLETENESS, OPERABILITY, QUALITY OF SERVICE, OR NON-INFRINGEMENT.
IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. OR ANY COPYRIGHT HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, REVENUE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED OR BASED ON ANY THEORY OF LIABILITY
ARISING IN ANY WAY RELATED TO THIS MATERIAL, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE. THE ENTIRE AND AGGREGATE LIABILITY OF ADVANCED MICRO DEVICES,
INC. AND ANY COPYRIGHT HOLDERS AND CONTRIBUTORS SHALL NOT EXCEED TEN DOLLARS
(US $10.00). ANYONE REDISTRIBUTING OR ACCESSING OR USING THIS MATERIAL ACCEPTS
THIS ALLOCATION OF RISK AND AGREES TO RELEASE ADVANCED MICRO DEVICES, INC. AND
ANY COPYRIGHT HOLDERS AND CONTRIBUTORS FROM ANY AND ALL LIABILITIES,
OBLIGATIONS, CLAIMS, OR DEMANDS IN EXCESS OF TEN DOLLARS (US $10.00). THE
FOREGOING ARE ESSENTIAL TERMS OF THIS LICENSE AND, IF ANY OF THESE TERMS ARE
CONSTRUED AS UNENFORCEABLE, FAIL IN ESSENTIAL PURPOSE, OR BECOME VOID OR
DETRIMENTAL TO ADVANCED MICRO DEVICES, INC. OR ANY COPYRIGHT HOLDERS OR
CONTRIBUTORS FOR ANY REASON, THEN ALL RIGHTS TO REDISTRIBUTE, ACCESS OR USE
THIS MATERIAL SHALL TERMINATE IMMEDIATELY. MOREOVER, THE FOREGOING SHALL
SURVIVE ANY EXPIRATION OR TERMINATION OF THIS LICENSE OR ANY AGREEMENT OR
ACCESS OR USE RELATED TO THIS MATERIAL.
NOTICE IS HEREBY PROVIDED, AND BY REDISTRIBUTING OR ACCESSING OR USING THIS
MATERIAL SUCH NOTICE IS ACKNOWLEDGED, THAT THIS MATERIAL MAY BE SUBJECT TO
RESTRICTIONS UNDER THE LAWS AND REGULATIONS OF THE UNITED STATES OR OTHER
COUNTRIES, WHICH INCLUDE BUT ARE NOT LIMITED TO, U.S. EXPORT CONTROL LAWS SUCH
AS THE EXPORT ADMINISTRATION REGULATIONS AND NATIONAL SECURITY CONTROLS AS
DEFINED THEREUNDER, AS WELL AS STATE DEPARTMENT CONTROLS UNDER THE U.S.
MUNITIONS LIST. THIS MATERIAL MAY NOT BE USED, RELEASED, TRANSFERRED, IMPORTED,
EXPORTED AND/OR RE-EXPORTED IN ANY MANNER PROHIBITED UNDER ANY APPLICABLE LAWS,
INCLUDING U.S. EXPORT CONTROL LAWS REGARDING SPECIFICALLY DESIGNATED PERSONS,
COUNTRIES AND NATIONALS OF COUNTRIES SUBJECT TO NATIONAL SECURITY CONTROLS.
MOREOVER, THE FOREGOING SHALL SURVIVE ANY EXPIRATION OR TERMINATION OF ANY
LICENSE OR AGREEMENT OR ACCESS OR USE RELATED TO THIS MATERIAL.
NOTICE REGARDING THE U.S. GOVERNMENT AND DOD AGENCIES: This material is
provided with "RESTRICTED RIGHTS" and/or "LIMITED RIGHTS" as applicable to
computer software and technical data, respectively. Use, duplication,
distribution or disclosure by the U.S. Government and/or DOD agencies is
subject to the full extent of restrictions in all applicable regulations,
including those found at FAR52.227 and DFARS252.227 et seq. and any successor
regulations thereof. Use of this material by the U.S. Government and/or DOD
agencies is acknowledgment of the proprietary rights of any copyright holders
and contributors, including those of Advanced Micro Devices, Inc., as well as
the provisions of FAR52.227-14 through 23 regarding privately developed and/or
commercial computer software.
This license forms the entire agreement regarding the subject matter hereof and
supersedes all proposals and prior discussions and writings between the parties
with respect thereto. This license does not affect any ownership, rights, title,
or interest in, or relating to, this material. No terms of this license can be
modified or waived, and no breach of this license can be excused, unless done
so in a writing signed by all affected parties. Each term of this license is
separately enforceable. If any term of this license is determined to be or
becomes unenforceable or illegal, such term shall be reformed to the minimum
extent necessary in order for this license to remain in effect in accordance
with its terms as modified by such reformation. This license shall be governed
by and construed in accordance with the laws of the State of Texas without
regard to rules on conflicts of law of any state or jurisdiction or the United
Nations Convention on the International Sale of Goods. All disputes arising out
of this license shall be subject to the jurisdiction of the federal and state
courts in Austin, Texas, and all defenses are hereby waived concerning personal
jurisdiction and venue of these courts.
============================================================ */
#ifndef __CALCL_H__
#define __CALCL_H__
#include "cal.h"
#include "gsl_enum.h"
#include "gsl_types.h"
#include "cm_enum.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ProgramGridRec
{
gslDomain3D gridBlock; /**< size of a block of data */
gslDomain3D gridSize; /**< size of 'blocks' to execute. */
gslDomain3D partialGridBlock;/** Partial grid block */
CALuint localSize; /** size of OpenCL Local Memory in bytes */
} ProgramGrid;
// flags for calCtxWaitForEvents
typedef enum CALwaitTypeEnum
{
CAL_WAIT_POLLING = 0,
CAL_WAIT_LOW_CPU_UTILIZATION = 1,
} CALwaitType;
//
// calResAllocView typedefs
//
typedef enum CALresallocviewflagsRec {
CAL_RESALLOCVIEW_GLOBAL_BUFFER = CAL_RESALLOC_GLOBAL_BUFFER, /**< used for global import/export buffer */
CAL_RESALLOCVIEW_LINEAR_ALIGNED = CAL_RESALLOC_GLOBAL_BUFFER, /**< 256 byte alignment restriction. */
CAL_RESALLOCVIEW_LINEAR_UNALIGNED = 3, /**< no alignment restrictions */
} CALresallocviewflags;
typedef struct CALresourceDescRec {
gslMemObjectAttribLocation type;
gslResource3D size;
cmSurfFmt format;
gslChannelOrder channelOrder;
gslMemObjectAttribType dimension;
CALuint mipLevels;
CALvoid* systemMemory;
CALuint flags;
CALuint systemMemorySize;
CALuint64 busAddress[2];
mcaddr vaBase;
gslMemObjectAttribSection section;
} CALresourceDesc;
typedef enum CALresallocsliceviewflagsRec {
CAL_RESALLOCSLICEVIEW_GLOBAL_BUFFER = CAL_RESALLOC_GLOBAL_BUFFER, /**< used for global import/export buffer */
CAL_RESALLOCSLICEVIEW_LINEAR_ALIGNED = CAL_RESALLOC_GLOBAL_BUFFER, /**< 256 byte alignment restriction. */
CAL_RESALLOCSLICEVIEW_LINEAR_UNALIGNED = CAL_RESALLOCVIEW_LINEAR_UNALIGNED, /**< no alignment restrictions */
CAL_RESALLOCSLICEVIEW_LEVEL = 0x10, /**< sliceDesc.layer is not used, the whole level is only*/
CAL_RESALLOCSLICEVIEW_LAYER = 0x20, /**< sliceDesc.layer is not used, the whole level is only*/
CAL_RESALLOCSLICEVIEW_LEVEL_AND_LAYER = CAL_RESALLOCSLICEVIEW_LEVEL | CAL_RESALLOCSLICEVIEW_LAYER,
} CALresallocsliceviewflags;
//
// Thread Trace Extension
//
typedef struct CALthreadTraceConfigRec CALthreadTraceConfig;
//
// Video Extension
//
typedef struct CALvideoPropertiesRec CALvideoProperties;
typedef struct CALprogramVideoRec CALprogramVideo;
typedef struct CALdeviceVideoAttribsRec CALdeviceVideoAttribs;
typedef struct CALcontextPropertiesRec CALcontextProperties;
typedef struct CALprogramVideoDecodeRec CALprogramVideoDecode;
typedef struct CALprogramVideoEncodeRec CALprogramVideoEncode;
typedef struct CALvideoAttribRec CALvideoAttrib;
typedef struct CALvideoEncAttribRec CALvideoEncAttrib;
// VCE
typedef struct CALEncodeCreateVCERec CALEncodeCreateVCE;
typedef struct CALEncodeGetDeviceInfoRec CALEncodeGetDeviceInfo;
typedef struct CALEncodeGetNumberOfModesRec CALEncodeGetNumberOfModes;
typedef struct CALEncodeGetModesRec CALEncodeGetModes;
typedef struct CALEncodeGetDeviceCAPRec CALEncodeGetDeviceCAP;
typedef struct CALEncodeSetStateRec CALEncodeSetState;
typedef struct CALEncodeGetPictureControlConfigRec CALEncodeGetPictureControlConfig;
typedef struct CALEncodeGetRateControlConfigRec CALEncodeGetRateControlConfig;
typedef struct CALEncodeGetMotionEstimationConfigRec CALEncodeGetMotionEstimationConfig;
typedef struct CALEncodeGetRDOControlConfigRec CALEncodeGetRDOControlConfig;
typedef enum
{
CAL_VID_NV12_INTERLEAVED = 1,// NV12
CAL_VID_YV12_INTERLEAVED, // YV12
} CALdecodeFormat;
typedef enum
{
CAL_VID_H264_BASELINE = 1, // H.264 bitstream acceleration baseline profile
CAL_VID_H264_MAIN, // H.264 bitstream acceleration main profile
CAL_VID_H264_HIGH, // H.264 bitstream acceleration high profile
CAL_VID_VC1_SIMPLE, // VC-1 bitstream acceleration simple profile
CAL_VID_VC1_MAIN, // VC-1 bitstream acceleration main profile
CAL_VID_VC1_ADVANCED, // VC-1 bitstream acceleration advanced profile
CAL_VID_MPEG2_VLD, // MPEG2 bitstream acceleration VLD profile
} CALdecodeProfile;
typedef enum
{
CAL_VID_ENC_H264_BASELINE = 1, // H.264 bitstream acceleration baseline profile
CAL_VID_ENC_H264_MAIN, // H.264 bitstream acceleration main profile
CAL_VID_ENC_H264_HIGH, // H.264 bitstream acceleration high profile
} CALencodeProfile;
typedef enum
{
CAL_CONTEXT_VIDEO = 1,
CAL_CONTEXT_3DCOMPUTE = 2,
CAL_CONTEXT_COMPUTE0 = 3,
CAL_CONTEXT_COMPUTE1 = 4,
CAL_CONTEXT_DRMDMA0 = 5,
CAL_CONTEXT_DRMDMA1 = 6,
CAL_CONTEXT_VIDEO_VCE,
CALcontextEnum_FIRST = CAL_CONTEXT_VIDEO,
CALcontextEnum_LAST = CAL_CONTEXT_VIDEO_VCE,
} CALcontextEnum;
typedef enum
{
CAL_PRIORITY_NEUTRAL = 0,
CAL_PRIORITY_HIGH = 1,
CAL_PRIORITY_LOW = 2
} CALpriorityEnum;
typedef enum
{
CAL_VIDEO_DECODE = 1,
CAL_VIDEO_ENCODE = 2
} CALvideoType;
struct CALcontextPropertiesRec
{
CALcontextEnum name;
CALpriorityEnum priority;
CALvoid* data;
};
struct CALthreadTraceConfigRec
{
CALuint cu; // target compute unit [cu]
CALuint sh; // target shader array [sh],that contains target cu
CALuint simd_mask; // bitmask to enable or disable target tokens for different SIMDs
CALuint vm_id_mask; // virtual memory [vm] IDs to capture
CALuint token_mask; // bitmask indicating which trace token IDs will be included in the trace
CALuint reg_mask; // bitmask indicating which register types should be included in the trace
CALuint inst_mask; // types of instruction scheduling updates which should be recorded
CALuint random_seed; // linear feedback shift register [LFSR] seed
CALuint user_data; // user data ,which is written as payload
CALuint capture_mode; // indicator for the way how THREAD_TRACE_START / STOP events affect token collection
CALboolean is_user_data; // indicator if user_data is set
CALboolean is_wrapped; // indicator if the memory buffer should be wrapped around instead of stopping at the end
};
struct CALvideoPropertiesRec
{
CALuint size;
CALuint flags;
CALdecodeProfile profile;
CALdecodeFormat format;
CALuint width;
CALuint height;
CALcontextEnum VideoEngine_name;
};
struct CALprogramVideoRec
{
CALuint size;
CALvideoType type;
CALuint flags;
};
struct CALprogramVideoDecodeRec
{
CALprogramVideo videoType;
void* picture_parameter_1;
void* picture_parameter_2;
CALuint picture_parameter_2_size;
void* bitstream_data;
CALuint bitstream_data_size;
void* slice_data_control;
CALuint slice_data_size;
};
struct CALprogramVideoEncodeRec
{
CALprogramVideo videoType;
CALuint pictureParam1Size;
CALuint pictureParam2Size;
void* pictureParam1;
void* pictureParam2;
CALuint uiTaskID;
};
struct CALvideoAttribRec
{
CALdecodeProfile decodeProfile;
CALdecodeFormat decodeFormat;
};
struct CALvideoEncAttribRec
{
CALencodeProfile encodeProfile;
CALdecodeFormat encodeFormat; // decode format is the same as the encode format
};
struct CALdeviceVideoAttribsRec
{
CALuint data_size; // in - size of the struct,
// out - bytes of data incl. pointed to
CALuint max_decode_sessions;
const CALvideoAttrib* video_attribs; // list of supported
// profile/format pairs
const CALvideoEncAttrib* video_enc_attribs;
};
////// VCE
struct CALEncodeCreateVCERec
{
CALvoid* VCEsession;
};
struct CALEncodeGetDeviceInfoRec
{
unsigned int device_id;
unsigned int max_encode_stream;
unsigned int encode_cap_list_size;
};
struct CALEncodeGetNumberOfModesRec
{
unsigned int num_of_encode_Mode;
};
typedef enum
{
CAL_VID_encode_MODE_NONE = 0,
CAL_VID_encode_AVC_FULL = 1,
CAL_VID_encode_AVC_ENTROPY = 2,
} CALencodeMode;
struct CALEncodeGetModesRec
{
CALuint NumEncodeModesToRetrieve;
CALencodeMode *pEncodeModes;
};
typedef enum
{
CAL_VID_ENCODE_JOB_PRIORITY_NONE = 0,
CAL_VID_ENCODE_JOB_PRIORITY_LEVEL1 = 1, // Always in normal queue
CAL_VID_ENCODE_JOB_PRIORITY_LEVEL2 = 2 // possibly in low-latency queue
} CAL_VID_ENCODE_JOB_PRIORITY;
typedef struct _CAL_VID_PROFILE_LEVEL
{
CALuint profile; //based on H.264 standard
CALuint level;
} CAL_VID_PROFILE_LEVEL;
typedef enum
{
CAL_VID_PICTURE_NONOE = 0,
CAL_VID_PICTURE_NV12 = 1,
} CAL_VID_PICTURE_FORMAT;
#define CAL_VID_MAX_NUM_PICTURE_FORMATS_H264_AVC 10
#define CAL_VID_MAX_NUM_PROFILE_LEVELS_H264_AVC 20
typedef struct
{
CALuint maxPicSizeInMBs; // Max picture size in MBs
CALuint minPicSizeInMBs; // Min picture size in MBs
CALuint numPictureFormats; // number of supported picture formats
CAL_VID_PICTURE_FORMAT supportedPictureFormats[CAL_VID_MAX_NUM_PICTURE_FORMATS_H264_AVC];
CALuint numProfileLevels; // number of supported profiles/levels returne;
CAL_VID_PROFILE_LEVEL supportedProfileLevel[CAL_VID_MAX_NUM_PROFILE_LEVELS_H264_AVC];
CALuint maxBitRate; // Max bit rate
CALuint minBitRate; // min bit rate
CAL_VID_ENCODE_JOB_PRIORITY supportedJobPriority;// supported max level of job priority
}CAL_VID_ENCODE_CAPS_FULL;
typedef struct
{
CAL_VID_ENCODE_JOB_PRIORITY supportedJobPriority;// supported max level of job priority
CALuint maxJobQueueDepth; // Max job queue depth
}CAL_VID_ENCODE_CAPS_ENTROPY;
typedef struct
{
CALencodeMode EncodeModes;
CALuint encode_cap_size;
union
{
CAL_VID_ENCODE_CAPS_FULL *encode_cap_full;
CAL_VID_ENCODE_CAPS_ENTROPY *encode_cap_entropy;
void *encode_cap;
} caps;
} CAL_VID_ENCODE_CAPS;
struct CALEncodeGetDeviceCAPRec
{
CALuint num_of_encode_cap;
CAL_VID_ENCODE_CAPS *encode_caps;
};
typedef enum
{
CAL_VID__ENCODE_STATE_START = 1,
CAL_VID__ENCODE_STATE_PAUSE = 2,
CAL_VID__ENCODE_STATE_RESUME = 3,
CAL_VID__ENCODE_STATE_STOP = 4
} CAL_VID_ENCODE_STATE ;
typedef struct
{
CALuint size; // structure size
CALuint useConstrainedIntraPred; // binary var - force the use of constrained intra prediction when set to 1
//CABAC options
CALuint cabacEnable; // Enable CABAC entropy coding
CALuint cabacIDC; // cabac_init_id = 0; cabac_init_id = 1; cabac_init_id = 2;
CALuint loopFilterDisable; // binary var - disable loop filter when 1 - enable loop filter when 0 (0 and 1 are the only two supported cases)
int encLFBetaOffset; // -- move with loop control flag , Loop filter control, slice_beta_offset (N.B. only used if deblocking filter is not disabled, and there is no div2 as defined in the h264 bitstream syntax)
int encLFAlphaC0Offset; // Loop filter control, slice_alpha_c0_offset (N.B. only used if deblocking filter is not disabled, and there is no div2 as defined in the h264 bitstream syntax)
CALuint encIDRPeriod;
CALuint encIPicPeriod; // spacing for I pictures, in case driver doesnt force/select a picture type, this will be used for inference
int encHeaderInsertionSpacing; // spacing for inserting SPS/PPS. Example usage cases are: 0 for inserting at the beginning of the stream only, 1 for every picture, "GOP size" to align it with GOP boundaries etc. For compliance reasons, these headers might be inserted when SPS/PPS parameters change from the config packages.
CALuint encCropLeftOffset;
CALuint encCropRightOffset;
CALuint encCropTopOffset;
CALuint encCropBottomOffset;
CALuint encNumMBsPerSlice; // replaces encSliceArgument - Slice control - number of MBs per slice
CALuint encNumSlicesPerFrame; // Slice control - number of slices in this frame, pre-calculated to avoid DIV operation in firmware
CALuint encForceIntraRefresh; // 1 serves to load intra refresh bitmap from address force_intra_refresh_bitmap_mc_addr when equal to 1, 3 also loads dirty clean bitmap on top of the intra refresh
CALuint encForceIMBPeriod; // --- package with intra referesh -Intra MB spacing. if encForceIntraRefresh = 2, shifts intra refreshed MBs by frame number
CALuint encInsertVUIParam; // insert VUI params in SPS
CALuint encInsertSEIMsg; // insert SEI messages (bit 0 for buffering period; bit 1 for picture timing; bit 2 for pan scan)
} CAL_VID_ENCODE_PICTURE_CONTROL;
typedef struct
{
CALuint size; // structure size
CALuint encRateControlMethod; // rate control method to be used
CALuint encRateControlTargetBitRate; // target bit rate
CALuint encRateControlPeakBitRate; // peak bit rate
CALuint encRateControlFrameRateNumerator; // target frame rate
CALuint encGOPSize; // RC GOP size
CALuint encRCOptions; // packed bitfield definition for extending options here, bit 0: RC will not generate skipped frames in order to meet GOP target, bits 1-30: up for grabs by the RC alg designer
CALuint encQP_I; // I frame quantization only if rate control is disabled
CALuint encQP_P; // P frame quantization if rate control is disabled
CALuint encQP_B; // B frame quantization if rate control is disabled
CALuint encVBVBufferSize; // VBV buffer size - this is CPB Size, and the default is per Table A-1 of the spec
CALuint encRateControlFrameRateDenominator;// target frame rate
} CAL_VID_ENCODE_RATE_CONTROL;
// mode estimation control options
typedef struct
{
CALuint size; // structure size
CALuint imeDecimationSearch; // decimation search is on
CALuint motionEstHalfPixel; // enable half pel motion estimation
CALuint motionEstQuarterPixel; // enable quarter pel motion estimation
CALuint disableFavorPMVPoint; // disable favorization of PMV point
CALuint forceZeroPointCenter; // force [0,0] point as search window center in IME
CALuint lsmVert; // Luma Search window in MBs, set to either VCE_ENC_SEARCH_WIND_5x3 or VCE_ENC_SEARCH_WIND_9x5 or VCE_ENC_SEARCH_WIND_13x7
CALuint encSearchRangeX; // forward prediction - Manual limiting of horizontal motion vector range (for performance) in pel resolution
CALuint encSearchRangeY; // forward prediction - Manual limiting of vertical motion vector range (for performance)
CALuint encSearch1RangeX; // for 2nd ref - curr IME_SEARCH_SIZE doesn't have SIZE__SEARCH1_X bitfield
CALuint encSearch1RangeY; // for 2nd ref
CALuint disable16x16Frame1; // second reference (B frame) limitation
CALuint disableSATD; // Disable SATD cost calculation (SAD only)
CALuint enableAMD; // FME advanced mode decision
CALuint encDisableSubMode; // --- FME
CALuint encIMESkipX; // sub sample search window horz --- UENC_IME_OPTIONS.SKIP_POINT_X
CALuint encIMESkipY; // sub sample search window vert --- UENC_IME_OPTIONS.SKIP_POINT_Y
CALuint encEnImeOverwDisSubm; // Enable overwriting of fme_disable_submode in IME with enabled mode number equal to ime_overw_dis_subm_no (only 8x8 and above could be enabled)
CALuint encImeOverwDisSubmNo; // Numbers of mode IME will pick if en_ime_overw_dis_subm equal to 1.
CALuint encIME2SearchRangeX; // IME Additional Search Window Size: horizontal 1-4 (+- this value left and right from center)
CALuint encIME2SearchRangeY; // IME Additional Search Window Size: vertical not-limited (+- this value up and down from center)
// (+- this value up and down from center)
} CAL_VID_ENCODE_MOTION_ESTIMATION_CONTROL; // structure aligned to 88 bytes
typedef struct
{
CALuint size; // structure size
CALuint encDisableTbePredIFrame; // Disable Prediction Modes For I-Frames
CALuint encDisableTbePredPFrame; // same as above for P frames
CALuint useFmeInterpolY; // zero_residues_luma
CALuint useFmeInterpolUV; // zero_residues_chroma
CALuint enc16x16CostAdj; // --- UENC_FME_MD.M16x16_COST_ADJ
CALuint encSkipCostAdj; // --- UENC_FME_MD.MSkip_COST_ADJ
unsigned char encForce16x16skip;
} CAL_VID_ENCODE_RDO_CONTROL;
struct CALEncodeSetStateRec
{
CAL_VID_ENCODE_STATE encode_states;
};
struct CALEncodeGetPictureControlConfigRec
{
CAL_VID_ENCODE_PICTURE_CONTROL encode_picture_control;
};
struct CALEncodeGetRateControlConfigRec
{
CAL_VID_ENCODE_RATE_CONTROL encode_rate;
};
struct CALEncodeGetMotionEstimationConfigRec
{
CAL_VID_ENCODE_MOTION_ESTIMATION_CONTROL encode_motion_estimation;
};
struct CALEncodeGetRDOControlConfigRec
{
CAL_VID_ENCODE_RDO_CONTROL encode_RDO;
};
typedef enum
{
CAL_VID_CONFIG_TYPE_NONE = 0,
CAL_VID_CONFIG_TYPE_PICTURECONTROL = 1,
CAL_VID_CONFIG_TYPE_RATECONTROL = 2,
CAL_VID_CONFIG_TYPE_MOTIONSESTIMATION = 3,
CAL_VID_CONFIG_TYPE_RDO = 4
} CAL_VID_CONFIG_TYPE;
typedef struct
{
CAL_VID_CONFIG_TYPE configType;
union
{
CAL_VID_ENCODE_PICTURE_CONTROL* pPictureControl;
CAL_VID_ENCODE_RATE_CONTROL* pRateControl;
CAL_VID_ENCODE_MOTION_ESTIMATION_CONTROL* pMotionEstimation;
CAL_VID_ENCODE_RDO_CONTROL* pRDO;
} config;
} CAL_VID_CONFIG;
typedef enum
{
CAL_VID_PICTURE_STRUCTURE_H264_NONE = 0,
CAL_VID_PICTURE_STRUCTURE_H264_FRAME = 1,
CAL_VID_PICTURE_STRUCTURE_H264_TOP_FIELD = 2,
CAL_VID_PICTURE_STRUCTURE_H264_BOTTOM_FIELD = 3
} CAL_VID_PICTURE_STRUCTURE_H264;
// Used to force picture type
typedef enum _CU_VID_PICTURE_TYPE_H264
{
CAL_VID_PICTURE_TYPE_H264_NONE = 0,
CAL_VID_PICTURE_TYPE_H264_SKIP = 1,
CAL_VID_PICTURE_TYPE_H264_IDR = 2,
CAL_VID_PICTURE_TYPE_H264_I = 3,
CAL_VID_PICTURE_TYPE_H264_P = 4
} CAL_VID_PICTURE_TYPE_H264;
typedef union _CAL_VID_ENCODE_PARAMETERS_H264_FLAGS
{
struct
{
// enable/disable features
unsigned int reserved : 32; // reserved fields must be set to zero
} flags;
unsigned int value;
}CAL_VID_ENCODE_PARAMETERS_H264_FLAGS;
typedef struct
{
CALuint size; // structure size. Must be always set to the size of AVE_ENCODE_PARAMETERS_H264.
CAL_VID_ENCODE_PARAMETERS_H264_FLAGS flags; // enable/disable any supported features
CALboolean insertSPS;
CAL_VID_PICTURE_STRUCTURE_H264 pictureStructure;
CALboolean forceRefreshMap;
CALuint forceIMBPeriod;
CAL_VID_PICTURE_TYPE_H264 forcePicType;
} CAL_VID_ENCODE_PARAMETERS_H264;
typedef enum
{
CAL_VID_BUFFER_TYPE_NONE = 0,
CAL_VID_BUFFER_TYPE_ENCODE_PARAM_H264 = 1,
CAL_VID_BUFFER_TYPE_PICTURE = 2,
CAL_VID_BUFFER_TYPE_SLICE_HEADER = 3,
CAL_VID_BUFFER_TYPE_SLICE = 4,
CAL_VID_BUFFER_TYPE_RECONSTRUCTED_PICTURE_OUTPUT = 5
} CAL_VID_BUFFER_TYPE;
#define CAL_VID_SURFACE_HANDLE void*
typedef struct
{
CAL_VID_BUFFER_TYPE bufferType;
union
{
CAL_VID_ENCODE_PARAMETERS_H264* pEncodeParamH264;
CAL_VID_SURFACE_HANDLE pPicture;
CAL_VID_SURFACE_HANDLE pSliceHeader;
CAL_VID_SURFACE_HANDLE pSlice;
CAL_VID_SURFACE_HANDLE pReconstructedPictureOutput;
} buffer;
} CAL_VID_BUFFER_DESCRIPTION;
typedef enum
{
CAL_VID_TASK_STATUS_NONE = 0,
CAL_VID_TASK_STATUS_COMPLETE = 1, // encoding task has finished successfully.
CAL_VID_TASK_STATUS_FAILED = 2 // encoding task has finished but failed.
} CAL_VID_TASK_STATUS;
typedef struct
{
CALuint size; // structure size
CALuint taskID; // task ID
CAL_VID_TASK_STATUS status; // Task status. May be duplicated if current task has multiple output blocks.
CALuint size_of_bitstream_data; // data size of the output block
void* bitstream_data; // read pointer the top portion of the generated bitstream data for the current task
} CAL_VID_OUTPUT_DESCRIPTION;
typedef enum CALmemcopyflagsEnum
{
CAL_MEMCOPY_DEFAULT = 0, /**< default CAL behavior of partial sync */
CAL_MEMCOPY_SYNC = 1, /**< used to synchronize with the specified CAL context */
CAL_MEMCOPY_ASYNC = 2, /**< used to indicate completely asynchronous behavior */
} CALmemcopyflags;
typedef enum CALResGLBufferTypeEnum{
CAL_RES_GL_BUFFER_TYPE_TEXTURE = 0,
CAL_RES_GL_BUFFER_TYPE_FRAMEBUFFER = 1,
CAL_RES_GL_BUFFER_TYPE_RENDERBUFFER = 2,
CAL_RES_GL_BUFFER_TYPE_VERTEXBUFFER = 3
}CALResGLBufferType;
typedef struct CALDeviceGLParamsRec {
CALvoid *GLplatformContext;
CALvoid *GLdeviceContext;
CALuint flags;
} CALDeviceGLParams;
#ifdef __cplusplus
} /* extern "C" { */
#endif
#endif /* __CALCL_H__ */
@@ -0,0 +1,284 @@
/*****************************************************************************
*
*
*
* Trade secret of ATI Technologies, Inc.
* Copyright 2006, ATI Technologies, Inc., (unpublished)
*
* All rights reserved. This notice is intended as a precaution against
* inadvertent publication and does not imply publication or any waiver
* of confidentiality. The year included in the foregoing notice is the
* year of creation of the work.
*
*
****************************************************************************
*/
#ifndef __CALIF_H__
#define __CALIF_H__
#define CALIF_VERSION_MAJOR 1
#define CALIF_VERSION_MINOR 1
#define CALIF_HELPER_SURF_WIDTH 256
#define CALIF_HELPER_SURF_HEIGHT 8
#define CALIF_SEMAPHORE_SURF_WIDTH 8
#define CALIF_SEMAPHORE_SURF_HEIGHT 1
// Structure for commuticating with driver through Lock backdoor
typedef struct _CALIF_LOCK_COMM_HEADER
{
UINT uCmd;
UINT *puRes;
PVOID pInputBuffer;
UINT uInputBufferSize;
PVOID pOutputBuffer;
UINT uOutputBufferSize;
} CALIF_LOCK_COMM_HEADER, *PCALIF_LOCK_COMM_HEADER;
// Commands for LOCK backdoor
typedef enum _CALIF_LOCK_CMD
{
CALIF_LOCK_CMD_GET_VERSION = 1,
CALIF_LOCK_CMD_NEXT_SURF_INFO = 2,
CALIF_LOCK_CMD_GET_SURF_INFO = 3,
CALIF_LOCK_CMD_SET_ALIAS_INFO = 4,
CALIF_LOCK_CMD_SET_CAL_TARGET = 5,
CALIF_LOCK_CMD_GET_CAL_STATUS = 6,
CALIF_LOCK_CMD_GET_RENDER_STATUS = 7,
CALIF_LOCK_CMD_INVALID = 0xFFFFFFFF,
} CALIF_LOCK_CMD;
typedef enum _CALIF_LOCK_CMD_RES
{
CALIF_LOCK_CMD_RES_OK = 0,
CALIF_LOCK_CMD_RES_ERROR = 1,
CALIF_LOCK_CMD_RES_INVALID = 0xFFFFFFFF,
} CALIF_LOCK_CMD_RES;
// Input structure
typedef struct _CALIF_CAL_TARGET
{
ULONG ulSize;
ULONG ulFlags;
ULONG ulNumTargets;
ULONG ulTargets[MAX_CAL_TARGETS];
ULONG ulReserved[1]; // 16 byte alignment
} CALIF_CAL_TARGET, *PCALIF_CAL_TARGET;
#define CALIF_DEV_CAP_CAPABLE 0x00000001
#define CALIF_DEV_CAP_ENABLE 0x00000002
#define CALIF_DEV_CAP_PRIMARY 0x80000000
typedef struct _CALIF_DEV_INFO
{
ULONG ulIndex;
ULONG ulCaps; // CALIF_DEV_CAP_XXX
ULONG ulFBSize;
LONGLONG llFBSharedSize;
UCHAR ucDevicePath[MAX_REGISTRY_PATH];
ULONG ulReserved[2];
} CALIF_DEV_INFO, *PCALIF_DEV_INFO;
// Output structure
typedef struct _CALIF_CAL_STATUS
{
ULONG ulSize;
ULONG ulFlags;
ULONG ulCurrentIndex;
ULONG ulAdapterCount;
LONGLONG llSharedCacheableSize;
LONGLONG llSharedUSWCSize;
ULONG ulLinkCount;
ULONG ulLinkAdaper[MAX_CAL_TARGETS];
BOOL bP2PCap[MAX_CAL_DEVICE][MAX_CAL_DEVICE];
CALIF_DEV_INFO devInfo[MAX_CAL_DEVICE];
ULONG ulReserved[3];
} CALIF_CAL_STATUS, *PCALIF_CAL_STATUS;
// Output structure
typedef struct _CALIF_VERSION
{
ULONG ulSize;
ULONG ulFlags;
UINT uMajor; // Major version
UINT uMinor; // Minor version
} CALIF_VERSION, *PCALIF_VERSION;
// Surface heap choice
typedef enum _CALIF_SURF_HEAP
{
CALIF_SURF_HEAP_UNKNOWN = 0, // VCAM real mode or dummy surf
CALIF_SURF_HEAP_LOCAL = 1, // Local Visible + Local Invisible
CALIF_SURF_HEAP_LOCALIF_VISIBLE = 2,
CALIF_SURF_HEAP_USWC = 3,
CALIF_SURF_HEAP_CACHEABLE = 4,
CALIF_SURF_HEAP_SHARED_USWC = 5,
CALIF_SURF_HEAP_SHARED_CACHEABLE = 6,
CALIF_SURF_HEAP_INVALID = 0xFFFFFFFF,
} CALIF_SURF_HEAP;
// Surface flag
#define CALIF_NEXT_SURF_FLAG_DUMMY 0x80000000
#define CALIF_NEXT_SURF_FLAG_LINEAR 0x40000000
#define CALIF_NEXT_SURF_FLAG_ARENA 0x20000000
// Input structure
typedef struct _CALIF_NEXT_SURF_INFO
{
ULONG ulSize;
ULONG ulFlags;
// to match it later at surface creation time
UINT uWidth;
UINT uHeight;
D3DFORMAT d3dFormat;
ULONG_PTR lpProcessID;
// info
CALIF_SURF_HEAP uHeap;
UINT uFlags;
#if _WIN64
ULONG ulReserved[3];
#endif
} CALIF_NEXT_SURF_INFO, *PCALIF_NEXT_SURF_INFO;
// Output structure
typedef struct _CALIF_SURF_INFO
{
ULONG ulSize;
ULONG ulFlags;
ULONG ulDeviceIndex; // current device id
ULONG_PTR lpSurfHandle; // VCAM handle if VCAM is on
LARGE_INTEGER gpuDevAddr; // mc address of the surface
LONGLONG llHeapOffset; // offset from the beginning of the heap
UINT uMemSize; // total memory size
CALIF_SURF_HEAP uHeap; // memory pool
UINT uGranularity; // minimum RT aligment
UINT uBitsPerPixel; // bits per pixel
UINT uActualWidth; // padded width pixel pitch
UINT uActualHeight; // padded height pitch
UINT uPitch; // padded width byte pitch
UINT uTile; // Tiling of surface
UINT uTileSwizzle; // Tile swizzle of surface
#if !_WIN64
ULONG ulReserved[1];
#endif
} CALIF_SURF_INFO, *PCALIF_SURF_INFO;
// Input structure
typedef struct _CALIF_ALIAS_SURF_INFO
{
ULONG ulSize;
ULONG ulFlags;
ULONG ulDeviceIndex; // device id we want to alias to
ULONG_PTR lpSurfHandle;
LONGLONG llHeapOffset; // offset from the beginning of the heap
UINT uMemSize; // total memory size
CALIF_SURF_HEAP uHeap; // memory pool
UINT uGranularity; // minimum RT aligment
UINT uBitsPerPixel; // bits per pixel
UINT uActualWidth; // padded width pixel pitch
UINT uActualHeight; // padded height pitch
UINT uPitch; // padded width byte pitch
#if _WIN64
ULONG ulReserved[3];
#endif
} CALIF_ALIAS_SURF_INFO, *PCALIF_ALIAS_SURF_INFO;
// Output structure
typedef struct _CALIF_RENDER_STATUS
{
ULONG ulSize;
ULONG ulFlags;
BOOL bSurfBusy;
ULONG ulReserved[1];
} CALIF_RENDER_STATUS, *PCALIF_RENDER_STATUS;
// Commands for StretchBlt backdoor
typedef enum _CALIF_SBLT_CMD
{
CALIF_SBLT_CMD_SURF_MARK_HELPER = 0x2200,
CALIF_SBLT_CMD_SURF_GET_SURF_INFO = 0x2400,
CALIF_SBLT_CMD_SURF_ALIAS = 0x2600,
CALIF_SBLT_CMD_SEMAPHORE_WAIT = 0x4200,
CALIF_SBLT_CMD_SEMAPHORE_SIGNAL = 0x4400,
CALIF_SBLT_CMD_OUTPUT_CACHE_FLUSH = 0x4600,
CALIF_SBLT_CMD_INPUT_CACHE_INVALIDATE = 0x6200,
CALIF_SBLT_CMD_GET_RENDER_STATUS = 0x6400,
CALIF_SBLT_CMD_PIN_SURF = 0x6600,
CALIF_SBLT_CMD_INVALID = 0xFFFF,
} CALIF_SBLT_CMD;
#define CALIF_SBLT_CMD_RECT_MASK__LEFT 0x000F
#define CALIF_SBLT_CMD_RECT_MASK__TOP 0x00F0
#define CALIF_SBLT_CMD_RECT_MASK__RIGHT 0x0F00
#define CALIF_SBLT_CMD_RECT_MASK__BOTTOM 0xF000
#define CALIF_SBLT_CMD_RECT_SHIFT__LEFT 0
#define CALIF_SBLT_CMD_RECT_SHIFT__TOP 4
#define CALIF_SBLT_CMD_RECT_SHIFT__RIGHT 8
#define CALIF_SBLT_CMD_RECT_SHIFT__BOTTOM 12
#endif//__CALIF_H__
@@ -0,0 +1,99 @@
/*****************************************************************************
*
*
*
* Trade secret of ATI Technologies, Inc.
* Copyright 2000, ATI Technologies, Inc., (unpublished)
*
* All rights reserved. This notice is intended as a precaution against
* inadvertent publication and does not imply publication or any waiver
* of confidentiality. The year included in the foregoing notice is the
* year of creation of the work.
*
*
****************************************************************************
*/
#ifndef __D3DSHADERDEFS_H__
#define __D3DSHADERDEFS_H__
#define D3DSI_OPCODE_PARAM (1 << 31)
#define D3DSI_GETCOMMENTSIZE(token) (((token) & D3DSI_COMMENTSIZE_MASK) >> \
D3DSI_COMMENTSIZE_SHIFT)
#define D3DSI_GETDSTSHIFT(token) (((token) & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT)
// D3D uses 2 swizzle bits per component. Define them since they are not
// available in d3d header files.
#define D3DSP_SWIZZLE_BITS_PER_COMP 2
#define D3DSP_SWIZZLE_XYZW_MASK 0x3
// DST related: Parameter definition writemask shifts - missing from D3D header
#define D3DSP_WRITEMASK_SHIFT 16
#define D3DSP_WRITEMASK_ASHIFT 19
// DX9 Ref uses 7. But if only upto _X8 & _D8 are supported, the mask should be 3
#define D3DSP_D3D_DSTSHIFT_MASK 3
#define D3DSP_SHADER_TYPE_MASK 0xFFFF0000
#define D3DSP_PS_TYPE 0xFFFF0000
#define D3DSP_VS_TYPE 0xFFFE0000
// This is necessary to avoid a duplicate definition of these functions
// in C++ source files that use this header. These functions are already
// defined in d3dhal.h inside a "#ifdef __cplusplus" block.
#ifndef __cplusplus
// This gets regtype, and also maps D3DSPR_CONSTn to D3DSPR_CONST
// (for easier parsing)
ATI_INLINE DWORD D3DSI_GETREGTYPE_RESOLVING_CONSTANTS(DWORD token)
{
DWORD RegType = D3DSI_GETREGTYPE(token);
switch (RegType)
{
case D3DSPR_CONST4:
case D3DSPR_CONST3:
case D3DSPR_CONST2:
return D3DSPR_CONST;
default:
return RegType;
}
}
// The inline function below retrieves register number for an opcode,
// taking into account that: if the type is a
// D3DSPR_CONSTn, the register number needs to be remapped.
//
// D3DSPR_CONST is for c0-c2047
// D3DSPR_CONST2 is for c2048-c4095
// D3DSPR_CONST3 is for c4096-c6143
// D3DSPR_CONST4 is for c6144-c8191
//
// For example if the instruction token specifies type D3DSPR_CONST4, reg# 3,
// the register number retrieved is 6147.
// For other register types, the register number is just returned unchanged.
ATI_INLINE DWORD D3DSI_GETREGNUM_RESOLVING_CONSTANTS(DWORD token)
{
DWORD RegType = D3DSI_GETREGTYPE(token);
DWORD RegNum = D3DSI_GETREGNUM(token);
switch(RegType)
{
case D3DSPR_CONST4:
return RegNum + 6144;
case D3DSPR_CONST3:
return RegNum + 4096;
case D3DSPR_CONST2:
return RegNum + 2048;
default:
return RegNum;
}
}
#endif // __cplusplus
#define PSTR_MAX_NUMSRCPARAMS 6
#define PSTR_NUM_COMPONENTS_IN_REGISTER 4
#endif // __D3DSHADERDEFS_H__
@@ -0,0 +1,110 @@
//
// Workfile: fourcc.h
//
// Description: FourCC definitions
//
// Trade secret of ATI Technologies, Inc.
// Copyright 1999, ATI Technologies, Inc., (unpublished)
//
// All rights reserved. This notice is intended as a precaution against
// inadvertent publication and does not imply publication or any waiver
// of confidentiality. The year included in the foregoing notice is the
// year of creation of the work.
//
//
#ifndef _FOURCC_H_
#define _FOURCC_H_
//#include "atidxinc.h"
#define FOURCC_YUY2 MAKEFOURCC('Y','U','Y','2')
#define FOURCC_UYVY MAKEFOURCC('U','Y','V','Y')
#define FOURCC_YV12 MAKEFOURCC('Y','V','1','2')
#define FOURCC_YUV12 FOURCC_YV12
#define FOURCC_YVU9 MAKEFOURCC('Y','V','U','9')
#define FOURCC_IF09 MAKEFOURCC('I','F','0','9')
#define FOURCC_IMC4 MAKEFOURCC('I','M','C','4')
#define FOURCC_IYUV MAKEFOURCC('I','Y','U','V')
#define FOURCC_NV11 MAKEFOURCC('N','V','1','1')
#define FOURCC_NV12 MAKEFOURCC('N','V','1','2')
#define FOURCC_NV21 MAKEFOURCC('N','V','2','1')
//Microsoft specific format for WebTV
#define FOURCC_VBID MAKEFOURCC('V','B','I','D')
#define FOURCC_MCAM MAKEFOURCC('M','C','A','M')
#define FOURCC_MC12 MAKEFOURCC('M','C','1','2')
#define FOURCC_MCR4 MAKEFOURCC('M','C','R','4')
#define FOURCC_M2IA MAKEFOURCC('M','2','I','A')
#define FOURCC_M2AM MAKEFOURCC('M','2','A','M')
#define FOURCC_M2R4 MAKEFOURCC('M','2','R','4')
#define FOURCC_AYUV MAKEFOURCC('A','Y','U','V')
#define FOURCC_AI44 MAKEFOURCC('A','I','4','4')
#define FOURCC_XENC MAKEFOURCC('X','E','N','C')
// OpenGL Surfaces
#define FOURCC_OGLZ MAKEFOURCC('O','G','L','Z')
#define FOURCC_OGNZ MAKEFOURCC('O','G','N','Z')
#define FOURCC_OGLS MAKEFOURCC('O','G','L','S')
#define FOURCC_OGNS MAKEFOURCC('O','G','N','S')
#define FOURCC_OGLT MAKEFOURCC('O','G','L','T')
#define FOURCC_OGNT MAKEFOURCC('O','G','N','T')
#define FOURCC_OGLB MAKEFOURCC('O','G','L','B')
#define FOURCC_DDES MAKEFOURCC('D','D','E','S')
#define FOURCC_PBSM MAKEFOURCC('P','B','S','M')
#define FOURCC_ATI1 MAKEFOURCC('A','T','I','1')
#define FOURCC_ATI2 MAKEFOURCC('A','T','I','2')
// Alias of ARGB-8888 for special MM app. to store security content
#define FOURCC_SORT MAKEFOURCC('S','O','R','T')
// Alias of YUY2 for special MM app. to store security content
#define FOURCC_SYV2 MAKEFOURCC('S','Y','V','2')
// Communication surface for special MM app. to enable security content playback
#define FOURCC_EAPI MAKEFOURCC('E','A','P','I')
// Communication surface
#define FOURCC_ATIC MAKEFOURCC('A','T','I','C')
// Fake format for exposing DX9c geometry instancing
#define FOURCC_INST MAKEFOURCC('I','N','S','T')
// Fake format for exposing R2VB support
// must match FOURCC_R2VB in d3d/atir2vb.h
#define FOURCC_R2VB MAKEFOURCC('R','2','V','B')
// Depth Stencil Texture formats.
#define FOURCC_DF16 MAKEFOURCC('D','F','1','6')
#define FOURCC_DF24 MAKEFOURCC('D','F','2','4')
// FP_11_11_10 format - used internally for optimization
#define FOURCC_FP11 MAKEFOURCC('F','P','1','1')
// Fetch4:
// GET4 is used both as fake format for exposing Fetch4 and as enable value.
// GET1 is used only as disable value.
#define FOURCC_GET4 MAKEFOURCC('G','E','T','4')
#define FOURCC_GET1 MAKEFOURCC('G','E','T','1')
// ATI Compute Abstraction Layer (CAL)
// U8X1 stands for unsigned 8 bits by 1 component
// S6X4 stands for signed 16 bits by 4 components
#define FOURCC_ATIP MAKEFOURCC('A','T','I','P')
#define FOURCC_U8X1 MAKEFOURCC('U','8','X','1')
#define FOURCC_S8X1 MAKEFOURCC('S','8','X','1')
#define FOURCC_U8X2 MAKEFOURCC('U','8','X','2')
#define FOURCC_S8X2 MAKEFOURCC('S','8','X','2')
#define FOURCC_S8X4 MAKEFOURCC('S','8','X','4')
#define FOURCC_U6X1 MAKEFOURCC('U','6','X','1')
#define FOURCC_S6X1 MAKEFOURCC('S','6','X','1')
#define FOURCC_S6X2 MAKEFOURCC('S','6','X','2')
#define FOURCC_S6X4 MAKEFOURCC('S','6','X','4')
// ATI semaphore, currently used by CAL
#define FOURCC_SEMA MAKEFOURCC('S','E','M','A')
#endif // _FOURCC_H_
@@ -0,0 +1,2 @@
Promotions directory contains functionality from other staging branches copied
(promoted) into the CAL tree.
@@ -0,0 +1,88 @@
#ifndef __DXXOPENCLINTEROPEXT_H__
#define __DXXOPENCLINTEROPEXT_H__
// Abstract extension interface class
// Each extension interface (e.g. OpenCL Interop extension) will derive from this class
class IAmdDxExtInterface
{
public:
virtual unsigned int AddRef(void) = 0;
virtual unsigned int Release(void) = 0;
protected:
IAmdDxExtInterface() {};
virtual ~IAmdDxExtInterface() = 0 {};
};
// forward declaration for d3d specific interfaces
interface ID3D10Device;
interface ID3D11Device;
interface IDirect3DDevice9Ex;
interface ID3D10Resource;
interface ID3D11Resource;
interface IDirect3DSurface9;
// forward declaration of extended primitive topology enumeration
enum AmdDxExtPrimitiveTopology;
// Extension version information
struct AmdDxExtVersion
{
unsigned int majorVersion;
unsigned int minorVersion;
};
// This class serves as the main extension interface.
// AmdDxExtCreate returns a pointer to an instantiation of this interface.
// This object is used to retrieve extension version information
// and to get specific extension interfaces desired.
class IAmdDxExt : public IAmdDxExtInterface
{
public:
virtual HRESULT GetVersion(AmdDxExtVersion* pExtVer) = 0;
virtual IAmdDxExtInterface* GetExtInterface(unsigned int iface) = 0;
// General extensions
virtual HRESULT IaSetPrimitiveTopology(unsigned int topology) = 0;
virtual HRESULT IaGetPrimitiveTopology(AmdDxExtPrimitiveTopology* pExtTopology) = 0;
virtual HRESULT SetSingleSampleRead(ID3D10Resource* pResource, BOOL singleSample) = 0;
virtual HRESULT SetSingleSampleRead11(ID3D11Resource* pResource, BOOL singleSample) = 0;
virtual HRESULT SetSingleSampleRead9(IDirect3DSurface9* pResource, BOOL singleSample) = 0;
protected:
IAmdDxExt() {};
virtual ~IAmdDxExt() = 0 {};
};
// OpenCL Interop extension ID passed to IAmdDxExt::GetExtInterface()
const unsigned int AmdDxExtCLInteropID = 7;
// Abstract OpenCL Interop extension interface class
class IAmdDxExtCLInterop : public IAmdDxExtInterface
{
public:
virtual HRESULT QueryInteropGpuMask(UINT* gpuIdBitmask) = 0;
virtual HRESULT CLAcquireResource(ID3D10Resource* pResource, UINT* gpuIdBitmask) = 0;
virtual HRESULT CLReleaseResource(ID3D10Resource* pResource, UINT* gpuIdBitmask) = 0;
virtual HRESULT CLAcquireResource11(ID3D11Resource* pResource, UINT* gpuIdBitmask) = 0;
virtual HRESULT CLReleaseResource11(ID3D11Resource* pResource, UINT* gpuIdBitmask) = 0;
virtual HRESULT CLAcquireResource9(IDirect3DSurface9* pResource, UINT* gpuIdBitmask) = 0;
virtual HRESULT CLReleaseResource9(IDirect3DSurface9* pResource, UINT* gpuIdBitmask) = 0;
};
// Use GetProcAddress, etc. to retrieve exported functions
// The associated typedef provides a convenient way to define the function pointer
HRESULT __cdecl AmdDxExtCreate(ID3D10Device* pDevice, IAmdDxExt** ppExt);
typedef HRESULT (__cdecl *PFNAmdDxExtCreate)(ID3D10Device* pDevice, IAmdDxExt** ppExt);
HRESULT __cdecl AmdDxExtCreate11(ID3D11Device* pDevice, IAmdDxExt** ppExt);
typedef HRESULT (__cdecl *PFNAmdDxExtCreate11)(ID3D11Device* pDevice, IAmdDxExt** ppExt);
HRESULT __cdecl AmdDxExtCreate9(IDirect3DDevice9Ex* pDevice, IAmdDxExt** ppExt);
typedef HRESULT (__cdecl *PFNAmdDxExtCreate9)(IDirect3DDevice9Ex* pDevice, IAmdDxExt** ppExt);
#endif
@@ -0,0 +1,202 @@
#include "EventQueue.h"
#include "query/QueryObject.h"
#include "gsl_ctx.h"
EventQueue::EventQueue()
{
m_cs = NULL;
m_queueSize = c_staticQueueSize;
memset(m_queries,0,sizeof(m_queries));
memset(m_flushed,0,sizeof(m_flushed));
m_latestRetired = 0;
m_headId = m_queueSize - 1 ;
m_tail = 0;
}
EventQueue::~EventQueue()
{
for (unsigned int i = 0; i < c_staticQueueSize; i++)
{
assert(m_queries[i] == 0);
}
}
bool
EventQueue::open(gsCtx* cs, gslQueryTarget target, EQManagerConfig config, uint32 engineMask)
{
assert((config == EQManager_HIGH) || (config == EQManager_LOW));
setSlotCount((int) config);
assert((GpuEvent::InvalidID+1) % m_queueSize == 0);
m_cs = cs;
m_headId = m_queueSize - 1 ;
m_tail = 0;
m_latestRetired = 0;
m_target = target;
m_engineMask = engineMask;
for (unsigned int i = 0; i < m_queueSize; i++)
{
m_queries[i] = cs->createQuery(target);
}
return true;
}
void
EventQueue::close()
{
if (!m_cs) // the queue is unintialized.
{
return;
}
for (unsigned int i = 0; i < m_queueSize; i++)
{
m_cs->destroyQuery(m_queries[i]);
}
memset(m_queries, 0, sizeof(m_queries));
memset(m_flushed, 0, sizeof(m_flushed));
m_latestRetired = 0;
m_headId = m_queueSize - 1 ;
m_tail = 0;
m_cs = NULL;
}
void
EventQueue::begin()
{
const CALuint slot = m_headId % m_queueSize;
gslErrorCode ec = m_queries[slot]->BeginQuery(m_cs, m_target, 0, m_engineMask);
assert(ec == GSL_NO_ERROR);
m_flushed[slot] = false; // we've started a query, but it hasn't been checked yet...
}
uint32
EventQueue::end()
{
uint32 ret = m_headId;
const uint32 slot = m_headId % m_queueSize;
m_queries[slot]->EndQuery(m_cs, 0);
m_headId++;
m_tail++;
if (GpuEvent::InvalidID == m_headId)
{
// Flush on an event ID wrap around or when the Queue is going to wrap in
flush();
//roll numbers back to the beginning
m_latestRetired = 0;
m_headId = m_headId % m_queueSize;
m_tail = m_tail % m_queueSize;
}
return ret;
}
bool
EventQueue::isDone(uint32 event)
{
assert((event < GpuEvent::InvalidID) && "illegal event handle");
// if the event is older the the last known retired event we
// do not need to process it.
if (event <= m_latestRetired)
{
return true;
}
// if the event is older than the oldest event handle we have
// we synchronize with the oldest event.
if (event < m_tail)
{
return waitForEvent(m_tail, CAL_WAIT_LOW_CPU_UTILIZATION);
}
//
// If we've never called flush on the query object, go ahead flush the first time to ensure
// we never infinite loop
//
const uint32 slot = event % m_queueSize;
if (!m_flushed[slot])
{
flush();
}
//
// Since we're in between, we actually have to check to see if things are truely done
//
bool retVal = m_queries[slot]->IsResultAvailable(m_cs);
// cache the most recently retired event
if (retVal && (event < m_headId) && (event > m_latestRetired))
{
m_latestRetired = event;
}
return retVal;
}
bool
EventQueue::waitForEvent(uint32 event, uint32 waitType)
{
// if we already retired a younger event we don't to process current events
if (event <= m_latestRetired)
{
return true;
}
// if the event is older than the oldest event handle we have
// we synchronize with the oldest event
if (event < m_tail)
{
event = m_tail;
}
//
// If we've never called flush on the query object, go ahead flush the first time to ensure
// we never infinite loop
//
const uint32 slot = event % m_queueSize;
if (!m_flushed[slot])
{
flush();
}
uint64 param;
m_queries[slot]->GetResult(m_cs, &param, waitType);
// cache the most recently retired event
if ((event < m_headId) && (event > m_latestRetired))
{
m_latestRetired = event;
}
return (param != 0);
}
bool
EventQueue::flush()
{
m_cs->Flush(false, m_engineMask);
memset(m_flushed, 1, sizeof(m_flushed));
return true;
}
void
EventQueue::setSlotCount(uint32 slotCount)
{
if (slotCount < c_staticQueueSize)
{
m_queueSize = slotCount;
}
else
{
m_queueSize = c_staticQueueSize;
}
}
@@ -0,0 +1,57 @@
#ifndef __EventQueue_h__
#define __EventQueue_h__
#include "cal.h"
#include "backend.h"
#include "atitypes.h"
#include "gsl_types.h"
#include "gsl_config.h"
//#define USE_3D_SYNC 1
namespace gsl
{
class gsCtx;
};
enum EQManagerConfig
{
EQManager_HIGH = 512,
EQManager_LOW = 32
};
class EventQueue {
public:
static const unsigned int c_staticQueueSize = EQManager_HIGH;
EventQueue();
~EventQueue();
bool open(gsl::gsCtx* cs, gslQueryTarget target, EQManagerConfig config, uint32 engineMask = GSL_ENGINEMASK_ALL_BUT_UVD_VCE);
void close();
void begin();
uint32 end();
bool isDone(uint32 event);
bool waitForEvent(uint32 event, uint32 waitType);
bool flush();
private:
gsl::gsCtx* m_cs;
uint32 m_queueSize;
gslQueryTarget m_target;
uint32 m_engineMask; // EngineMask for this Query
uint32 m_tail; //represents the oldest event we have
uint32 m_headId;
uint32 m_latestRetired; //!< most recentyl retired event.
gslQueryObject m_queries[c_staticQueueSize];
bool m_flushed[c_staticQueueSize];
///////////////////////
// private functions //
///////////////////////
void setSlotCount(uint32 slotCount);
};
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,180 @@
#ifndef __GSLContext_h__
#define __GSLContext_h__
#include "atitypes.h"
#include "gsl_types.h"
#include "gsl_vid_if.h"
#include "cal.h"
#include "calcl.h"
#include "EventQueue.h"
#include "amuABI.h"
#define SC_INFO_CONSTANTBUFFER (147-128)
#define SC_SR_INIT_CONSTANTBUFFER 0
#define HW_R800_MAX_UAV 12
#define SC_R800_ARENA_UAV_SHORT_ID 9
#define SC_R800_ARENA_UAV_BYTE_ID 10
#define SC_R800_ARENA_UAV_DWORD_ID 11
class CALGSLDevice;
namespace gsl
{
class gsAdaptor;
};
class CALGSLContext
{
public:
CALGSLContext();
~CALGSLContext();
bool open(const CALGSLDevice* pDeviceObject, uint32 nEngines, gslEngineDescriptor *engines);
void close(gsl::gsAdaptor* native);
bool setInput(uint32 physUnit, gslMemObject mem);
bool setOutput(uint32 physUnit, gslMemObject mem);
bool setConstantBuffer(uint32 physUnit, gslMemObject mem, CALuint offset, size_t size);
bool setUAVBuffer(uint32 physUnit, gslMemObject mem, gslUAVType uavType);
void setUavMask(const CALUavMask& uavMask);
void setUAVChannelOrder(uint32 physUnit, gslMemObject mem);
void setProgram(gslProgramObject func);
bool runProgramGrid(GpuEvent& event, const ProgramGrid* pProgramGrid, const gslMemObject* mems, uint32 numMems);
bool runProgramVideoDecode(GpuEvent& event, gslMemObject mo, const CALprogramVideoDecode& decode);
void runAqlDispatch(GpuEvent& event, const void* aqlPacket, const gslMemObject* mems,
uint32 numMems, gslMemObject scratch, const void* cpuKernelCode, uint64 hsaQueueVA);
mcaddr virtualQueueDispatcherStart();
void virtualQueueDispatcherEnd(GpuEvent& event, const gslMemObject* mems, uint32 numMems, mcaddr signal, mcaddr loopStart);
void virtualQueueHandshake(GpuEvent& event, const gslMemObject mem, mcaddr parentState, uint32 newStateValue, mcaddr parentChildCounter, mcaddr signal);
bool isDone(GpuEvent* event);
void waitForEvent(GpuEvent* event);
void flushIOCaches() const;
void flushL1Cache() const;
void eventBegin(EngineType engId)
{
m_eventQueue[engId].begin();
const static bool Begin = true;
profileEvent(engId, Begin);
}
void eventEnd(EngineType engId, GpuEvent& event)
{
const static bool End = false;
profileEvent(engId, End);
event.id = m_eventQueue[engId].end();
event.engineId_ = engId;
}
gslProgramObject createProgramObject(uint32 type);
void destroyProgramObject(gslProgramObject func);
bool copyPartial(GpuEvent& event, gslMemObject srcMem, size_t* srcOffset,
gslMemObject destMem, size_t* destOffset, size_t* size, CALmemcopyflags flags, bool enableCopyRect);
void setSamplerParameter(uint32 sampler, gslTexParameterPname param, CALvoid* vals);
gslQueryObject createCounter(gslQueryTarget target) const;
void configPerformanceCounter(gslQueryObject counter, CALuint block, CALuint index, CALuint event) const;
void destroyCounter(gslQueryObject counter) const;
void beginCounter(gslQueryObject counter, gslQueryTarget target) const;
void endCounter(gslQueryObject counter, GpuEvent& event);
void getCounter(uint64* result, gslQueryObject counter) const;
gslMemObject createConstants(uint32 count) const;
void setConstants(gslMemObject constants) const;
void destroyConstants(gslMemObject constants) const;
bool recompileShader(CALimage srcImage, CALimage* newImage, const CALuint type);
bool getMachineType(CALuint* pMachine, CALuint* pType, CALimage image);
void getFuncInfo(gslProgramObject func, gslProgramTarget target, CALfuncInfo* pInfo);
bool openVideoSession(CALvideoProperties& properties);
void closeVideoSession(void);
void bindAtomicCounter(uint32 index, gslMemObject obj);
void syncAtomicCounter(GpuEvent& event, uint32 index, bool read);
void setGWSResource(uint32 index, uint32 value);
void createVCE(CALEncodeCreateVCE* pEncodeVCE, CALuint flags);
void destroyVCE(CALuint flags);
void getDeviceInfoVCE(CALuint *num_device, CALEncodeGetDeviceInfo* pEncodeDeviceInfo, CALuint flags);
void getNumberOfModesVCE(CALEncodeGetNumberOfModes* pEncodeNumberOfModes, CALuint flags);
void getModesVCE(CALuint device_id, CALuint NumEncodeModesToRetrieve, CALEncodeGetModes* pEncodeMode, CALuint flags);
void getDeviceCAPVCE(CALuint device_id, CALuint encode_cap_total_size, CALEncodeGetDeviceCAP *pEncodeCAP, CALuint flags);
void createEncodeSession(CALuint device_id, CALencodeMode encode_mode, CAL_VID_PROFILE_LEVEL encode_profile_level,
CAL_VID_PICTURE_FORMAT encode_formatm, CALuint encode_width, CALuint encode_height,
CALuint frameRateNum, CALuint frameRateDenom, CAL_VID_ENCODE_JOB_PRIORITY encode_priority_level);
void closeVideoEncodeSession(CALuint device_id);
void setState(CALEncodeSetState state, CALuint flags);
void getPictureConfig(CALEncodeGetPictureControlConfig *pPictureControlConfig, CALuint flags);
void getRateControlConfig(CALEncodeGetRateControlConfig *pRateControConfig, CALuint flags);
void getMotionEstimationConfig(CALEncodeGetMotionEstimationConfig *pMotionEstimationConfig, CALuint flags);
void getRDOConfig(CALEncodeGetRDOControlConfig *pRODConfig, CALuint flags);
void SendConfig(CALuint num_of_config_buffers, CAL_VID_CONFIG *pConfigBuffers, CALuint flags);
void EncodeePicture(GpuEvent& event, CALuint num_of_encode_task_input_buffer, CAL_VID_BUFFER_DESCRIPTION *encode_task_input_buffer_list, void *picture_parameter, CALuint *pTaskID, gslMemObject input_NV12_surface, CALuint flags);
void QueryTaskDescription(CALuint num_of_task_description_request, CALuint *num_of_task_description_return, CAL_VID_OUTPUT_DESCRIPTION *task_description_list, CALuint flags);
void ReleaseOutputResource(CALuint taskID, CALuint flags);
bool moduleLoad(CALimage image, gslProgramObject* func, gslMemObject* constants, CALUavMask* uavMask);
bool WaitSignal(gslMemObject mem, CALuint value);
bool WriteSignal(gslMemObject mem, CALuint value, CALuint64 offset);
bool MakeBuffersResident(CALuint numObjects, gslMemObject* pMemObjects, CALuint64* surfBusAddress, CALuint64* markerBusAddress);
gslQueryObject createThreadTrace(void) const;
void destroyThreadTrace(gslQueryObject) const;
gslShaderTraceBufferObject CreateThreadTraceBuffer(void) const;
void DestroyThreadTraceBuffer(gslShaderTraceBufferObject,uint32) const;
uint32 getThreadTraceQueryRes(gslQueryObject) const;
void configMemThreadTrace(gslShaderTraceBufferObject,gslMemObject,uint32,uint32) const;
void beginThreadTrace(gslQueryObject,gslQueryObject, gslQueryTarget,uint32,CALthreadTraceConfig&) const;
void endThreadTrace(gslQueryObject,uint32) const;
void pauseThreadTrace(uint32) const;
void resumeThreadTrace(uint32) const;
void writeTimer(bool sdma, const gslMemObject mem, uint32 offset) const;
void writeSurfRaw(GpuEvent& event, gslMemObject mem, size_t size, const void* data);
protected:
void setScratchBuffer(gslMemObject mem, int32 engineId);
virtual void profileEvent(EngineType engine, bool type) const {}
CALwaitType m_waitType; //!< Wait type
private:
enum {
MAX_OUTPUTS = 12,
MAX_CONSTANTBUFFERS = 20,
MAX_APICONSTANTBUFFERS = 16,
MAX_SAMPLERS = 16,
MAX_RESOURCES = 128,
MAX_SCRATCHBUFFERS = 1,
MAX_SHADERENGINES = 4,
MAX_UAVS = 1024,
};
const CALGSLDevice* m_Dev;
const CALGSLDevice* dev() const { return m_Dev; }
gsl::gsCtx* m_cs;
gslRenderState m_rs;
gslConstantBufferObject m_constantBuffers[MAX_CONSTANTBUFFERS];
gslUAVObject m_uavResources[MAX_UAVS];
gslTextureResourceObject m_textureResources[MAX_RESOURCES];
gslSamplerObject m_textureSamplers[MAX_SAMPLERS];
gslDrawBuffers m_drawBuffers;
gslFramebufferObject m_fb;
gslScratchBufferObject m_scratchBuffers;
EventQueue m_eventQueue[AllEngines];
bool m_allowDMA;
gslVidSession m_videoSession;
gslVideoContext m_videocontext;
gslVidSession m_EncodevideoSession;
};
#endif // __GSLContext_h__
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,229 @@
#ifndef __GSLDevice_h__
#define __GSLDevice_h__
#include "cal.h"
#include "calcl.h"
#include "atitypes.h"
#include "gsl_types.h"
#include "gsl_config.h"
#include "gsl_vid_if.h"
#include "thread/monitor.hpp"
#ifdef ATI_OS_LINUX
typedef unsigned int IDirect3DDevice9;
typedef unsigned int IDirect3DSurface9;
typedef unsigned int IDirect3DQuery9;
typedef unsigned int RECT;
#else
#undef APIENTRY
#include <d3d9.h>
#endif
#include <map>
namespace gsl
{
class gsAdaptor;
};
typedef enum
{
USE_NONE,
USE_CPDMA,
USE_DRMDMA,
USE_DRMDMA_L2T,
USE_DRMDMA_T2L,
} CopyType;
class CALGSLDevice
{
public:
struct GLResAssociate {
void* GLContext; //(IN) handle to HGLRC or GLXContext
void* GLdeviceContext; //(IN) a handle to device context
uint name; //(IN) gl identifier of the object
CALResGLBufferType type; // (IN) type of the interop object .
uint flags; // (IN) flags assigned to 'GLResource' struct
void* mbResHandle; // (OUT) Internal GL driver handle for the resource
gslMemObject mem_base; // (OUT) Base memory object for the resource
gslMemObject memObject; //(OUT) Alias gsl memory object for the resource
gslMemObject fMaskObject; //(OUT) gsl memobject of the an MSAA resource F-mask.
};
CALGSLDevice();
~CALGSLDevice();
bool open(uint32 gpuIndex, bool enableHighPerformanceState, bool reportAsOCL12Device);
void close();
gslMemObject resAlloc(const CALresourceDesc* desc) const;
bool resMapLocal(void*& pPtr, size_t& pitch, gslMemObject res, gslMapAccessType flags);
bool resUnmapLocal(gslMemObject res);
void resFree(gslMemObject mem) const;
bool resMapRemote(void*& pPtr, size_t& pitch, gslMemObject res, gslMapAccessType flags) const;
bool resUnmapRemote(gslMemObject res) const;
gslMemObject resGetHeap(size_t size) const;
gslMemObject resAllocView(gslMemObject res, gslResource3D size,
CALdomain offset, cmSurfFmt format, gslChannelOrder channelOrder,
gslMemObjectAttribType resType, uint32 level, uint32 layer,
uint32 flags, uint64 bytePitch = (uint64)-1) const;
bool associateD3D11Device(void* d3d11Device); //void* is of type ID3D11Device*
bool associateD3D10Device(void* d3d10Device); //void* is of type ID3D10Device*
bool associateD3D9Device(void* d3d9Device); //void* is of type IDirect3DDevice9*
gslMemObject resMapD3DResource(
const CALresourceDesc* desc, uint64 sharedhandle, bool displayable) const;
bool glAssociate(CALvoid *GLplatformContext, CALvoid* GLdeviceContext);
bool glDissociate(CALvoid *GLplatformContext, CALvoid* GLdeviceContext);
//! @brief This function is called once for every interop resource on the first clEnqeueuAcquireGL.
bool resGLAssociate(GLResAssociate & resData) const;
//! @brief This function is called once for every interop resource on resource destruction.
bool resGLFree (CALvoid* GLplatformContext,
CALvoid* GLdeviceContext, gslMemObject mem, gslMemObject mem_base,
CALvoid* mbResHandle, CALuint type) const;
//! @brief Decompresses depth/MSAA surfaces.This function is called on every 'clEnqeueuAcquireGLObject'.
bool resGLAcquire( CALvoid* GLplatformContext,CALvoid* mbResHandle, CALuint type) const;
//! @brief This function is called on every 'clEnqeueuReleaseGLObject'.
bool resGLRelease(CALvoid* GLplatformContext,CALvoid* mbResHandle) const;
gsl::gsAdaptor* getNative() const;
CALuint getElfMachine() const { return m_elfmachine; };
uint32 getGpuIndex() const { return m_gpuIndex; };
uint32 getMaxTextureSize() const;
const CALdeviceattribs& getAttribs() const { return m_attribs; }
const CALdeviceVideoAttribs& getVideoAttribs() const { return m_videoAttribs; }
const CALdevicestatus& getStatus() const {return m_deviceStatus; }
void getMemInfo(gslMemInfo* memInfo) const;
bool isVmMode() const { return m_vmMode; };
void closeNativeDisplayHandle();
uint32 getVPUCount();
void setVPUMask(uint32 mask);
uint32 getVPUMask() const { return m_vpuMask; }
bool uavInCB() const { return m_uavInCB; }
bool canDMA() const { return m_canDMA; }
gslMemObject m_srcDRMDMAMem, m_dstDRMDMAMem; // memory object of flush buffer, used for DRMDMA flush
void resCopy(gslMemObject srcRes, gslMemObject dstRes, uint32 flags) const;
void PerformAdapterInitialization() const;
void PerformFullInitialization() const;
void queryDeviceEngines(uint32* nEngines, gslEngineDescriptor* engines);
CopyType GetCopyType(gslMemObject srcMem, gslMemObject destMem, size_t* srcOffset,
size_t* destOffset, bool allowDMA, uint32 flags, uint64& surfaceSize,
size_t size, bool enableCopyRect) const;
uint32 calcScratchBufferSize(uint32 regNum) const;
amd::Monitor& gslDeviceOps() const { return *gslDeviceOps_; }
void fillImageHwState(gslMemObject mem, void* hwState, uint32 hwStateSize) const;
void fillSamplerHwState(bool unnorm, uint32 min, uint32 mag, uint32 addr, void* hwState, uint32 hwStateSize) const;
gslSamplerObject txSampler() const { return m_textureSampler; }
void convertInputChannelOrder(intp *channelOrder) const;
gsl::gsCtx* gslCtx() const { return m_cs; }
protected:
//
/// channel order enumerants
//
//channelSwizzleMode and channelSwizzle match the hwl equivalent hwtxSwizzleMode and hwtxUnitSwizzle in hwl_tx_if.h.
enum channelSwizzleMode {
SWIZZLE_COMPONENT0, ///< Select Component0
SWIZZLE_COMPONENT1, ///< Select Component1
SWIZZLE_COMPONENT2, ///< Select Component2
SWIZZLE_COMPONENT3, ///< Select Component3
SWIZZLE_ZERO, ///< Select Zero
SWIZZLE_ONE, ///< Select One
};
//
/// channel order swizzle type
//
typedef struct channelSwizzleRec
{
channelSwizzleMode r : 8; ///< Red channel of texture
channelSwizzleMode g : 8; ///< Green channel of texture
channelSwizzleMode b : 8; ///< Blue channel of texture
channelSwizzleMode a : 8; ///< Alpha channel of texture
} channelSwizzle;
private:
gsl::gsAdaptor* m_adp;
gsl::gsCtx* m_cs;
gslRenderState m_rs;
CALtarget m_target;
CALuint m_elfmachine;
uint32 m_revision;
uint32 m_vpuMask;
uint32 m_chainIndex;
int32 m_vpucount;
int32 m_maxtexturesize;
uint32 m_gpuIndex;
void* m_nativeDisplayHandle;
gslDeviceModeEnum m_deviceMode;
typedef std::map<gslMemObject, intp> Hack;
Hack m_hack;
gslQueryObject m_mapQuery;
gslQueryObject m_mapDMAQuery;
gslQueryObject m_mapUVDQuery;
gslQueryObject m_mapVCEQuery;
gslStaticRuntimeConfig m_scfg;
gslDynamicRuntimeConfig m_dcfg;
//GL Extension specific
void initGLInteropPrivateExt(CALvoid* GLplatformContext, CALvoid* GLdeviceContext) const;
bool glCanInterop(CALvoid* GLplatformContext, CALvoid* GLdeviceContext);
bool PerformDMACopy(gslMemObject srcMem, gslMemObject destMem, cmSurfFmt format, CALuint flags);
void Initialize(void);
bool SetupAdapter(int32 &asic_id);
bool SetupContext(int32 &asic_id);
void PerformAdapterInitialization_int();
void PerformFullInitialization_int();
void getAttribs_int(gsl::gsCtx* cs);
void getVideoAttribs_int(gslVideoContext* vsHandle);
void getStatus_int(gsl::gsCtx* cs);
bool ResolveAperture(const gslMemObjectAttribTiling tiling) const;
CALdeviceattribs m_attribs;
CALdeviceVideoAttribs m_videoAttribs;
CALdevicestatus m_deviceStatus;
gslTextureResourceObject m_textureResource;
gslSamplerObject m_textureSampler;
union {
struct {
uint m_canDMA : 1;
uint m_allowDMA : 1;
uint m_computeRing : 1;
uint m_usePerVPUAdapterModel : 1;
uint m_PerformLazyDeviceInit : 1;
uint m_vmMode : 1;
uint m_uavInCB : 1;
};
};
amd::Monitor* gslDeviceOps_; //!< Lock to serialize GSL device
};
#endif // __GSLDevice_h__
@@ -0,0 +1,231 @@
#include "gsl_ctx.h"
#include "GSLDevice.h"
#if defined(ATI_OS_WIN)
#include <D3D10_1.h>
/**************************************************************************************************************
* Note: ideally the DXX extension interfaces should be mapped from the DXX perforce branch.
* This means CAL client spec will need to change to include headers directly from the DXX perforce tree.
* However, CAL only cares about the DXX OpenCL extension interface class. The spec cannot change
* without notification. So it is safe to use a local copy of the relevant DXX extension interface classes.
**************************************************************************************************************/
#include "DxxOpenCLInteropExt.h"
static bool
queryD3D10DeviceGPUMask(ID3D10Device* pd3d10Device, UINT* pd3d10DeviceGPUMask)
{
HMODULE hDLL = NULL;
IAmdDxExt* pExt = NULL;
IAmdDxExtCLInterop* pCLExt = NULL;
PFNAmdDxExtCreate AmdDxExtCreate;
HRESULT hr = S_OK;
// Get a handle to the DXX DLL with extension API support
#if defined _WIN64
static const CHAR dxxModuleName[13] = "atidxx64.dll";
#else
static const CHAR dxxModuleName[13] = "atidxx32.dll";
#endif
hDLL = GetModuleHandle(dxxModuleName);
if (hDLL == NULL)
{
hr = E_FAIL;
}
// Get the exported AmdDxExtCreate() function pointer
if (SUCCEEDED(hr))
{
AmdDxExtCreate = reinterpret_cast<PFNAmdDxExtCreate>(GetProcAddress(hDLL, "AmdDxExtCreate"));
if (AmdDxExtCreate == NULL)
{
hr = E_FAIL;
}
}
// Create the extension object
if (SUCCEEDED(hr))
{
hr = AmdDxExtCreate(pd3d10Device, &pExt);
}
// Get the extension version information
if (SUCCEEDED(hr))
{
AmdDxExtVersion extVersion;
hr = pExt->GetVersion(&extVersion);
if (extVersion.majorVersion == 0)
{
hr = E_FAIL;
}
}
// Get the OpenCL Interop interface
if (SUCCEEDED(hr))
{
pCLExt = static_cast<IAmdDxExtCLInterop*>(pExt->GetExtInterface(AmdDxExtCLInteropID));
if (pCLExt != NULL)
{
// Get the GPU mask using the CL Interop extension.
pCLExt->QueryInteropGpuMask(pd3d10DeviceGPUMask);
}
else
{
hr = E_FAIL;
}
}
if (pCLExt != NULL)
{
pCLExt->Release();
}
if (pExt != NULL)
{
pExt->Release();
}
return (SUCCEEDED(hr));
}
bool
CALGSLDevice::associateD3D10Device(void* d3d10Device)
{
bool canInteroperate = false;
LUID calDevAdapterLuid = {0, 0};
UINT calDevChainBitMask = 0;
UINT d3d10DeviceGPUMask = 0;
ID3D10Device* pd3d10Device = static_cast<ID3D10Device*>(d3d10Device);
IDXGIDevice* pDXGIDevice;
pd3d10Device->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice);
IDXGIAdapter* pDXGIAdapter;
pDXGIDevice->GetAdapter(&pDXGIAdapter);
DXGI_ADAPTER_DESC adapterDesc;
pDXGIAdapter->GetDesc(&adapterDesc);
// match the adapter
if (m_adp->getMVPUinfo(&calDevAdapterLuid, &calDevChainBitMask))
{
canInteroperate = ((calDevAdapterLuid.HighPart == adapterDesc.AdapterLuid.HighPart) &&
(calDevAdapterLuid.LowPart == adapterDesc.AdapterLuid.LowPart));
}
// match the chain ID
if (canInteroperate)
{
if (queryD3D10DeviceGPUMask(pd3d10Device, &d3d10DeviceGPUMask))
{
canInteroperate = (calDevChainBitMask & d3d10DeviceGPUMask) != 0;
}
else
{
// special handling for Intel iGPU + AMD dGPU in LDA mode (only occurs on a PX platform) where
// the D3D10Device object is created on the Intel iGPU and passed to AMD dGPU (secondary) to interoperate.
if (calDevChainBitMask > 1)
{
canInteroperate = false;
}
}
}
pDXGIDevice->Release();
pDXGIAdapter->Release();
return canInteroperate;
}
gslMemObject
CALGSLDevice::resMapD3DResource(const CALresourceDesc* desc, uint64 sharedhandle, bool displayable) const
{
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps_);
gslMemObject mem = NULL;
gslMemObjectAttribs attribs(
GSL_MOA_TEXTURE_2D, // type
GSL_MOA_MEMORY_ALIAS, // location
GSL_MOA_TILING_TILED, // tiling
GSL_MOA_DISPLAYABLE_NO, // displayable
ATIGL_FALSE, // mipmap
1, // samples
0, // cpu_address
GSL_MOA_SIGNED_NO, // signed_format
GSL_MOA_FORMAT_DERIVED, // numFormat
DRIVER_MODULE_GLL, // module
GSL_ALLOCATION_INSTANCED // alloc_type
);
HANDLE h = (HANDLE)sharedhandle;
attribs.cpu_address = h;
attribs.alias_swizzle = 0;
attribs.channelOrder = desc->channelOrder;
attribs.type = desc->dimension;
switch (desc->dimension)
{
case GSL_MOA_BUFFER:
attribs.tiling = GSL_MOA_TILING_LINEAR;
mem = m_cs->createMemObject1D(desc->format, desc->size.width, &attribs);
break;
case GSL_MOA_TEXTURE_1D:
attribs.tiling = GSL_MOA_TILING_LINEAR;
mem = m_cs->createMemObject1D(desc->format, desc->size.width, &attribs);
break;
case GSL_MOA_TEXTURE_2D:
{
uint32 height = (uint32)desc->size.height;
if (displayable)
{
attribs.displayable = GSL_MOA_DISPLAYABLE_YES;
}
mem = m_cs->createMemObject2D(desc->format, desc->size.width, height, &attribs);
}
break;
case GSL_MOA_TEXTURE_3D:
mem = m_cs->createMemObject3D(desc->format, desc->size.width,
(uint32)desc->size.height, (uint32)desc->size.depth, &attribs);
break;
case GSL_MOA_TEXTURE_BUFFER:
attribs.type = GSL_MOA_TEXTURE_BUFFER;
mem = m_cs->createMemObject1D(desc->format, desc->size.width, &attribs);
break;
case GSL_MOA_TEXTURE_1D_ARRAY:
mem = m_cs->createMemObject3D(desc->format, desc->size.width,
1, (uint32)desc->size.height, &attribs);
break;
case GSL_MOA_TEXTURE_2D_ARRAY:
mem = m_cs->createMemObject3D(desc->format, desc->size.width,
(uint32)desc->size.height, (uint32)desc->size.depth, &attribs);
break;
default:
break;
}
return mem;
}
#else // !ATI_OS_WIN
bool
CALGSLDevice::associateD3D10Device(void* d3d10Device)
{
return false;
}
gslMemObject
CALGSLDevice::resMapD3DResource(const CALresourceDesc* desc, uint64 sharedhandle, bool displayable) const
{
return 0;
}
#endif // !ATI_OS_WIN
@@ -0,0 +1,154 @@
#include "gsl_ctx.h"
#include "GSLDevice.h"
#if defined(ATI_OS_WIN)
#include <D3D11.h>
/**************************************************************************************************************
* Note: ideally the DXX extension interfaces should be mapped from the DXX perforce branch.
* This means CAL client spec will need to change to include headers directly from the DXX perforce tree.
* However, CAL only cares about the DXX OpenCL extension interface class. The spec cannot change
* without notification. So it is safe to use a local copy of the relevant DXX extension interface classes.
**************************************************************************************************************/
#include "DxxOpenCLInteropExt.h"
static bool
queryD3D11DeviceGPUMask(ID3D11Device* pd3d11Device, UINT* pd3d11DeviceGPUMask)
{
HMODULE hDLL = NULL;
IAmdDxExt* pExt = NULL;
IAmdDxExtCLInterop* pCLExt = NULL;
PFNAmdDxExtCreate11 AmdDxExtCreate11;
HRESULT hr = S_OK;
// Get a handle to the DXX DLL with extension API support
#if defined _WIN64
static const CHAR dxxModuleName[13] = "atidxx64.dll";
#else
static const CHAR dxxModuleName[13] = "atidxx32.dll";
#endif
hDLL = GetModuleHandle(dxxModuleName);
if (hDLL == NULL)
{
hr = E_FAIL;
}
// Get the exported AmdDxExtCreate() function pointer
if (SUCCEEDED(hr))
{
AmdDxExtCreate11 = reinterpret_cast<PFNAmdDxExtCreate11>(GetProcAddress(hDLL, "AmdDxExtCreate11"));
if (AmdDxExtCreate11 == NULL)
{
hr = E_FAIL;
}
}
// Create the extension object
if (SUCCEEDED(hr))
{
hr = AmdDxExtCreate11(pd3d11Device, &pExt);
}
// Get the extension version information
if (SUCCEEDED(hr))
{
AmdDxExtVersion extVersion;
hr = pExt->GetVersion(&extVersion);
if (extVersion.majorVersion == 0)
{
hr = E_FAIL;
}
}
// Get the OpenCL Interop interface
if (SUCCEEDED(hr))
{
pCLExt = static_cast<IAmdDxExtCLInterop*>(pExt->GetExtInterface(AmdDxExtCLInteropID));
if (pCLExt != NULL)
{
// Get the GPU mask using the CL Interop extension.
pCLExt->QueryInteropGpuMask(pd3d11DeviceGPUMask);
}
else
{
hr = E_FAIL;
}
}
if (pCLExt != NULL)
{
pCLExt->Release();
}
if (pExt != NULL)
{
pExt->Release();
}
return (SUCCEEDED(hr));
}
bool
CALGSLDevice::associateD3D11Device(void* d3d11Device)
{
bool canInteroperate = false;
LUID calDevAdapterLuid = {0, 0};
UINT calDevChainBitMask = 0;
UINT d3d11DeviceGPUMask = 0;
ID3D11Device* pd3d11Device = static_cast<ID3D11Device*>(d3d11Device);
IDXGIDevice* pDXGIDevice;
pd3d11Device->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice);
IDXGIAdapter* pDXGIAdapter;
pDXGIDevice->GetAdapter(&pDXGIAdapter);
DXGI_ADAPTER_DESC adapterDesc;
pDXGIAdapter->GetDesc(&adapterDesc);
// match the adapter
if (m_adp->getMVPUinfo(&calDevAdapterLuid, &calDevChainBitMask))
{
canInteroperate = ((calDevAdapterLuid.HighPart == adapterDesc.AdapterLuid.HighPart) &&
(calDevAdapterLuid.LowPart == adapterDesc.AdapterLuid.LowPart));
}
// match the chain ID
if (canInteroperate)
{
if (queryD3D11DeviceGPUMask(pd3d11Device, &d3d11DeviceGPUMask))
{
canInteroperate = (calDevChainBitMask & d3d11DeviceGPUMask) != 0;
}
else
{
// special handling for Intel iGPU + AMD dGPU in LDA mode (only occurs on a PX platform) where
// the D3D11Device object is created on the Intel iGPU and passed to AMD dGPU (secondary) to interoperate.
if (calDevChainBitMask > 1)
{
canInteroperate = false;
}
}
}
pDXGIDevice->Release();
pDXGIAdapter->Release();
return canInteroperate;
}
#else // !ATI_OS_WIN
bool
CALGSLDevice::associateD3D11Device(void* d3d11Device)
{
return false;
}
#endif // !ATI_OS_WIN
@@ -0,0 +1,56 @@
#include "gsl_ctx.h"
#include "GSLDevice.h"
#if defined(ATI_OS_WIN)
#include <d3d9.h>
#include <dxgi.h>
/**************************************************************************************************************
* Note: ideally the DXX extension interfaces should be mapped from the DXX perforce branch.
* This means CAL client spec will need to change to include headers directly from the DXX perforce tree.
* However, CAL only cares about the DXX OpenCL extension interface class. The spec cannot change
* without notification. So it is safe to use a local copy of the relevant DXX extension interface classes.
**************************************************************************************************************/
#include "DxxOpenCLInteropExt.h"
bool
CALGSLDevice::associateD3D9Device(void* d3d9Device)
{
bool canInteroperate = false;
D3DCAPS9 pCaps;
LUID calDevAdapterLuid = {0, 0};
UINT calDevChainBitMask = 0;
IDirect3D9* p3d9dev;
LUID d3d9deviceLuid = {0, 0};
IDirect3DDevice9* pd3d9Device = static_cast<IDirect3DDevice9*>(d3d9Device);
// Get D3D9 Device caps
pd3d9Device->GetDeviceCaps(&pCaps);
// Get 3D9 Device
pd3d9Device->GetDirect3D(&p3d9dev);
IDirect3D9Ex* p3d9devEx = static_cast<IDirect3D9Ex*>(p3d9dev);
p3d9devEx->GetAdapterLUID(pCaps.AdapterOrdinal, &d3d9deviceLuid);
// match the adapter
if (m_adp->getMVPUinfo(&calDevAdapterLuid, &calDevChainBitMask))
{
canInteroperate = ((calDevAdapterLuid.HighPart == d3d9deviceLuid.HighPart) &&
(calDevAdapterLuid.LowPart == d3d9deviceLuid.LowPart));
}
return canInteroperate;
}
#else // !ATI_OS_WIN
bool
CALGSLDevice::associateD3D9Device(void* d3dDevice)
{
return false;
}
#endif // !ATI_OS_WIN
@@ -0,0 +1,883 @@
#include "gsl_ctx.h"
#include "GSLDevice.h"
#include "component_types.h"
#include "cwddeci.h"
#include <GL/gl.h>
#include "GL/glATIInternal.h"
#ifdef ATI_OS_LINUX
#include <stdlib.h>
#include <dlfcn.h>
#include "GL/glx.h"
#include "GL/glxext.h"
#include "GL/glXATIPrivate.h"
#else
#include "GL/wglATIPrivate.h"
#endif
#include "memory/MemObject.h"
typedef struct cmFormatXlateRec{
cmSurfFmt raw_cmFormat;
cmSurfFmt cal_cmFormat;
gslChannelOrder channelOrder;
} cmFormatXlateParams;
// relates full range of cm surface formats to those supported by CAL
static const cmFormatXlateParams cmFormatXlateTable [] = {
{CM_SURF_FMT_LUMINANCE8, CM_SURF_FMT_R8I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE16, CM_SURF_FMT_R16, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE16F, CM_SURF_FMT_R16F, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE32F, CM_SURF_FMT_R32F, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_INTENSITY8, CM_SURF_FMT_INTENSITY8, GSL_CHANNEL_ORDER_REPLICATE_R},
{CM_SURF_FMT_INTENSITY16, CM_SURF_FMT_R16, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_INTENSITY16F, CM_SURF_FMT_R16F, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_INTENSITY32F, CM_SURF_FMT_R32F, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_ALPHA8, CM_SURF_FMT_R8I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_ALPHA16, CM_SURF_FMT_R16, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_ALPHA16F, CM_SURF_FMT_R16F, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_ALPHA32F, CM_SURF_FMT_R32F, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE8_ALPHA8, CM_SURF_FMT_RG8I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_LUMINANCE16_ALPHA16, CM_SURF_FMT_RG16I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_LUMINANCE16F_ALPHA16F, CM_SURF_FMT_RG16F, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_LUMINANCE32F_ALPHA32F, CM_SURF_FMT_RG16F, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_B2_G3_R3, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_B5_G6_R5, CM_SURF_FMT_B5_G6_R5, GSL_CHANNEL_ORDER_RGB},
{CM_SURF_FMT_BGRX4, (cmSurfFmt)500, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_BGR5_X1, CM_SURF_FMT_BGR5_X1, GSL_CHANNEL_ORDER_RGB},
{CM_SURF_FMT_BGRX8, CM_SURF_FMT_RGBA8, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_BGR10_X2, CM_SURF_FMT_BGR10_X2, GSL_CHANNEL_ORDER_RGB},
{CM_SURF_FMT_BGRX16, CM_SURF_FMT_RGBA16, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_BGRX16F, CM_SURF_FMT_RGBA16F, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_BGRX32F, CM_SURF_FMT_RGBA32F, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_RGBX4, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGB5_X1, CM_SURF_FMT_BGR5_X1, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBX8, CM_SURF_FMT_RGBA8, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGB10_X2, CM_SURF_FMT_BGR10_X2, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBX16, CM_SURF_FMT_RGBA16, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBX16F, CM_SURF_FMT_RGBA16F, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBX32F, CM_SURF_FMT_RGBA32F, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_BGRA4, (cmSurfFmt)500, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_BGR5_A1, CM_SURF_FMT_BGR5_X1, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_BGRA8, CM_SURF_FMT_RGBA8, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_BGR10_A2, CM_SURF_FMT_BGR10_X2, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_BGRA16, CM_SURF_FMT_RGBA16, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_BGRA16F, CM_SURF_FMT_RGBA16, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_BGRA32F, CM_SURF_FMT_RGBA32F, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_RGBA4, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGB5_A1, CM_SURF_FMT_BGR5_X1, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBA8, CM_SURF_FMT_RGBA8, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGB10_A2, CM_SURF_FMT_BGR10_X2, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBA16, CM_SURF_FMT_RGBA16, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBA16F, CM_SURF_FMT_RGBA16F, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBA32I, CM_SURF_FMT_RGBA32I, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBA32F, CM_SURF_FMT_RGBA32F, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_DUDV8, CM_SURF_FMT_RG8I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_DXT1, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_DXT2_3, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_DXT4_5, (cmSurfFmt)00, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_ATI1N, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_ATI2N, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_DEPTH16, CM_SURF_FMT_DEPTH16, GSL_CHANNEL_ORDER_REPLICATE_R},
{CM_SURF_FMT_DEPTH16F, CM_SURF_FMT_R16F, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_DEPTH24_X8, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_DEPTH24F_X8, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_DEPTH24_STEN8, CM_SURF_FMT_DEPTH24_STEN8, GSL_CHANNEL_ORDER_REPLICATE_R},
{CM_SURF_FMT_DEPTH24F_STEN8, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_DEPTH32F_X24_STEN8, CM_SURF_FMT_RG32I, GSL_CHANNEL_ORDER_REPLICATE_R},
{CM_SURF_FMT_DEPTH32F, CM_SURF_FMT_R32F, GSL_CHANNEL_ORDER_REPLICATE_R},
{CM_SURF_FMT_sR11_sG11_sB10, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sU16, CM_SURF_FMT_sU16, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sUV16, CM_SURF_FMT_sUV16, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_sUVWQ16, CM_SURF_FMT_sUVWQ16, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RG16, CM_SURF_FMT_RG16, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_RG16F, CM_SURF_FMT_RG16F, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_RG32F, CM_SURF_FMT_RG32F, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_ABGR4, (cmSurfFmt)500, GSL_CHANNEL_ORDER_ARGB},
{CM_SURF_FMT_A1_BGR5, CM_SURF_FMT_BGR5_X1, GSL_CHANNEL_ORDER_ARGB},
{CM_SURF_FMT_ABGR8, CM_SURF_FMT_RGBA8, GSL_CHANNEL_ORDER_ARGB},
{CM_SURF_FMT_A2_BGR10, CM_SURF_FMT_BGR10_X2, GSL_CHANNEL_ORDER_ARGB},
{CM_SURF_FMT_ABGR16, CM_SURF_FMT_RGBA16, GSL_CHANNEL_ORDER_ARGB},
{CM_SURF_FMT_ABGR16F, CM_SURF_FMT_RGBA16F, GSL_CHANNEL_ORDER_ARGB},
{CM_SURF_FMT_ABGR32F, CM_SURF_FMT_RGBA32F, GSL_CHANNEL_ORDER_ARGB},
{CM_SURF_FMT_DXT1A, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sRGB10_A2, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_sR8, CM_SURF_FMT_sR8, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sRG8, CM_SURF_FMT_sRG8, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_sR32I, CM_SURF_FMT_sR32I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sRG32I, CM_SURF_FMT_sRG32I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_sRGBA32I, CM_SURF_FMT_sRGBA32I, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_R32I, CM_SURF_FMT_R32I, GSL_CHANNEL_ORDER_REPLICATE_R},
{CM_SURF_FMT_RG32I, CM_SURF_FMT_RG32I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_RG8, CM_SURF_FMT_RG8, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_sRGBA8, CM_SURF_FMT_sRGBA8, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_R11F_G11F_B10F, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGB9_E5, CM_SURF_FMT_RGBA8, GSL_CHANNEL_ORDER_ARGB},
{CM_SURF_FMT_LUMINANCE_LATC1, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_SIGNED_LUMINANCE_LATC1,(cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_LUMINANCE_ALPHA_LATC2, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_SIGNED_LUMINANCE_ALPHA_LATC2, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RED_RGTC1, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_SIGNED_RED_RGTC1, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RED_GREEN_RGTC2, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_SIGNED_RED_GREEN_RGTC2,(cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_R8, CM_SURF_FMT_INTENSITY8, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_R16, CM_SURF_FMT_R16, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_R16F, CM_SURF_FMT_R16F, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_R32F, CM_SURF_FMT_R32F, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_R8I, CM_SURF_FMT_R8I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sR8I, CM_SURF_FMT_sR8I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_RG8I, CM_SURF_FMT_RG8I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_sRG8I, CM_SURF_FMT_sRG8I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_R16I, CM_SURF_FMT_R16I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sR16I, CM_SURF_FMT_sR16I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_RG16I, CM_SURF_FMT_RG16I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_sRG16I, CM_SURF_FMT_sRG16I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_RGBA32UI, CM_SURF_FMT_RGBA32UI, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBX32UI, CM_SURF_FMT_RGBA32UI, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_ALPHA32UI, CM_SURF_FMT_R32I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_INTENSITY32UI, CM_SURF_FMT_R32I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE32UI, CM_SURF_FMT_R32I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE_ALPHA32UI, CM_SURF_FMT_RG32I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_RGBA16UI, CM_SURF_FMT_RGBA16UI, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBX16UI, CM_SURF_FMT_RGBA16UI, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_ALPHA16UI, CM_SURF_FMT_R16I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_INTENSITY16UI, CM_SURF_FMT_R16I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE16UI, CM_SURF_FMT_R16I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE_ALPHA16UI, CM_SURF_FMT_R32I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_RGBA8UI, CM_SURF_FMT_RGBA8UI, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBX8UI, CM_SURF_FMT_RGBA8UI, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_ALPHA8UI, CM_SURF_FMT_R8I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_INTENSITY8UI, CM_SURF_FMT_R8I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE8UI, CM_SURF_FMT_R8I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE_ALPHA8UI, CM_SURF_FMT_RG8I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_sRGBA32I_EXT, CM_SURF_FMT_sRGBA32I, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_sRGBX32I, CM_SURF_FMT_sRGBA32I, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_sALPHA32I, CM_SURF_FMT_sR32I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sINTENSITY32I, CM_SURF_FMT_sR32I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sLUMINANCE32I, CM_SURF_FMT_sR32I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sLUMINANCE_ALPHA32I, CM_SURF_FMT_sRG32I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_sRGBA16I, CM_SURF_FMT_sRGBA16I, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_sRGBX16I, CM_SURF_FMT_sRGBA16I, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_sALPHA16I, CM_SURF_FMT_sR16I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sINTENSITY16I, CM_SURF_FMT_sR16I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sLUMINANCE16I, CM_SURF_FMT_sR16I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sLUMINANCE_ALPHA16I, CM_SURF_FMT_sRG16I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_sRGBA8I, CM_SURF_FMT_sRGBA8I, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_sRGBX8I, CM_SURF_FMT_sRGBA8I, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_sALPHA8I, CM_SURF_FMT_sR8I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sINTENSITY8I, CM_SURF_FMT_sR8I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sLUMINANCE8I, CM_SURF_FMT_sR8I, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_sLUMINANCE_ALPHA8I, CM_SURF_FMT_sRG8I, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_sDXT6, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_DXT6, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_DXT7, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE8_SNORM, CM_SURF_FMT_sR8, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE16_SNORM, CM_SURF_FMT_sU16, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_INTENSITY8_SNORM, CM_SURF_FMT_sR8, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_INTENSITY16_SNORM, CM_SURF_FMT_sU16, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_ALPHA8_SNORM, CM_SURF_FMT_sR8, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_ALPHA16_SNORM, CM_SURF_FMT_sU16, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_LUMINANCE_ALPHA8_SNORM,CM_SURF_FMT_sRG8, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_LUMINANCE_ALPHA16_SNORM,CM_SURF_FMT_sUV16, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_R8_SNORM, CM_SURF_FMT_sR8, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_R16_SNORM, CM_SURF_FMT_sU16, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_RG8_SNORM, CM_SURF_FMT_sRG8, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_RG16_SNORM, CM_SURF_FMT_sUV16, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_RGBX8_SNORM, CM_SURF_FMT_sRGBA8, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBX16_SNORM, CM_SURF_FMT_sUVWQ16, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBA8_SNORM, CM_SURF_FMT_sRGBA8, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBA16_SNORM, CM_SURF_FMT_sUVWQ16, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGB8_ETC2, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGB},
{CM_SURF_FMT_SRGB8_ETC2, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGB},
{CM_SURF_FMT_RGB8_PT_ALPHA1_ETC2, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_SRGB8_PT_ALPHA1_ETC2, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_RGBA8_ETC2_EAC, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_SRGB8_ALPHA8_ETC2_EAC, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_R11_EAC, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_SIGNED_R11_EAC, (cmSurfFmt)500, GSL_CHANNEL_ORDER_R},
{CM_SURF_FMT_RG11_EAC, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_SIGNED_RG11_EAC, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RG},
{CM_SURF_FMT_BGR10_A2UI, (cmSurfFmt)501, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_A2_BGR10UI, (cmSurfFmt)501, GSL_CHANNEL_ORDER_ARGB},
{CM_SURF_FMT_A2_RGB10UI, (cmSurfFmt)501, GSL_CHANNEL_ORDER_ABGR},
{CM_SURF_FMT_B5_G6_R5UI, (cmSurfFmt)500, GSL_CHANNEL_ORDER_BGRA},
{CM_SURF_FMT_R5_G6_B5UI, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_DEPTH32F_X24_STEN8_UNCLAMPED, CM_SURF_FMT_RG32I, GSL_CHANNEL_ORDER_REPLICATE_R},
{CM_SURF_FMT_DEPTH32F_UNCLAMPED, CM_SURF_FMT_R32F, GSL_CHANNEL_ORDER_REPLICATE_R},
{CM_SURF_FMT_L8_X16_A8_SRGB, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_L8_X24_SRGB, (cmSurfFmt)500, GSL_CHANNEL_ORDER_RGBA},
{CM_SURF_FMT_STENCIL8, CM_SURF_FMT_R8I, GSL_CHANNEL_ORDER_R},
};
FINLINE void
dummyAssertIfCmSurfFmtChanges(void)
{
//
// Assert if cmSurfFmt defined in ugl/src/include/cmndefs.h changes.
//
COMPILE_TIME_ASSERT(cmSurfFmt_FIRST == CM_SURF_FMT_LUMINANCE8);
COMPILE_TIME_ASSERT( 0 == CM_SURF_FMT_LUMINANCE8);
COMPILE_TIME_ASSERT( 1 == CM_SURF_FMT_LUMINANCE16);
COMPILE_TIME_ASSERT( 2 == CM_SURF_FMT_LUMINANCE16F);
COMPILE_TIME_ASSERT( 3 == CM_SURF_FMT_LUMINANCE32F);
COMPILE_TIME_ASSERT( 4 == CM_SURF_FMT_INTENSITY8);
COMPILE_TIME_ASSERT( 5 == CM_SURF_FMT_INTENSITY16);
COMPILE_TIME_ASSERT( 6 == CM_SURF_FMT_INTENSITY16F);
COMPILE_TIME_ASSERT( 7 == CM_SURF_FMT_INTENSITY32F);
COMPILE_TIME_ASSERT( 8 == CM_SURF_FMT_ALPHA8);
COMPILE_TIME_ASSERT( 9 == CM_SURF_FMT_ALPHA16);
COMPILE_TIME_ASSERT( 10 == CM_SURF_FMT_ALPHA16F);
COMPILE_TIME_ASSERT( 11 == CM_SURF_FMT_ALPHA32F);
COMPILE_TIME_ASSERT( 12 == CM_SURF_FMT_LUMINANCE8_ALPHA8);
COMPILE_TIME_ASSERT( 13 == CM_SURF_FMT_LUMINANCE16_ALPHA16);
COMPILE_TIME_ASSERT( 14 == CM_SURF_FMT_LUMINANCE16F_ALPHA16F);
COMPILE_TIME_ASSERT( 15 == CM_SURF_FMT_LUMINANCE32F_ALPHA32F);
COMPILE_TIME_ASSERT( 16 == CM_SURF_FMT_B2_G3_R3);
COMPILE_TIME_ASSERT( 17 == CM_SURF_FMT_B5_G6_R5);
COMPILE_TIME_ASSERT( 18 == CM_SURF_FMT_BGRX4);
COMPILE_TIME_ASSERT( 19 == CM_SURF_FMT_BGR5_X1);
COMPILE_TIME_ASSERT( 20 == CM_SURF_FMT_BGRX8);
COMPILE_TIME_ASSERT( 21 == CM_SURF_FMT_BGR10_X2);
COMPILE_TIME_ASSERT( 22 == CM_SURF_FMT_BGRX16);
COMPILE_TIME_ASSERT( 23 == CM_SURF_FMT_BGRX16F);
COMPILE_TIME_ASSERT( 24 == CM_SURF_FMT_BGRX32F);
COMPILE_TIME_ASSERT( 25 == CM_SURF_FMT_RGBX4);
COMPILE_TIME_ASSERT( 26 == CM_SURF_FMT_RGB5_X1);
COMPILE_TIME_ASSERT( 27 == CM_SURF_FMT_RGBX8);
COMPILE_TIME_ASSERT( 28 == CM_SURF_FMT_RGB10_X2);
COMPILE_TIME_ASSERT( 29 == CM_SURF_FMT_RGBX16);
COMPILE_TIME_ASSERT( 30 == CM_SURF_FMT_RGBX16F);
COMPILE_TIME_ASSERT( 31 == CM_SURF_FMT_RGBX32F);
COMPILE_TIME_ASSERT( 32 == CM_SURF_FMT_BGRA4);
COMPILE_TIME_ASSERT( 33 == CM_SURF_FMT_BGR5_A1);
COMPILE_TIME_ASSERT( 34 == CM_SURF_FMT_BGRA8);
COMPILE_TIME_ASSERT( 35 == CM_SURF_FMT_BGR10_A2);
COMPILE_TIME_ASSERT( 36 == CM_SURF_FMT_BGRA16);
COMPILE_TIME_ASSERT( 37 == CM_SURF_FMT_BGRA16F);
COMPILE_TIME_ASSERT( 38 == CM_SURF_FMT_BGRA32F);
COMPILE_TIME_ASSERT( 39 == CM_SURF_FMT_RGBA4);
COMPILE_TIME_ASSERT( 40 == CM_SURF_FMT_RGB5_A1);
COMPILE_TIME_ASSERT( 41 == CM_SURF_FMT_RGBA8);
COMPILE_TIME_ASSERT( 42 == CM_SURF_FMT_RGB10_A2);
COMPILE_TIME_ASSERT( 43 == CM_SURF_FMT_RGBA16);
COMPILE_TIME_ASSERT( 44 == CM_SURF_FMT_RGBA16F);
COMPILE_TIME_ASSERT( 45 == CM_SURF_FMT_RGBA32I);
COMPILE_TIME_ASSERT( 46 == CM_SURF_FMT_RGBA32F);
COMPILE_TIME_ASSERT( 47 == CM_SURF_FMT_DUDV8);
COMPILE_TIME_ASSERT( 48 == CM_SURF_FMT_DXT1);
COMPILE_TIME_ASSERT( 49 == CM_SURF_FMT_DXT2_3);
COMPILE_TIME_ASSERT( 50 == CM_SURF_FMT_DXT4_5);
COMPILE_TIME_ASSERT( 51 == CM_SURF_FMT_ATI1N);
COMPILE_TIME_ASSERT( 52 == CM_SURF_FMT_ATI2N);
COMPILE_TIME_ASSERT( 53 == CM_SURF_FMT_DEPTH16);
COMPILE_TIME_ASSERT( 54 == CM_SURF_FMT_DEPTH16F);
COMPILE_TIME_ASSERT( 55 == CM_SURF_FMT_DEPTH24_X8);
COMPILE_TIME_ASSERT( 56 == CM_SURF_FMT_DEPTH24F_X8);
COMPILE_TIME_ASSERT( 57 == CM_SURF_FMT_DEPTH24_STEN8);
COMPILE_TIME_ASSERT( 58 == CM_SURF_FMT_DEPTH24F_STEN8);
COMPILE_TIME_ASSERT( 59 == CM_SURF_FMT_DEPTH32F_X24_STEN8);
COMPILE_TIME_ASSERT( 60 == CM_SURF_FMT_DEPTH32F);
COMPILE_TIME_ASSERT( 61 == CM_SURF_FMT_sR11_sG11_sB10);
COMPILE_TIME_ASSERT( 62 == CM_SURF_FMT_sU16);
COMPILE_TIME_ASSERT( 63 == CM_SURF_FMT_sUV16);
COMPILE_TIME_ASSERT( 64 == CM_SURF_FMT_sUVWQ16);
COMPILE_TIME_ASSERT( 65 == CM_SURF_FMT_RG16);
COMPILE_TIME_ASSERT( 66 == CM_SURF_FMT_RG16F);
COMPILE_TIME_ASSERT( 67 == CM_SURF_FMT_RG32F);
COMPILE_TIME_ASSERT( 68 == CM_SURF_FMT_ABGR4);
COMPILE_TIME_ASSERT( 69 == CM_SURF_FMT_A1_BGR5);
COMPILE_TIME_ASSERT( 70 == CM_SURF_FMT_ABGR8);
COMPILE_TIME_ASSERT( 71 == CM_SURF_FMT_A2_BGR10);
COMPILE_TIME_ASSERT( 72 == CM_SURF_FMT_ABGR16);
COMPILE_TIME_ASSERT( 73 == CM_SURF_FMT_ABGR16F);
COMPILE_TIME_ASSERT( 74 == CM_SURF_FMT_ABGR32F);
COMPILE_TIME_ASSERT( 75 == CM_SURF_FMT_DXT1A);
COMPILE_TIME_ASSERT( 76 == CM_SURF_FMT_sRGB10_A2);
COMPILE_TIME_ASSERT( 77 == CM_SURF_FMT_sR8);
COMPILE_TIME_ASSERT( 78 == CM_SURF_FMT_sRG8);
COMPILE_TIME_ASSERT( 79 == CM_SURF_FMT_sR32I);
COMPILE_TIME_ASSERT( 80 == CM_SURF_FMT_sRG32I);
COMPILE_TIME_ASSERT( 81 == CM_SURF_FMT_sRGBA32I);
COMPILE_TIME_ASSERT( 82 == CM_SURF_FMT_R32I);
COMPILE_TIME_ASSERT( 83 == CM_SURF_FMT_RG32I);
COMPILE_TIME_ASSERT( 84 == CM_SURF_FMT_RG8);
COMPILE_TIME_ASSERT( 85 == CM_SURF_FMT_sRGBA8);
COMPILE_TIME_ASSERT( 86 == CM_SURF_FMT_R11F_G11F_B10F);
COMPILE_TIME_ASSERT( 87 == CM_SURF_FMT_RGB9_E5);
COMPILE_TIME_ASSERT( 88 == CM_SURF_FMT_LUMINANCE_LATC1);
COMPILE_TIME_ASSERT( 89 == CM_SURF_FMT_SIGNED_LUMINANCE_LATC1);
COMPILE_TIME_ASSERT( 90 == CM_SURF_FMT_LUMINANCE_ALPHA_LATC2);
COMPILE_TIME_ASSERT( 91 == CM_SURF_FMT_SIGNED_LUMINANCE_ALPHA_LATC2);
COMPILE_TIME_ASSERT( 92 == CM_SURF_FMT_RED_RGTC1);
COMPILE_TIME_ASSERT( 93 == CM_SURF_FMT_SIGNED_RED_RGTC1);
COMPILE_TIME_ASSERT( 94 == CM_SURF_FMT_RED_GREEN_RGTC2);
COMPILE_TIME_ASSERT( 95 == CM_SURF_FMT_SIGNED_RED_GREEN_RGTC2);
COMPILE_TIME_ASSERT( 96 == CM_SURF_FMT_R8);
COMPILE_TIME_ASSERT( 97 == CM_SURF_FMT_R16);
COMPILE_TIME_ASSERT( 98 == CM_SURF_FMT_R16F);
COMPILE_TIME_ASSERT( 99 == CM_SURF_FMT_R32F);
COMPILE_TIME_ASSERT(100 == CM_SURF_FMT_R8I);
COMPILE_TIME_ASSERT(101 == CM_SURF_FMT_sR8I);
COMPILE_TIME_ASSERT(102 == CM_SURF_FMT_RG8I);
COMPILE_TIME_ASSERT(103 == CM_SURF_FMT_sRG8I);
COMPILE_TIME_ASSERT(104 == CM_SURF_FMT_R16I);
COMPILE_TIME_ASSERT(105 == CM_SURF_FMT_sR16I);
COMPILE_TIME_ASSERT(106 == CM_SURF_FMT_RG16I);
COMPILE_TIME_ASSERT(107 == CM_SURF_FMT_sRG16I);
COMPILE_TIME_ASSERT(108 == CM_SURF_FMT_RGBA32UI);
COMPILE_TIME_ASSERT(109 == CM_SURF_FMT_RGBX32UI);
COMPILE_TIME_ASSERT(110 == CM_SURF_FMT_ALPHA32UI);
COMPILE_TIME_ASSERT(111 == CM_SURF_FMT_INTENSITY32UI);
COMPILE_TIME_ASSERT(112 == CM_SURF_FMT_LUMINANCE32UI);
COMPILE_TIME_ASSERT(113 == CM_SURF_FMT_LUMINANCE_ALPHA32UI);
COMPILE_TIME_ASSERT(114 == CM_SURF_FMT_RGBA16UI);
COMPILE_TIME_ASSERT(115 == CM_SURF_FMT_RGBX16UI);
COMPILE_TIME_ASSERT(116 == CM_SURF_FMT_ALPHA16UI);
COMPILE_TIME_ASSERT(117 == CM_SURF_FMT_INTENSITY16UI);
COMPILE_TIME_ASSERT(118 == CM_SURF_FMT_LUMINANCE16UI);
COMPILE_TIME_ASSERT(119 == CM_SURF_FMT_LUMINANCE_ALPHA16UI);
COMPILE_TIME_ASSERT(120 == CM_SURF_FMT_RGBA8UI);
COMPILE_TIME_ASSERT(121 == CM_SURF_FMT_RGBX8UI);
COMPILE_TIME_ASSERT(122 == CM_SURF_FMT_ALPHA8UI);
COMPILE_TIME_ASSERT(123 == CM_SURF_FMT_INTENSITY8UI);
COMPILE_TIME_ASSERT(124 == CM_SURF_FMT_LUMINANCE8UI);
COMPILE_TIME_ASSERT(125 == CM_SURF_FMT_LUMINANCE_ALPHA8UI);
COMPILE_TIME_ASSERT(126 == CM_SURF_FMT_sRGBA32I_EXT);
COMPILE_TIME_ASSERT(127 == CM_SURF_FMT_sRGBX32I);
COMPILE_TIME_ASSERT(128 == CM_SURF_FMT_sALPHA32I);
COMPILE_TIME_ASSERT(129 == CM_SURF_FMT_sINTENSITY32I);
COMPILE_TIME_ASSERT(130 == CM_SURF_FMT_sLUMINANCE32I);
COMPILE_TIME_ASSERT(131 == CM_SURF_FMT_sLUMINANCE_ALPHA32I);
COMPILE_TIME_ASSERT(132 == CM_SURF_FMT_sRGBA16I);
COMPILE_TIME_ASSERT(133 == CM_SURF_FMT_sRGBX16I);
COMPILE_TIME_ASSERT(134 == CM_SURF_FMT_sALPHA16I);
COMPILE_TIME_ASSERT(135 == CM_SURF_FMT_sINTENSITY16I);
COMPILE_TIME_ASSERT(136 == CM_SURF_FMT_sLUMINANCE16I);
COMPILE_TIME_ASSERT(137 == CM_SURF_FMT_sLUMINANCE_ALPHA16I);
COMPILE_TIME_ASSERT(138 == CM_SURF_FMT_sRGBA8I);
COMPILE_TIME_ASSERT(139 == CM_SURF_FMT_sRGBX8I);
COMPILE_TIME_ASSERT(140 == CM_SURF_FMT_sALPHA8I);
COMPILE_TIME_ASSERT(141 == CM_SURF_FMT_sINTENSITY8I);
COMPILE_TIME_ASSERT(142 == CM_SURF_FMT_sLUMINANCE8I);
COMPILE_TIME_ASSERT(143 == CM_SURF_FMT_sLUMINANCE_ALPHA8I);
COMPILE_TIME_ASSERT(144 == CM_SURF_FMT_sDXT6);
COMPILE_TIME_ASSERT(145 == CM_SURF_FMT_DXT6);
COMPILE_TIME_ASSERT(146 == CM_SURF_FMT_DXT7);
COMPILE_TIME_ASSERT(147 == CM_SURF_FMT_LUMINANCE8_SNORM);
COMPILE_TIME_ASSERT(148 == CM_SURF_FMT_LUMINANCE16_SNORM);
COMPILE_TIME_ASSERT(149 == CM_SURF_FMT_INTENSITY8_SNORM);
COMPILE_TIME_ASSERT(150 == CM_SURF_FMT_INTENSITY16_SNORM);
COMPILE_TIME_ASSERT(151 == CM_SURF_FMT_ALPHA8_SNORM);
COMPILE_TIME_ASSERT(152 == CM_SURF_FMT_ALPHA16_SNORM);
COMPILE_TIME_ASSERT(153 == CM_SURF_FMT_LUMINANCE_ALPHA8_SNORM);
COMPILE_TIME_ASSERT(154 == CM_SURF_FMT_LUMINANCE_ALPHA16_SNORM);
COMPILE_TIME_ASSERT(155 == CM_SURF_FMT_R8_SNORM);
COMPILE_TIME_ASSERT(156 == CM_SURF_FMT_R16_SNORM);
COMPILE_TIME_ASSERT(157 == CM_SURF_FMT_RG8_SNORM);
COMPILE_TIME_ASSERT(158 == CM_SURF_FMT_RG16_SNORM);
COMPILE_TIME_ASSERT(159 == CM_SURF_FMT_RGBX8_SNORM);
COMPILE_TIME_ASSERT(160 == CM_SURF_FMT_RGBX16_SNORM);
COMPILE_TIME_ASSERT(161 == CM_SURF_FMT_RGBA8_SNORM);
COMPILE_TIME_ASSERT(162 == CM_SURF_FMT_RGBA16_SNORM);
COMPILE_TIME_ASSERT(163 == CM_SURF_FMT_RGB10_A2UI);
COMPILE_TIME_ASSERT(164 == CM_SURF_FMT_RGB32F);
COMPILE_TIME_ASSERT(165 == CM_SURF_FMT_RGB32I);
COMPILE_TIME_ASSERT(166 == CM_SURF_FMT_RGB32UI);
COMPILE_TIME_ASSERT(167 == CM_SURF_FMT_RGBX8_SRGB);
COMPILE_TIME_ASSERT(168 == CM_SURF_FMT_RGBA8_SRGB);
COMPILE_TIME_ASSERT(169 == CM_SURF_FMT_DXT1_SRGB);
COMPILE_TIME_ASSERT(170 == CM_SURF_FMT_DXT1A_SRGB);
COMPILE_TIME_ASSERT(171 == CM_SURF_FMT_DXT2_3_SRGB);
COMPILE_TIME_ASSERT(172 == CM_SURF_FMT_DXT4_5_SRGB);
COMPILE_TIME_ASSERT(173 == CM_SURF_FMT_DXT7_SRGB);
COMPILE_TIME_ASSERT(174 == CM_SURF_FMT_RGB8_ETC2);
COMPILE_TIME_ASSERT(175 == CM_SURF_FMT_SRGB8_ETC2);
COMPILE_TIME_ASSERT(176 == CM_SURF_FMT_RGB8_PT_ALPHA1_ETC2);
COMPILE_TIME_ASSERT(177 == CM_SURF_FMT_SRGB8_PT_ALPHA1_ETC2);
COMPILE_TIME_ASSERT(178 == CM_SURF_FMT_RGBA8_ETC2_EAC);
COMPILE_TIME_ASSERT(179 == CM_SURF_FMT_SRGB8_ALPHA8_ETC2_EAC);
COMPILE_TIME_ASSERT(180 == CM_SURF_FMT_R11_EAC);
COMPILE_TIME_ASSERT(181 == CM_SURF_FMT_SIGNED_R11_EAC);
COMPILE_TIME_ASSERT(182 == CM_SURF_FMT_RG11_EAC);
COMPILE_TIME_ASSERT(183 == CM_SURF_FMT_SIGNED_RG11_EAC);
COMPILE_TIME_ASSERT(184 == CM_SURF_FMT_BGR10_A2UI);
COMPILE_TIME_ASSERT(185 == CM_SURF_FMT_A2_BGR10UI);
COMPILE_TIME_ASSERT(186 == CM_SURF_FMT_A2_RGB10UI);
COMPILE_TIME_ASSERT(187 == CM_SURF_FMT_B5_G6_R5UI);
COMPILE_TIME_ASSERT(188 == CM_SURF_FMT_R5_G6_B5UI);
COMPILE_TIME_ASSERT(189 == CM_SURF_FMT_DEPTH32F_X24_STEN8_UNCLAMPED);
COMPILE_TIME_ASSERT(190 == CM_SURF_FMT_DEPTH32F_UNCLAMPED);
COMPILE_TIME_ASSERT(191 == CM_SURF_FMT_L8_X16_A8_SRGB);
COMPILE_TIME_ASSERT(192 == CM_SURF_FMT_L8_X24_SRGB);
COMPILE_TIME_ASSERT(193 == CM_SURF_FMT_STENCIL8);
COMPILE_TIME_ASSERT(cmSurfFmt_LAST == CM_SURF_FMT_STENCIL8);
COMPILE_TIME_ASSERT(cmSurfFmt_LAST < 501);
}
#ifdef ATI_OS_LINUX
typedef void* (*PFNGlxGetProcAddress)(const GLubyte* procName);
static PFNGlxGetProcAddress pfnGlxGetProcAddress=NULL;
static PFNGLXBEGINCLINTEROPAMD glXBeginCLInteropAMD = NULL;
static PFNGLXENDCLINTEROPAMD glXEndCLInteropAMD = NULL;
static PFNGLXRESOURCEATTACHAMD glXResourceAttachAMD = NULL;
static PFNGLXRESOURCEDETACHAMD glxResourceAcquireAMD = NULL;
static PFNGLXRESOURCEDETACHAMD glxResourceReleaseAMD = NULL;
static PFNGLXRESOURCEDETACHAMD glXResourceDetachAMD = NULL;
static PFNGLXGETCONTEXTMVPUINFOAMD glXGetContextMVPUInfoAMD = NULL;
#else
static PFNWGLBEGINCLINTEROPAMD wglBeginCLInteropAMD = NULL;
static PFNWGLENDCLINTEROPAMD wglEndCLInteropAMD = NULL;
static PFNWGLRESOURCEATTACHAMD wglResourceAttachAMD = NULL;
static PFNWGLRESOURCEDETACHAMD wglResourceAcquireAMD = NULL;
static PFNWGLRESOURCEDETACHAMD wglResourceReleaseAMD = NULL;
static PFNWGLRESOURCEDETACHAMD wglResourceDetachAMD = NULL;
static PFNWGLGETCONTEXTGPUINFOAMD wglGetContextGPUInfoAMD = NULL;
#endif
void
CALGSLDevice::initGLInteropPrivateExt(CALvoid* GLplatformContext, CALvoid* GLdeviceContext) const
{
#ifdef ATI_OS_LINUX
GLXContext ctx = (GLXContext)GLplatformContext;
void * pModule = dlopen("libGL.so.1",RTLD_NOW);
if(NULL == pModule){
return;
}
pfnGlxGetProcAddress = (PFNGlxGetProcAddress) dlsym(pModule,"glXGetProcAddress");
if (NULL == pfnGlxGetProcAddress){
return;
}
if (!glXBeginCLInteropAMD || !glXEndCLInteropAMD || !glXResourceAttachAMD || !glXResourceDetachAMD || !glXGetContextMVPUInfoAMD)
{
glXBeginCLInteropAMD = (PFNGLXBEGINCLINTEROPAMD) pfnGlxGetProcAddress ((const GLubyte *)"glXBeginCLInteroperabilityAMD");
glXEndCLInteropAMD = (PFNGLXENDCLINTEROPAMD) pfnGlxGetProcAddress ((const GLubyte *)"glXEndCLInteroperabilityAMD");
glXResourceAttachAMD = (PFNGLXRESOURCEATTACHAMD) pfnGlxGetProcAddress ((const GLubyte *)"glXResourceAttachAMD");
glxResourceAcquireAMD = (PFNGLXRESOURCEDETACHAMD) pfnGlxGetProcAddress ((const GLubyte *)"glXResourceAcquireAMD");
glxResourceReleaseAMD = (PFNGLXRESOURCEDETACHAMD) pfnGlxGetProcAddress ((const GLubyte *)"glXResourceReleaseAMD");
glXResourceDetachAMD = (PFNGLXRESOURCEDETACHAMD) pfnGlxGetProcAddress ((const GLubyte *)"glXResourceDetachAMD");
glXGetContextMVPUInfoAMD = (PFNGLXGETCONTEXTMVPUINFOAMD) pfnGlxGetProcAddress ((const GLubyte *)"glXGetContextMVPUInfoAMD");
}
#else
if (!wglBeginCLInteropAMD || !wglEndCLInteropAMD || !wglResourceAttachAMD || !wglResourceDetachAMD || !wglGetContextGPUInfoAMD)
{
HGLRC fakeRC = NULL;
if (!wglGetCurrentContext())
{
fakeRC = wglCreateContext((HDC)GLdeviceContext);
wglMakeCurrent((HDC)GLdeviceContext, fakeRC);
}
wglBeginCLInteropAMD = (PFNWGLBEGINCLINTEROPAMD) wglGetProcAddress ("wglBeginCLInteroperabilityAMD");
wglEndCLInteropAMD = (PFNWGLENDCLINTEROPAMD) wglGetProcAddress ("wglEndCLInteroperabilityAMD");
wglResourceAttachAMD = (PFNWGLRESOURCEATTACHAMD) wglGetProcAddress ("wglResourceAttachAMD");
wglResourceAcquireAMD = (PFNWGLRESOURCEDETACHAMD) wglGetProcAddress ("wglResourceAcquireAMD");
wglResourceReleaseAMD = (PFNWGLRESOURCEDETACHAMD) wglGetProcAddress ("wglResourceReleaseAMD");
wglResourceDetachAMD = (PFNWGLRESOURCEDETACHAMD) wglGetProcAddress ("wglResourceDetachAMD");
wglGetContextGPUInfoAMD = (PFNWGLGETCONTEXTGPUINFOAMD) wglGetProcAddress ("wglGetContextGPUInfoAMD");
if (fakeRC)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(fakeRC);
}
}
#endif
}
bool
CALGSLDevice::glCanInterop(CALvoid* GLplatformContext, CALvoid* GLdeviceContext)
{
bool canInteroperate = false;
#ifdef ATI_OS_WIN
LUID glAdapterLuid = {0, 0};
UINT glChainBitMask = 0;
LUID calAdapterLuid = {0, 0};
UINT calChainBitMask = 0;
HGLRC hRC = (HGLRC)GLplatformContext;
//get GL context's LUID and chainBitMask from UGL
if (wglGetContextGPUInfoAMD && wglGetContextGPUInfoAMD(hRC, &glAdapterLuid, &glChainBitMask))
{
//now check against the CAL device' LUID and chainBitMask.
if (m_adp->getMVPUinfo(&calAdapterLuid, &calChainBitMask))
{
canInteroperate = ((glAdapterLuid.HighPart == calAdapterLuid.HighPart) &&
(glAdapterLuid.LowPart == calAdapterLuid.LowPart) &&
(glChainBitMask == calChainBitMask));
}
}
#elif defined (ATI_OS_LINUX)
//if the extension is supported by the base driver
if (NULL != glXGetContextMVPUInfoAMD)
{
GLuint glDeviceId = 0 ;
GLuint glChainMask = 0 ;
GLXContext ctx = (GLXContext)GLplatformContext;
if ( glXGetContextMVPUInfoAMD(ctx,&glDeviceId,&glChainMask)){
GLuint deviceId = 0 ;
GLuint chainMask = 0 ;
if (m_adp->getMVPUinfo(&deviceId, &chainMask))
{
// we allow intoperability only with GL context
// reside on a single GPU
if (deviceId == glDeviceId && chainMask == glChainMask){
canInteroperate = true;
}
}
}
}
#endif
return canInteroperate;
}
bool
CALGSLDevice::glAssociate(CALvoid* GLplatformContext, CALvoid* GLdeviceContext)
{
//initialize pointers to the gl extension that supports interoperability
initGLInteropPrivateExt(GLplatformContext, GLdeviceContext);
bool canInterop = glCanInterop(GLplatformContext, GLdeviceContext);
#ifdef ATI_OS_LINUX
GLXContext ctx = (GLXContext)GLplatformContext;
if (canInterop && glXBeginCLInteropAMD && glXBeginCLInteropAMD(ctx, 0))
{
return true;
}
#else
HGLRC hRC = (HGLRC)GLplatformContext;
if (canInterop && wglBeginCLInteropAMD && wglBeginCLInteropAMD(hRC, 0))
{
return true;
}
#endif
return false;
}
bool
CALGSLDevice::glDissociate(CALvoid* GLplatformContext, CALvoid* GLdeviceContext)
{
initGLInteropPrivateExt(GLplatformContext, GLdeviceContext);
#ifdef ATI_OS_LINUX
GLXContext ctx = (GLXContext)GLplatformContext;
if(glXEndCLInteropAMD && glXEndCLInteropAMD(ctx, 0))
{
return true;
}
#else
HGLRC hRC = (HGLRC)GLplatformContext;
if (wglEndCLInteropAMD && wglEndCLInteropAMD(hRC, 0))
{
return true;
}
#endif
return false;
}
bool
CALGSLDevice::resGLAssociate(GLResAssociate & resData) const
{
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
GLResource hRes = {0};
bool status = false;
cmSurfFmt cal_cmFormat;
uint32 depth;
gslMemObjectAttribs attribs(
GSL_MOA_TEXTURE_2D, // type
GSL_MOA_MEMORY_ALIAS, // location
GSL_MOA_TILING_TILED, // tiling
GSL_MOA_DISPLAYABLE_NO, // displayable
ATIGL_FALSE, // mipmap
1, // samples
0, // cpu_address
GSL_MOA_SIGNED_NO, // signed_format
GSL_MOA_FORMAT_DERIVED, // numFormat
DRIVER_MODULE_GLL, // module
GSL_ALLOCATION_INSTANCED // alloc_type
);
switch(resData.type)
{
case CAL_RES_GL_BUFFER_TYPE_TEXTURE:
hRes.type = GL_RESOURCE_ATTACH_TEXTURE_AMD;
break;
case CAL_RES_GL_BUFFER_TYPE_FRAMEBUFFER:
hRes.type = GL_RESOURCE_ATTACH_FRAMEBUFFER_AMD;
break;
case CAL_RES_GL_BUFFER_TYPE_RENDERBUFFER:
hRes.type = GL_RESOURCE_ATTACH_RENDERBUFFER_AMD;
break;
case CAL_RES_GL_BUFFER_TYPE_VERTEXBUFFER:
hRes.type = GL_RESOURCE_ATTACH_VERTEXBUFFER_AMD;
break;
default:
return false;
}
GLResourceData* hData = new GLResourceData;
if (NULL == hData)
{
return false;
}
memset(hData, 0, sizeof(GLResourceData));
hRes.name = resData.name;
hRes.flags = resData.flags;
hData->version = GL_RESOURCE_DATA_VERSION;
initGLInteropPrivateExt(resData.GLContext, resData.GLdeviceContext);
#ifdef ATI_OS_LINUX
GLXContext ctx = (GLXContext)resData.GLContext;
if (glXResourceAttachAMD && glXResourceAttachAMD(ctx, &hRes, hData))
{
attribs.dynamicSharedBufferID = hData->sharedBufferID ;
status = true;
}
#else
HGLRC hRC = (HGLRC)resData.GLContext;
if (wglResourceAttachAMD && wglResourceAttachAMD(hRC, &hRes, hData))
{
status = true;
}
#endif
if (!status)
{
return false;
}
// for now, to be safe, allow only textures to have a depth other than 1
if (hRes.type == GL_RESOURCE_ATTACH_TEXTURE_AMD)
{
depth = hData->rawDimensions.depth;
}
else
{
depth = 1;
}
attribs.type = static_cast<gslMemObjectAttribType>(hData->objectAttribType);
osAssert(depth <= GLRDATA_MAX_LAYERS);
osAssert(depth >= 1);
attribs.alias_swizzles = (uint32*)malloc(depth * 2 * sizeof(uint32));
osAssert(attribs.alias_swizzles);
memcpy (attribs.alias_swizzles, hData->swizzles, sizeof(uint32) * depth);
if (hData->levels > 1)
{
attribs.mipmap = ATIGL_TRUE;
attribs.levels = static_cast<GLuint>(hData->levels);
memcpy (&attribs.alias_swizzles[depth], hData->swizzlesMip, sizeof(uint32) * depth);
}
attribs.cpu_address = (void*)hData->handle;
attribs.alias_subtile = hData->tilingMode;
attribs.mcaddress = hData->cardAddr;
// VBOs are hardcoded to have a UINT8 type format
if (hRes.type == GL_RESOURCE_ATTACH_VERTEXBUFFER_AMD)
{
hData->format = CM_SURF_FMT_LUMINANCE8;
}
// CAL supports only a limited number of cm_surf formats, so we
// have to translate incoming cm_surf formats
uint32 index = hData->format - (uint32)CM_SURF_FMT_LUMINANCE8;
if (index >= sizeof(cmFormatXlateTable)/sizeof(cmFormatXlateParams))
{
free(attribs.alias_swizzles);
delete hData;
return false;
}
osAssert(static_cast<cmSurfFmt>(hData->format) == cmFormatXlateTable[index].raw_cmFormat);
cal_cmFormat = cmFormatXlateTable[index].cal_cmFormat;
if (cal_cmFormat == 500)
{
free(attribs.alias_swizzles);
delete hData;
return false; // format is not supported by CAL
}
attribs.channelOrder = cmFormatXlateTable[index].channelOrder;
attribs.alias_perSurfTileInfo = hData->perSurfTileInfo;
attribs.alias_GLInterop = ATIGL_TRUE;
attribs.numFormat = GSL_MOA_FORMAT_DERIVED;
gslMemObject mem;
if (hData->offset != 0)
{
osAssert((hData->rawDimensions.height == 1) && (depth == 1));
mem = m_cs->createMemObject2D(CM_SURF_FMT_LUMINANCE8, hData->surfaceSize, 1, &attribs);
}
else
{
mem = m_cs->createMemObject3D(cal_cmFormat, hData->paddedDimensions.width,
hData->rawDimensions.height, depth, &attribs);
}
if (hRes.type == GL_RESOURCE_ATTACH_VERTEXBUFFER_AMD)
{
attribs.tiling = mem->getAttribs().tiling;
resData.mem_base = mem;
mem = m_cs->createOffsetMemObject2D(resData.mem_base, (static_cast<uintp>(hData->offset)),
cal_cmFormat,
hData->paddedDimensions.width,
1, &attribs);
}
else if ((hData->offset != 0) && (hData->rawDimensions.height == 1) && (depth == 1))
{
resData.mem_base = mem;
attribs.tiling = mem->getAttribs().tiling;
mem = m_cs->createOffsetMemObject3D(resData.mem_base, (static_cast<uintp>(hData->offset)),
cal_cmFormat, hData->paddedDimensions.width,
hData->rawDimensions.height, depth, &attribs);
}
free (attribs.alias_swizzles);
resData.mbResHandle = (CALvoid*)hData->mbResHandle;
resData.memObject = mem;
delete hData;
return mem != 0;
}
bool
CALGSLDevice::resGLAcquire(CALvoid* GLplatformContext,
CALvoid* mbResHandle,
CALuint type) const
{
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
GLResource hRes;
osAssert(mbResHandle);
hRes.mbResHandle = (GLuintp)mbResHandle;
switch(type)
{
case CAL_RES_GL_BUFFER_TYPE_TEXTURE:
hRes.type = GL_RESOURCE_ATTACH_TEXTURE_AMD;
break;
case CAL_RES_GL_BUFFER_TYPE_RENDERBUFFER:
hRes.type = GL_RESOURCE_ATTACH_RENDERBUFFER_AMD;
break;
break;
default:
return false;
}
bool status = false;
#ifdef ATI_OS_LINUX
GLXContext ctx = (GLXContext) GLplatformContext;
if (glxResourceAcquireAMD && glxResourceAcquireAMD(ctx, &hRes))
{
status = true;
}
#else
HGLRC hRC = wglGetCurrentContext();
if ( wglResourceAcquireAMD && wglResourceAcquireAMD(hRC, &hRes))
{
status = true;
}
#endif
return status;
}
bool
CALGSLDevice::resGLRelease(CALvoid* GLplatformContext,
CALvoid* mbResHandle) const
{
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
GLResource hRes;
osAssert(mbResHandle);
bool status = false;
hRes.mbResHandle = (GLuintp)mbResHandle;
#ifdef ATI_OS_LINUX
//TODO : make sure the application GL context is current. if not no
// point calling into the GL RT.
GLXContext ctx = (GLXContext) GLplatformContext;
if ((0 != ctx) && glxResourceReleaseAMD && glxResourceReleaseAMD(ctx, &hRes))
{
status = true;
}
#else
//make the call into the GL driver only if the application GL context is current
HGLRC hRC = wglGetCurrentContext();
if ( (0 != hRC) && wglResourceReleaseAMD && wglResourceReleaseAMD(hRC, &hRes))
{
status = true;
}
#endif
return status;
}
bool
CALGSLDevice::resGLFree (
CALvoid* GLplatformContext,
CALvoid* GLdeviceContext,
gslMemObject mem,
gslMemObject mem_base,
CALvoid* mbResHandle,
CALuint type) const
{
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
GLResource hRes;
osAssert(mbResHandle);
hRes.mbResHandle = (GLuintp)mbResHandle;
switch(type)
{
case CAL_RES_GL_BUFFER_TYPE_TEXTURE:
hRes.type = GL_RESOURCE_ATTACH_TEXTURE_AMD;
break;
case CAL_RES_GL_BUFFER_TYPE_FRAMEBUFFER:
hRes.type = GL_RESOURCE_ATTACH_FRAMEBUFFER_AMD;
break;
case CAL_RES_GL_BUFFER_TYPE_RENDERBUFFER:
hRes.type = GL_RESOURCE_ATTACH_RENDERBUFFER_AMD;
break;
case CAL_RES_GL_BUFFER_TYPE_VERTEXBUFFER:
hRes.type = GL_RESOURCE_ATTACH_VERTEXBUFFER_AMD;
break;
default:
return false;
}
initGLInteropPrivateExt(GLplatformContext, GLdeviceContext);
#ifdef ATI_OS_LINUX
GLXContext ctx = (GLXContext)GLplatformContext;
if (!glXResourceDetachAMD || !glXResourceDetachAMD(ctx, &hRes))
{
return true;
}
#else
HGLRC hRC = (HGLRC)GLplatformContext;
if (!wglResourceDetachAMD || !wglResourceDetachAMD(hRC, &hRes))
{
return false;
}
#endif
m_cs->Flush();
if (mem_base)
{
m_cs->destroyMemObject(mem_base);
}
m_cs->destroyMemObject(mem);
return true;
};
@@ -0,0 +1,9 @@
#include <X11/Xlib.h>
#include "GSLDevice.h"
#include <stdio.h>
void CALGSLDevice::closeNativeDisplayHandle()
{
//do nothing native handle should be close by lower layers
}
@@ -0,0 +1,9 @@
#include "gsl_ctx.h"
#include "GSLDevice.h"
#include <windows.h>
void CALGSLDevice::closeNativeDisplayHandle()
{
DeleteDC((HDC)m_nativeDisplayHandle);
m_nativeDisplayHandle = NULL;
}
@@ -0,0 +1,134 @@
#include "os_if.h"
#include "osws_if.h"
#include "atidefines.h"
#include "atitypes.h"
#include "scl_types.h"
#include "SCInterface.h"
//
// This file represents the entry points that are stubbed out to satisfy the
// linker, but aren't used in the runtime of GSL operations.
//
enum fsComponentType {
FS_BYTE,
FS_UNSIGNED_BYTE,
FS_SHORT,
FS_UNSIGNED_SHORT,
FS_INT,
FS_UNSIGNED_INT,
FS_FLOAT,
FS_FLOAT16,
};
enum fsInstrSet {
FS_INSTR_KHAN, ///< Generate Khan based instruction set
FS_INSTR_PELE ///< Generate Pele based instruction set
};
enum fsUsage {
FS_USAGE_HW, ///< An actual hardware stream
FS_USAGE_SW ///< A place holder stream (to support SW path)
};
struct fsInstr {
fsUsage usage; ///< How the stream is going to be used (place holder or actual hardware stream)
uint32 components; ///< Number of components to the input vector
fsComponentType type; ///< Type of each component
bool32 normalize; ///< Should the components be normalized to the -1..1 range
uint32 stride; ///< Stride between vectors
uint32 ivmOffset; ///< location in input vector memory
};
sclHandle CONV
sclInit(const sclShaderConstantAddress* shaderStateConstTable,
const sclProfile& profile,
const sclLimits& fpLimits,
const sclLimits& vpLimits)
{
return 0;
}
void CONV
sclDestroy(sclHandle hSCL)
{
}
sclProgram* CONV
sclCompile(sclHandle hSCL,
const sclInputShader& shader,
const sclCompilerParams& params,
const sclLimits& limits)
{
return 0;
}
sclProgramPair* CONV
sclLink(sclHandle hSCL,
const sclInputMultShaderPair *shader,
const sclCompilerParams& params,
const sclLimits& fpLimits,
const sclLimits& vpLimits)
{
return 0;
}
void CONV
sclFreeProgram(sclHandle hSCL,
sclProgram* program)
{
}
sclShaderReplaceHandle CONV
sclRegisterShaderString(sclHandle hSCL,
const sclInputShader& src,
const sclInputShader& dst)
{
return 0;
}
void CONV
sclUnregisterShaderString(sclHandle hSCL,
sclShaderReplaceHandle hReplacement)
{
}
bool32 CONV
fsCompile(fsInstrSet instrSet,
uint32 instrCount,
const fsInstr* instr,
void*& binary,
uint32& length,
bool32 dumpShader,
bool32 doCacheOpt,
const sclCompilerParamTessellation& tessParams)
{
return ATIGL_TRUE;
}
void CONV
fsFreeBinary(void* binary)
{
}
void CONV
oswsInit(HOSInstance hOSInst)
{
//
// do nothing...
//
}
void CONV
oswsExit()
{
//
// do nothing...
//
}
@@ -0,0 +1,206 @@
#include "gsl_ctx.h"
#include "GSLContext.h"
#include "backend.h"
#include "GSLDevice.h"
#include "os_if.h"
#include <stdlib.h>
#ifdef ATI_OS_LINUX
#include <X11/Xlib.h>
#endif
#include "amuABI.h"
bool
getFuncInfoFromImage(CALimage image, CALfuncInfo *pFuncInfo)
{
if (image == 0)
{
return false;
}
if (pFuncInfo == 0)
{
return false;
}
//Initialize the pFuncInfo
pFuncInfo->maxScratchRegsNeeded = 0;
pFuncInfo->numSharedGPRUser = 0;
pFuncInfo->numSharedGPRTotal = 0;
pFuncInfo->eCsSetupMode = false;
pFuncInfo->numThreadPerGroup = 0;
pFuncInfo->numThreadPerGroupX = 0;
pFuncInfo->numThreadPerGroupY = 0;
pFuncInfo->numThreadPerGroupZ = 0;
pFuncInfo->totalNumThreadGroup = 0;
pFuncInfo->numWavefrontPerSIMD = 0;
pFuncInfo->isMaxNumWavePerSIMD = false;
pFuncInfo->setBufferForNumGroup = false;
pFuncInfo->wavefrontSize = 0;
pFuncInfo->numGPRsAvailable = 0;
pFuncInfo->numGPRsUsed = 0;
pFuncInfo->numSGPRsAvailable = 0;
pFuncInfo->numSGPRsUsed = 0;
pFuncInfo->numVGPRsAvailable = 0;
pFuncInfo->numVGPRsUsed = 0;
pFuncInfo->LDSSizeAvailable = 0;
pFuncInfo->LDSSizeUsed = 0;
pFuncInfo->stackSizeAvailable = 0;
pFuncInfo->stackSizeUsed = 0;
//read data from image file
AMUabiMultiBinary mb;
amuABIMultiBinaryCreate(&mb);
if (!amuABIMultiBinaryUnpack(mb, (void*) image))
{
amuABIMultiBinaryDestroy(mb);
return false;
}
unsigned int encodingCount;
if (!amuABIMultiBinaryGetEncodingCount(&encodingCount, mb))
{
amuABIMultiBinaryDestroy(mb);
return false;
}
AMUabiEncoding encoding;
//get encoding info for the first encoding
if ((encodingCount > 0)&& !amuABIMultiBinaryGetEncoding( &encoding, mb, 0))
{
amuABIMultiBinaryDestroy(mb);
return false;
}
unsigned int machine, type;
if (!amuABIEncodingGetSignature(&machine, &type, encoding))
{
amuABIMultiBinaryDestroy(mb);
return false;
}
if (!amuABIMultiBinaryFindEncoding(&encoding, mb, machine, type))
{
amuABIMultiBinaryDestroy(mb);
return false;
}
unsigned int progInfosCount = 0;
CALProgramInfoEntry* pInfos = 0;
if (!amuABIEncodingGetProgInfos(&progInfosCount, &pInfos, encoding))
{
amuABIMultiBinaryDestroy(mb);
return false;
}
for (CALuint i =0; i < progInfosCount; i++)
{
switch(pInfos[i].address)
{
case AMU_ABI_CS_MAX_SCRATCH_REGS:
pFuncInfo->maxScratchRegsNeeded = pInfos[i].value;
break;
case AMU_ABI_CS_NUM_SHARED_GPR_USER:
pFuncInfo->numSharedGPRUser = pInfos[i].value;
break;
case AMU_ABI_CS_NUM_SHARED_GPR_TOTAL:
pFuncInfo->numSharedGPRTotal = pInfos[i].value;
break;
case AMU_ABI_ECS_SETUP_MODE:
pFuncInfo->eCsSetupMode = (0 != pInfos[i].value) ? true : false;
break;
case AMU_ABI_NUM_THREAD_PER_GROUP:
pFuncInfo->numThreadPerGroup = pInfos[i].value;
break;
case AMU_ABI_NUM_THREAD_PER_GROUP_X:
pFuncInfo->numThreadPerGroupX = pInfos[i].value;
break;
case AMU_ABI_NUM_THREAD_PER_GROUP_Y:
pFuncInfo->numThreadPerGroupY = pInfos[i].value;
break;
case AMU_ABI_NUM_THREAD_PER_GROUP_Z:
pFuncInfo->numThreadPerGroupZ = pInfos[i].value;
break;
case AMU_ABI_TOTAL_NUM_THREAD_GROUP:
pFuncInfo->totalNumThreadGroup = pInfos[i].value;
break;
case AMU_ABI_NUM_WAVEFRONT_PER_SIMD:
case AMU_ABI_MAX_WAVEFRONT_PER_SIMD: //CAL_USE_SC_PRM
pFuncInfo->numWavefrontPerSIMD = pInfos[i].value;
break;
case AMU_ABI_IS_MAX_NUM_WAVE_PER_SIMD:
pFuncInfo->isMaxNumWavePerSIMD = (0 != pInfos[i].value) ? true : false;
break;
case AMU_ABI_SET_BUFFER_FOR_NUM_GROUP:
pFuncInfo->setBufferForNumGroup = (0 != pInfos[i].value) ? true : false;
break;
case AMU_ABI_WAVEFRONT_SIZE:
pFuncInfo->wavefrontSize = pInfos[i].value;
break;
case AMU_ABI_NUM_GPR_AVAIL:
pFuncInfo->numGPRsAvailable = pInfos[i].value;
break;
case AMU_ABI_NUM_GPR_USED:
pFuncInfo->numGPRsUsed = pInfos[i].value;
break;
case AMU_ABI_LDS_SIZE_AVAIL:
pFuncInfo->LDSSizeAvailable = pInfos[i].value;
break;
case AMU_ABI_LDS_SIZE_USED:
pFuncInfo->LDSSizeUsed = pInfos[i].value;
break;
case AMU_ABI_STACK_SIZE_AVAIL:
pFuncInfo->stackSizeAvailable = pInfos[i].value;
break;
case AMU_ABI_STACK_SIZE_USED:
pFuncInfo->stackSizeUsed = pInfos[i].value;
break;
case AMU_ABI_SI_NUM_SGPRS_AVAIL:
pFuncInfo->numSGPRsAvailable = pInfos[i].value;
break;
case AMU_ABI_SI_NUM_SGPRS:
pFuncInfo->numSGPRsUsed = pInfos[i].value;
break;
case AMU_ABI_SI_NUM_VGPRS_AVAIL:
pFuncInfo->numVGPRsAvailable = pInfos[i].value;
break;
case AMU_ABI_SI_NUM_VGPRS:
pFuncInfo->numVGPRsUsed = pInfos[i].value;
break;
default:
//GSLAssert(0 && "Unknown address in program info");
break;
}
}
amuABIEncodingGetScratchRegisterCount(&pFuncInfo->maxScratchRegsNeeded, encoding);
amuABIMultiBinaryDestroy(mb);
return true;
}
gslMemObjectAttribTiling g_CALBETiling_Tiled = GSL_MOA_TILING_TILED;
void
calInit(void)
{
gslInit(); // initialize GSL
}
void
calShutdown(void)
{
gslExit();
}
uint32
calGetDeviceCount()
{
return gsAdaptor::enumerateAdaptors();
}
@@ -0,0 +1,54 @@
#ifndef __BACKEND_H__
#define __BACKEND_H__
#include "cal.h"
#include "calcl.h"
//internal
#include <vector>
#include <cassert>
class CALGSLDevice;
//! Engine types
enum EngineType
{
MainEngine = 0,
SdmaEngine,
AllEngines
};
struct GpuEvent
{
static const unsigned int InvalidID = ((1<<30) - 1);
EngineType engineId_; ///< type of the id
unsigned int id; ///< actual event id
//! GPU event default constructor
GpuEvent(): engineId_(MainEngine), id(InvalidID) {}
//! Returns true if the current event is valid
bool isValid() const { return (id != InvalidID) ? true : false; }
//! Set invalid event id
void invalidate() { id = InvalidID; }
};
typedef enum CALBEtilingEnum
{
CALBE_TILING_DEFAULT,
CALBE_TILING_LINEAR,
CALBE_TILING_TILED,
CALBEtiling_FIRST = CALBE_TILING_DEFAULT,
CALBEtiling_LAST = CALBE_TILING_TILED,
} CALBEtiling;
/*
* GPU Backend functions
*/
void calInit(void);
void calShutdown(void);
uint32 calGetDeviceCount();
#endif
@@ -0,0 +1,95 @@
#include "inifile.h"
#include "ini_export.h"
#include "ini_values.h"
#include "gsl_enum.h"
extern gslMemObjectAttribTiling g_CALBETiling_Tiled;
void
getConfigFromFile(gslStaticRuntimeConfig& scfg,
gslDynamicRuntimeConfig& dcfg)
{
const char* calIniFile = getenv("CAL_INI_FILE");
IniFile iniFile(cmString(calIniFile ? calIniFile : INI_FILE));
CALboolean dumpIL = CAL_FALSE;
CALboolean dumpISA = CAL_FALSE;
CALboolean macro = CAL_TRUE;
CALboolean micro = CAL_TRUE;
CALboolean breakonload = CAL_FALSE;
CALint useRectPrim = 0;
CALboolean forceRemoteMemory = CAL_FALSE;
CALboolean disableAsyncDma = CAL_FALSE;
CALboolean disableVM = CAL_FALSE;
dcfg.bEmulator.hasValue = ATIGL_TRUE;
dcfg.DropFlush.hasValue = ATIGL_TRUE;
dcfg.EnableCommandbufferDump.hasValue = ATIGL_TRUE;
dcfg.WaitForIdleAfterSubmit.hasValue = ATIGL_TRUE;
dcfg.FlushAfterRender.hasValue = ATIGL_TRUE;
dcfg.nPatchDumpLevel.hasValue = ATIGL_TRUE;
cmString commandbufferDumpFilename;
iniFile.getValue(section, CAL_EMULATOR, (CALboolean*) &dcfg.bEmulator.value);
iniFile.getValue(section, CAL_ENABLE_FORCE_ASIC_ID, (CALboolean*) &dcfg.forceAsicID.hasValue);
iniFile.getValue(section, CAL_FORCE_ASIC_ID, (CALint*) &dcfg.forceAsicID.value);
iniFile.getValue(section, CAL_DROPFLUSH, (CALboolean*) &dcfg.DropFlush.value);
iniFile.getValue(section, CAL_ENABLEPACKETDUMP, (CALboolean*) &dcfg.EnableCommandbufferDump.value);
// Check if location string is longer than 128 then assign, if not default location will be C:\packet.txt in gsl_ctx.cpp: gsCtxManager::PacketDump()
uintp length = commandbufferDumpFilename.length();
if (length > 0 && length < sizeof(dcfg.CommandbufferDumpFilename))
strcpy(dcfg.CommandbufferDumpFilename, commandbufferDumpFilename.c_str());
iniFile.getValue(section, CAL_ENABLEPATCHDUMP, (CALint*) &dcfg.nPatchDumpLevel.value);
iniFile.getValue(section, CAL_ENABLEMACROTILE, (CALboolean*) &macro);
iniFile.getValue(section, CAL_ENABLEMICROTILE, (CALboolean*) &micro);
iniFile.getValue(section, CAL_BREAK_ON_LOAD, (CALboolean*) &breakonload);
iniFile.getValue(section, CAL_FORCE_REMOTE_MEMORY, (CALboolean*) &forceRemoteMemory);
iniFile.getValue(section, CAL_DISABLE_ASYNC_DMA, (CALboolean*) &disableAsyncDma);
iniFile.getValue(section, CAL_WAITFORIDLEAFTERSUBMIT, (CALboolean*) &dcfg.WaitForIdleAfterSubmit.value);
iniFile.getValue(section, CAL_ENABLE_DUMP_IL, (CALboolean*) &dumpIL);
iniFile.getValue(section, CAL_ENABLE_DUMP_ISA, (CALboolean*) &dumpISA);
iniFile.getValue(section, CAL_ENABLE_FLUSH_AFTER_RENDER, (CALboolean*) &dcfg.FlushAfterRender.value);
iniFile.getValue(section, CAL_DISABLE_VM, (CALboolean*) &disableVM);
if (disableVM)
{
scfg.VMMode = GSL_CONFIG_VM_MODE_FORCE_OFF;
}
if (!macro && !micro)
{
g_CALBETiling_Tiled = GSL_MOA_TILING_LINEAR;
}
if (breakonload)
{
#ifndef ATI_OS_LINUX
__debugbreak();
#endif
}
switch (forceRemoteMemory)
{
case 1:
//
// Also set linear, due to CAL expectations about different memory regions
//
g_CALBETiling_Tiled = GSL_MOA_TILING_LINEAR;
break;
default:
break;
}
if (disableAsyncDma)
{
dcfg.drmdmaMode.hasValue = ATIGL_TRUE;
dcfg.drmdmaMode.value = GSL_CONFIG_DRMDMA_MODE_FORCE_OFF;
}
}
@@ -0,0 +1,13 @@
#ifndef __INI_EXPORT_H__
#define __INI_EXPORT_H__
#include "gsl_config.h"
void
getConfigFromFile(gslStaticRuntimeConfig& scfg,
gslDynamicRuntimeConfig& dcfg);
#endif
@@ -0,0 +1,334 @@
#ifndef __INI_VALUES_H__
#define __INI_VALUES_H__
#include "cm_string.h"
const cmString section("CAL");
const cmString INI_FILE("cal.ini");
/* VSYNC COMMENTS
0 - always off
1 - app preference (default off)
2 - app preference (default on)
3 - always on
*/
const cmString CAL_OGLWAITVERTICALSYNC("VSyncControl");
// Private panel setting for V-sync control
const cmString CAL_ENABLETEARFREESWAP("VSyncControl");
// Public panel setting to set max anisotropy: 0=app pref, 2=2x, 4=4x, 8=8x, 16=16x
const cmString CAL_OGLMAXANISOTROPY("MaxAnisotropy");
// Public panel setting to select performance Aniso
const cmString CAL_OGLANISOPERF("AnisoPerf");
// Public panel setting to select quality mode
const cmString CAL_OGLANISOQUAL("AnisoQuality");
// Public panel setting
const cmString CAL_OGLANISOTYPE("AnisoType");
// Private panel
const cmString CAL_ENABLEANISOTROPICFILTERING("AnisoFiltering");
// Public panel setting
const cmString CAL_OGLALIASSLIDER("AnisoDegree");
// Public panel setting for LOD bias; ranges from 0(high quality) to 3(high performance);
const cmString CAL_OGLLODBIAS("TextureLod");
// Public panel setting to force Z buffer depth
const cmString CAL_OGLFORCEZBUFFERDEPTH("ForceZBufferDepth");
// Public panel setting to select alpha dither method
const cmString CAL_OGLALPHADITHERMETHOD("DitherAlpha");
// Private Panel Setting for setting multisample value for FSAA
const cmString CAL_MULTISAMPLE("Multisample");
// Public Panel setting for forcing AA
const cmString CAL_ACE_OGLENABLEFSAA("AntiAlias");
// Public panel setting to Enable fast full scene anti-aliasing
const cmString CAL_OGLENABLEFASTFULLSCENEAA("FSAAPerfMode");
//Private Panel setting to force FSAA on
const cmString CAL_ENABLEFASTFULLSCENEAA("FastFullSceneAntiAlias");
// Public panel setting to set full scene anti-aliasing scale.
// Acceptable values are 0, 2-6
const cmString CAL_OGLFULLSCENEAASCALE("AntiAliasSamples");
// Private panel setting to force FSAA, Acceptable values are 0, 2-6.
const cmString CAL_FULLSCENEAASCALE("FullSceneAntiAliasScale");
// Public panel setting to enable triple-buffering
const cmString CAL_OGLENABLETRIPLEBUFFERING("EnableTripleBuffering");
// Public panel setting to set texture optimization
const cmString CAL_OGLTEXTUREOPT("TextureOpt");
// Public panel settings to set postprocessing shaders
const cmString CAL_OGLSELECTEDSWAPEFFECT("SwapEffect");
// Public panel settings to control CatalystAI settings
const cmString CAL_OGLCATALYSTAI("CatalystAI");
// Public panel settings to set postprocessing shaders
const cmString CAL_OGLSUPPORTEDSWAPEFFECTS("SupportedSwapEffects");
const cmString CAL_OGLCUSTOMSWAPSOURCEFILE("CustomSwapSourceFile");
//Public panel setting for allowing special pixel shaders to be applied at swap time.
const cmString CAL_SPECIALSWAP("SpecialSwap");
//Public panel setting for special swap file
const cmString CAL_SPECIALSWAPFILE("SpecialSwapFile");
// Private Panel specific Defines
//
// Private panel setting to force SW path
const cmString CAL_PICKSOFTWARE("PickSoftware");
// Private panel setting to force Microsoft path
const cmString CAL_PICKSOFTWAREMICROSOFT("PickSoftwareMicrosoft");
// Private Panel setting to enable TCL (versus forcing SW TCL)
const cmString CAL_ENABLETCL("EnableTCL");
// Private Panel setting to control HW Flips
const cmString CAL_ALLOWHWFLIP("AllowHWFlip");
// Private Panel setting to allow Z compression
const cmString CAL_ENABLEZCOMPRESSION("ZCompression");
// Private Panel setting to use fast z clears
const cmString CAL_ENABLEFASTZMASKCLEAR("FastZMaskClear");
// Private Panel setting to enable hierarchical Z
const cmString CAL_ENABLEHIERARCHICALZ("HierachicalZ");
// Private Panel setting to enable/disable cmask clears
const cmString CAL_ENABLECMASKCLEARS("MaskClears");
// Private Panel setting to force cmask clear after swap
const cmString CAL_CLEARCMASKAFTERSWAP("ClearCMaskAfterSwap");
// Private Panel setting to enable cmask compression
const cmString CAL_ENABLECMASKCOMPRESSION("CMaskCompression");
// Private Panel setting to force LOD Bias
const cmString CAL_LODBIAS("LODBias");
// Private Panel setting enable fast trilinear
const cmString CAL_FASTTRILINEAR("FastTrilinear");
// Private Panel setting to force clears to be skipped
const cmString CAL_DISABLECLEAR("DisableClear");
// Private Panel setting to control swapping
const cmString CAL_DISABLESWAP("DisableSwap");
// Private Panel setting to force HW idle after submit
const cmString CAL_WAITFORIDLEAFTERSUBMIT("WaitForIdleAfterSubmit");
// Private Panel setting to force single buffered rendering
const cmString CAL_FORCESINGLEBUFFER("ForceSingleBuffer");
// Private Panel setting to force buffer config for single buffered
// configs
const cmString CAL_SINGLE_BUF_CONFIG("SingleBufferConfig");
// Private Panel setting to force buffer config for double buffered
const cmString CAL_DOUBLE_BUF_CONFIG("DoubleBufferConfig");
// Private Panel setting to cause driver to breka on load
const cmString CAL_BREAK_ON_LOAD("BreakOnLoad");
// Private Panel setting for asserting when we set an error
const cmString CAL_ASSERTONERROR("AssertOnError");
// Private Panel setting to turn on shader dumping
const cmString CAL_ENABLESHADERDUMP("EnableShaderDump");
// Private Panel setting to turn on packet dumping
const cmString CAL_ENABLEPACKETDUMP("EnablePacketDump");
// Private Panel setting to set location of packet dump
const cmString CAL_PACKETDUMPLOCATION("PacketDumpLocation");
// Private Panel setting to set what type of file to be written
const cmString CAL_PACKETDUMPTYPE("PacketDumpType");
// Private Panel setting to select file overwrite
const cmString CAL_ONLYSAVELASTPACKET("OnlySaveLastPacket");
// Private Panel setting to turn on vcop patchlist dumping
const cmString CAL_ENABLEPATCHDUMP("EnablePatchDump");
// Private Panel setting to set dump file name
const cmString CAL_DUMPFILENAME("DumpFilename");
// Private Panel setting to control level of HW detail dumped
const cmString CAL_DUMPADDITIONALHWINFO("DumpAdditionalHWInfo");
// Private Panel setting to select frames to dump
const cmString CAL_FRAMESTORECORD("FrameStoreCord");
// Private Panel setting to drop all PM4 packets
const cmString CAL_DROPFLUSH("DropFlush");
// Private Panel setting to furce use of dummy QS
const cmString CAL_ENABLEDUMMYQS("DummyQS");
// Private Panel setting to stub post setup
const cmString CAL_STUBPOSTSETUP("StubPostSetup");
// Private Panel setting to stub post TCL
const cmString CAL_STUBPOSTTCL("StubPostTCL");
// Private Panel setting to disable RB3D
const cmString CAL_DISABLERB3D("DisableR3D");
// Private Panel setting to disable alpha blend
const cmString CAL_DISABLEALPHABLEND("DisableAlphaBlend");
// Private Panel setting to force use of tiny textures
const cmString CAL_FORCETINYTEXTURES("ForceTinyTextures");
// Private Panel setting to prevent object allocation in AGP
const cmString CAL_OBJBUFINAGP("OBJBufferInAGP");
// Private Panel setting to prevent object allcoation in local
const cmString CAL_OBJBUFINLOCAL("OBJBufferInLocal");
// Private Panel setting to set the length of the swap queue
const cmString CAL_SWAPQUEUELENGTH("SwapQueueLength");
// Private Panel setting to enable macro tiling for textures
const cmString CAL_ENABLEMACROTILE("MacroTile");
// Private Panel setting to enable micro tiling for textures
const cmString CAL_ENABLEMICROTILE("MicroTile");
// Private Panel setting for allowing early z
const cmString CAL_ALLOWEARLYZ("AllowEarlyZ");
//Private Panel setting to allow for window to be broken into
// multiple pieces(allows full use of C and Z mask on R300 at high res);
const cmString CAL_ALLOWSPLITSCREEN("AllowSplitScreen");
//Private Panel setting for aniso threshold
const cmString CAL_ANISOTHRESHOLD("AnisoThreshold");
//Private Panel setting for aniso bias
const cmString CAL_ANISOLOD("AnisoLod");
//Private Panel setting fpr aniso bias
const cmString CAL_ANISOBIAS("AnisoBias");
//Private Panel setting to control ainos theshold mode
const cmString CAL_ANISOTHRESHMODE("AnisoThreshmode");
// Private Panel Setting for turnning off multi vpu mode(ie render everything to both) for the rest of a frame after a glCopyTexImage or glCopyTexSubImage happen.
const cmString CAL_DISABLEMVPUONCOPYTEX("DisableMVPUOnCopyTexture");
// Private Panel Setting for forcing swap to happen on slave vpu(useful for debugging);
const cmString CAL_FORCEMVPUSWAPONSLAVE("ForceMVPUSwapOnSlave");
// Private Panel Setting for skipping multi-vpu synchronization
const cmString CAL_SKIPMVPUSYNCH("SkipMVPUSynch");
// Private Panel Setting for controlling the percent of screen rendered on the master vpu
const cmString CAL_PERCENTONMASTERMVPU("PercentOnMasterMVPU");
// Private Panel Setting for controlling the mode of mvpu operation
const cmString CAL_MODEMVPU("ModeMVPU");
// Private Panel Setting for drawing a line where the scissored split happened in mvpu mode
const cmString CAL_DRAWSPLITLINEMVPU("DrawSplitLineMVPU");
// Private Panel Setting for controlling whether or not to unroll loops in the GLSL parser
const cmString CAL_UNROLL_LOOPS("UnrollLoops");
// Private Panel Spare setting 1
const cmString CAL_SPARE1("Spare1");
// Private Panel Spare setting 2
const cmString CAL_SPARE2("Spare2");
// Private Panel Spare setting 3
const cmString CAL_SPARE3("Spare3");
// Private Panel Spare setting 4
const cmString CAL_SPARE4("Spare4");
// Private Panel Spare setting 5
const cmString CAL_SPARE5("Spare5");
// Private Panel Spare setting 6
const cmString CAL_SPARE6("Spare6");
// Private Panel Spare setting 7
const cmString CAL_SPARE7("Spare7");
// Private Panel Spare setting 8
const cmString CAL_SPARE8("Spare8");
// Private Panel Spare setting 9
const cmString CAL_SPARE9("Spare9");
// Private Panel Spare setting 10
const cmString CAL_SPARE10("Spare10");
// Private Panel Spare setting 11 - accepts numbers, not just 0 and 1
const cmString CAL_SPARE11("Spare11");
// Private Panel Spare setting 12 - accepts numbers, not just 0 and 1
const cmString CAL_SPARE12("Spare12");
// Private Panel Spare setting 12 - accepts numbers, not just 0 and 1
const cmString CAL_PS3ENABLE("PS3Enable");
// Private Panel setting for asserting when we punt to SW
const cmString CAL_ASSERTONSWPUNT("OrcaAssertOnSWPunt");
// Private Panel setting for logging when we punt to SW
const cmString CAL_LOGSWPUNTCASES("OrcaLogSWPuntCases");
// Private Panel setting to set punt log file name
const cmString CAL_PUNTLOGFILENAME("OrcaPuntLogFileName");
// softVAP mode
const cmString CAL_SOFTVAP("SoftVAP");
// softVAP il compile mode
const cmString CAL_SVPOFFLINECOMPILE("SvpOfflineCompile");
const cmString CAL_EMULATOR("Emulator");
const cmString CAL_ENABLE_FORCE_ASIC_ID("EnableForceAsicID");
const cmString CAL_FORCE_ASIC_ID("ForceAsicID");
const cmString CAL_FORCE_REMOTE_MEMORY("ForceRemoteMemory");
const cmString CAL_DISABLE_ASYNC_DMA("DisableAsyncDma");
const cmString CAL_ENABLE_DUMP_IL("DumpIL");
const cmString CAL_ENABLE_DUMP_ISA("DumpISA");
// TDR
const cmString CAL_ENABLE_FLUSH_AFTER_RENDER("FlushAfterRender");
// VM Disabling
const cmString CAL_DISABLE_VM("DisableVM");
#endif
@@ -0,0 +1,537 @@
//
// Trade secret of ATI Technologies, Inc.
// Copyright 2005, ATI Technologies, Inc., (unpublished)
//
// All rights reserved. This notice is intended as a precaution against
// inadvertent publication and does not imply publication or any waiver
// of confidentiality. The year included in the foregoing notice is the
// year of creation of the work.
//
/// @file inifile.cpp
/// @brief INI File Parser
#include "inifile.h"
#include "cm_string.h"
#include "inifile_parser.h"
#include "cal.h"
#include "assert.h"
#include <iostream>
#include <istream>
#include <fstream>
#ifdef DEBUG
#include <sstream>
#include <string>
#endif
/**
* IniValueString members
*/
IniValueString::IniValueString()
{
value = cmString("");
}
IniValueString::IniValueString(const IniValueString& val)
{
value = val.value;
}
IniValueString::IniValueString(cmString val)
{
value = val;
}
IniValueString& IniValueString::operator=(IniValueString& v)
{
value = v.value;
return *this;
}
CALboolean IniValueString::getValue(cmString* value)
{
*value = this->value;
return CAL_TRUE;
}
/**
* IniValueBool members
*/
IniValueBool::IniValueBool()
{
value = CAL_FALSE;
}
IniValueBool::IniValueBool(const IniValueBool& val)
{
value = val.value;
}
IniValueBool::IniValueBool(CALboolean val)
{
value = val;
}
IniValueBool& IniValueBool::operator=(IniValueBool& v)
{
value = v.value;
return *this;
}
CALboolean IniValueBool::getValue(CALboolean* value)
{
*value = this->value;
return CAL_TRUE;
}
/**
* IniValueInt members
*/
IniValueInt::IniValueInt()
{
value = 0;
}
IniValueInt::IniValueInt(const IniValueInt& val)
{
value = val.value;
}
IniValueInt::IniValueInt(CALint val)
{
value = val;
}
IniValueInt& IniValueInt::operator=(IniValueInt& v)
{
value = v.value;
return *this;
}
CALboolean IniValueInt::getValue(CALint* value)
{
*value = this->value;
return CAL_TRUE;
}
/**
* IniValueFloat members
*/
IniValueFloat::IniValueFloat()
{
value = 0;
}
IniValueFloat::IniValueFloat(const IniValueFloat& val)
{
value = val.value;
}
IniValueFloat::IniValueFloat(CALfloat val)
{
value = val;
}
IniValueFloat& IniValueFloat::operator=(IniValueFloat& v)
{
value = v.value;
return *this;
}
CALboolean IniValueFloat::getValue(CALfloat* value)
{
*value = this->value;
return CAL_TRUE;
}
/**
* IniSection Members
*/
IniSection::IniSection()
{
name = cmString("");
}
IniSection::IniSection(const IniSection& s)
{
name = s.name;
for(EntryDBIterator iter = s.entryDB.begin() ; iter != s.entryDB.end(); iter++)
{
entryDB[iter->first] = iter->second;
}
}
IniSection::IniSection(cmString n)
{
name = n;
}
IniSection::~IniSection()
{
for(EntryDBIterator iter = entryDB.begin() ; iter != entryDB.end(); iter++)
{
delete iter->second;
}
entryDB.clear();
}
IniSection& IniSection::operator=(IniSection& s)
{
name = s.name;;
entryDB.clear();
for(EntryDBIterator iter = s.entryDB.begin() ; iter != s.entryDB.end(); iter++)
{
entryDB[iter->first] = iter->second;
}
return *this;
}
void IniSection::addEntry(cmString name, IniValue* value)
{
IniValue* v = findEntry(name);
if (v)
{
delete v;
}
entryDB[name] = value;
}
IniValue* IniSection::findEntry(cmString name)
{
EntryDBIterator iter = entryDB.find(name);
if(iter != entryDB.end())
{
return iter->second;
}
else
{
return NULL;
}
}
/**
* IniFile members
*/
IniFile::IniFile(cmString filename)
{
#ifdef DEBUG
SanityTest();
#endif
std::ifstream in(filename.c_str());
IniFileParser::Parse(in, *this);
}
IniFile::IniFile(std::istream& in)
{
IniFileParser::Parse(in, *this);
}
IniFile::~IniFile()
{
for(SectionDBIterator iter = sectionDB.begin() ; iter != sectionDB.end(); iter++)
{
delete iter->second;
}
sectionDB.clear();
}
const cmString IniSection::getName()
{
return name;
}
void IniFile::addSection(IniSection* section)
{
IniSection* v = findSection(section->getName());
if (v)
{
delete v;
}
sectionDB[section->getName()] = section;
}
IniSection* IniFile::findSection(cmString section)
{
SectionDBIterator iter = sectionDB.find(section);
if (iter != sectionDB.end())
{
return iter->second;
}
else
{
return NULL;
}
}
IniValue* IniFile::getValue(cmString section, cmString entry)
{
IniSection* s = findSection(section);
if(s == NULL)
{
return NULL;
}
return s->findEntry(entry);
}
CALboolean IniFile::getValue(cmString section, cmString entry, CALboolean* value)
{
IniValue* v = getValue(section, entry);
if (v != NULL)
{
return v->getValue(value);
}
return CAL_FALSE;
}
CALboolean IniFile::getValue(cmString section, cmString entry, CALint* value)
{
IniValue* v = getValue(section, entry);
if (v != NULL)
{
return v->getValue(value);
}
return CAL_FALSE;
}
CALboolean IniFile::getValue(cmString section, cmString entry, CALfloat* value)
{
IniValue* v = getValue(section, entry);
if (v != NULL)
{
return v->getValue(value);
}
return CAL_FALSE;
}
CALboolean IniFile::getValue(cmString section, cmString entry, cmString* value)
{
IniValue* v = getValue(section, entry);
if (v != NULL)
{
return v->getValue(value);
}
return CAL_FALSE;
}
/**
* Debug only methods
*
*/
#ifdef DEBUG
void IniValueString::printAST()
{
std::cerr << value.c_str() << " [string]\n";
}
void IniValueBool::printAST()
{
std::cerr << value << " [bool]\n";
}
void IniValueInt::printAST()
{
std::cerr << value << " [int]\n";
}
void IniValueFloat::printAST()
{
std::cerr << value << " [float]\n";
}
void IniSection::printAST()
{
for(EntryDBIterator iter = entryDB.begin() ; iter != entryDB.end(); iter++)
{
cmString name = iter->first;
IniValue *v = iter->second;
std::cerr << name.c_str() << " = ";
v->printAST();
}
}
void IniFile::printAST()
{
for(SectionDBIterator iter = sectionDB.begin() ; iter != sectionDB.end(); iter++)
{
IniSection* s = iter->second;
std::cerr << "[" << s->getName().c_str() << "]\n";
s->printAST();
}
std::cerr << "\n";
}
void IniFile::SanityTest()
{
//std::cerr << "Running IniFile Sanity...\n";
static const cmString section("section");
static const std::string file1(
"[section]\n\
bool1=true\n\
bool2=false\n\
int=3\n\
float=1.1111\n\
string=abc def\n");
std::istringstream s1(file1);
IniFile* iniFile = new IniFile(s1);
//iniFile->printAST();
CALboolean b;
assert(iniFile->getValue(section, cmString("bool1"), &b) == CAL_TRUE);
assert(b == CAL_TRUE);
assert(iniFile->getValue(section, cmString("bool2"), &b) == CAL_TRUE);
assert(b == CAL_FALSE);
CALint i;
assert(iniFile->getValue(section, cmString("int"), &i) == CAL_TRUE);
assert(i == 3);
CALfloat f;
assert(iniFile->getValue(section, cmString("float"), &f) == CAL_TRUE);
assert(f == 1.1111f);
cmString s;
assert(iniFile->getValue(section, cmString("string"), &s) == CAL_TRUE);
assert(s == cmString("abc def"));
i = -1;
// Wrong section
assert(iniFile->getValue(cmString("dummy"), cmString("int"), &i) == CAL_FALSE);
assert(i == -1);
// Wrong entry
assert(iniFile->getValue(section, cmString("dummy"), &i) == CAL_FALSE);
assert(i == -1);
static const std::string file2(
"[section]\n\
bool1=1true\n\
bool2=false2\n\
int=3a\n\
float=1.1111b\n\
string=1\n");
delete iniFile;
std::istringstream s2(file2);
iniFile = new IniFile(s2);
//iniFile->printAST();
cmString str;
b = CAL_FALSE;
// try to get a bool, then a string
assert(iniFile->getValue(section, cmString("bool1"), &b) == CAL_FALSE);
assert(b == CAL_FALSE);
assert(iniFile->getValue(section, cmString("bool1"), &str) == CAL_TRUE);
assert(str == cmString("1true"));
// try to get a bool, then a string
assert(iniFile->getValue(section, cmString("bool2"), &b) == CAL_FALSE);
assert(b == CAL_FALSE);
assert(iniFile->getValue(section, cmString("bool2"), &str) == CAL_TRUE);
assert(str == cmString("false2"));
i = -1;
// try to get an int, then a string
assert(iniFile->getValue(section, cmString("int"), &i) == CAL_FALSE);
assert(i == -1);
assert(iniFile->getValue(section, cmString("int"), &str) == CAL_TRUE);
assert(str == cmString("3a"));
f = -1.1f;
// try to get a float, then a string
assert(iniFile->getValue(section, cmString("float"), &f) == CAL_FALSE);
assert(f == -1.1f);
assert(iniFile->getValue(section, cmString("float"), &str) == CAL_TRUE);
assert(str == cmString("1.1111b"));
// try to get a string, value is an int
assert(iniFile->getValue(section, cmString("string"), &str) == CAL_FALSE);
assert(str == cmString("1.1111b"));
assert(iniFile->getValue(section, cmString("string"), &i) == CAL_TRUE);
assert(i == 1);
static const cmString section1("section1");
static const cmString section2("section2");
static const cmString section3("section3");
static const std::string file3(
"[section1\n\
bool1=false\n\
bool2=false\n\
int=1\n\
float=1.1\n\
string=abc\n\
[section2]\n\
bool1=true\n\
bool2=true\n\
int=2\n\
float=1.2\n\
string=def\n\
[section3]\n\
int=3\n\
[section2]\n\
float=1.3\n");
delete iniFile;
std::istringstream s3(file3);
iniFile = new IniFile(s3);
//iniFile->printAST();
// section1 should not exist (syntax error)
assert(iniFile->getValue(section1, cmString("bool1"), &str) == CAL_FALSE);
assert(iniFile->getValue(section1, cmString("bool2"), &str) == CAL_FALSE);
assert(iniFile->getValue(section1, cmString("int"), &str) == CAL_FALSE);
assert(iniFile->getValue(section1, cmString("float"), &str) == CAL_FALSE);
assert(iniFile->getValue(section1, cmString("string"), &str) == CAL_FALSE);
// section2 should exist, only with the float
assert(iniFile->getValue(section2, cmString("bool1"), &b) == CAL_FALSE);
assert(iniFile->getValue(section2, cmString("bool2"), &b) == CAL_FALSE);
assert(iniFile->getValue(section2, cmString("int"), &i) == CAL_FALSE);
// overridden
assert(iniFile->getValue(section2, cmString("float"), &f) == CAL_TRUE);
assert(f == 1.3f);
assert(iniFile->getValue(section2, cmString("string"), &str) == CAL_FALSE);
// section3 had a differant int
assert(iniFile->getValue(section3, cmString("int"), &i) == CAL_TRUE);
assert(i == 3);
delete iniFile;
//std::cerr << "Done!";
}
#endif
@@ -0,0 +1,164 @@
#ifndef INIFILE_H
#define INIFILE_H
//
// Trade secret of ATI Technologies, Inc.
// Copyright 2005, ATI Technologies, Inc., (unpublished)
//
// All rights reserved. This notice is intended as a precaution against
// inadvertent publication and does not imply publication or any waiver
// of confidentiality. The year included in the foregoing notice is the
// year of creation of the work.
//
/// @file inifile.h
/// @brief INI File Parser
#include "cm_string.h"
#include "cal.h"
#include <map>
#include <istream>
class IniValue
{
public:
virtual ~IniValue() {}
virtual CALboolean getValue(CALboolean* value) { return CAL_FALSE; };
virtual CALboolean getValue(CALint* value) { return CAL_FALSE; };
virtual CALboolean getValue(CALfloat* value) { return CAL_FALSE; };
virtual CALboolean getValue(cmString* value) { return CAL_FALSE; };
#ifdef DEBUG
virtual void printAST() {};
#endif
private:
};
class IniValueBool : public IniValue
{
public:
IniValueBool();
IniValueBool(const IniValueBool& val);
IniValueBool(CALboolean val);
IniValueBool& operator=(IniValueBool& v);
CALboolean getValue(CALboolean* value);
#ifdef DEBUG
void printAST();
#endif
private:
CALboolean value;
};
class IniValueString : public IniValue
{
public:
IniValueString();
IniValueString(const IniValueString& val);
IniValueString(cmString val);
IniValueString& operator=(IniValueString& v);
CALboolean getValue(cmString* value);
#ifdef DEBUG
void printAST();
#endif
private:
cmString value;
};
class IniValueInt : public IniValue
{
public:
IniValueInt();
IniValueInt(const IniValueInt& val);
IniValueInt(CALint val);
IniValueInt& operator=(IniValueInt& v);
CALboolean getValue(CALint* value);
void printAST();
private:
CALint value;
};
class IniValueFloat : public IniValue
{
public:
IniValueFloat();
IniValueFloat(const IniValueFloat& val);
IniValueFloat(CALfloat val);
IniValueFloat& operator=(IniValueFloat& v);
CALboolean getValue(CALfloat* value);
#ifdef DEBUG
void printAST();
#endif
private:
CALfloat value;
};
class IniSection
{
public:
IniSection();
IniSection(const IniSection& s);
IniSection(cmString n);
~IniSection();
IniSection& operator=(IniSection& s);
void addEntry(cmString name, IniValue* value);
IniValue* findEntry(cmString name);
const cmString getName();
#ifdef DEBUG
void printAST();
#endif
private:
typedef std::map<cmString, IniValue*> EntryDB;
typedef EntryDB::const_iterator EntryDBIterator;
typedef std::pair<cmString, IniValue*> EntryDBPair;
cmString name;
EntryDB entryDB;
};
class IniFile
{
public:
IniFile(cmString filename);
IniFile(std::istream& in);
~IniFile();
CALboolean getValue(cmString section, cmString entry, CALboolean* value);
CALboolean getValue(cmString section, cmString entry, CALint* value);
CALboolean getValue(cmString section, cmString entry, CALfloat* value);
CALboolean getValue(cmString section, cmString entry, cmString* value);
// should be protected
void addSection(IniSection* section);
IniSection* findSection(cmString section);
#ifdef DEBUG
void printAST();
static void SanityTest();
#endif
private:
typedef std::map<cmString, IniSection*> SectionDB;
typedef SectionDB::const_iterator SectionDBIterator;
typedef std::pair<cmString, IniSection*> SectionDBPair;
IniValue* getValue(cmString section, cmString entry);
SectionDB sectionDB;
};
#endif
@@ -0,0 +1,225 @@
//
// Trade secret of ATI Technologies, Inc.
// Copyright 2005, ATI Technologies, Inc., (unpublished)
//
// All rights reserved. This notice is intended as a precaution against
// inadvertent publication and does not imply publication or any waiver
// of confidentiality. The year included in the foregoing notice is the
// year of creation of the work.
//
/// @file inifile_parser.cpp
/// @brief INI File Parser Implementation
#include "inifile.h"
#include "inifile_parser.h"
#include "cm_string.h"
#include <cctype>
#include <string>
#include <istream>
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <cctype>
void IniFileParser::Parse(std::istream& in, IniFile& iniFile)
{
CALuint count = 0;
std::string line;
bool inSection = false;
std::string sectionName;
IniSection* section = NULL;
while(std::getline(in, line)) {
count++;
cleanup(line);
if(line.empty())
{
continue;
}
if(parseSectionName(line, sectionName))
{
section = new IniSection(cmString(sectionName.c_str()));
iniFile.addSection(section);
inSection = true;
}
else if(inSection)
{
parseLine(line, section, count);
}
}
}
void IniFileParser::parseLine( std::string line, IniSection* section, CALuint count ) {
std::string::size_type equals = line.find( '=' );
if ( equals == std::string::npos ) {
#ifdef DEBUG
std::cerr << "IniFileParser: Could not parse line " << count << ", ignoring.\n";
#endif
return;
}
std::string name( line, 0, equals );
IniValue* value = parseValue( std::string( line, equals + 1, std::string::npos));
section->addEntry(cmString(trim(name).c_str()), value);
}
void IniFileParser::cleanup( std::string& line ) {
std::string copy = line;
unsigned int begin = 0;
while ( begin != line.size() && isspace(line[begin]))
{
++begin;
}
bool inQuote = false;
unsigned int end;
for(end = begin; end != line.size(); ++end)
{
if ( line[end] == '\"' )
{
inQuote = !inQuote;
}
// comments starts with # or ;
else if ( (line[end] == '#' || line[end] == ';') && !inQuote )
{
break;
}
else if ( line[ end ] == '\\' )
{
++end; // ignore next character
if ( end == line.size() ) {
#ifdef DEBUG
std::cerr << "INIFileParser: Error parsing file: \\ character "
"at the end of line (sorry, not supported)\n";
#endif
break;
}
}
}
while ( end > begin && isspace( line[ end - 1 ] ) ) --end;
// This is used over assign so that we don't have memcpy overrun
// errors in valgrind.
line = line.substr(begin, end - begin);
}
class isint
{
public:
isint()
{
is_int = true;
}
void operator() (char c)
{
is_int = is_int && isdigit(c);
}
bool is_int;
};
class isfloat
{
public:
isfloat()
{
is_float = true;
}
void operator() (char c)
{
is_float = is_float && (isdigit(c) || c == '.');
}
bool is_float;
};
int cmp_nocase(const std::string s1, const std::string s2)
{
std::string::const_iterator p1 = s1.begin();
std::string::const_iterator p2 = s2.begin();
while( p1 != s1.end() && p2 != s2.end())
{
if(toupper(*p1) != toupper(*p2))
{
return (toupper(*p1) < toupper(*p2)) ? -1 : 1;
}
++p1;
++p2;
}
return static_cast<int>(s2.size()-s1.size());
}
IniValue* IniFileParser::parseValue(std::string value ) {
std::string trimmed = trim(value);
std::stringstream ss(trimmed);
// look for a boolean
static const std::string strTrue("true");
static const std::string strFalse("false");
if(cmp_nocase(trimmed, strTrue) == 0)
{
return new IniValueBool(CAL_TRUE);
}
if(cmp_nocase(trimmed, strFalse) == 0)
{
return new IniValueBool(CAL_FALSE);
}
// try now to get an int
isint ii;
ii = std::for_each(trimmed.begin(),trimmed.end(), ii);
if(ii.is_int)
{
CALint intValue = 0;
ss >> intValue;
return new IniValueInt(intValue);
}
// if not an int, try to get a float
isfloat isf;
isf = std::for_each(trimmed.begin(),trimmed.end(), isf);
if(isf.is_float)
{
CALfloat floatValue;
// mbeuchat: Remove STL conversion of string to float. When compiled
// on Linux, DK g++ with optimization requires linking against
// libstdc++-6.0.9 which is not available on all Linux systems.
// ss >> floatValue;
floatValue = (float)atof(ss.str().c_str());
return new IniValueFloat(floatValue);
}
// finally, default to a string
return new IniValueString(cmString(trimmed.c_str()));
}
bool IniFileParser::parseSectionName(std::string line, std::string& section )
{
if ( line[ 0 ] != '[' ) return false;
if ( line[ line.size() - 1 ] != ']' ) return false;
section.assign( line, 1, line.size() - 2 );
return true;
}
std::string IniFileParser::trim(std::string const& source, char const* delims) {
std::string result(source);
std::string::size_type index = result.find_last_not_of(delims);
if(index != std::string::npos)
result.erase(++index);
index = result.find_first_not_of(delims);
if(index != std::string::npos)
result.erase(0, index);
else
result.erase();
return result;
}
@@ -0,0 +1,42 @@
#ifndef INIFILE_PARSER_H
#define INIFILE_PARSER_H
//
// Trade secret of ATI Technologies, Inc.
// Copyright 2005, ATI Technologies, Inc., (unpublished)
//
// All rights reserved. This notice is intended as a precaution against
// inadvertent publication and does not imply publication or any waiver
// of confidentiality. The year included in the foregoing notice is the
// year of creation of the work.
//
/// @file inifile_parser.h
/// @brief INI File Parser Implementation
// if compiled from OGTST, add the following, normally defined in atitypes.h
#include "inifile.h"
#include "cm_string.h"
#include "cal.h"
#include <istream>
#include <iostream>
#include <string>
class IniFileParser
{
public:
static void Parse(std::istream& in, IniFile& iniFile);
private:
static void parseLine( std::string line, IniSection* section, CALuint count );
static bool parseSectionName(std::string line, std::string& section );
static IniValue* parseValue(std::string value );
static void cleanup( std::string& line );
static std::string trim(std::string const& source, char const* delims = " \t\r\n");
};
#endif