Files
rocm-systems/rocclr/runtime/device/gpu/gslbe/src/rt/GSLDevice.cpp
T
foreman 28a35ae54d P4 to Git Change 1139180 by wchau@wchau_WINDOWS7_OCL on 2015/04/09 15:42:22
ECR #399840 - OpenCL Runtime HW Debug support development - resolve the TDR issues on Kaveri.

	1. update the resource descriptors in the runtime trap handler to match those in the HSA HW debug implementation
	2. force to use SDMA for device memory map function, which is called when using clHwDbgSetGlobalMemoryAMD() and clEnqueueMapImage() functions, for HW debug

Affected files ...

... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuresource.cpp#214 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gputrap.hpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuvirtual.cpp#358 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gslbe/src/rt/GSLDevice.cpp#115 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gslbe/src/rt/GSLDevice.h#47 edit
2015-04-09 17:45:47 -04:00

1754 lines
53 KiB
C++

#include "gsl_ctx.h"
#include "GSLDevice.h"
#include "EventQueue.h"
#include "ini_export.h"
#include "GSLContext.h"
#include "cm_if.h"
#include "utils/flags.hpp"
#include "query/QueryObject.h"
#include "memory/MemObject.h"
#include "sampler/SamplerObject.h"
#include "texture/TextureResourceObject.h"
extern gslMemObjectAttribTiling g_CALBETiling_Tiled;
void
CALGSLDevice::resFree(gslMemObject mem) const
{
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
m_cs->destroyMemObject(mem);
}
void CALGSLDevice::Initialize()
{
m_adp = 0;
m_cs = 0;
m_rs = 0;
m_textureResource = 0;
m_textureSampler = 0;
m_target = (CALtarget)0xffffffff;
m_vpucount = 1;
m_srcDRMDMAMem = NULL ;
m_dstDRMDMAMem = NULL ;
m_videoAttribs.video_attribs = NULL;
m_nativeDisplayHandle = NULL;
m_deviceMode = GSL_DEVICE_MODE_GFX;
m_gpuIndex = 0;
m_usePerVPUAdapterModel = false;
m_chainIndex = 0;
m_vpuMask = 1;
m_PerformLazyDeviceInit = false;
m_computeRing = false;
m_isComputeRingIDForced = false;
m_forcedComputeEngineID = GSL_ENGINEID_INVALID;
gslDeviceOps_ = NULL;
}
CALGSLDevice::CALGSLDevice()
{
Initialize();
}
CALGSLDevice::~CALGSLDevice()
{
assert(m_adp == 0); /// CALBE client must call close explicitly. Check that here
delete gslDeviceOps_;
delete [] m_videoAttribs.video_attribs;
switch(m_deviceMode)
{
case GSL_DEVICE_MODE_NONE:
case GSL_DEVICE_MODE_CONSOLE:
delete static_cast<char*>(m_nativeDisplayHandle);
break;
case GSL_DEVICE_MODE_GFX:
closeNativeDisplayHandle();
break;
}
}
gsl::gsAdaptor*
CALGSLDevice::getNative() const
{
return m_adp;
}
uint32
CALGSLDevice::getMaxTextureSize() const
{
return static_cast<uint32>(m_maxtexturesize);
}
void
CALGSLDevice::getMemInfo(gslMemInfo* memInfo) const
{
m_cs->getMemInfo(memInfo, GSL_MEMINFO_BASIC);
}
void
CALGSLDevice::getAttribs_int(gsl::gsCtx* cs)
{
m_attribs.struct_size = sizeof(CALdeviceattribs);
m_attribs.target = m_target;
m_attribs.targetRevision = m_revision;
gslMemInfo memInfo;
cs->getMemInfo(&memInfo, GSL_MEMINFO_BASIC);
m_attribs.localRAM = (uint32)((memInfo.cardMemTotalBytes + memInfo.cardExtMemTotalBytes) / (1024 * 1024));
m_attribs.uncachedRemoteRAM = (uint32)(memInfo.agpMemTotalBytes / (1024 * 1024));
m_attribs.cachedRemoteRAM = (uint32)(memInfo.agpMemTotalCacheableBytes / (1024 * 1024));
m_attribs.totalVisibleHeap = (uint32) (memInfo.cardMemTotalBytes / (1024 * 1024));
m_attribs.totalInvisibleHeap = (uint32) (memInfo.cardExtMemTotalBytes / (1024 * 1024));
m_attribs.totalDirectHeap = (uint32) (memInfo.directTotalBytes / (1024 * 1024));
m_attribs.totalCoherentHeap = (uint32) (memInfo.coherentTotalBytes / (1024 * 1024));
m_attribs.totalRemoteSharedHeap = (uint32) (memInfo.sharedTotalBytes / (1024 * 1024));
m_attribs.totalCachedRemoteSharedHeap = (uint32) (memInfo.sharedCacheableTotalBytes / (1024 * 1024));
m_attribs.totalSDIHeap = (uint32) (memInfo.busAddressableTotalBytes / (1024 * 1024));
m_attribs.engineClock = cs->getMaxEngineClock();
m_attribs.memoryClock = cs->getMaxMemoryClock();
m_attribs.numberOfSIMD = cs->getNumSIMD();
m_attribs.numberOfCUsperShaderArray = cs->getNumCUsPerShaderArray();
m_attribs.wavefrontSize = cs->getWaveFrontSize();
m_attribs.doublePrecision = cs->getIsDoublePrecisionSupported();
m_attribs.localDataShare = cs->getIsLocalDataShareSupported();
m_attribs.globalDataShare = cs->getIsGlobalDataShareSupported();
m_attribs.globalGPR = cs->getIsGlobalGPRSupported();
m_attribs.computeShader = cs->getIsComputeShaderSupported();
m_attribs.memExport = cs->getIsMemExportSupported();
m_attribs.memBusWidth = cs->getVramBitWidth();
m_attribs.numMemBanks = cs->getVramBanks();
m_attribs.isWorkstation = cs->getIsWorkstation();
// Add this to HWL query
m_attribs.pitch_alignment = 256;
#ifdef ATI_OS_WIN
// 4KB aligned on Windows
m_attribs.surface_alignment = 4096;
#else
// 256B aligned on Linux
m_attribs.surface_alignment = 256;
#endif
m_attribs.numberOfUAVs = cs->getNumUAVs();
m_attribs.bUAVMemExport = cs->getIsUAVAsMemExport();
m_attribs.numberOfShaderEngines = cs->getNumShaderEngines();
m_attribs.pciTopologyInformation = m_adp->getLocationId();
const uint8* boardName = cs->getString(GSL_GS_RENDERER);
::strncpy(m_attribs.boardName, (char*)boardName, CAL_ASIC_INFO_MAX_LEN * sizeof(char));
m_attribs.vectorBufferInstructionAddr64 = cs->getVectorBufferInstructionAddr64Supported();
m_attribs.memRandomAccessTargetInstructions = cs->getMemRandomAccessTargetInstructionsSupported();
m_attribs.counterFreq = cs->getCounterFreq();
m_attribs.nanoSecondsPerTick = 1000000000.0 / cs->getCounterFreq();
m_attribs.longIdleDetect = cs->getLongIdleDetect();
m_attribs.svmAtomics = m_adp->pAsicInfo->svmAtomics;
m_attribs.vaStart = static_cast<CALuint64>(m_adp->pAsicInfo->vaStart);
m_attribs.vaEnd = static_cast<CALuint64>(m_adp->pAsicInfo->vaEnd);
m_attribs.numOfVpu = m_adp->pAsicInfo->numberOfVPU;
m_attribs.isOpenCL200Device = m_adp->pAsicInfo->bIsOpen2Device;
m_attribs.isSVMFineGrainSystem = m_adp->pAsicInfo->svmFineGrainSystem;
}
void
CALGSLDevice::getVideoAttribs_int(gslVideoContext* vsHandle)
{
gslVidGetInfoStruc vidInfo = {0};
gslVidGetInfo(vsHandle, &vidInfo);
if (vidInfo.num_attribs > 0)
{
CALvideoAttrib * video_attribs = new CALvideoAttrib[vidInfo.num_attribs];
for (uint32 i=0; i < vidInfo.num_attribs; i++)
{
video_attribs[i].decodeProfile = static_cast<CALdecodeProfile>(vidInfo.video_attribs[i].decodeProfile);
video_attribs[i].decodeFormat = static_cast<CALdecodeFormat>(vidInfo.video_attribs[i].decodeFormat);
}
m_videoAttribs.max_decode_sessions = vidInfo.num_attribs ;
m_videoAttribs.video_attribs = video_attribs;
}
else
{
m_videoAttribs.max_decode_sessions = 0;
m_videoAttribs.video_attribs = NULL;
}
m_videoAttribs.data_size = sizeof(CALdeviceVideoAttribs) + sizeof(CALvideoAttrib) * vidInfo.num_attribs;
}
void
CALGSLDevice::getStatus_int(gsl::gsCtx* cs)
{
m_deviceStatus.struct_size = sizeof(CALdevicestatus);
gslMemInfo memInfo;
cs->getMemInfo(&memInfo, GSL_MEMINFO_BASIC);
m_deviceStatus.availLocalRAM = (uint32)((memInfo.cardMemAvailableBytes + memInfo.cardExtMemAvailableBytes) / (1024 * 1024));
m_deviceStatus.availUncachedRemoteRAM = (uint32)(memInfo.agpMemAvailableBytes / (1024 * 1024));
m_deviceStatus.availCachedRemoteRAM = (uint32)(memInfo.agpMemAvailableCacheableBytes / (1024 * 1024));
m_deviceStatus.availVisibleHeap = (uint32) (memInfo.cardMemAvailableBytes / (1024 * 1024));
m_deviceStatus.availInvisibleHeap = (uint32) (memInfo.cardExtMemAvailableBytes / (1024 * 1024));
m_deviceStatus.availDirectHeap = (uint32) (memInfo.directAvailableBytes / (1024 * 1024));
m_deviceStatus.availCoherentHeap = (uint32) (memInfo.coherentAvailableBytes / (1024 * 1024));
m_deviceStatus.availRemoteSharedHeap = (uint32) (memInfo.sharedAvailableBytes / (1024 * 1024));
m_deviceStatus.availCachedRemoteSharedHeap = (uint32) (memInfo.sharedCacheableAvailableBytes / (1024 * 1024));
m_deviceStatus.largestBlockVisibleHeap = (uint32) (memInfo.cardLargestFreeBlockBytes / (1024 * 1024));
m_deviceStatus.largestBlockInvisibleHeap = (uint32) (memInfo.cardExtLargestFreeBlockBytes / (1024 * 1024));
m_deviceStatus.largestBlockRemoteHeap = (uint32) (memInfo.agpLargestFreeBlockBytes / (1024 * 1024));
m_deviceStatus.largestBlockCachedRemoteHeap = (uint32) (memInfo.agpCacheableLargestFreeBlockBytes / (1024 * 1024));
m_deviceStatus.largestBlockDirectHeap = (uint32) (memInfo.directLargestFreeBlockBytes / (1024 * 1024));
m_deviceStatus.largestBlockCoherentHeap = (uint32) (memInfo.coherentLargestFreeBlockBytes / (1024 * 1024));
m_deviceStatus.largestBlockRemoteSharedHeap = (uint32) (memInfo.sharedLargestFreeBlockBytes / (1024 * 1024));
m_deviceStatus.largestBlockCachedRemoteSharedHeap = (uint32) (memInfo.sharedCacheableLargestFreeBlockBytes / (1024 * 1024));
}
bool
CALGSLDevice::open(uint32 gpuIndex, bool enableHighPerformanceState, bool reportAsOCL12Device)
{
gslDeviceOps_ = new amd::Monitor("GSL Device Ops Lock", true);
if (NULL == gslDeviceOps_) {
return false;
}
unsigned int chainIndex = 0;
#ifdef ATI_OS_WIN
m_gpuIndex = gpuIndex;
m_usePerVPUAdapterModel = true;
m_PerformLazyDeviceInit = true;
#else
void * nativeHandle;
gslDeviceMode deviceMode;
gsAdaptor::getDeviceInitData(gpuIndex, &deviceMode, &chainIndex, &nativeHandle);
m_nativeDisplayHandle = nativeHandle;
m_deviceMode = deviceMode;
#endif
m_chainIndex = chainIndex;
m_vpuMask = 1 << chainIndex;
//
// CALBE is required to explicitly manage multiple opens and closes
// assert on the condition for correct usage
//
assert(m_adp == 0);
memset(&m_dcfg, 0, sizeof(m_dcfg));
extern void getConfigFromFile(gslStaticRuntimeConfig &scfg, gslDynamicRuntimeConfig &dcfg);
getConfigFromFile(m_scfg, m_dcfg);
m_scfg.UsePerVPUAdapterModel.hasValue = true;
m_scfg.UsePerVPUAdapterModel.value = m_usePerVPUAdapterModel;
m_scfg.DX10SamplerResources.hasValue = true;
m_scfg.DX10SamplerResources.value = true;
m_scfg.vpuMask.hasValue = true;
m_scfg.vpuMask.value = m_vpuMask;
m_scfg.bEnableHighPerformanceState.hasValue = true;
m_scfg.bEnableHighPerformanceState.value = enableHighPerformanceState;
m_dcfg.disableMarkUsedInCmdBuf.hasValue = true;
m_dcfg.disableMarkUsedInCmdBuf.value = false;
// Enable immediate memory release
m_dcfg.immediateMemoryRelease.hasValue = true;
m_dcfg.immediateMemoryRelease.value = true;
m_dcfg.bEnableSvm.hasValue = true;
m_dcfg.bEnableSvm.value = reportAsOCL12Device ? false : OPENCL_MAJOR >= 2;
m_dcfg.bEnableFlatAddressing.hasValue = true;
#ifdef ATI_BITS_32
m_dcfg.bEnableFlatAddressing.value = false;
#else
m_dcfg.bEnableFlatAddressing.value = reportAsOCL12Device ? false : (OPENCL_MAJOR >= 2);
#endif
//we can use environment variable CAL_ENABLE_ASYNC_DMA to force dma on or off when we need it
char *s = NULL;
if((s = getenv("CAL_ENABLE_ASYNC_DMA")))
{
m_dcfg.drmdmaMode.hasValue = true;
m_dcfg.drmdmaMode.value = (atoi(s) == 0) ? GSL_CONFIG_DRMDMA_MODE_FORCE_OFF : GSL_CONFIG_DRMDMA_MODE_DEFAULT;
}
// Use GPU_USE_SYNC_OBJECTS to force syncobject on or off when we need it
m_dcfg.syncObjectMode.hasValue = true;
m_dcfg.syncObjectMode.value = (GPU_USE_SYNC_OBJECTS) ?
GSL_CONFIG_SYNCOBJECT_MODE_ON : GSL_CONFIG_SYNCOBJECT_MODE_OFF;
// Use GPU_IFH_MODE to test with IFH mode enabled
m_dcfg.DropFlush.hasValue = true;
m_dcfg.DropFlush.value = (GPU_IFH_MODE == 1);
// Enable TC compatible htile mode. It's HW feature for VI+ and controlled in HWL.
// Depth interop doesn't support TC compatible htile mode, but OCL needs correct tiling setup.
m_dcfg.bEnableTCCompatibleHtile.hasValue = true;
m_dcfg.bEnableTCCompatibleHtile.value = true;
int32 asic_id = 0;
if (!SetupAdapter(asic_id))
{
return false;
}
if (!SetupContext(asic_id))
{
return false;
}
if (m_PerformLazyDeviceInit)
{
// close the adaptor
gsAdaptor::closeAdaptor(m_adp);
m_adp = 0;
}
else
{
PerformFullInitialization();
}
return true;
}
void
CALGSLDevice::close()
{
gslVidShutdown();
if (m_cs != NULL)
{
m_cs->Flush();
}
if (m_dstDRMDMAMem)
{
resFree(m_dstDRMDMAMem);
m_dstDRMDMAMem = NULL ;
}
if (m_srcDRMDMAMem)
{
resFree(m_srcDRMDMAMem);
m_srcDRMDMAMem = NULL ;
}
if (m_cs != NULL)
{
m_cs->destroyTextureResource(m_textureResource);
m_cs->destroySampler(m_textureSampler);
m_cs->destroyQuery(m_mapQuery);
m_cs->destroyQuery(m_mapDMAQuery);
m_cs->destroyQuery(m_mapUVDQuery);
m_cs->destroyQuery(m_mapVCEQuery);
m_cs->setRenderState(0);
m_cs->destroyRenderState(m_rs);
m_rs = 0;
m_adp->deleteContext(m_cs);
m_cs = 0;
}
if (m_adp != NULL)
{
gsAdaptor::closeAdaptor(m_adp);
m_adp = 0;
}
}
void
CALGSLDevice::PerformAdapterInitialization() const
{
CALGSLDevice* mutable_this = const_cast<CALGSLDevice*>(this);
mutable_this->PerformAdapterInitialization_int();
}
void
CALGSLDevice::PerformFullInitialization() const
{
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
CALGSLDevice* mutable_this = const_cast<CALGSLDevice*>(this);
mutable_this->PerformFullInitialization_int();
}
bool
CALGSLDevice::SetupAdapter(int32 &asic_id)
{
PerformAdapterInitialization();
if (m_adp == 0)
{
return false;
}
m_vpucount = m_adp->getNumLinkedVPUs();
asic_id = m_adp->getAsicID();
bool hasDmaEngine = m_adp->findDMAEngine();
bool hasComputeEngine = m_adp->findComputeEngine();
m_canDMA = hasDmaEngine;
m_adp->queryAvailableEngines(&m_nEngines, m_engines);
//Disable DRMDMA on CFX mode for linux on all GPUs.
#ifdef ATI_OS_LINUX
if ((m_vpucount > 1) && !DRMDMA_FOR_LNX_CF)
{
m_canDMA = ATIGL_FALSE;
}
#endif
if (asic_id < GSL_ATIASIC_ID_TAHITI_P ||
asic_id == GSL_ATIASIC_ID_DEVASTATOR ||
asic_id == GSL_ATIASIC_ID_SCRAPPER)
{
m_computeRing = false;
}
else
{
m_computeRing = true;
}
if (!flagIsDefault(GPU_NUM_COMPUTE_RINGS))
{
m_computeRing = (GPU_NUM_COMPUTE_RINGS != 0);
}
if ((!flagIsDefault(GPU_SELECT_COMPUTE_RINGS_ID)) && (m_computeRing))
{
gslEngineID engineID;
engineID = static_cast<gslEngineID>(GPU_SELECT_COMPUTE_RINGS_ID + GSL_ENGINEID_COMPUTE0);
if ((engineID >= GSL_ENGINEID_COMPUTE0) && (engineID <= GSL_ENGINEID_COMPUTE7))
{
for (uint i = 0; i < m_nEngines; ++i) {
if (m_engines[i].id == engineID){
m_isComputeRingIDForced = true;
m_forcedComputeEngineID = engineID;
break;
}
}
}
}
if (m_computeRing && !hasComputeEngine)
{
return false;
}
return true;
}
bool
CALGSLDevice::SetupContext(int32 &asic_id)
{
gsl::gsCtx* temp_cs = m_adp->createComputeContext(m_computeRing ? (m_isComputeRingIDForced ? m_forcedComputeEngineID : GSL_ENGINEID_COMPUTE0)
: GSL_ENGINEID_3DCOMPUTE0, m_canDMA ? GSL_ENGINEID_DRMDMA0 : GSL_ENGINEID_INVALID);
temp_cs->getMainSubCtx()->setVPUMask(m_vpuMask);
m_revision = temp_cs->getChipRev();
m_maxtexturesize = temp_cs->getMaxTextureSize();
switch (asic_id)
{
case GSL_ATIASIC_ID_R870:
m_target = CAL_TARGET_CYPRESS;
m_elfmachine = ED_ATI_CAL_MACHINE_CYPRESS_ISA;
break;
case GSL_ATIASIC_ID_R830:
m_target = CAL_TARGET_JUNIPER;
m_elfmachine = ED_ATI_CAL_MACHINE_JUNIPER_ISA;
break;
case GSL_ATIASIC_ID_REDWOOD:
m_target = CAL_TARGET_REDWOOD;
m_elfmachine = ED_ATI_CAL_MACHINE_REDWOOD_ISA;
break;
case GSL_ATIASIC_ID_CEDAR:
m_target = CAL_TARGET_CEDAR;
m_elfmachine = ED_ATI_CAL_MACHINE_CEDAR_ISA;
break;
case GSL_ATIASIC_ID_CAYMAN:
m_target = CAL_TARGET_CAYMAN;
m_elfmachine = ED_ATI_CAL_MACHINE_CAYMAN_ISA;
break;
case GSL_ATIASIC_ID_BARTS:
m_target = CAL_TARGET_BARTS;
m_elfmachine = ED_ATI_CAL_MACHINE_BARTS_ISA;
break;
case GSL_ATIASIC_ID_TURKS:
m_target = CAL_TARGET_TURKS;
m_elfmachine = ED_ATI_CAL_MACHINE_TURKS_ISA;
break;
case GSL_ATIASIC_ID_CAICOS:
m_target = CAL_TARGET_CAICOS;
m_elfmachine = ED_ATI_CAL_MACHINE_CAICOS_ISA;
break;
case GSL_ATIASIC_ID_SUMO:
m_target = CAL_TARGET_SUMO;
m_elfmachine = ED_ATI_CAL_MACHINE_SUMO_ISA;
break;
case GSL_ATIASIC_ID_SUPERSUMO:
m_target = CAL_TARGET_SUPERSUMO;
m_elfmachine = ED_ATI_CAL_MACHINE_SUPERSUMO_ISA;
break;
case GSL_ATIASIC_ID_WRESTLER:
m_target = CAL_TARGET_WRESTLER;
m_elfmachine = ED_ATI_CAL_MACHINE_WRESTLER_ISA;
break;
case GSL_ATIASIC_ID_TAHITI_P:
m_target = CAL_TARGET_TAHITI;
m_elfmachine = ED_ATI_CAL_MACHINE_TAHITI_ISA;
break;
case GSL_ATIASIC_ID_PITCAIRN_PM:
m_target = CAL_TARGET_PITCAIRN;
m_elfmachine = ED_ATI_CAL_MACHINE_PITCAIRN_ISA;
break;
case GSL_ATIASIC_ID_CAPEVERDE_M:
m_target = CAL_TARGET_CAPEVERDE;
m_elfmachine = ED_ATI_CAL_MACHINE_CAPEVERDE_ISA;
break;
case GSL_ATIASIC_ID_DEVASTATOR:
m_target = CAL_TARGET_DEVASTATOR;
m_elfmachine = ED_ATI_CAL_MACHINE_DEVASTATOR_ISA;
break;
case GSL_ATIASIC_ID_SCRAPPER:
m_target = CAL_TARGET_SCRAPPER;
m_elfmachine = ED_ATI_CAL_MACHINE_SCRAPPER_ISA;
break;
case GSL_ATIASIC_ID_OLAND_M:
m_target = CAL_TARGET_OLAND;
m_elfmachine = ED_ATI_CAL_MACHINE_OLAND_ISA;
break;
case GSL_ATIASIC_ID_HAINAN_M:
m_target = CAL_TARGET_HAINAN;
m_elfmachine = ED_ATI_CAL_MACHINE_HAINAN_ISA;
break;
case GSL_ATIASIC_ID_BONAIRE_M:
m_target = CAL_TARGET_BONAIRE;
m_elfmachine = ED_ATI_CAL_MACHINE_BONAIRE_ISA;
break;
case GSL_ATIASIC_ID_SPECTRE:
m_target = CAL_TARGET_SPECTRE;
m_elfmachine = ED_ATI_CAL_MACHINE_SPECTRE_ISA;
break;
case GSL_ATIASIC_ID_SPOOKY:
m_target = CAL_TARGET_SPOOKY;
m_elfmachine = ED_ATI_CAL_MACHINE_SPOOKY_ISA;
break;
case GSL_ATIASIC_ID_KALINDI:
m_target = CAL_TARGET_KALINDI;
m_elfmachine = ED_ATI_CAL_MACHINE_KALINDI_ISA;
break;
case GSL_ATIASIC_ID_HAWAII_P:
m_target = CAL_TARGET_HAWAII;
m_elfmachine = ED_ATI_CAL_MACHINE_HAWAII_ISA;
break;
case GSL_ATIASIC_ID_ICELAND_M:
m_target = CAL_TARGET_ICELAND;
m_elfmachine = ED_ATI_CAL_MACHINE_ICELAND_ISA;
break;
case GSL_ATIASIC_ID_TONGA_P:
m_target = CAL_TARGET_TONGA;
m_elfmachine = ED_ATI_CAL_MACHINE_TONGA_ISA;
break;
case GSL_ATIASIC_ID_GODAVARI:
m_target = CAL_TARGET_GODAVARI;
m_elfmachine = ED_ATI_CAL_MACHINE_GODAVARI_ISA;
break;
case GSL_ATIASIC_ID_FIJI_P:
m_target = CAL_TARGET_FIJI;
m_elfmachine = ED_ATI_CAL_MACHINE_FIJI_ISA;
break;
case GSL_ATIASIC_ID_CARRIZO:
m_target = CAL_TARGET_CARRIZO;
m_elfmachine = ED_ATI_CAL_MACHINE_CARRIZO_ISA;
break;
case GSL_ATIASIC_ID_ELLESMERE:
m_target = CAL_TARGET_ELLESMERE;
m_elfmachine = ED_ATI_CAL_MACHINE_ELLESMERE_ISA;
break;
case GSL_ATIASIC_ID_BAFFIN:
m_target = CAL_TARGET_BAFFIN;
m_elfmachine = ED_ATI_CAL_MACHINE_BAFFIN_ISA;
break;
case GSL_ATIASIC_ID_GREENLAND:
m_target = CAL_TARGET_GREENLAND;
m_elfmachine = ED_ATI_CAL_MACHINE_GREENLAND_ISA;
break;
default:
// 6XX is not supported
m_adp->deleteContext(temp_cs);
gsAdaptor::closeAdaptor(m_adp);
m_adp = 0;
assert(0);
return false;
}
gslVidInit();
//cache device details
gslVideoContext temp_vid_context;
temp_vid_context.m_gsCtx = temp_cs;
temp_vid_context.VideoEngine_name = GSL_VID_CONTEXT_VIDEO;
getAttribs_int(temp_cs);
getVideoAttribs_int(&temp_vid_context);
getStatus_int(temp_cs);
m_vmMode = temp_cs->getVMMode();
m_adp->deleteContext(temp_cs);
return true;
}
void
CALGSLDevice::PerformAdapterInitialization_int()
{
if (m_adp == 0)
{
if (m_usePerVPUAdapterModel)
{
m_adp = gsAdaptor::openAdaptorByIndex<gsl::gsAdaptor>(m_gpuIndex, &m_scfg, &m_dcfg);
}
else
{
m_adp = gsAdaptor::openAdaptor(m_nativeDisplayHandle, m_chainIndex, &m_scfg, &m_dcfg);
}
assert(m_adp != 0);
}
}
void
CALGSLDevice::PerformFullInitialization_int()
{
if (m_adp == 0)
{
PerformAdapterInitialization_int();
}
if (m_cs == 0)
{
m_cs = m_adp->createComputeContext(m_computeRing ? (m_isComputeRingIDForced ? m_forcedComputeEngineID : GSL_ENGINEID_COMPUTE0)
: GSL_ENGINEID_3DCOMPUTE0, m_canDMA ? GSL_ENGINEID_DRMDMA0 : GSL_ENGINEID_INVALID);
m_cs->getMainSubCtx()->setVPUMask(m_vpuMask);
//
// Check if the command stream has a DMA connection and allow DMA if there
// is a connection and we can actually DMA
//
bool dmaConnection = m_cs->getDrmDma0Ctx() && m_cs->getDrmDma0Ctx()->ioInfo.iolConnection;
m_allowDMA = (dmaConnection && m_canDMA);
m_rs = m_cs->createRenderState();
m_cs->setRenderState(m_rs);
m_cs->Flush();
m_mapQuery = m_cs->createQuery(GSL_SYNC_ATI);
m_mapDMAQuery = m_cs->createQuery(GSL_DRMDMA_SYNC_ATI);
m_mapUVDQuery = m_cs->createQuery(GSL_UVD_SYNC_ATI);
m_mapVCEQuery = m_cs->createQuery(GSL_VCE_SYNC_ATI);
// Allocate 1x1 FART and Vid memory for DMA flush
CALresourceDesc desc;
memset(&desc, 0, sizeof(CALresourceDesc));
desc.type = GSL_MOA_MEMORY_AGP;
desc.size.width = 1;
desc.size.height = 1;
desc.format = CM_SURF_FMT_R32F;
desc.channelOrder = GSL_CHANNEL_ORDER_R;
desc.dimension = GSL_MOA_TEXTURE_2D;
m_srcDRMDMAMem = resAlloc(&desc);
desc.type = GSL_MOA_MEMORY_CARD_EXT_NONEXT;
m_dstDRMDMAMem = resAlloc(&desc);
m_cs->setDMAFlushBuf(m_srcDRMDMAMem, m_dstDRMDMAMem, 4 /*size of CM_SURF_FMT_R32F*/);
m_PerformLazyDeviceInit = false;
m_uavInCB = m_cs->getIsUAVInCB();
m_textureResource = m_cs->createTextureResource();
m_textureSampler = m_cs->createSampler();
}
}
uint32
CALGSLDevice::getVPUCount()
{
return m_vpucount;
}
void
Wait(gsl::gsCtx* cs, gslQueryTarget target, gslQueryObject object)
{
uint64 param;
// This should never be called for UVD/VCE Sync queries in case it is
// Please correctly pass on EngineMask else queries may be messed up
assert(target != GSL_UVD_SYNC_ATI || target != GSL_VCE_SYNC_ATI);
uint32 mask = (target == GSL_DRMDMA_SYNC_ATI) ? GSL_ENGINE_MASK(GSL_ENGINEID_DRMDMA0) | GSL_ENGINE_MASK(GSL_ENGINEID_DRMDMA1) : GSL_ENGINEMASK_ALL_BUT_UVD_VCE;
object->BeginQuery(cs, target, 0, mask);
object->EndQuery(cs, 0);
object->GetResult(cs, &param);
assert(param == 1);
}
bool
CALGSLDevice::ResolveAperture(const gslMemObjectAttribTiling tiling) const
{
// Don't ask for aperture if the tiling is linear.
if ((GSL_MOA_TILING_LINEAR == tiling) ||
(GSL_MOA_TILING_LINEAR_GENERAL == tiling))
{
return false;
}
// Use aperture.
return true;
}
gslMemObject
CALGSLDevice::resAlloc(const CALresourceDesc* desc) const
{
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
assert(m_cs != 0);
gslMemObject mem = 0;
uint32 flags = desc->flags;
gslMemObjectAttribs attribs(
GSL_MOA_TEXTURE_1D, // type
GSL_MOA_MEMORY_CARD_EXT_NONEXT, // location XXX
(flags & CAL_RESALLOC_GLOBAL_BUFFER) ? GSL_MOA_TILING_LINEAR : g_CALBETiling_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
);
attribs.location = desc->type;
attribs.vaBase = desc->vaBase;
attribs.section = desc->section;
attribs.isAllocExecute = desc->isAllocExecute;
attribs.minAlignment = desc->minAlignment;
//!@note GSL asserts with tiled 1D images of any type.
if ((desc->dimension == GSL_MOA_BUFFER) ||
(desc->dimension == GSL_MOA_TEXTURE_1D) ||
(desc->dimension == GSL_MOA_TEXTURE_1D_ARRAY) ||
(desc->dimension == GSL_MOA_TEXTURE_BUFFER))
{
attribs.tiling = GSL_MOA_TILING_LINEAR;
}
if (desc->type == GSL_MOA_MEMORY_SYSTEM)
{
// CPU addres and size for pinning
attribs.cpu_address = desc->systemMemory;
attribs.size = desc->systemMemorySize;
if ((desc->size.width % 64) == 0)
{
attribs.tiling = GSL_MOA_TILING_LINEAR;
}
else
{
// Use linear general if width isn't aligned
attribs.tiling = GSL_MOA_TILING_LINEAR_GENERAL;
}
}
else if (desc->type == GSL_MOA_MEMORY_CARD_EXTERNAL_PHYSICAL)
{
attribs.cpu_address = (void*)desc->busAddress;
}
// Don't ask for aperture if the tiling is linear.
attribs.useAperture = ResolveAperture(attribs.tiling);
attribs.channelOrder = desc->channelOrder;
attribs.type = desc->dimension;
if (desc->mipLevels > 1) {
attribs.levels = desc->mipLevels;
attribs.mipmap = true;
}
switch (desc->dimension)
{
case GSL_MOA_BUFFER:
mem = m_cs->createMemObject1D(desc->format, desc->size.width, &attribs);
break;
case GSL_MOA_TEXTURE_1D:
mem = m_cs->createMemObject1D(desc->format, desc->size.width, &attribs);
break;
case GSL_MOA_TEXTURE_2D:
mem = m_cs->createMemObject2D(desc->format, desc->size.width, (uint32)desc->size.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;
}
#ifdef ATI_OS_WIN
if ((desc->section == GSL_SECTION_SVM || desc->section == GSL_SECTION_SVM_ATOMICS) && mem == NULL) {
//svm allocation failure, try one more time after wait.
Wait(m_cs, GSL_SYNC_ATI, m_mapQuery);
mem = m_cs->createMemObject1D(desc->format, desc->size.width, &attribs);
}
#endif
return mem;
}
gslMemObject
CALGSLDevice::resAllocView(gslMemObject res, gslResource3D size, CALdomain offset, cmSurfFmt format,
gslChannelOrder channelOrder, gslMemObjectAttribType resType, uint32 level, uint32 layer, uint32 flags,
uint64 bytePitch) const
{
assert(m_cs != 0);
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
gslMemObjectAttribs attribs(
GSL_MOA_TEXTURE_2D, // type. Filled in below based on the base type.
GSL_MOA_MEMORY_ALIAS, // location. Filled in below based on the base location.
GSL_MOA_TILING_LINEAR, // tiling. Filled in below based on the flags passed in.
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
);
attribs.bytePitch = bytePitch;
attribs.section = res->getAttribs().section;
attribs.isAllocExecute = res->getAttribs().isAllocExecute;
// Need to get the alignment info from hwl.
// Not sure hwl is correct though. Linear aligned 256b, tiled 8kb according to the address library.
uint32 alignment;
switch (flags & ~CAL_RESALLOCSLICEVIEW_LEVEL_AND_LAYER)
{
case CAL_RESALLOCSLICEVIEW_LINEAR_ALIGNED:
alignment = 256;
attribs.tiling = GSL_MOA_TILING_LINEAR;
break;
case CAL_RESALLOCSLICEVIEW_LINEAR_UNALIGNED:
alignment = 1;
attribs.tiling = GSL_MOA_TILING_LINEAR_GENERAL;
break;
default:
alignment = 8192;
// GSL asserts if this tiled mode is differnt from the original surface.
// (For example, original is GSL_MOA_TILING_MACRO and the new one is GSL_MOA_TILING_TILED)
// Use the original mode for view allocation.
attribs.tiling = res->getAttribs().tiling;
if (attribs.tiling == GSL_MOA_TILING_LINEAR || attribs.tiling == GSL_MOA_TILING_LINEAR_GENERAL)
{
alignment = 256;
}
break;
};
// Don't handle offsets for tiled surfaces.
if (offset.x != 0 &&
offset.y != 0 &&
attribs.tiling == GSL_MOA_TILING_TILED)
{
return 0;
}
// Check any alignment restrictions.
uint64 resPitch = res->getPitch();
cmSurfFmt baseFormat = res->getFormat();
uint32 elementSize = cmGetSurfElementSize(static_cast<cmSurfFmt>(baseFormat));
uint64 offsetInBytes = (offset.y * (uint32)resPitch + offset.x) * elementSize;
if (offsetInBytes % alignment)
{
return 0; //offset doesn't match alignment requirements.
}
// alias has same location as the base resource.
attribs.type = res->getAttribs().type;
attribs.location = res->getAttribs().location;
attribs.displayable = res->getAttribs().displayable;
attribs.channelOrder = channelOrder;
gslMemObject mo = NULL, levelobject = res;
if (flags & CAL_RESALLOCSLICEVIEW_LEVEL)
{
const gsSubImageParam levelParam(level);
levelobject = m_cs->createSubMemObject(res, GSL_LEVEL, levelParam);
attribs.bytePitch = static_cast<size_t>(levelobject->getPitch()) *
(levelobject->getBitsPerElement() / 8);
}
if (flags & CAL_RESALLOCSLICEVIEW_LAYER)
{
const gsSubImageParam layerParam(layer);
mo = m_cs->createSubMemObject(levelobject, GSL_LAYER, layerParam);
if (levelobject != res)
{
m_cs->destroyMemObject(levelobject);
}
levelobject = mo;
}
attribs.type = resType;
switch (resType)
{
case GSL_MOA_BUFFER:
mo = m_cs->createOffsetMemObject1D(levelobject, offsetInBytes, format,
size.width, &attribs);
break;
case GSL_MOA_TEXTURE_1D:
mo = m_cs->createOffsetMemObject1D(levelobject, offsetInBytes, format,
size.width, &attribs);
break;
case GSL_MOA_TEXTURE_2D:
mo = m_cs->createOffsetMemObject2D(levelobject, offsetInBytes, format,
size.width, (uint32)size.height, &attribs);
break;
case GSL_MOA_TEXTURE_3D:
mo = m_cs->createOffsetMemObject3D(levelobject, offsetInBytes, format,
size.width, (uint32)size.height, (uint32)size.depth, &attribs);
break;
case GSL_MOA_TEXTURE_BUFFER:
mo = m_cs->createOffsetMemObject1D(levelobject, offsetInBytes, format,
size.width, &attribs);
break;
case GSL_MOA_TEXTURE_1D_ARRAY:
mo = m_cs->createOffsetMemObject3D(levelobject, offsetInBytes, format,
size.width, 1, (uint32)size.height, &attribs);
break;
case GSL_MOA_TEXTURE_2D_ARRAY:
mo = m_cs->createOffsetMemObject3D(levelobject, offsetInBytes, format,
size.width, (uint32)size.height, (uint32)size.depth, &attribs);
break;
default:
break;
}
if (levelobject != res)
{
m_cs->destroyMemObject(levelobject);
}
return mo;
}
enum MemMap_DMA
{
MemMap_DMA_None,
MemMap_DMA_DRMDMA,
MemMap_DMA_CPDMA
};
typedef struct _GSLDeviceMemMap_
{
gslMemObject mem;
MemMap_DMA dma;
uint32 flags;
bool32 lockable;
} GSLDeviceMemMap;
bool
CALGSLDevice::resMapLocal(void*& pPtr,
size_t& pitch,
gslMemObject mem,
gslMapAccessType flags,
bool isHwDebug)
{
assert(m_cs != 0);
assert(mem != 0);
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
//
// Allocate map structure for the unmap call
//
GSLDeviceMemMap* memMap = (GSLDeviceMemMap*)malloc(sizeof(GSLDeviceMemMap));
if (memMap == NULL)
{
return false;
}
gslMemObjectAttribLocation location = mem->getAttribs().location;
gslMemObject newMemDest = 0;
gslMemObject newMemSrc = 0;
bool needDestroy = 0;
uint64 width = mem->getRectWidth();
intp height = mem->getRectHeight();
cmSurfFmt format = mem->getFormat();
gslMemObjectAttribType dstType = mem->getAttribs().type;
gslMemObjectAttribs attribsDest(
dstType, // type
GSL_MOA_MEMORY_REMOTE_CACHEABLE, // location
GSL_MOA_TILING_LINEAR, // 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
);
attribsDest.channelOrder = mem->getAttribs().channelOrder;
//
// DMA 1D surfaces
//
MemMap_DMA dma = MemMap_DMA_DRMDMA;
if (location == GSL_MOA_MEMORY_CARD_LOCKABLE)
{
//
// direct lock
//
dma = MemMap_DMA_None;
memMap->lockable = ATIGL_TRUE;
// Get tiling mode and resolve the aperture settings.
bool useAperture;
gslMemObjectAttribTiling tiling = mem->getAttribs().tiling;
useAperture = ResolveAperture(tiling);
pPtr = mem->map(m_cs, GSL_MAP_NOSYNC, GSL_GPU_0, false, useAperture);
if (pPtr == NULL)
{
free(memMap);
return false;
}
//
// obtain the pitch of the buffer
//
uint64 tmppitch = mem->getPitch();
pitch = static_cast<size_t>(tmppitch);
m_hack.insert(std::pair<gslMemObject, intp>(mem, (intp) memMap));
}
else
{
memMap->lockable = ATIGL_FALSE;
//
// Create the target destination buffer
//
memMap->mem = m_cs->createMemObject2D(format, width, (uint32)height, &attribsDest);
if (memMap->mem == NULL)
{
attribsDest.location = GSL_MOA_MEMORY_AGP;
memMap->mem = m_cs->createMemObject2D(format, width, (uint32)height, &attribsDest);
if (memMap->mem == NULL)
{
free(memMap);
return false;
}
}
//
// set the pointer to it as the return buffer
//
void* tmp = memMap->mem->map(m_cs, GSL_MAP_NOSYNC, GSL_GPU_0, false, false);
if (tmp == 0)
{
m_cs->destroyMemObject(memMap->mem);
free(memMap);
return false;
}
pPtr = tmp;
//
// obtain the pitch of the temporary buffer
//
uint64 tmppitch = memMap->mem->getPitch();
pitch = static_cast<size_t>(tmppitch);
uint64 surfaceSize;
// avoid using CPDMA, which may cause deadlock with HW Debug
uint32 copyFlag = (isHwDebug) ? CAL_MEMCOPY_ASYNC : 0;
CopyType copy = GetCopyType(mem, memMap->mem, 0, 0, m_allowDMA, copyFlag, surfaceSize, 0, 0);
switch (copy)
{
case USE_CPDMA:
dma = MemMap_DMA_CPDMA;
break;
case USE_DRMDMA:
dma = MemMap_DMA_DRMDMA;
break;
default:
dma = MemMap_DMA_None;
break;
}
//
// For write only cases, we don't care about the data
//
switch (dma)
{
case MemMap_DMA_DRMDMA:
if (flags != GSL_MAP_WRITE_ONLY)
{
PerformDMACopy(mem, memMap->mem, (cmSurfFmt)format, CAL_MEMCOPY_SYNC, isHwDebug);
//
// Flush then wait
//
m_cs->Flush();
#ifdef USE_3D_SYNC
Wait(m_cs, GSL_SYNC_ATI, m_mapQuery);
#else
Wait(m_cs, GSL_DRMDMA_SYNC_ATI, m_mapDMAQuery);
#endif
}
break;
case MemMap_DMA_CPDMA:
memMap->mem->unmap(m_cs);
m_cs->destroyMemObject(memMap->mem);
memMap->mem = NULL;
pPtr = mem->map(m_cs, flags, GSL_GPU_0, true, false);
if (pPtr == NULL)
{
assert(0);
free(memMap);
return false;
}
break;
case MemMap_DMA_None:
assert(0);
break;
}
//
// XXX - lock free?
m_hack.insert(std::pair<gslMemObject, intp>(mem, (intp) memMap));
if (needDestroy)
{
m_cs->destroyMemObject(newMemSrc);
m_cs->destroyMemObject(newMemDest);
}
}
memMap->dma = dma;
memMap->flags = flags;
return true;
}
bool
CALGSLDevice::resUnmapLocal(gslMemObject mem, bool isHwDebug)
{
assert(m_cs != 0);
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
//
// Find the pairing
//
Hack::iterator iter = m_hack.find(mem);
if (iter == m_hack.end())
{
mem->unmap(m_cs);
return true;
}
GSLDeviceMemMap* memMap = (GSLDeviceMemMap*)iter->second;
m_hack.erase(iter);
if (memMap->lockable)
{
//
// direct unlock
//
mem->unmap(m_cs);
}
else
{
//
// Handle the different map cases. For readonly cases, we can forgo the
// copy back
//
//
// 770 flushes denorms to 0 during the copy. To be consistent with other platforms, we
// alias the memory as uint32 when doing the copies.
//
cmSurfFmt format = mem->getFormat();
switch (memMap->dma)
{
case MemMap_DMA_CPDMA:
mem->unmap(m_cs);
//
// Flush then wait
//
m_cs->Flush();
Wait(m_cs, GSL_SYNC_ATI, m_mapQuery);
break;
case MemMap_DMA_DRMDMA:
memMap->mem->unmap(m_cs);
if (memMap->flags != GSL_MAP_READ_ONLY)
{
if (PerformDMACopy(memMap->mem, mem, format, CAL_MEMCOPY_SYNC, isHwDebug) == false)
{
assert(0);
}
//
// Flush then wait
//
m_cs->Flush();
#ifdef USE_3D_SYNC
Wait(m_cs, GSL_SYNC_ATI, m_mapQuery);
#else
Wait(m_cs, GSL_DRMDMA_SYNC_ATI, m_mapDMAQuery);
#endif
}
m_cs->destroyMemObject(memMap->mem);
break;
case MemMap_DMA_None:
assert(0);
break;
}
}
free(memMap);
return true;
}
gslMemObject
CALGSLDevice::resGetHeap(size_t size) const
{
assert(m_cs != 0);
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
gslMemObjectAttribs attribs(
GSL_MOA_VIRTUAL_HEAP, // type
GSL_MOA_MEMORY_SYSTEM, // location
GSL_MOA_TILING_LINEAR, // 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
0, // channel_order
0 // size of cpu_address
);
gslMemObject rval = m_cs->createMemObject1D(CM_SURF_FMT_R32I, size, &attribs);
return rval;
}
bool
CALGSLDevice::resMapRemote(void*& pPtr,
size_t& pitch,
gslMemObject mem,
gslMapAccessType flags) const
{
assert(m_cs != 0);
assert(mem != 0);
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
pPtr = mem->map(m_cs, GSL_MAP_NOSYNC, GSL_GPU_0, false, false);
if (pPtr == NULL)
{
return false;
}
uint64 tmppitch = mem->getPitch();
pitch = static_cast<size_t>(tmppitch);
return true;
}
bool
CALGSLDevice::resUnmapRemote(gslMemObject mem) const
{
assert(m_cs != 0);
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
mem->unmap(m_cs);
return true;
}
bool
CALGSLDevice::PerformDMACopy(gslMemObject srcMem, gslMemObject destMem, cmSurfFmt format, CALuint flags, bool isHwDebug)
{
assert(m_cs != 0);
uint64 surfaceSize = srcMem->getSurfaceSize();
uint64 dstSize = destMem->getSurfaceSize();
//
// XXX -- this is somewhat lame. Need the actual amount of data
// to copy. Not the surface sizes. Since one is linear and one
// could be tiled. The smaller one should contain the size we need.
//
surfaceSize = (surfaceSize > dstSize) ? dstSize : surfaceSize;
uint32 mode;
if (isHwDebug) {
mode = 0; // Cannot use any sync flag to avoid possible deadlock due to halted wave
}
else {
switch (flags)
{
case CAL_MEMCOPY_SYNC:
mode = GSL_SYNCUPLOAD_SYNC_WAIT | GSL_SYNCUPLOAD_SYNC_START;
break;
case CAL_MEMCOPY_ASYNC:
assert(0);
//
// XXX -- not currently supported so fall through
//
case CAL_MEMCOPY_DEFAULT:
default:
mode = GSL_SYNCUPLOAD_SYNC_START;
break;
}
}
m_cs->DMACopy(srcMem, 0, destMem, 0, surfaceSize, mode, NULL);
return true;
}
void
CALGSLDevice::resCopy(gslMemObject srcRes, gslMemObject dstRes, uint32 flags) const
{
assert(m_cs != 0);
assert(srcRes != 0);
assert(dstRes != 0);
//! @note: GSL device isn't thread safe
amd::ScopedLock k(gslDeviceOps());
uint64 surfaceSize;
CopyType type = GetCopyType(srcRes, dstRes, 0, 0, m_allowDMA, 0, surfaceSize, 0, 0);
if (type == USE_DRMDMA)
{
m_cs->DMACopy(srcRes, 0, dstRes, 0, surfaceSize, GSL_SYNCUPLOAD_SYNC_WAIT, NULL);
m_cs->Flush();
Wait(m_cs, GSL_DRMDMA_SYNC_ATI, m_mapDMAQuery);
}
else if (type == USE_CPDMA)
{
m_cs->syncUploadRaw(srcRes, 0, dstRes, 0, surfaceSize, 0);
m_cs->Flush();
Wait(m_cs, GSL_SYNC_ATI, m_mapQuery);
}
else
{
assert(0 && "No copy engine is being used");
}
}
#define CPDMA_THRESHOLD 131072
CopyType
CALGSLDevice::GetCopyType(
gslMemObject srcMem,
gslMemObject destMem,
size_t* srcOffset,
size_t* destOffset,
bool allowDMA,
uint32 flags,
uint64& surfaceSize,
size_t size,
bool enableCopyRect) const
{
CopyType type = USE_NONE;
intp bppSrc = 0;
intp bppDst = 0;
gslMemObjectAttribTiling srcTiling = srcMem->getAttribs().tiling;
gslMemObjectAttribTiling dstTiling = destMem->getAttribs().tiling;
gslMemObjectAttribType srcType = srcMem->getAttribs().type;
gslMemObjectAttribType dstType = destMem->getAttribs().type;
uint64 srcSize = srcMem->getSurfaceSize();
uint64 dstSize = destMem->getSurfaceSize();
surfaceSize = (srcSize > dstSize) ? dstSize : srcSize;
if( size != 0)
srcSize = (srcSize > size) ? size : srcSize;
if(allowDMA == false) {
if(((srcTiling != GSL_MOA_TILING_LINEAR) && (srcTiling != GSL_MOA_TILING_LINEAR_GENERAL)) ||
((dstTiling != GSL_MOA_TILING_LINEAR) && (dstTiling != GSL_MOA_TILING_LINEAR_GENERAL))) {
type = USE_NONE;
return type;
}
}
// CPDMA isnt possible for anything other than a 1D_TEXURE or a BUFFER as it does a blind blob copy without regards to padding
bool isCPDMApossible = ((srcTiling == GSL_MOA_TILING_LINEAR) || srcTiling == GSL_MOA_TILING_LINEAR_GENERAL) &&
((dstTiling == GSL_MOA_TILING_LINEAR) || dstTiling == GSL_MOA_TILING_LINEAR_GENERAL) &&
(dstType == GSL_MOA_TEXTURE_1D || dstType == GSL_MOA_BUFFER) &&
(srcType == dstType);
//
// Use CPDMA for transfers < 128KB
//
if(isCPDMApossible && (((flags != CAL_MEMCOPY_ASYNC) && (srcSize <= CPDMA_THRESHOLD) && !enableCopyRect) ||
(allowDMA == false)) )
{
type = USE_CPDMA;
}
// ### Check for Particular kind of DRMDMA here
else if (allowDMA &&
(((srcType == GSL_MOA_TEXTURE_2D) && (dstType == GSL_MOA_BUFFER)) ||
((dstType == GSL_MOA_TEXTURE_2D) && (srcType == GSL_MOA_BUFFER))))
{
uint64 pitch;
uint64 linearBytePitch = 0;
if ((srcTiling != GSL_MOA_TILING_LINEAR) &&
(dstTiling == GSL_MOA_TILING_LINEAR))
{
bppSrc = srcMem->getBitsPerElement();
pitch = srcMem->getPitch();
linearBytePitch = size * (bppSrc / 8);
// Make sure linear pitch in bytes is 128 bytes aligned
// Note: Cypress restriction, Cayman should have 4 bytes
if (((linearBytePitch % 0x80) == 0) &&
// another DRM restriciton... Cayman has 4 pixels
(srcOffset[0] % 8 == 0))
{
type = USE_DRMDMA_T2L;
}
else
{
type = USE_NONE;
}
}
else if ((srcTiling == GSL_MOA_TILING_LINEAR) &&
(dstTiling != GSL_MOA_TILING_LINEAR))
{
bppDst = destMem->getBitsPerElement();
pitch = destMem->getPitch();
linearBytePitch = size * (bppDst / 8);
// Make sure linear pitch in bytes is 128 bytes aligned
// Note: Cypress restriction, Cayman should have 4 bytes
if (((linearBytePitch % 0x80) == 0) &&
// another DRM restriciton... Cayman has 4 pixels
(destOffset[0] % 8 == 0))
{
type = USE_DRMDMA_L2T;
}
else
{
type = USE_NONE;
}
}
else
{
type = USE_NONE;
}
}
else if (dstType == srcType)
{
type = USE_DRMDMA;
}
//
// Machine specific issues here
//
if (allowDMA && ((m_target == CAL_TARGET_CAYMAN) ||
(m_target == CAL_TARGET_DEVASTATOR) ||
(m_target == CAL_TARGET_SCRAPPER)
) &&
((bppSrc == 128 || bppDst == 128) &&
((srcTiling != GSL_MOA_TILING_LINEAR) ||
(dstTiling != GSL_MOA_TILING_LINEAR)))
)
{
type = USE_NONE;
}
return type;
}
uint32
CALGSLDevice::calcScratchBufferSize(uint32 regNum) const
{
gslProgramTargetEnum target = GSL_COMPUTE_PROGRAM;
// Determine the scratch size we need to allocate.
cmScratchSpaceNeededPerShaderStage scratchSpacePerShaderStage;
memset(&scratchSpacePerShaderStage, 0, sizeof(scratchSpacePerShaderStage));
uint32 scratchBufferSizes[gslProgramTarget_COUNT];
memset(scratchBufferSizes, 0, sizeof(scratchBufferSizes));
uint32 enabledShadersFlag = 0;
if (!uavInCB())
{
enabledShadersFlag |= CM_FRAGMENT_SHADER_BIT;
scratchSpacePerShaderStage.scratchSpace[CM_FRAGMENT_SHADER] = regNum;
target = GSL_FRAGMENT_PROGRAM;
}
else
{
enabledShadersFlag |= CM_COMPUTE_SHADER_BIT;
scratchSpacePerShaderStage.scratchSpace[CM_COMPUTE_SHADER] = regNum;
}
m_cs->CalcAllScratchBufferSizes(enabledShadersFlag, scratchSpacePerShaderStage,
scratchBufferSizes);
return scratchBufferSizes[target];
}
void
CALGSLDevice::convertInputChannelOrder(intp*channelOrder) const
{
// set default to indicate that we don't want to override the channel order.
// set all order to zero to indicate default.
channelSwizzle chanSwiz = {SWIZZLE_ZERO,
SWIZZLE_ZERO,
SWIZZLE_ZERO,
SWIZZLE_ZERO};
switch (*channelOrder) {
case GSL_CHANNEL_ORDER_R:
chanSwiz.r = SWIZZLE_COMPONENT0;
chanSwiz.g = SWIZZLE_ZERO;
chanSwiz.b = SWIZZLE_ZERO;
chanSwiz.a = SWIZZLE_ONE;
break;
case GSL_CHANNEL_ORDER_A:
chanSwiz.r = SWIZZLE_ZERO;
chanSwiz.g = SWIZZLE_ZERO;
chanSwiz.b = SWIZZLE_ZERO;
chanSwiz.a = SWIZZLE_COMPONENT0;
break;
case GSL_CHANNEL_ORDER_RG:
chanSwiz.r = SWIZZLE_COMPONENT0;
chanSwiz.g = SWIZZLE_COMPONENT1;
chanSwiz.b = SWIZZLE_ZERO;
chanSwiz.a = SWIZZLE_ONE;
break;
case GSL_CHANNEL_ORDER_RA:
chanSwiz.r = SWIZZLE_COMPONENT0;
chanSwiz.g = SWIZZLE_ZERO;
chanSwiz.b = SWIZZLE_ZERO;
chanSwiz.a = SWIZZLE_COMPONENT1;
break;
case GSL_CHANNEL_ORDER_RGB:
chanSwiz.r = SWIZZLE_COMPONENT0;
chanSwiz.g = SWIZZLE_COMPONENT1;
chanSwiz.b = SWIZZLE_COMPONENT2;
chanSwiz.a = SWIZZLE_ONE;
break;
case GSL_CHANNEL_ORDER_RGBA:
chanSwiz.r = SWIZZLE_COMPONENT0;
chanSwiz.g = SWIZZLE_COMPONENT1;
chanSwiz.b = SWIZZLE_COMPONENT2;
chanSwiz.a = SWIZZLE_COMPONENT3;
break;
case GSL_CHANNEL_ORDER_ARGB:
chanSwiz.r = SWIZZLE_COMPONENT1;
chanSwiz.g = SWIZZLE_COMPONENT2;
chanSwiz.b = SWIZZLE_COMPONENT3;
chanSwiz.a = SWIZZLE_COMPONENT0;
break;
case GSL_CHANNEL_ORDER_BGRA:
chanSwiz.r = SWIZZLE_COMPONENT2;
chanSwiz.g = SWIZZLE_COMPONENT1;
chanSwiz.b = SWIZZLE_COMPONENT0;
chanSwiz.a = SWIZZLE_COMPONENT3;
break;
case GSL_CHANNEL_ORDER_SRGB:
chanSwiz.r = SWIZZLE_COMPONENT0;
chanSwiz.g = SWIZZLE_COMPONENT1;
chanSwiz.b = SWIZZLE_COMPONENT2;
chanSwiz.a = SWIZZLE_ONE;
break;
case GSL_CHANNEL_ORDER_SRGBX:
chanSwiz.r = SWIZZLE_COMPONENT0;
chanSwiz.g = SWIZZLE_COMPONENT1;
chanSwiz.b = SWIZZLE_COMPONENT2;
chanSwiz.a = SWIZZLE_ONE;
break;
case GSL_CHANNEL_ORDER_SRGBA:
chanSwiz.r = SWIZZLE_COMPONENT0;
chanSwiz.g = SWIZZLE_COMPONENT1;
chanSwiz.b = SWIZZLE_COMPONENT2;
chanSwiz.a = SWIZZLE_COMPONENT3;
break;
case GSL_CHANNEL_ORDER_SBGRA:
chanSwiz.r = SWIZZLE_COMPONENT2;
chanSwiz.g = SWIZZLE_COMPONENT1;
chanSwiz.b = SWIZZLE_COMPONENT0;
chanSwiz.a = SWIZZLE_COMPONENT3;
break;
case GSL_CHANNEL_ORDER_REPLICATE_R:
chanSwiz.r = SWIZZLE_COMPONENT0;
chanSwiz.g = SWIZZLE_COMPONENT0;
chanSwiz.b = SWIZZLE_COMPONENT0;
chanSwiz.a = SWIZZLE_COMPONENT0;
break;
case GSL_CHANNEL_ORDER_INTENSITY:
chanSwiz.r = SWIZZLE_COMPONENT0;
chanSwiz.g = SWIZZLE_COMPONENT0;
chanSwiz.b = SWIZZLE_COMPONENT0;
chanSwiz.a = SWIZZLE_COMPONENT0;
break;
case GSL_CHANNEL_ORDER_LUMINANCE:
chanSwiz.r = SWIZZLE_COMPONENT0;
chanSwiz.g = SWIZZLE_COMPONENT0;
chanSwiz.b = SWIZZLE_COMPONENT0;
chanSwiz.a = SWIZZLE_ONE;
break;
default: assert(0); break;
};
*channelOrder = *(uint32 *)&chanSwiz;
}
void
CALGSLDevice::fillImageHwState(gslMemObject mem, void* hwState, uint32 hwStateSize) const
{
amd::ScopedLock k(gslDeviceOps());
intp channelOrder = mem->getAttribs().channelOrder;
convertInputChannelOrder(&channelOrder);
m_textureResource->updateDepthTextureParam(mem);
m_textureResource->getTextureSrd(m_cs, mem, reinterpret_cast<const char*>(&channelOrder),
hwState, hwStateSize);
}
void
CALGSLDevice::fillSamplerHwState(bool unnorm, uint32 min, uint32 mag, uint32 addr,
float minLod, float maxLod, void* hwState, uint32 hwStateSize) const
{
amd::ScopedLock k(gslDeviceOps());
m_textureSampler->setUnnormalizedMode(m_cs, unnorm);
m_textureSampler->setMinFilter(m_cs, static_cast<gslTexParameterParamMinFilter>(min));
m_textureSampler->setMagFilter(m_cs, static_cast<gslTexParameterParamMagFilter>(mag));
m_textureSampler->setWrap(m_cs, GSL_TEXTURE_WRAP_S, static_cast<gslTexParameterParamWrap>(addr));
m_textureSampler->setWrap(m_cs, GSL_TEXTURE_WRAP_T, static_cast<gslTexParameterParamWrap>(addr));
m_textureSampler->setWrap(m_cs, GSL_TEXTURE_WRAP_R, static_cast<gslTexParameterParamWrap>(addr));
m_textureSampler->setMinLOD(m_cs, static_cast<float32>(minLod));
m_textureSampler->setMaxLOD(m_cs, static_cast<float32>(maxLod));
m_textureSampler->getSamplerSrd(m_cs, hwState, hwStateSize);
}