/* * Copyright (C) 2019-2020 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/source/command_container/command_encoder.h" #include "shared/source/gmm_helper/gmm.h" #include "shared/source/gmm_helper/gmm_helper.h" #include "shared/source/gmm_helper/resource_info.h" #include "shared/source/helpers/blit_commands_helper.h" #include "shared/source/helpers/hw_helper.h" #include "shared/source/helpers/timestamp_packet.h" namespace NEO { template uint64_t BlitCommandsHelper::getMaxBlitWidth() { if (DebugManager.flags.LimitBlitterMaxWidth.get() != -1) { return static_cast(DebugManager.flags.LimitBlitterMaxWidth.get()); } return BlitterConstants::maxBlitWidth; } template uint64_t BlitCommandsHelper::getMaxBlitHeight() { if (DebugManager.flags.LimitBlitterMaxHeight.get() != -1) { return static_cast(DebugManager.flags.LimitBlitterMaxHeight.get()); } return BlitterConstants::maxBlitHeight; } template void BlitCommandsHelper::dispatchPostBlitCommand(LinearStream &linearStream) { bool useFlush = false; if (DebugManager.flags.FlushAfterEachBlit.get() != -1) { useFlush = static_cast(DebugManager.flags.FlushAfterEachBlit.get()); } if (useFlush) { EncodeMiFlushDW::programMiFlushDw(linearStream, 0, 0, false, false); } else { auto miArbCheckStream = linearStream.getSpaceForCmd(); *miArbCheckStream = GfxFamily::cmdInitArbCheck; } } template size_t BlitCommandsHelper::estimatePostBlitCommandSize() { bool useFlush = false; if (DebugManager.flags.FlushAfterEachBlit.get() != -1) { useFlush = static_cast(DebugManager.flags.FlushAfterEachBlit.get()); } if (useFlush) { return sizeof(typename GfxFamily::MI_FLUSH_DW); } return sizeof(typename GfxFamily::MI_ARB_CHECK); } template size_t BlitCommandsHelper::estimateBlitCommandsSize(Vec3 copySize, const CsrDependencies &csrDependencies, bool updateTimestampPacket, bool profilingEnabled) { size_t numberOfBlits = 0; uint64_t width = 1; uint64_t height = 1; for (uint64_t slice = 0; slice < copySize.z; slice++) { for (uint64_t row = 0; row < copySize.y; row++) { uint64_t sizeToBlit = copySize.x; while (sizeToBlit != 0) { if (sizeToBlit > getMaxBlitWidth()) { // dispatch 2D blit: maxBlitWidth x (1 .. maxBlitHeight) width = getMaxBlitWidth(); height = std::min((sizeToBlit / width), getMaxBlitHeight()); } else { // dispatch 1D blt: (1 .. maxBlitWidth) x 1 width = sizeToBlit; height = 1; } sizeToBlit -= (width * height); numberOfBlits++; } } } const size_t cmdsSizePerBlit = (sizeof(typename GfxFamily::XY_COPY_BLT) + estimatePostBlitCommandSize()); size_t timestampCmdSize = 0; if (updateTimestampPacket) { if (profilingEnabled) { timestampCmdSize = 4 * sizeof(typename GfxFamily::MI_STORE_REGISTER_MEM); } else { timestampCmdSize = EncodeMiFlushDW::getMiFlushDwCmdSizeForDataWrite(); } } return TimestampPacketHelper::getRequiredCmdStreamSize(csrDependencies) + (cmdsSizePerBlit * numberOfBlits) + timestampCmdSize; } template size_t BlitCommandsHelper::estimateBlitCommandsSize(const BlitPropertiesContainer &blitPropertiesContainer, const HardwareInfo &hwInfo, bool profilingEnabled) { size_t size = 0; for (auto &blitProperties : blitPropertiesContainer) { size += BlitCommandsHelper::estimateBlitCommandsSize(blitProperties.copySize, blitProperties.csrDependencies, blitProperties.outputTimestampPacket != nullptr, profilingEnabled); } size += MemorySynchronizationCommands::getSizeForAdditonalSynchronization(hwInfo); size += EncodeMiFlushDW::getMiFlushDwCmdSizeForDataWrite() + sizeof(typename GfxFamily::MI_BATCH_BUFFER_END); return alignUp(size, MemoryConstants::cacheLineSize); } template uint64_t BlitCommandsHelper::calculateBlitCommandDestinationBaseAddress(const BlitProperties &blitProperties, uint64_t offset, uint64_t row, uint64_t slice) { return blitProperties.dstGpuAddress + blitProperties.dstOffset.x + offset + blitProperties.dstOffset.y * blitProperties.dstRowPitch + blitProperties.dstOffset.z * blitProperties.dstSlicePitch + row * blitProperties.dstRowPitch + slice * blitProperties.dstSlicePitch; } template uint64_t BlitCommandsHelper::calculateBlitCommandSourceBaseAddress(const BlitProperties &blitProperties, uint64_t offset, uint64_t row, uint64_t slice) { return blitProperties.srcGpuAddress + blitProperties.srcOffset.x + offset + blitProperties.srcOffset.y * blitProperties.srcRowPitch + blitProperties.srcOffset.z * blitProperties.srcSlicePitch + row * blitProperties.srcRowPitch + slice * blitProperties.srcSlicePitch; } template void BlitCommandsHelper::dispatchBlitCommandsForBuffer(const BlitProperties &blitProperties, LinearStream &linearStream, const RootDeviceEnvironment &rootDeviceEnvironment) { uint64_t width = 1; uint64_t height = 1; for (uint64_t slice = 0; slice < blitProperties.copySize.z; slice++) { for (uint64_t row = 0; row < blitProperties.copySize.y; row++) { uint64_t offset = 0; uint64_t sizeToBlit = blitProperties.copySize.x; while (sizeToBlit != 0) { if (sizeToBlit > getMaxBlitWidth()) { // dispatch 2D blit: maxBlitWidth x (1 .. maxBlitHeight) width = getMaxBlitWidth(); height = std::min((sizeToBlit / width), getMaxBlitHeight()); } else { // dispatch 1D blt: (1 .. maxBlitWidth) x 1 width = sizeToBlit; height = 1; } { auto bltCmd = GfxFamily::cmdInitXyCopyBlt; bltCmd.setTransferWidth(static_cast(width)); bltCmd.setTransferHeight(static_cast(height)); bltCmd.setDestinationPitch(static_cast(width)); bltCmd.setSourcePitch(static_cast(width)); auto dstAddr = calculateBlitCommandDestinationBaseAddress(blitProperties, offset, row, slice); auto srcAddr = calculateBlitCommandSourceBaseAddress(blitProperties, offset, row, slice); bltCmd.setDestinationBaseAddress(dstAddr); bltCmd.setSourceBaseAddress(srcAddr); appendBlitCommandsForBuffer(blitProperties, bltCmd, rootDeviceEnvironment); auto bltStream = linearStream.getSpaceForCmd(); *bltStream = bltCmd; } dispatchPostBlitCommand(linearStream); auto blitSize = width * height; sizeToBlit -= blitSize; offset += blitSize; } } } } template template void BlitCommandsHelper::dispatchBlitMemoryFill(NEO::GraphicsAllocation *dstAlloc, uint32_t *pattern, LinearStream &linearStream, size_t size, const RootDeviceEnvironment &rootDeviceEnvironment, COLOR_DEPTH depth) { using XY_COLOR_BLT = typename GfxFamily::XY_COLOR_BLT; auto blitCmd = GfxFamily::cmdInitXyColorBlt; blitCmd.setFillColor(pattern); blitCmd.setColorDepth(depth); uint64_t offset = 0; uint64_t sizeToFill = size; while (sizeToFill != 0) { auto tmpCmd = blitCmd; tmpCmd.setDestinationBaseAddress(ptrOffset(dstAlloc->getGpuAddress(), static_cast(offset))); uint64_t height = 0; uint64_t width = 0; if (sizeToFill <= getMaxBlitWidth()) { width = sizeToFill; height = 1; } else { width = getMaxBlitWidth(); height = std::min((sizeToFill / width), getMaxBlitHeight()); if (height > 1) { appendTilingEnable(tmpCmd); } } tmpCmd.setTransferWidth(static_cast(width)); tmpCmd.setTransferHeight(static_cast(height)); tmpCmd.setDestinationPitch(static_cast(width)); appendBlitCommandsForFillBuffer(dstAlloc, tmpCmd, rootDeviceEnvironment); auto cmd = linearStream.getSpaceForCmd(); *cmd = tmpCmd; auto blitSize = width * height; offset += (blitSize); sizeToFill -= blitSize; } } template void BlitCommandsHelper::dispatchBlitCommandsForImages(const BlitProperties &blitProperties, LinearStream &linearStream, const RootDeviceEnvironment &rootDeviceEnvironment) { auto dstAllocation = blitProperties.dstAllocation; auto srcAllocation = blitProperties.srcAllocation; UNRECOVERABLE_IF(blitProperties.copySize.x > BlitterConstants::maxBlitWidth || blitProperties.copySize.y > BlitterConstants::maxBlitWidth); auto bltCmd = GfxFamily::cmdInitXyCopyBlt; bltCmd.setSourceBaseAddress(srcAllocation->getGpuAddress()); bltCmd.setDestinationBaseAddress(dstAllocation->getGpuAddress()); bltCmd.setDestinationX1CoordinateLeft(static_cast(blitProperties.dstOffset.x)); bltCmd.setDestinationY1CoordinateTop(static_cast(blitProperties.dstOffset.y)); bltCmd.setTransferWidth(static_cast(blitProperties.dstOffset.x + blitProperties.copySize.x)); bltCmd.setTransferHeight(static_cast(blitProperties.dstOffset.y + blitProperties.copySize.y)); bltCmd.setSourceX1CoordinateLeft(static_cast(blitProperties.srcOffset.x)); bltCmd.setSourceY1CoordinateTop(static_cast(blitProperties.srcOffset.y)); appendBlitCommandsForBuffer(blitProperties, bltCmd, rootDeviceEnvironment); appendBlitCommandsForImages(blitProperties, bltCmd); appendColorDepth(blitProperties, bltCmd); appendSurfaceType(blitProperties, bltCmd); for (uint32_t i = 0; i < blitProperties.copySize.z; i++) { appendSliceOffsets(blitProperties, bltCmd, i); auto cmd = linearStream.getSpaceForCmd(); *cmd = bltCmd; } } } // namespace NEO