initial commit
This commit is contained in:
@@ -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
|
||||
@@ -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, §ion, &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
|
||||
@@ -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
@@ -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_*/
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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_*/
|
||||
@@ -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
|
||||
@@ -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_
|
||||
|
||||
@@ -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
@@ -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_*/
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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_
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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_*/
|
||||
@@ -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.
|
||||
// It’s 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
|
||||
@@ -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.
|
||||
// It’s 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 = ¶ms[paramIdx];
|
||||
volatile __global HwDispatch* hwDisp =
|
||||
(volatile __global HwDispatch*)param->hw_queue;
|
||||
__global uint* signal = (__global uint*)(¶m->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*)¶m->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*)¶m->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*)¶m->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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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_
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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, ¶m, 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*) ¯o);
|
||||
iniFile.getValue(section, CAL_ENABLEMICROTILE, (CALboolean*) µ);
|
||||
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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user