/* * Copyright (c) 2017 - 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include "runtime/mem_obj/buffer.h" #include "runtime/memory_manager/svm_memory_manager.h" #include "runtime/gmm_helper/gmm_helper.h" #include "unit_tests/fixtures/device_fixture.h" #include "unit_tests/fixtures/memory_management_fixture.h" #include "unit_tests/helpers/debug_manager_state_restore.h" #include "unit_tests/helpers/memory_management.h" #include "unit_tests/mocks/mock_context.h" #include "unit_tests/mocks/mock_command_queue.h" #include "unit_tests/fixtures/platform_fixture.h" #include "unit_tests/libult/ult_command_stream_receiver.h" #include "runtime/helpers/options.h" #include "gtest/gtest.h" #include "gmock/gmock.h" #include "test.h" using namespace OCLRT; static const unsigned int g_scTestBufferSizeInBytes = 16; TEST(Buffer, FromCL_nullptr_returnsNullPtr) { EXPECT_EQ(nullptr, castToObject(nullptr)); } class BufferTest : public DeviceFixture, public testing::TestWithParam { public: BufferTest() { } protected: void SetUp() override { flags = GetParam(); DeviceFixture::SetUp(); contextMemoryManager = context.getMemoryManager(); context.setMemoryManager(pDevice->getMemoryManager()); } void TearDown() override { context.setMemoryManager(contextMemoryManager); DeviceFixture::TearDown(); } cl_int retVal = CL_SUCCESS; MockContext context; MemoryManager *contextMemoryManager; cl_mem_flags flags = 0; unsigned char pHostPtr[g_scTestBufferSizeInBytes]; }; typedef BufferTest NoHostPtr; TEST_P(NoHostPtr, ValidFlags) { auto buffer = Buffer::create( &context, flags, g_scTestBufferSizeInBytes, nullptr, retVal); ASSERT_EQ(CL_SUCCESS, retVal); ASSERT_NE(nullptr, buffer); auto address = buffer->getCpuAddress(); EXPECT_NE(nullptr, address); delete buffer; } TEST_P(NoHostPtr, GivenNoHostPtrWhenHwBufferCreationFailsThenReturnNullptr) { BufferFuncs BufferFuncsBackup[IGFX_MAX_CORE]; for (uint32_t i = 0; i < IGFX_MAX_CORE; i++) { BufferFuncsBackup[i] = bufferFactory[i]; bufferFactory[i].createBufferFunction = [](Context *, cl_mem_flags, size_t, void *, void *, GraphicsAllocation *, bool, bool, bool) -> OCLRT::Buffer * { return nullptr; }; } auto buffer = Buffer::create( &context, flags, g_scTestBufferSizeInBytes, nullptr, retVal); EXPECT_EQ(nullptr, buffer); for (uint32_t i = 0; i < IGFX_MAX_CORE; i++) { bufferFactory[i] = BufferFuncsBackup[i]; } } TEST_P(NoHostPtr, completionStamp) { auto buffer = Buffer::create( &context, flags, g_scTestBufferSizeInBytes, nullptr, retVal); FlushStamp expectedFlushstamp = 0; ASSERT_EQ(CL_SUCCESS, retVal); ASSERT_NE(nullptr, buffer); EXPECT_EQ(0u, buffer->getCompletionStamp().taskCount); EXPECT_EQ(expectedFlushstamp, buffer->getCompletionStamp().flushStamp); EXPECT_EQ(0u, buffer->getCompletionStamp().deviceOrdinal); EXPECT_EQ(0u, buffer->getCompletionStamp().engineType); CompletionStamp completionStamp; completionStamp.taskCount = 42; completionStamp.deviceOrdinal = 43; completionStamp.engineType = EngineType::ENGINE_RCS; completionStamp.flushStamp = 5; buffer->setCompletionStamp(completionStamp, nullptr, nullptr); EXPECT_EQ(completionStamp.taskCount, buffer->getCompletionStamp().taskCount); EXPECT_EQ(completionStamp.flushStamp, buffer->getCompletionStamp().flushStamp); EXPECT_EQ(completionStamp.deviceOrdinal, buffer->getCompletionStamp().deviceOrdinal); EXPECT_EQ(completionStamp.engineType, buffer->getCompletionStamp().engineType); delete buffer; } TEST_P(NoHostPtr, WithUseHostPtr_returnsError) { auto buffer = Buffer::create( &context, flags | CL_MEM_USE_HOST_PTR, g_scTestBufferSizeInBytes, nullptr, retVal); EXPECT_EQ(CL_INVALID_HOST_PTR, retVal); EXPECT_EQ(nullptr, buffer); delete buffer; } TEST_P(NoHostPtr, WithCopyHostPtr_returnsError) { auto buffer = Buffer::create( &context, flags | CL_MEM_COPY_HOST_PTR, g_scTestBufferSizeInBytes, nullptr, retVal); EXPECT_EQ(CL_INVALID_HOST_PTR, retVal); EXPECT_EQ(nullptr, buffer); delete buffer; } TEST_P(NoHostPtr, withBufferGraphicsAllocationReportsBufferType) { auto buffer = Buffer::create( &context, flags, g_scTestBufferSizeInBytes, nullptr, retVal); ASSERT_EQ(CL_SUCCESS, retVal); ASSERT_NE(nullptr, buffer); auto &allocation = *buffer->getGraphicsAllocation(); auto type = allocation.getAllocationType(); auto isTypeBuffer = !!(type & GraphicsAllocation::ALLOCATION_TYPE_BUFFER); EXPECT_TRUE(isTypeBuffer); auto isTypeWritable = !!(type & GraphicsAllocation::ALLOCATION_TYPE_WRITABLE); auto isBufferWritable = !(flags & (CL_MEM_READ_ONLY | CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS)); EXPECT_EQ(isBufferWritable, isTypeWritable); delete buffer; } // Parameterized test that tests buffer creation with all flags // that should be valid with a nullptr host ptr cl_mem_flags NoHostPtrFlags[] = { CL_MEM_READ_WRITE, CL_MEM_WRITE_ONLY, CL_MEM_READ_ONLY, CL_MEM_HOST_READ_ONLY, CL_MEM_HOST_WRITE_ONLY, CL_MEM_HOST_NO_ACCESS}; INSTANTIATE_TEST_CASE_P( BufferTest_Create, NoHostPtr, testing::ValuesIn(NoHostPtrFlags)); struct ValidHostPtr : public BufferTest, public MemoryManagementFixture, public PlatformFixture { typedef BufferTest BaseClass; using BufferTest::SetUp; using MemoryManagementFixture::SetUp; using PlatformFixture::SetUp; ValidHostPtr() { } void SetUp() override { MemoryManagementFixture::SetUp(); PlatformFixture::SetUp(numPlatformDevices, platformDevices); BaseClass::SetUp(); auto pDevice = pPlatform->getDevice(0); ASSERT_NE(nullptr, pDevice); } void TearDown() override { delete buffer; BaseClass::TearDown(); PlatformFixture::TearDown(); MemoryManagementFixture::TearDown(); } Buffer *createBuffer() { return Buffer::create( &context, flags, g_scTestBufferSizeInBytes, pHostPtr, retVal); } cl_int retVal = CL_INVALID_VALUE; Buffer *buffer = nullptr; }; TEST_P(ValidHostPtr, isResident_defaultsToFalseAfterCreate) { buffer = createBuffer(); ASSERT_NE(nullptr, buffer); EXPECT_FALSE(buffer->getGraphicsAllocation()->isResident()); } TEST_P(ValidHostPtr, isResident_returnsValueFromSetResident) { buffer = createBuffer(); ASSERT_NE(nullptr, buffer); buffer->getGraphicsAllocation()->residencyTaskCount = 1; EXPECT_TRUE(buffer->getGraphicsAllocation()->isResident()); buffer->getGraphicsAllocation()->residencyTaskCount = ObjectNotResident; EXPECT_FALSE(buffer->getGraphicsAllocation()->isResident()); } TEST_P(ValidHostPtr, getAddress) { buffer = createBuffer(); ASSERT_NE(nullptr, buffer); auto address = buffer->getCpuAddress(); EXPECT_NE(nullptr, address); if (flags & CL_MEM_USE_HOST_PTR && buffer->isMemObjZeroCopy()) { // Buffer should use host ptr EXPECT_EQ(pHostPtr, address); } else { // Buffer should have a different ptr EXPECT_NE(pHostPtr, address); } if (flags & CL_MEM_COPY_HOST_PTR) { // Buffer should contain a copy of host memory EXPECT_EQ(0, memcmp(pHostPtr, address, sizeof(g_scTestBufferSizeInBytes))); } } TEST_P(ValidHostPtr, getSize) { buffer = createBuffer(); ASSERT_NE(nullptr, buffer); EXPECT_EQ(g_scTestBufferSizeInBytes, buffer->getSize()); } TEST_P(ValidHostPtr, givenValidHostPtrParentFlagsWhenSubBufferIsCreatedWithZeroFlagsThenItCreatesSuccesfuly) { auto retVal = CL_SUCCESS; auto clBuffer = clCreateBuffer(&context, flags, g_scTestBufferSizeInBytes, pHostPtr, &retVal); ASSERT_NE(nullptr, clBuffer); cl_buffer_region region = {0, g_scTestBufferSizeInBytes}; auto subBuffer = clCreateSubBuffer(clBuffer, 0, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &retVal); EXPECT_EQ(CL_SUCCESS, retVal); retVal = clReleaseMemObject(subBuffer); EXPECT_EQ(CL_SUCCESS, retVal); retVal = clReleaseMemObject(clBuffer); EXPECT_EQ(CL_SUCCESS, retVal); } TEST_P(ValidHostPtr, givenValidHostPtrParentFlagsWhenSubBufferIsCreatedWithParentFlagsThenItIsCreatedSuccesfuly) { auto retVal = CL_SUCCESS; auto clBuffer = clCreateBuffer(&context, flags, g_scTestBufferSizeInBytes, pHostPtr, &retVal); ASSERT_NE(nullptr, clBuffer); cl_buffer_region region = {0, g_scTestBufferSizeInBytes}; const cl_mem_flags allValidFlags = CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS; cl_mem_flags unionFlags = flags & allValidFlags; auto subBuffer = clCreateSubBuffer(clBuffer, unionFlags, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &retVal); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_NE(nullptr, subBuffer); retVal = clReleaseMemObject(subBuffer); EXPECT_EQ(CL_SUCCESS, retVal); retVal = clReleaseMemObject(clBuffer); EXPECT_EQ(CL_SUCCESS, retVal); } TEST_P(ValidHostPtr, givenValidHostPtrParentFlagsWhenSubBufferIsCreatedWithInvalidParentFlagsThenCreationFails) { auto retVal = CL_SUCCESS; cl_mem_flags invalidFlags = 0; if (flags & CL_MEM_READ_ONLY) { invalidFlags |= CL_MEM_WRITE_ONLY; } if (flags & CL_MEM_WRITE_ONLY) { invalidFlags |= CL_MEM_READ_ONLY; } if (flags & CL_MEM_HOST_NO_ACCESS) { invalidFlags |= CL_MEM_HOST_READ_ONLY; } if (flags & CL_MEM_HOST_READ_ONLY) { invalidFlags |= CL_MEM_HOST_WRITE_ONLY; } if (flags & CL_MEM_HOST_WRITE_ONLY) { invalidFlags |= CL_MEM_HOST_READ_ONLY; } if (invalidFlags == 0) { return; } auto clBuffer = clCreateBuffer(&context, flags, g_scTestBufferSizeInBytes, pHostPtr, &retVal); ASSERT_NE(nullptr, clBuffer); cl_buffer_region region = {0, g_scTestBufferSizeInBytes}; auto subBuffer = clCreateSubBuffer(clBuffer, invalidFlags, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &retVal); EXPECT_NE(CL_SUCCESS, retVal); EXPECT_EQ(nullptr, subBuffer); retVal = clReleaseMemObject(clBuffer); EXPECT_EQ(CL_SUCCESS, retVal); } TEST_P(ValidHostPtr, failedAllocationInjection) { InjectedFunction method = [this](size_t failureIndex) { delete buffer; buffer = nullptr; // System under test buffer = createBuffer(); if (nonfailingAllocation == failureIndex) { EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_NE(nullptr, buffer); } else { EXPECT_EQ(CL_OUT_OF_HOST_MEMORY, retVal) << "for allocation " << failureIndex; EXPECT_EQ(nullptr, buffer); } }; injectFailures(method); } TEST_P(ValidHostPtr, SvmHostPtr) { const DeviceInfo &devInfo = pPlatform->getDevice(0)->getDeviceInfo(); if (devInfo.svmCapabilities != 0) { auto ptr = clSVMAlloc(&context, CL_MEM_READ_WRITE, 64, 64); auto bufferSvm = Buffer::create(&context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, 64, ptr, retVal); EXPECT_NE(nullptr, bufferSvm); EXPECT_TRUE(bufferSvm->isMemObjWithHostPtrSVM()); EXPECT_EQ(context.getSVMAllocsManager()->getSVMAlloc(ptr), bufferSvm->getGraphicsAllocation()); EXPECT_EQ(CL_SUCCESS, retVal); clSVMFree(&context, ptr); delete bufferSvm; } } // Parameterized test that tests buffer creation with all flags that should be // valid with a valid host ptr cl_mem_flags ValidHostPtrFlags[] = { 0 | CL_MEM_USE_HOST_PTR, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, CL_MEM_HOST_READ_ONLY | CL_MEM_USE_HOST_PTR, CL_MEM_HOST_WRITE_ONLY | CL_MEM_USE_HOST_PTR, CL_MEM_HOST_NO_ACCESS | CL_MEM_USE_HOST_PTR, 0 | CL_MEM_COPY_HOST_PTR, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, CL_MEM_HOST_READ_ONLY | CL_MEM_COPY_HOST_PTR, CL_MEM_HOST_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, CL_MEM_HOST_NO_ACCESS | CL_MEM_COPY_HOST_PTR}; INSTANTIATE_TEST_CASE_P( BufferTest_Create, ValidHostPtr, testing::ValuesIn(ValidHostPtrFlags)); class BufferCalculateHostPtrSize : public testing::TestWithParam> { public: BufferCalculateHostPtrSize(){}; protected: void SetUp() override { std::tie(origin[0], origin[1], origin[2], region[0], region[1], region[2], rowPitch, slicePitch, hostPtrSize) = GetParam(); } void TearDown() override { } size_t origin[3]; size_t region[3]; size_t rowPitch; size_t slicePitch; size_t hostPtrSize; }; /* origin, region, rowPitch, slicePitch, hostPtrSize*/ static std::tuple Inputs[] = {std::make_tuple(0, 0, 0, 1, 1, 1, 10, 1, 1), std::make_tuple(0, 0, 0, 7, 1, 1, 10, 1, 7), std::make_tuple(0, 0, 0, 7, 3, 1, 10, 1, 27), std::make_tuple(0, 0, 0, 7, 1, 3, 10, 10, 27), std::make_tuple(0, 0, 0, 7, 2, 3, 10, 20, 57), std::make_tuple(0, 0, 0, 7, 1, 3, 10, 30, 67), std::make_tuple(0, 0, 0, 7, 2, 3, 10, 30, 77), std::make_tuple(9, 0, 0, 1, 1, 1, 10, 1, 10), std::make_tuple(0, 2, 0, 7, 3, 1, 10, 1, 27 + 20), std::make_tuple(0, 0, 1, 7, 1, 3, 10, 10, 27 + 10), std::make_tuple(0, 2, 1, 7, 2, 3, 10, 20, 57 + 40), std::make_tuple(1, 1, 1, 7, 1, 3, 10, 30, 67 + 41), std::make_tuple(2, 0, 2, 7, 2, 3, 10, 30, 77 + 62)}; TEST_P(BufferCalculateHostPtrSize, CheckReturnedSize) { size_t calculatedSize = Buffer::calculateHostPtrSize(origin, region, rowPitch, slicePitch); EXPECT_EQ(hostPtrSize, calculatedSize); } INSTANTIATE_TEST_CASE_P( BufferCalculateHostPtrSizes, BufferCalculateHostPtrSize, testing::ValuesIn(Inputs)); TEST(Buffers64on32Tests, given32BitBufferCreatedWithUseHostPtrFlagThatIsZeroCopyWhenAskedForStorageThenHostPtrIsReturned) { DebugManagerStateRestore dbgRestorer; { DebugManager.flags.Force32bitAddressing.set(true); MockContext context; auto size = MemoryConstants::pageSize; void *ptr = (void *)0x1000; auto ptrOffset = MemoryConstants::cacheLineSize; uintptr_t offsetedPtr = (uintptr_t)ptr + ptrOffset; auto retVal = CL_SUCCESS; auto buffer = Buffer::create( &context, CL_MEM_USE_HOST_PTR, size, (void *)offsetedPtr, retVal); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_TRUE(buffer->isMemObjZeroCopy()); EXPECT_EQ((void *)offsetedPtr, buffer->getCpuAddressForMapping()); EXPECT_EQ((void *)offsetedPtr, buffer->getCpuAddressForMemoryTransfer()); delete buffer; DebugManager.flags.Force32bitAddressing.set(false); } } TEST(Buffers64on32Tests, given32BitBufferCreatedWithAllocHostPtrFlagThatIsZeroCopyWhenAskedForStorageThenStorageIsEqualToMemoryStorage) { DebugManagerStateRestore dbgRestorer; { DebugManager.flags.Force32bitAddressing.set(true); MockContext context; auto size = MemoryConstants::pageSize; auto retVal = CL_SUCCESS; auto buffer = Buffer::create( &context, CL_MEM_ALLOC_HOST_PTR, size, nullptr, retVal); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_TRUE(buffer->isMemObjZeroCopy()); EXPECT_EQ(buffer->getCpuAddress(), buffer->getCpuAddressForMapping()); EXPECT_EQ(buffer->getCpuAddress(), buffer->getCpuAddressForMemoryTransfer()); delete buffer; DebugManager.flags.Force32bitAddressing.set(false); } } TEST(Buffers64on32Tests, given32BitBufferThatIsCreatedWithUseHostPtrButIsNotZeroCopyThenProperPointersAreReturned) { DebugManagerStateRestore dbgRestorer; { DebugManager.flags.Force32bitAddressing.set(true); MockContext context; auto size = MemoryConstants::pageSize; void *ptr = (void *)alignedMalloc(size * 2, MemoryConstants::pageSize); auto ptrOffset = 1; uintptr_t offsetedPtr = (uintptr_t)ptr + ptrOffset; auto retVal = CL_SUCCESS; auto buffer = Buffer::create( &context, CL_MEM_USE_HOST_PTR, size, (void *)offsetedPtr, retVal); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_FALSE(buffer->isMemObjZeroCopy()); EXPECT_EQ((void *)offsetedPtr, buffer->getCpuAddressForMapping()); EXPECT_EQ(buffer->getCpuAddress(), buffer->getCpuAddressForMemoryTransfer()); delete buffer; DebugManager.flags.Force32bitAddressing.set(false); alignedFree(ptr); } } class BufferTests : public ::testing::Test { protected: void SetUp() override { } void TearDown() override { } MockContext context; }; typedef BufferTests BufferSetSurfaceTests; HWTEST_F(BufferSetSurfaceTests, givenBufferSetSurfaceThatMemoryPtrAndSizeIsAlignedToCachelineThenL3CacheShouldBeOn) { auto size = MemoryConstants::pageSize; auto ptr = (void *)alignedMalloc(size * 2, MemoryConstants::pageSize); using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; RENDER_SURFACE_STATE surfaceState = {}; Buffer::setSurfaceState( &context, &surfaceState, size, ptr); auto mocs = surfaceState.getMemoryObjectControlState(); EXPECT_EQ(Gmm::getMOCS(GMM_RESOURCE_USAGE_OCL_BUFFER), mocs); alignedFree(ptr); } HWTEST_F(BufferSetSurfaceTests, givenBufferSetSurfaceThatMemoryPtrIsUnalignedToCachelineThenL3CacheShouldBeOff) { auto size = MemoryConstants::pageSize; auto ptr = alignedMalloc(size * 2, MemoryConstants::pageSize); auto ptrOffset = 1; auto offsetedPtr = (void *)((uintptr_t)ptr + ptrOffset); using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; RENDER_SURFACE_STATE surfaceState = {}; Buffer::setSurfaceState( &context, &surfaceState, size, offsetedPtr); auto mocs = surfaceState.getMemoryObjectControlState(); EXPECT_EQ(Gmm::getMOCS(GMM_RESOURCE_USAGE_OCL_BUFFER_CACHELINE_MISALIGNED), mocs); alignedFree(ptr); } HWTEST_F(BufferSetSurfaceTests, givenBufferSetSurfaceThatMemorySizeIsUnalignedToCachelineThenL3CacheShouldBeOff) { auto size = MemoryConstants::pageSize; auto ptr = alignedMalloc(size * 2, MemoryConstants::pageSize); auto sizeOffset = 1; auto offsetedSize = size + sizeOffset; using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; RENDER_SURFACE_STATE surfaceState = {}; Buffer::setSurfaceState( &context, &surfaceState, offsetedSize, ptr); auto mocs = surfaceState.getMemoryObjectControlState(); EXPECT_EQ(Gmm::getMOCS(GMM_RESOURCE_USAGE_OCL_BUFFER_CACHELINE_MISALIGNED), mocs); alignedFree(ptr); } HWTEST_F(BufferSetSurfaceTests, givenBufferSetSurfaceThatMemoryIsUnalignedToCachelineButReadOnlyThenL3CacheShouldBeStillOn) { auto size = MemoryConstants::pageSize; auto ptr = alignedMalloc(size * 2, MemoryConstants::pageSize); auto sizeOffset = 1; auto offsetedSize = size + sizeOffset; using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; RENDER_SURFACE_STATE surfaceState = {}; Buffer::setSurfaceState( &context, &surfaceState, offsetedSize, ptr, nullptr, CL_MEM_READ_ONLY); auto mocs = surfaceState.getMemoryObjectControlState(); EXPECT_EQ(Gmm::getMOCS(GMM_RESOURCE_USAGE_OCL_BUFFER), mocs); alignedFree(ptr); } HWTEST_F(BufferSetSurfaceTests, givenBufferSetSurfaceThatMemorySizeIsUnalignedThenSurfaceSizeShouldBeAlignedToFour) { auto size = MemoryConstants::pageSize; auto ptr = alignedMalloc(size * 2, MemoryConstants::pageSize); auto sizeOffset = 1; auto offsetedSize = size + sizeOffset; using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; RENDER_SURFACE_STATE surfaceState = {}; Buffer::setSurfaceState( &context, &surfaceState, offsetedSize, ptr); auto width = surfaceState.getWidth(); EXPECT_EQ(alignUp(width, 4), width); alignedFree(ptr); } HWTEST_F(BufferSetSurfaceTests, givenBufferSetSurfaceThatMemoryPtrIsNotNullThenBufferSurfaceShouldBeUsed) { auto size = MemoryConstants::pageSize; auto ptr = alignedMalloc(size * 2, MemoryConstants::pageSize); using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; RENDER_SURFACE_STATE surfaceState = {}; Buffer::setSurfaceState( &context, &surfaceState, size, ptr); auto surfType = surfaceState.getSurfaceType(); EXPECT_EQ(RENDER_SURFACE_STATE::SURFACE_TYPE_SURFTYPE_BUFFER, surfType); alignedFree(ptr); } HWTEST_F(BufferSetSurfaceTests, givenBufferSetSurfaceThatMemoryPtrIsNullThenNullSurfaceShouldBeUsed) { using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; RENDER_SURFACE_STATE surfaceState = {}; Buffer::setSurfaceState( &context, &surfaceState, 0, nullptr); auto surfType = surfaceState.getSurfaceType(); EXPECT_EQ(RENDER_SURFACE_STATE::SURFACE_TYPE_SURFTYPE_NULL, surfType); } HWTEST_F(BufferSetSurfaceTests, givenBufferSetSurfaceThatAddressIsForcedTo32bitWhenSetArgStatefulIsCalledThenSurfaceBaseAddressIsPopulatedWithGpuAddress) { DebugManagerStateRestore dbgRestorer; { DebugManager.flags.Force32bitAddressing.set(true); MockContext context; auto size = MemoryConstants::pageSize; auto ptr = (void *)alignedMalloc(size * 2, MemoryConstants::pageSize); auto retVal = CL_SUCCESS; auto buffer = Buffer::create( &context, CL_MEM_USE_HOST_PTR, size, ptr, retVal); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_TRUE(is64bit ? buffer->getGraphicsAllocation()->is32BitAllocation : true); using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; RENDER_SURFACE_STATE surfaceState = {}; buffer->setArgStateful(&surfaceState); auto surfBaseAddress = surfaceState.getSurfaceBaseAddress(); auto bufferAddress = buffer->getGraphicsAllocation()->getGpuAddress(); EXPECT_EQ(bufferAddress, surfBaseAddress); delete buffer; alignedFree(ptr); DebugManager.flags.Force32bitAddressing.set(false); } } HWTEST_F(BufferSetSurfaceTests, givenBufferWithOffsetWhenSetArgStatefulIsCalledThenSurfaceBaseAddressIsProperlyOffseted) { MockContext context; auto size = MemoryConstants::pageSize; auto ptr = (void *)alignedMalloc(size * 2, MemoryConstants::pageSize); auto retVal = CL_SUCCESS; auto buffer = Buffer::create( &context, CL_MEM_USE_HOST_PTR, size, ptr, retVal); EXPECT_EQ(CL_SUCCESS, retVal); cl_buffer_region region = {4, 8}; retVal = -1; auto subBuffer = buffer->createSubBuffer(CL_MEM_READ_WRITE, ®ion, retVal); ASSERT_NE(nullptr, subBuffer); ASSERT_EQ(CL_SUCCESS, retVal); using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; RENDER_SURFACE_STATE surfaceState = {}; subBuffer->setArgStateful(&surfaceState); auto surfBaseAddress = surfaceState.getSurfaceBaseAddress(); auto bufferAddress = buffer->getGraphicsAllocation()->getGpuAddress(); EXPECT_EQ(bufferAddress + region.origin, surfBaseAddress); subBuffer->release(); delete buffer; alignedFree(ptr); DebugManager.flags.Force32bitAddressing.set(false); } struct BufferUnmapTest : public DeviceFixture, public ::testing::Test { void SetUp() override { DeviceFixture::SetUp(); } void TearDown() override { DeviceFixture::TearDown(); } }; HWTEST_F(BufferUnmapTest, givenBufferWithSharingHandlerWhenUnmappingThenUseEnqueueWriteBuffer) { MockContext context(pDevice); MockCommandQueueHw cmdQ(&context, pDevice, nullptr); auto retVal = CL_SUCCESS; std::unique_ptr buffer(Buffer::create(&context, CL_MEM_ALLOC_HOST_PTR, 123, nullptr, retVal)); EXPECT_EQ(CL_SUCCESS, retVal); buffer->setSharingHandler(new SharingHandler()); EXPECT_NE(nullptr, buffer->peekSharingHandler()); auto mappedPtr = clEnqueueMapBuffer(&cmdQ, buffer.get(), CL_TRUE, CL_MAP_READ, 0, 1, 0, nullptr, nullptr, &retVal); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_EQ(0u, cmdQ.EnqueueWriteBufferCounter); retVal = clEnqueueUnmapMemObject(&cmdQ, buffer.get(), mappedPtr, 0, nullptr, nullptr); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_EQ(1u, cmdQ.EnqueueWriteBufferCounter); EXPECT_TRUE(cmdQ.blockingWriteBuffer); } HWTEST_F(BufferUnmapTest, givenBufferWithoutSharingHandlerWhenUnmappingThenDontUseEnqueueWriteBuffer) { MockContext context(pDevice); MockCommandQueueHw cmdQ(&context, pDevice, nullptr); auto retVal = CL_SUCCESS; std::unique_ptr buffer(Buffer::create(&context, CL_MEM_ALLOC_HOST_PTR, 123, nullptr, retVal)); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_EQ(nullptr, buffer->peekSharingHandler()); auto mappedPtr = clEnqueueMapBuffer(&cmdQ, buffer.get(), CL_TRUE, CL_MAP_READ, 0, 1, 0, nullptr, nullptr, &retVal); EXPECT_EQ(CL_SUCCESS, retVal); retVal = clEnqueueUnmapMemObject(&cmdQ, buffer.get(), mappedPtr, 0, nullptr, nullptr); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_EQ(0u, cmdQ.EnqueueWriteBufferCounter); }