From 496012d82fb6bb0fa45d1de3cdd05742e95b1e88 Mon Sep 17 00:00:00 2001 From: Lukasz Jobczyk Date: Wed, 28 Aug 2024 10:25:16 +0000 Subject: [PATCH] performance: Use copy buffer rect middle builtin Signed-off-by: Lukasz Jobczyk --- .../built_ins/builtins_dispatch_builder.cpp | 252 +++++++++++++----- .../enqueue_copy_buffer_rect_tests.cpp | 2 +- shared/source/os_interface/product_helper.h | 1 + .../product_helper_bdw_and_later.inl | 5 + .../source/os_interface/product_helper_hw.h | 1 + .../product_helper_xe2_and_later.inl | 5 + .../product_helper_xe_hpg_and_xe_hpc.inl | 5 + .../test/common/mocks/mock_product_helper.cpp | 5 + 8 files changed, 214 insertions(+), 62 deletions(-) diff --git a/opencl/source/built_ins/builtins_dispatch_builder.cpp b/opencl/source/built_ins/builtins_dispatch_builder.cpp index 8a4ded383c..4bb993b128 100644 --- a/opencl/source/built_ins/builtins_dispatch_builder.cpp +++ b/opencl/source/built_ins/builtins_dispatch_builder.cpp @@ -182,91 +182,191 @@ class BuiltInOp : public BuiltinDispatchInfoBuilder template bool buildDispatchInfosTyped(MultiDispatchInfo &multiDispatchInfo) const { - DispatchInfoBuilder kernelNoSplit3DBuilder(clDevice); auto &operationParams = multiDispatchInfo.peekBuiltinOpParams(); size_t hostPtrSize = 0; + size_t srcOffsetFromAlignedPtr = 0; + size_t dstOffsetFromAlignedPtr = 0; bool is3D = false; + auto srcPtr = operationParams.srcPtr; + auto dstPtr = operationParams.dstPtr; if (operationParams.srcMemObj && operationParams.dstMemObj) { - DEBUG_BREAK_IF(!((operationParams.srcPtr == nullptr) && (operationParams.dstPtr == nullptr))); + DEBUG_BREAK_IF(!((srcPtr == nullptr) && (dstPtr == nullptr))); is3D = (operationParams.size.z > 1) || (operationParams.srcOffset.z > 0) || (operationParams.dstOffset.z > 0); } else { - if (operationParams.srcPtr) { + if (srcPtr) { size_t origin[] = {operationParams.srcOffset.x, operationParams.srcOffset.y, operationParams.srcOffset.z}; size_t region[] = {operationParams.size.x, operationParams.size.y, operationParams.size.z}; hostPtrSize = Buffer::calculateHostPtrSize(origin, region, operationParams.srcRowPitch, operationParams.srcSlicePitch); is3D = (operationParams.size.z > 1) || (operationParams.dstOffset.z > 0); - } else if (operationParams.dstPtr) { + if (!is3D) { + auto srcPtrOffset = ptrOffset(srcPtr, operationParams.srcOffset.z * operationParams.srcSlicePitch); + srcPtr = alignDown(srcPtrOffset, 4); + srcOffsetFromAlignedPtr = ptrDiff(srcPtrOffset, srcPtr); + } + } else if (dstPtr) { size_t origin[] = {operationParams.dstOffset.x, operationParams.dstOffset.y, operationParams.dstOffset.z}; size_t region[] = {operationParams.size.x, operationParams.size.y, operationParams.size.z}; hostPtrSize = Buffer::calculateHostPtrSize(origin, region, operationParams.dstRowPitch, operationParams.dstSlicePitch); is3D = (operationParams.size.z > 1) || (operationParams.srcOffset.z > 0); + if (!is3D) { + auto dstPtrOffset = ptrOffset(dstPtr, operationParams.dstOffset.z * operationParams.dstSlicePitch); + dstPtr = alignDown(dstPtrOffset, 4); + dstOffsetFromAlignedPtr = ptrDiff(dstPtrOffset, dstPtr); + } } else { DEBUG_BREAK_IF(!false); } } - uint32_t rootDeviceIndex = clDevice.getRootDeviceIndex(); + const uint32_t rootDeviceIndex = clDevice.getRootDeviceIndex(); + const int dimensions = is3D ? 3 : 2; - // Set-up ISA - int dimensions = is3D ? 3 : 2; - kernelNoSplit3DBuilder.setKernel(kernelBytes[dimensions - 1]->getKernel(rootDeviceIndex)); + if (this->clDevice.getProductHelper().isCopyBufferRectSplitSupported()) { + DispatchInfoBuilder kernelSplit3DBuilder(clDevice); - size_t srcOffsetFromAlignedPtr = 0; - size_t dstOffsetFromAlignedPtr = 0; - - // arg0 = src - if (operationParams.srcMemObj) { - kernelNoSplit3DBuilder.setArg(0, operationParams.srcMemObj); - } else { - void *srcPtrToSet = operationParams.srcPtr; - if (!is3D) { - auto srcPtr = ptrOffset(operationParams.srcPtr, operationParams.srcOffset.z * operationParams.srcSlicePitch); - srcPtrToSet = alignDown(srcPtr, 4); - srcOffsetFromAlignedPtr = ptrDiff(srcPtr, srcPtrToSet); + const auto totalSize = operationParams.size.x * operationParams.size.y * operationParams.size.z; + if (totalSize == 0u) { + return true; } - kernelNoSplit3DBuilder.setArgSvm(0, hostPtrSize, srcPtrToSet, nullptr, CL_MEM_READ_ONLY); - } - bool isDestinationInSystem = false; - // arg1 = dst - if (operationParams.dstMemObj) { - kernelNoSplit3DBuilder.setArg(1, operationParams.dstMemObj); - isDestinationInSystem = Kernel::graphicsAllocationTypeUseSystemMemory(operationParams.dstMemObj->getGraphicsAllocation(rootDeviceIndex)->getAllocationType()); - } else { - void *dstPtrToSet = operationParams.dstPtr; - if (!is3D) { - auto dstPtr = ptrOffset(operationParams.dstPtr, operationParams.dstOffset.z * operationParams.dstSlicePitch); - dstPtrToSet = alignDown(dstPtr, 4); - dstOffsetFromAlignedPtr = ptrDiff(dstPtr, dstPtrToSet); + const uintptr_t start = reinterpret_cast(dstPtr) + operationParams.dstOffset.x; + + constexpr size_t middleAlignment = MemoryConstants::cacheLineSize; + constexpr size_t middleElSize = sizeof(uint32_t) * 4; + + uintptr_t leftSize = start % middleAlignment; + leftSize = (leftSize > 0) ? (middleAlignment - leftSize) : 0; // calc left leftover size + leftSize = std::min(leftSize, operationParams.size.x); // clamp left leftover size to requested size + + uintptr_t rightSize = (start + operationParams.size.x) % middleAlignment; // calc right leftover size + rightSize = std::min(rightSize, (operationParams.size.x > leftSize) ? (operationParams.size.x - leftSize) : 0); // clamp + + const uintptr_t middleSizeBytes = (operationParams.size.x > leftSize + rightSize) ? operationParams.size.x - leftSize - rightSize : 0u; // calc middle size + + // corner case - fully optimized kernel requires DWORD alignment. If we don't have it, run slower, misaligned kernel + const auto srcMiddleStart = reinterpret_cast(srcPtr) + operationParams.srcOffset.x + leftSize; + const auto srcMisalignment = srcMiddleStart % sizeof(uint32_t); + const auto rowPitchMisalignment = operationParams.srcRowPitch % sizeof(uint32_t); + const auto slicePitchMisalignment = operationParams.srcSlicePitch % sizeof(uint32_t); + const auto isSrcMisaligned = srcMisalignment != 0u || rowPitchMisalignment != 0u || slicePitchMisalignment != 0u; + + const auto middleSizeEls = middleSizeBytes / middleElSize; // num work items in middle walker + + // Set-up ISA + + kernelSplit3DBuilder.setKernel(SplitDispatch::RegionCoordX::left, kernelLeft[dimensions - 1]->getKernel(rootDeviceIndex)); + if (isSrcMisaligned) { + kernelSplit3DBuilder.setKernel(SplitDispatch::RegionCoordX::middle, kernelBytes[dimensions - 1]->getKernel(rootDeviceIndex)); + } else { + kernelSplit3DBuilder.setKernel(SplitDispatch::RegionCoordX::middle, kernelMiddle[dimensions - 1]->getKernel(rootDeviceIndex)); } - kernelNoSplit3DBuilder.setArgSvm(1, hostPtrSize, dstPtrToSet, nullptr, 0u); - isDestinationInSystem = operationParams.dstPtr != nullptr; + kernelSplit3DBuilder.setKernel(SplitDispatch::RegionCoordX::right, kernelRight[dimensions - 1]->getKernel(rootDeviceIndex)); + + // arg0 = src + if (operationParams.srcMemObj) { + kernelSplit3DBuilder.setArg(0, operationParams.srcMemObj); + } else { + kernelSplit3DBuilder.setArgSvm(0, hostPtrSize, srcPtr, nullptr, CL_MEM_READ_ONLY); + } + + bool isDestinationInSystem = false; + // arg1 = dst + if (operationParams.dstMemObj) { + kernelSplit3DBuilder.setArg(1, operationParams.dstMemObj); + isDestinationInSystem = Kernel::graphicsAllocationTypeUseSystemMemory(operationParams.dstMemObj->getGraphicsAllocation(rootDeviceIndex)->getAllocationType()); + } else { + kernelSplit3DBuilder.setArgSvm(1, hostPtrSize, dstPtr, nullptr, 0u); + isDestinationInSystem = dstPtr != nullptr; + } + kernelSplit3DBuilder.setKernelDestinationArgumentInSystem(isDestinationInSystem); + + // arg2 = srcOrigin + OffsetType kSrcOrigin[4] = {static_cast(operationParams.srcOffset.x + srcOffsetFromAlignedPtr), static_cast(operationParams.srcOffset.y), static_cast(operationParams.srcOffset.z), 0}; + kernelSplit3DBuilder.setArg(SplitDispatch::RegionCoordX::left, 2, sizeof(OffsetType) * 4, kSrcOrigin); + kSrcOrigin[0] += static_cast(leftSize); + kernelSplit3DBuilder.setArg(SplitDispatch::RegionCoordX::middle, 2, sizeof(OffsetType) * 4, kSrcOrigin); + kSrcOrigin[0] += static_cast(middleSizeBytes); + kernelSplit3DBuilder.setArg(SplitDispatch::RegionCoordX::right, 2, sizeof(OffsetType) * 4, kSrcOrigin); + + // arg3 = dstOrigin + OffsetType kDstOrigin[4] = {static_cast(operationParams.dstOffset.x + dstOffsetFromAlignedPtr), static_cast(operationParams.dstOffset.y), static_cast(operationParams.dstOffset.z), 0}; + kernelSplit3DBuilder.setArg(SplitDispatch::RegionCoordX::left, 3, sizeof(OffsetType) * 4, kDstOrigin); + kDstOrigin[0] += static_cast(leftSize); + kernelSplit3DBuilder.setArg(SplitDispatch::RegionCoordX::middle, 3, sizeof(OffsetType) * 4, kDstOrigin); + kDstOrigin[0] += static_cast(middleSizeBytes); + kernelSplit3DBuilder.setArg(SplitDispatch::RegionCoordX::right, 3, sizeof(OffsetType) * 4, kDstOrigin); + + // arg4 = srcPitch + OffsetType kSrcPitch[2] = {static_cast(operationParams.srcRowPitch), static_cast(operationParams.srcSlicePitch)}; + kernelSplit3DBuilder.setArg(4, sizeof(OffsetType) * 2, kSrcPitch); + + // arg5 = dstPitch + OffsetType kDstPitch[2] = {static_cast(operationParams.dstRowPitch), static_cast(operationParams.dstSlicePitch)}; + kernelSplit3DBuilder.setArg(5, sizeof(OffsetType) * 2, kDstPitch); + + // Set-up work sizes + kernelSplit3DBuilder.setDispatchGeometry(SplitDispatch::RegionCoordX::left, Vec3{leftSize, operationParams.size.y, operationParams.size.z}, Vec3{0, 0, 0}, Vec3{0, 0, 0}); + kernelSplit3DBuilder.getDispatchInfo(0u).setDim(0u); + + kernelSplit3DBuilder.setDispatchGeometry(SplitDispatch::RegionCoordX::middle, Vec3{isSrcMisaligned ? middleSizeBytes : middleSizeEls, operationParams.size.y, operationParams.size.z}, Vec3{0, 0, 0}, Vec3{0, 0, 0}); + kernelSplit3DBuilder.getDispatchInfo(1u).setDim(0u); + + kernelSplit3DBuilder.setDispatchGeometry(SplitDispatch::RegionCoordX::right, Vec3{rightSize, operationParams.size.y, operationParams.size.z}, Vec3{0, 0, 0}, Vec3{0, 0, 0}); + kernelSplit3DBuilder.getDispatchInfo(2u).setDim(0u); + + kernelSplit3DBuilder.bake(multiDispatchInfo); + + UNRECOVERABLE_IF(leftSize + rightSize + middleSizeEls * middleElSize != operationParams.size.x); + + return true; + } else { + DispatchInfoBuilder kernelNoSplit3DBuilder(clDevice); + + // Set-up ISA + kernelNoSplit3DBuilder.setKernel(kernelBytes[dimensions - 1]->getKernel(rootDeviceIndex)); + + // arg0 = src + if (operationParams.srcMemObj) { + kernelNoSplit3DBuilder.setArg(0, operationParams.srcMemObj); + } else { + kernelNoSplit3DBuilder.setArgSvm(0, hostPtrSize, srcPtr, nullptr, CL_MEM_READ_ONLY); + } + + bool isDestinationInSystem = false; + // arg1 = dst + if (operationParams.dstMemObj) { + kernelNoSplit3DBuilder.setArg(1, operationParams.dstMemObj); + isDestinationInSystem = Kernel::graphicsAllocationTypeUseSystemMemory(operationParams.dstMemObj->getGraphicsAllocation(rootDeviceIndex)->getAllocationType()); + } else { + kernelNoSplit3DBuilder.setArgSvm(1, hostPtrSize, dstPtr, nullptr, 0u); + isDestinationInSystem = dstPtr != nullptr; + } + kernelNoSplit3DBuilder.setKernelDestinationArgumentInSystem(isDestinationInSystem); + + // arg2 = srcOrigin + OffsetType kSrcOrigin[4] = {static_cast(operationParams.srcOffset.x + srcOffsetFromAlignedPtr), static_cast(operationParams.srcOffset.y), static_cast(operationParams.srcOffset.z), 0}; + kernelNoSplit3DBuilder.setArg(2, sizeof(OffsetType) * 4, kSrcOrigin); + + // arg3 = dstOrigin + OffsetType kDstOrigin[4] = {static_cast(operationParams.dstOffset.x + dstOffsetFromAlignedPtr), static_cast(operationParams.dstOffset.y), static_cast(operationParams.dstOffset.z), 0}; + kernelNoSplit3DBuilder.setArg(3, sizeof(OffsetType) * 4, kDstOrigin); + + // arg4 = srcPitch + OffsetType kSrcPitch[2] = {static_cast(operationParams.srcRowPitch), static_cast(operationParams.srcSlicePitch)}; + kernelNoSplit3DBuilder.setArg(4, sizeof(OffsetType) * 2, kSrcPitch); + + // arg5 = dstPitch + OffsetType kDstPitch[2] = {static_cast(operationParams.dstRowPitch), static_cast(operationParams.dstSlicePitch)}; + kernelNoSplit3DBuilder.setArg(5, sizeof(OffsetType) * 2, kDstPitch); + + // Set-up work sizes + kernelNoSplit3DBuilder.setDispatchGeometry(operationParams.size, Vec3{0, 0, 0}, Vec3{0, 0, 0}); + kernelNoSplit3DBuilder.bake(multiDispatchInfo); + + return true; } - kernelNoSplit3DBuilder.setKernelDestinationArgumentInSystem(isDestinationInSystem); - - // arg2 = srcOrigin - OffsetType kSrcOrigin[4] = {static_cast(operationParams.srcOffset.x + srcOffsetFromAlignedPtr), static_cast(operationParams.srcOffset.y), static_cast(operationParams.srcOffset.z), 0}; - kernelNoSplit3DBuilder.setArg(2, sizeof(OffsetType) * 4, kSrcOrigin); - - // arg3 = dstOrigin - OffsetType kDstOrigin[4] = {static_cast(operationParams.dstOffset.x + dstOffsetFromAlignedPtr), static_cast(operationParams.dstOffset.y), static_cast(operationParams.dstOffset.z), 0}; - kernelNoSplit3DBuilder.setArg(3, sizeof(OffsetType) * 4, kDstOrigin); - - // arg4 = srcPitch - OffsetType kSrcPitch[2] = {static_cast(operationParams.srcRowPitch), static_cast(operationParams.srcSlicePitch)}; - kernelNoSplit3DBuilder.setArg(4, sizeof(OffsetType) * 2, kSrcPitch); - - // arg5 = dstPitch - OffsetType kDstPitch[2] = {static_cast(operationParams.dstRowPitch), static_cast(operationParams.dstSlicePitch)}; - kernelNoSplit3DBuilder.setArg(5, sizeof(OffsetType) * 2, kDstPitch); - - // Set-up work sizes - kernelNoSplit3DBuilder.setDispatchGeometry(operationParams.size, Vec3{0, 0, 0}, Vec3{0, 0, 0}); - kernelNoSplit3DBuilder.bake(multiDispatchInfo); - - return true; } bool buildDispatchInfos(MultiDispatchInfo &multiDispatchInfo) const override { @@ -275,6 +375,9 @@ class BuiltInOp : public BuiltinDispatchInfoBuilder protected: MultiDeviceKernel *kernelBytes[3]{}; + MultiDeviceKernel *kernelLeft[3]{}; + MultiDeviceKernel *kernelMiddle[3]{}; + MultiDeviceKernel *kernelRight[3]{}; BuiltInOp(BuiltIns &kernelsLib, ClDevice &device, bool populateKernels) : BuiltinDispatchInfoBuilder(kernelsLib, device) { if (populateKernels) { @@ -282,7 +385,16 @@ class BuiltInOp : public BuiltinDispatchInfoBuilder "", "CopyBufferRectBytes2d", kernelBytes[0], "CopyBufferRectBytes2d", kernelBytes[1], - "CopyBufferRectBytes3d", kernelBytes[2]); + "CopyBufferRectBytes3d", kernelBytes[2], + "CopyBufferRectBytes2d", kernelLeft[0], + "CopyBufferRectBytes2d", kernelLeft[1], + "CopyBufferRectBytes3d", kernelLeft[2], + "CopyBufferRectBytesMiddle2d", kernelMiddle[0], + "CopyBufferRectBytesMiddle2d", kernelMiddle[1], + "CopyBufferRectBytesMiddle3d", kernelMiddle[2], + "CopyBufferRectBytes2d", kernelRight[0], + "CopyBufferRectBytes2d", kernelRight[1], + "CopyBufferRectBytes3d", kernelRight[2]); } } }; @@ -296,7 +408,16 @@ class BuiltInOp : public BuiltInOp(multiDispatchInfo); @@ -312,7 +433,16 @@ class BuiltInOp : public BuiltInOp CompilerOptions::greaterThan4gbBuffersRequired, "CopyBufferRectBytes2d", kernelBytes[0], "CopyBufferRectBytes2d", kernelBytes[1], - "CopyBufferRectBytes3d", kernelBytes[2]); + "CopyBufferRectBytes3d", kernelBytes[2], + "CopyBufferRectBytes2d", kernelLeft[0], + "CopyBufferRectBytes2d", kernelLeft[1], + "CopyBufferRectBytes3d", kernelLeft[2], + "CopyBufferRectBytesMiddle2d", kernelMiddle[0], + "CopyBufferRectBytesMiddle2d", kernelMiddle[1], + "CopyBufferRectBytesMiddle3d", kernelMiddle[2], + "CopyBufferRectBytes2d", kernelRight[0], + "CopyBufferRectBytes2d", kernelRight[1], + "CopyBufferRectBytes3d", kernelRight[2]); } bool buildDispatchInfos(MultiDispatchInfo &multiDispatchInfo) const override { return buildDispatchInfosTyped(multiDispatchInfo); diff --git a/opencl/test/unit_test/command_queue/enqueue_copy_buffer_rect_tests.cpp b/opencl/test/unit_test/command_queue/enqueue_copy_buffer_rect_tests.cpp index f70b73446f..66aa7e6288 100644 --- a/opencl/test/unit_test/command_queue/enqueue_copy_buffer_rect_tests.cpp +++ b/opencl/test/unit_test/command_queue/enqueue_copy_buffer_rect_tests.cpp @@ -373,7 +373,7 @@ HWCMDTEST_F(IGFX_GEN8_CORE, EnqueueCopyBufferRectTest, WhenCopyingBufferRect3DTh // Verify GPGPU_WALKER parameters EXPECT_NE(0u, cmd->getThreadGroupIdXDimension()); EXPECT_NE(0u, cmd->getThreadGroupIdYDimension()); - EXPECT_LT(1u, cmd->getThreadGroupIdZDimension()); + EXPECT_NE(0u, cmd->getThreadGroupIdZDimension()); EXPECT_NE(0u, cmd->getRightExecutionMask()); EXPECT_NE(0u, cmd->getBottomExecutionMask()); EXPECT_EQ(GPGPU_WALKER::SIMD_SIZE_SIMD32, cmd->getSimdSize()); diff --git a/shared/source/os_interface/product_helper.h b/shared/source/os_interface/product_helper.h index b2c79347da..00dd82d8a5 100644 --- a/shared/source/os_interface/product_helper.h +++ b/shared/source/os_interface/product_helper.h @@ -153,6 +153,7 @@ class ProductHelper { virtual bool isIpSamplingSupported(const HardwareInfo &hwInfo) const = 0; virtual bool isGrfNumReportedWithScm() const = 0; virtual bool isThreadArbitrationPolicyReportedWithScm() const = 0; + virtual bool isCopyBufferRectSplitSupported() const = 0; virtual bool isCooperativeEngineSupported(const HardwareInfo &hwInfo) const = 0; virtual bool isTimestampWaitSupportedForEvents() const = 0; virtual bool isTilePlacementResourceWaRequired(const HardwareInfo &hwInfo) const = 0; diff --git a/shared/source/os_interface/product_helper_bdw_and_later.inl b/shared/source/os_interface/product_helper_bdw_and_later.inl index ed931f6168..876dc9a78a 100644 --- a/shared/source/os_interface/product_helper_bdw_and_later.inl +++ b/shared/source/os_interface/product_helper_bdw_and_later.inl @@ -75,6 +75,11 @@ bool ProductHelperHw::isTimestampWaitSupportedForEvents() const { return false; } +template +bool ProductHelperHw::isCopyBufferRectSplitSupported() const { + return false; +} + template uint32_t ProductHelperHw::getCommandBuffersPreallocatedPerCommandQueue() const { return 0u; diff --git a/shared/source/os_interface/product_helper_hw.h b/shared/source/os_interface/product_helper_hw.h index 99eb5d1f25..7b3260eb56 100644 --- a/shared/source/os_interface/product_helper_hw.h +++ b/shared/source/os_interface/product_helper_hw.h @@ -95,6 +95,7 @@ class ProductHelperHw : public ProductHelper { bool isIpSamplingSupported(const HardwareInfo &hwInfo) const override; bool isGrfNumReportedWithScm() const override; bool isThreadArbitrationPolicyReportedWithScm() const override; + bool isCopyBufferRectSplitSupported() const override; bool isFlatRingBufferSupported() const override; bool isCooperativeEngineSupported(const HardwareInfo &hwInfo) const override; bool isTimestampWaitSupportedForEvents() const override; diff --git a/shared/source/os_interface/product_helper_xe2_and_later.inl b/shared/source/os_interface/product_helper_xe2_and_later.inl index 9783c9041f..2fcdc467ff 100644 --- a/shared/source/os_interface/product_helper_xe2_and_later.inl +++ b/shared/source/os_interface/product_helper_xe2_and_later.inl @@ -78,6 +78,11 @@ bool ProductHelperHw::isInitBuiltinAsyncSupported(const HardwareInfo return false; } +template +bool ProductHelperHw::isCopyBufferRectSplitSupported() const { + return true; +} + template bool ProductHelperHw::isTimestampWaitSupportedForEvents() const { return true; diff --git a/shared/source/os_interface/product_helper_xe_hpg_and_xe_hpc.inl b/shared/source/os_interface/product_helper_xe_hpg_and_xe_hpc.inl index 052ca4a3f7..ad7d898428 100644 --- a/shared/source/os_interface/product_helper_xe_hpg_and_xe_hpc.inl +++ b/shared/source/os_interface/product_helper_xe_hpg_and_xe_hpc.inl @@ -74,6 +74,11 @@ bool ProductHelperHw::isInitBuiltinAsyncSupported(const HardwareInfo return true; } +template +bool ProductHelperHw::isCopyBufferRectSplitSupported() const { + return false; +} + template bool ProductHelperHw::isTimestampWaitSupportedForEvents() const { return true; diff --git a/shared/test/common/mocks/mock_product_helper.cpp b/shared/test/common/mocks/mock_product_helper.cpp index 41c024dfe5..82573105a1 100644 --- a/shared/test/common/mocks/mock_product_helper.cpp +++ b/shared/test/common/mocks/mock_product_helper.cpp @@ -221,6 +221,11 @@ bool ProductHelperHw::isInitBuiltinAsyncSupported(const HardwareIn return false; } +template <> +bool ProductHelperHw::isCopyBufferRectSplitSupported() const { + return false; +} + template <> bool ProductHelperHw::isAdditionalMediaSamplerProgrammingRequired() const { return false;