#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; 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(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(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.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.priSupport = m_adp->pAsicInfo->priSupport; m_attribs.vaStart = static_cast(m_adp->pAsicInfo->vaStart); m_attribs.vaEnd = static_cast(m_adp->pAsicInfo->vaEnd); m_attribs.numOfVpu = m_adp->pAsicInfo->numberOfVPU; m_attribs.isOpenCL200Device = m_adp->pAsicInfo->bIsOpen2Device; } 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(vidInfo.video_attribs[i].decodeProfile); video_attribs[i].decodeFormat = static_cast(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); 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(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(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; //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 switch (asic_id) { case GSL_ATIASIC_ID_TAHITI_P: case GSL_ATIASIC_ID_PITCAIRN_PM: case GSL_ATIASIC_ID_CAPEVERDE_M: case GSL_ATIASIC_ID_OLAND_M: case GSL_ATIASIC_ID_HAINAN_M: case GSL_ATIASIC_ID_BONAIRE_M: case GSL_ATIASIC_ID_KALINDI: case GSL_ATIASIC_ID_HAWAII_P: case GSL_ATIASIC_ID_ICELAND_M: case GSL_ATIASIC_ID_TONGA_P: case GSL_ATIASIC_ID_GODAVARI: case GSL_ATIASIC_ID_BERMUDA_P: case GSL_ATIASIC_ID_FIJI_P: case GSL_ATIASIC_ID_CARRIZO: m_computeRing = true; break; default: m_computeRing = false; break; } if (!flagIsDefault(GPU_NUM_COMPUTE_RINGS)) { m_computeRing = (GPU_NUM_COMPUTE_RINGS != 0); } if (m_computeRing && !hasComputeEngine) { return false; } return true; } bool CALGSLDevice::SetupContext(int32 &asic_id) { gsl::gsCtx* temp_cs = m_adp->createComputeContext(m_computeRing ? 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_BERMUDA_P: m_target = CAL_TARGET_BERMUDA; m_elfmachine = ED_ATI_CAL_MACHINE_BERMUDA_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; 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(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 ? 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, ¶m); 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.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; 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; // 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(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(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) { 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(tmppitch); m_hack.insert(std::pair(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(tmppitch); uint64 surfaceSize; CopyType copy = GetCopyType(mem, memMap->mem, 0, 0, m_allowDMA, 0, 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); // // 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(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) { 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) == 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(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) { 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; 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"); } } void CALGSLDevice::queryDeviceEngines(uint32 *nEngines, gslEngineDescriptor *engines) { PerformFullInitialization(); m_adp->queryAvailableEngines(nEngines, engines); } #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(&channelOrder), hwState, hwStateSize); } void CALGSLDevice::fillSamplerHwState(bool unnorm, uint32 min, uint32 mag, uint32 addr, void* hwState, uint32 hwStateSize) const { amd::ScopedLock k(gslDeviceOps()); m_textureSampler->setUnnormalizedMode(m_cs, unnorm); m_textureSampler->setMinFilter(m_cs, static_cast(min)); m_textureSampler->setMagFilter(m_cs, static_cast(mag)); m_textureSampler->setWrap(m_cs, GSL_TEXTURE_WRAP_S, static_cast(addr)); m_textureSampler->setWrap(m_cs, GSL_TEXTURE_WRAP_T, static_cast(addr)); m_textureSampler->setWrap(m_cs, GSL_TEXTURE_WRAP_R, static_cast(addr)); m_textureSampler->getSamplerSrd(m_cs, hwState, hwStateSize); }