/* * Copyright (C) 2017-2019 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "runtime/helpers/string.h" #include "runtime/memory_manager/allocations_list.h" #include "runtime/memory_manager/graphics_allocation.h" #include "runtime/os_interface/32bit_memory.h" #include "runtime/platform/platform.h" #include "runtime/program/program.h" #include "test.h" #include "unit_tests/mocks/mock_buffer.h" #include "unit_tests/mocks/mock_csr.h" #include "unit_tests/mocks/mock_program.h" #include "unit_tests/program/program_with_source.h" using namespace NEO; using namespace iOpenCL; static const char constValue[] = "11223344"; static const char globalValue[] = "55667788"; class ProgramDataTest : public testing::Test, public ContextFixture, public PlatformFixture, public ProgramFixture { using ContextFixture::SetUp; using PlatformFixture::SetUp; public: ProgramDataTest() { memset(&programBinaryHeader, 0x00, sizeof(SProgramBinaryHeader)); pCurPtr = nullptr; pProgramPatchList = nullptr; programPatchListSize = 0; } void buildAndDecodeProgramPatchList(); protected: void SetUp() override { PlatformFixture::SetUp(); cl_device_id device = pPlatform->getDevice(0); ContextFixture::SetUp(1, &device); ProgramFixture::SetUp(); CreateProgramWithSource( pContext, &device, "CopyBuffer_simd8.cl"); } void TearDown() override { deleteDataReadFromFile(knownSource); ProgramFixture::TearDown(); ContextFixture::TearDown(); PlatformFixture::TearDown(); } size_t setupConstantAllocation() { size_t constSize = strlen(constValue) + 1; EXPECT_EQ(nullptr, pProgram->getConstantSurface()); SPatchAllocateConstantMemorySurfaceProgramBinaryInfo allocateConstMemorySurface; allocateConstMemorySurface.Token = PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO; allocateConstMemorySurface.Size = static_cast(sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo) + constSize); allocateConstMemorySurface.ConstantBufferIndex = 0; allocateConstMemorySurface.InlineDataSize = static_cast(constSize); pAllocateConstMemorySurface.reset(new cl_char[allocateConstMemorySurface.Size]); memcpy_s(pAllocateConstMemorySurface.get(), sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo), &allocateConstMemorySurface, sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo)); memcpy_s((cl_char *)pAllocateConstMemorySurface.get() + sizeof(allocateConstMemorySurface), constSize, constValue, constSize); pProgramPatchList = (void *)pAllocateConstMemorySurface.get(); programPatchListSize = allocateConstMemorySurface.Size; return constSize; } size_t setupGlobalAllocation() { size_t globalSize = strlen(globalValue) + 1; EXPECT_EQ(nullptr, pProgram->getGlobalSurface()); SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo allocateGlobalMemorySurface; allocateGlobalMemorySurface.Token = PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO; allocateGlobalMemorySurface.Size = static_cast(sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo) + globalSize); allocateGlobalMemorySurface.GlobalBufferIndex = 0; allocateGlobalMemorySurface.InlineDataSize = static_cast(globalSize); pAllocateGlobalMemorySurface.reset(new cl_char[allocateGlobalMemorySurface.Size]); memcpy_s(pAllocateGlobalMemorySurface.get(), sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo), &allocateGlobalMemorySurface, sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo)); memcpy_s((cl_char *)pAllocateGlobalMemorySurface.get() + sizeof(allocateGlobalMemorySurface), globalSize, globalValue, globalSize); pProgramPatchList = pAllocateGlobalMemorySurface.get(); programPatchListSize = allocateGlobalMemorySurface.Size; return globalSize; } std::unique_ptr pAllocateConstMemorySurface; std::unique_ptr pAllocateGlobalMemorySurface; char *pCurPtr; SProgramBinaryHeader programBinaryHeader; void *pProgramPatchList; uint32_t programPatchListSize; }; void ProgramDataTest::buildAndDecodeProgramPatchList() { size_t headerSize = sizeof(SProgramBinaryHeader); cl_int error = CL_SUCCESS; programBinaryHeader.Magic = 0x494E5443; programBinaryHeader.Version = CURRENT_ICBE_VERSION; programBinaryHeader.Device = platformDevices[0]->platform.eRenderCoreFamily; programBinaryHeader.GPUPointerSizeInBytes = 8; programBinaryHeader.NumberOfKernels = 0; programBinaryHeader.PatchListSize = programPatchListSize; char *pProgramData = new char[headerSize + programBinaryHeader.PatchListSize]; ASSERT_NE(nullptr, pProgramData); pCurPtr = pProgramData; // program header memset(pCurPtr, 0, sizeof(SProgramBinaryHeader)); *(SProgramBinaryHeader *)pCurPtr = programBinaryHeader; pCurPtr += sizeof(SProgramBinaryHeader); // patch list memcpy_s(pCurPtr, programPatchListSize, pProgramPatchList, programPatchListSize); pCurPtr += programPatchListSize; //as we use mock compiler in unit test, replace the genBinary here. pProgram->storeGenBinary(pProgramData, headerSize + programBinaryHeader.PatchListSize); error = pProgram->processGenBinary(); EXPECT_EQ(CL_SUCCESS, error); delete[] pProgramData; } TEST_F(ProgramDataTest, EmptyProgramBinaryHeader) { buildAndDecodeProgramPatchList(); } TEST_F(ProgramDataTest, AllocateConstantMemorySurfaceProgramBinaryInfo) { auto constSize = setupConstantAllocation(); buildAndDecodeProgramPatchList(); EXPECT_NE(nullptr, pProgram->getConstantSurface()); EXPECT_EQ(0, memcmp(constValue, reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()), constSize)); } TEST_F(ProgramDataTest, givenConstantAllocationThatIsInUseByGpuWhenProgramIsBeingDestroyedThenItIsAddedToTemporaryAllocationList) { setupConstantAllocation(); buildAndDecodeProgramPatchList(); auto &csr = *pPlatform->getDevice(0)->getDefaultEngine().commandStreamReceiver; auto tagAddress = csr.getTagAddress(); auto constantSurface = pProgram->getConstantSurface(); constantSurface->updateTaskCount(*tagAddress + 1, csr.getOsContext().getContextId()); EXPECT_TRUE(csr.getTemporaryAllocations().peekIsEmpty()); delete pProgram; pProgram = nullptr; EXPECT_FALSE(csr.getTemporaryAllocations().peekIsEmpty()); EXPECT_EQ(constantSurface, csr.getTemporaryAllocations().peekHead()); } TEST_F(ProgramDataTest, givenGlobalAllocationThatIsInUseByGpuWhenProgramIsBeingDestroyedThenItIsAddedToTemporaryAllocationList) { setupGlobalAllocation(); buildAndDecodeProgramPatchList(); auto &csr = *pPlatform->getDevice(0)->getDefaultEngine().commandStreamReceiver; auto tagAddress = csr.getTagAddress(); auto globalSurface = pProgram->getGlobalSurface(); globalSurface->updateTaskCount(*tagAddress + 1, csr.getOsContext().getContextId()); EXPECT_TRUE(csr.getTemporaryAllocations().peekIsEmpty()); delete pProgram; pProgram = nullptr; EXPECT_FALSE(csr.getTemporaryAllocations().peekIsEmpty()); EXPECT_EQ(globalSurface, csr.getTemporaryAllocations().peekHead()); } TEST_F(ProgramDataTest, GivenDeviceForcing32BitMessagesWhenConstAllocationIsPresentInProgramBinariesThen32BitStorageIsAllocated) { auto constSize = setupConstantAllocation(); this->pContext->getDevice(0)->getMemoryManager()->setForce32BitAllocations(true); buildAndDecodeProgramPatchList(); EXPECT_NE(nullptr, pProgram->getConstantSurface()); EXPECT_EQ(0, memcmp(constValue, reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()), constSize)); if (is64bit) { EXPECT_TRUE(pProgram->getConstantSurface()->is32BitAllocation()); } } TEST_F(ProgramDataTest, AllocateGlobalMemorySurfaceProgramBinaryInfo) { auto globalSize = setupGlobalAllocation(); buildAndDecodeProgramPatchList(); EXPECT_NE(nullptr, pProgram->getGlobalSurface()); EXPECT_EQ(0, memcmp(globalValue, reinterpret_cast(pProgram->getGlobalSurface()->getUnderlyingBuffer()), globalSize)); } TEST_F(ProgramDataTest, GlobalPointerProgramBinaryInfo) { char globalValue; char *pGlobalPointerValue = &globalValue; size_t globalPointerSize = sizeof(pGlobalPointerValue); char *ptr; // simulate case when global surface was not allocated EXPECT_EQ(nullptr, pProgram->getGlobalSurface()); SPatchGlobalPointerProgramBinaryInfo globalPointer; globalPointer.Token = PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO; globalPointer.Size = sizeof(SPatchGlobalPointerProgramBinaryInfo); globalPointer.GlobalBufferIndex = 0; globalPointer.GlobalPointerOffset = 0; globalPointer.BufferIndex = 0; globalPointer.BufferType = PROGRAM_SCOPE_GLOBAL_BUFFER; cl_char *pGlobalPointer = new cl_char[globalPointer.Size]; memcpy_s(pGlobalPointer, sizeof(SPatchGlobalPointerProgramBinaryInfo), &globalPointer, sizeof(SPatchGlobalPointerProgramBinaryInfo)); pProgramPatchList = (void *)pGlobalPointer; programPatchListSize = globalPointer.Size; buildAndDecodeProgramPatchList(); EXPECT_EQ(nullptr, pProgram->getGlobalSurface()); delete[] pGlobalPointer; // regular case - global surface exists SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo allocateGlobalMemorySurface; allocateGlobalMemorySurface.Token = PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO; allocateGlobalMemorySurface.Size = static_cast(sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo) + globalPointerSize); allocateGlobalMemorySurface.GlobalBufferIndex = 0; allocateGlobalMemorySurface.InlineDataSize = static_cast(globalPointerSize); cl_char *pAllocateGlobalMemorySurface = new cl_char[allocateGlobalMemorySurface.Size]; memcpy_s(pAllocateGlobalMemorySurface, sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo), &allocateGlobalMemorySurface, sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo)); memcpy_s((cl_char *)pAllocateGlobalMemorySurface + sizeof(allocateGlobalMemorySurface), globalPointerSize, &pGlobalPointerValue, globalPointerSize); pProgramPatchList = (void *)pAllocateGlobalMemorySurface; programPatchListSize = allocateGlobalMemorySurface.Size; buildAndDecodeProgramPatchList(); EXPECT_NE(nullptr, pProgram->getGlobalSurface()); EXPECT_EQ(0, memcmp(&pGlobalPointerValue, reinterpret_cast(pProgram->getGlobalSurface()->getUnderlyingBuffer()), globalPointerSize)); delete[] pAllocateGlobalMemorySurface; // global pointer to global surface - simulate invalid GlobalBufferIndex globalPointer.Token = PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO; globalPointer.Size = sizeof(SPatchGlobalPointerProgramBinaryInfo); globalPointer.GlobalBufferIndex = 10; globalPointer.GlobalPointerOffset = 0; globalPointer.BufferIndex = 0; globalPointer.BufferType = PROGRAM_SCOPE_GLOBAL_BUFFER; pGlobalPointer = new cl_char[globalPointer.Size]; memcpy_s(pGlobalPointer, sizeof(SPatchGlobalPointerProgramBinaryInfo), &globalPointer, sizeof(SPatchGlobalPointerProgramBinaryInfo)); pProgramPatchList = (void *)pGlobalPointer; programPatchListSize = globalPointer.Size; buildAndDecodeProgramPatchList(); EXPECT_EQ(0, memcmp(&pGlobalPointerValue, reinterpret_cast(pProgram->getGlobalSurface()->getUnderlyingBuffer()), globalPointerSize)); delete[] pGlobalPointer; // global pointer to global surface - simulate invalid BufferIndex globalPointer.Token = PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO; globalPointer.Size = sizeof(SPatchGlobalPointerProgramBinaryInfo); globalPointer.GlobalBufferIndex = 0; globalPointer.GlobalPointerOffset = 0; globalPointer.BufferIndex = 10; globalPointer.BufferType = PROGRAM_SCOPE_GLOBAL_BUFFER; pGlobalPointer = new cl_char[globalPointer.Size]; memcpy_s(pGlobalPointer, sizeof(SPatchGlobalPointerProgramBinaryInfo), &globalPointer, sizeof(SPatchGlobalPointerProgramBinaryInfo)); pProgramPatchList = (void *)pGlobalPointer; programPatchListSize = globalPointer.Size; buildAndDecodeProgramPatchList(); EXPECT_EQ(0, memcmp(&pGlobalPointerValue, reinterpret_cast(pProgram->getGlobalSurface()->getUnderlyingBuffer()), globalPointerSize)); delete[] pGlobalPointer; // global pointer to global surface - simulate invalid BufferType globalPointer.Token = PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO; globalPointer.Size = sizeof(SPatchGlobalPointerProgramBinaryInfo); globalPointer.GlobalBufferIndex = 0; globalPointer.GlobalPointerOffset = 0; globalPointer.BufferIndex = 0; globalPointer.BufferType = PROGRAM_SCOPE_CONSTANT_BUFFER; pGlobalPointer = new cl_char[globalPointer.Size]; memcpy_s(pGlobalPointer, sizeof(SPatchGlobalPointerProgramBinaryInfo), &globalPointer, sizeof(SPatchGlobalPointerProgramBinaryInfo)); pProgramPatchList = (void *)pGlobalPointer; programPatchListSize = globalPointer.Size; buildAndDecodeProgramPatchList(); EXPECT_EQ(0, memcmp(&pGlobalPointerValue, reinterpret_cast(pProgram->getGlobalSurface()->getUnderlyingBuffer()), globalPointerSize)); delete[] pGlobalPointer; // regular case - global pointer to global surface - all parameters valid globalPointer.Token = PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO; globalPointer.Size = sizeof(SPatchGlobalPointerProgramBinaryInfo); globalPointer.GlobalBufferIndex = 0; globalPointer.GlobalPointerOffset = 0; globalPointer.BufferIndex = 0; globalPointer.BufferType = PROGRAM_SCOPE_GLOBAL_BUFFER; pGlobalPointer = new cl_char[globalPointer.Size]; memcpy_s(pGlobalPointer, sizeof(SPatchGlobalPointerProgramBinaryInfo), &globalPointer, sizeof(SPatchGlobalPointerProgramBinaryInfo)); pProgramPatchList = (void *)pGlobalPointer; programPatchListSize = globalPointer.Size; buildAndDecodeProgramPatchList(); auto globalSurface = pProgram->getGlobalSurface(); if (!globalSurface->is32BitAllocation()) { EXPECT_NE(0, memcmp(&pGlobalPointerValue, reinterpret_cast(pProgram->getGlobalSurface()->getUnderlyingBuffer()), globalPointerSize)); ptr = pGlobalPointerValue + reinterpret_cast(pProgram->getGlobalSurface()->getUnderlyingBuffer()); EXPECT_EQ(0, memcmp(&ptr, reinterpret_cast(pProgram->getGlobalSurface()->getUnderlyingBuffer()), globalPointerSize)); } delete[] pGlobalPointer; } TEST_F(ProgramDataTest, Given32BitDeviceWhenGlobalMemorySurfaceIsPresentThenItHas32BitStorage) { char globalValue[] = "55667788"; size_t globalSize = strlen(globalValue) + 1; this->pContext->getDevice(0)->getMemoryManager()->setForce32BitAllocations(true); EXPECT_EQ(nullptr, pProgram->getGlobalSurface()); SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo allocateGlobalMemorySurface; allocateGlobalMemorySurface.Token = PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO; allocateGlobalMemorySurface.Size = static_cast(sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo) + globalSize); allocateGlobalMemorySurface.GlobalBufferIndex = 0; allocateGlobalMemorySurface.InlineDataSize = static_cast(globalSize); cl_char *pAllocateGlobalMemorySurface = new cl_char[allocateGlobalMemorySurface.Size]; memcpy_s(pAllocateGlobalMemorySurface, sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo), &allocateGlobalMemorySurface, sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo)); memcpy_s((cl_char *)pAllocateGlobalMemorySurface + sizeof(allocateGlobalMemorySurface), globalSize, globalValue, globalSize); pProgramPatchList = (void *)pAllocateGlobalMemorySurface; programPatchListSize = allocateGlobalMemorySurface.Size; buildAndDecodeProgramPatchList(); EXPECT_NE(nullptr, pProgram->getGlobalSurface()); EXPECT_EQ(0, memcmp(globalValue, reinterpret_cast(pProgram->getGlobalSurface()->getUnderlyingBuffer()), globalSize)); if (is64bit) { EXPECT_TRUE(pProgram->getGlobalSurface()->is32BitAllocation()); } delete[] pAllocateGlobalMemorySurface; } TEST_F(ProgramDataTest, ConstantPointerProgramBinaryInfo) { const char *pConstantData = "01234567"; size_t constantDataLen = strlen(pConstantData); // simulate case when constant surface was not allocated EXPECT_EQ(nullptr, pProgram->getConstantSurface()); SPatchConstantPointerProgramBinaryInfo constantPointer; constantPointer.Token = PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO; constantPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo); constantPointer.ConstantBufferIndex = 0; constantPointer.ConstantPointerOffset = 0; constantPointer.BufferIndex = 0; constantPointer.BufferType = PROGRAM_SCOPE_CONSTANT_BUFFER; cl_char *pConstantPointer = new cl_char[constantPointer.Size]; memcpy_s(pConstantPointer, sizeof(SPatchConstantPointerProgramBinaryInfo), &constantPointer, sizeof(SPatchConstantPointerProgramBinaryInfo)); pProgramPatchList = (void *)pConstantPointer; programPatchListSize = constantPointer.Size; buildAndDecodeProgramPatchList(); EXPECT_EQ(nullptr, pProgram->getConstantSurface()); delete[] pConstantPointer; // regular case - constant surface exists SPatchAllocateConstantMemorySurfaceProgramBinaryInfo allocateConstMemorySurface; allocateConstMemorySurface.Token = PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO; // note : + sizeof(uint64_t) is to accomodate for constant buffer offset allocateConstMemorySurface.Size = static_cast(sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo) + constantDataLen + sizeof(uint64_t)); allocateConstMemorySurface.ConstantBufferIndex = 0; allocateConstMemorySurface.InlineDataSize = static_cast(constantDataLen + sizeof(uint64_t)); auto pAllocateConstMemorySurface = std::unique_ptr(new char[allocateConstMemorySurface.Size]); // copy the token header memcpy_s(pAllocateConstMemorySurface.get(), sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo), &allocateConstMemorySurface, sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo)); // copy the constant data memcpy_s((char *)pAllocateConstMemorySurface.get() + sizeof(allocateConstMemorySurface), constantDataLen, pConstantData, constantDataLen); // zero-out the constant buffer offset (will be patched during gen binary decoding) size_t constantBufferOffsetPatchOffset = constantDataLen; *(uint64_t *)((char *)pAllocateConstMemorySurface.get() + sizeof(allocateConstMemorySurface) + constantBufferOffsetPatchOffset) = 0U; pProgramPatchList = (void *)pAllocateConstMemorySurface.get(); programPatchListSize = allocateConstMemorySurface.Size; buildAndDecodeProgramPatchList(); EXPECT_NE(nullptr, pProgram->getConstantSurface()); EXPECT_EQ(0, memcmp(pConstantData, reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()), constantDataLen)); // there was no PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO, so constant buffer offset should be still 0 EXPECT_EQ(0U, *(uint64_t *)(reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()) + constantBufferOffsetPatchOffset)); // once finally constant buffer offset gets patched - the patch value depends on the bitness of the compute kernel auto patchOffsetValueStorage = std::unique_ptr(new uint64_t); // 4bytes for 32-bit compute kernel, full 8byte for 64-bit compute kernel uint64_t *patchOffsetValue = patchOffsetValueStorage.get(); if (pProgram->getConstantSurface()->is32BitAllocation() || (sizeof(void *) == 4)) { reinterpret_cast(patchOffsetValue)[0] = static_cast(pProgram->getConstantSurface()->getGpuAddressToPatch()); reinterpret_cast(patchOffsetValue)[1] = 0; // just pad with 0 } else { // full 8 bytes *reinterpret_cast(patchOffsetValue) = reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()); } // constant pointer to constant surface - simulate invalid GlobalBufferIndex constantPointer.Token = PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO; constantPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo); constantPointer.ConstantBufferIndex = 10; constantPointer.ConstantPointerOffset = 0; constantPointer.BufferIndex = 0; constantPointer.BufferType = PROGRAM_SCOPE_CONSTANT_BUFFER; pConstantPointer = new cl_char[constantPointer.Size]; memcpy_s(pConstantPointer, sizeof(SPatchConstantPointerProgramBinaryInfo), &constantPointer, sizeof(SPatchConstantPointerProgramBinaryInfo)); pProgramPatchList = (void *)pConstantPointer; programPatchListSize = constantPointer.Size; buildAndDecodeProgramPatchList(); EXPECT_EQ(0, memcmp(pConstantData, reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()), constantDataLen)); // check that constant pointer offset was not patched EXPECT_EQ(0U, *(uint64_t *)(reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()) + constantBufferOffsetPatchOffset)); // reset the constant pointer offset *(uint64_t *)((char *)pProgram->getConstantSurface()->getUnderlyingBuffer() + constantBufferOffsetPatchOffset) = 0U; delete[] pConstantPointer; // constant pointer to constant surface - simulate invalid BufferIndex constantPointer.Token = PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO; constantPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo); constantPointer.ConstantBufferIndex = 0; constantPointer.ConstantPointerOffset = 0; constantPointer.BufferIndex = 10; constantPointer.BufferType = PROGRAM_SCOPE_CONSTANT_BUFFER; pConstantPointer = new cl_char[constantPointer.Size]; memcpy_s(pConstantPointer, sizeof(SPatchConstantPointerProgramBinaryInfo), &constantPointer, sizeof(SPatchConstantPointerProgramBinaryInfo)); pProgramPatchList = (void *)pConstantPointer; programPatchListSize = constantPointer.Size; buildAndDecodeProgramPatchList(); EXPECT_EQ(0, memcmp(pConstantData, reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()), constantDataLen)); // check that constant pointer offset was not patched EXPECT_EQ(0U, *(uint64_t *)(reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()) + constantBufferOffsetPatchOffset)); // reset the constant pointer offset *(uint64_t *)((char *)pProgram->getConstantSurface()->getUnderlyingBuffer() + constantBufferOffsetPatchOffset) = 0U; delete[] pConstantPointer; // constant pointer to constant surface - simulate invalid BufferType constantPointer.Token = PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO; constantPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo); constantPointer.ConstantBufferIndex = 0; constantPointer.ConstantPointerOffset = 0; constantPointer.BufferIndex = 0; constantPointer.BufferType = PROGRAM_SCOPE_GLOBAL_BUFFER; pConstantPointer = new cl_char[constantPointer.Size]; memcpy_s(pConstantPointer, sizeof(SPatchConstantPointerProgramBinaryInfo), &constantPointer, sizeof(SPatchConstantPointerProgramBinaryInfo)); pProgramPatchList = (void *)pConstantPointer; programPatchListSize = constantPointer.Size; buildAndDecodeProgramPatchList(); EXPECT_EQ(0, memcmp(pConstantData, reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()), constantDataLen)); // check that constant pointer offset was not patched EXPECT_EQ(0U, *(uint64_t *)(reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()) + constantBufferOffsetPatchOffset)); // reset the constant pointer offset *(uint64_t *)((char *)pProgram->getConstantSurface()->getUnderlyingBuffer() + constantBufferOffsetPatchOffset) = 0U; delete[] pConstantPointer; // regular case - constant pointer to constant surface - all parameters valid constantPointer.Token = PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO; constantPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo); constantPointer.ConstantBufferIndex = 0; constantPointer.ConstantPointerOffset = constantDataLen; constantPointer.BufferIndex = 0; constantPointer.BufferType = PROGRAM_SCOPE_CONSTANT_BUFFER; pConstantPointer = new cl_char[constantPointer.Size]; memcpy_s(pConstantPointer, sizeof(SPatchConstantPointerProgramBinaryInfo), &constantPointer, sizeof(SPatchConstantPointerProgramBinaryInfo)); pProgramPatchList = (void *)pConstantPointer; programPatchListSize = constantPointer.Size; buildAndDecodeProgramPatchList(); EXPECT_EQ(0, memcmp(pConstantData, reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()), constantDataLen)); // check that constant pointer offset was patched EXPECT_EQ(*reinterpret_cast(patchOffsetValue), *(uint64_t *)(reinterpret_cast(pProgram->getConstantSurface()->getUnderlyingBuffer()) + constantBufferOffsetPatchOffset)); delete[] pConstantPointer; } TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeConstantBufferPatchTokensAreReadThenConstantPointerOffsetIsPatchedWith32bitPointer) { cl_device_id device = pPlatform->getDevice(0); CreateProgramWithSource(pContext, &device, "CopyBuffer_simd8.cl"); ASSERT_NE(nullptr, pProgram); MockProgram *prog = static_cast(pProgram); // simulate case when constant surface was not allocated EXPECT_EQ(nullptr, prog->getConstantSurface()); SPatchConstantPointerProgramBinaryInfo constantPointer; constantPointer.Token = PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO; constantPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo); constantPointer.ConstantBufferIndex = 0; constantPointer.ConstantPointerOffset = 0; constantPointer.BufferIndex = 0; constantPointer.BufferType = PROGRAM_SCOPE_CONSTANT_BUFFER; auto pConstantPointer = std::unique_ptr(new char[constantPointer.Size]); memcpy_s(pConstantPointer.get(), sizeof(SPatchConstantPointerProgramBinaryInfo), &constantPointer, sizeof(SPatchConstantPointerProgramBinaryInfo)); pProgramPatchList = (void *)pConstantPointer.get(); programPatchListSize = constantPointer.Size; MockBuffer constantSurface; ASSERT_LT(8U, constantSurface.getSize()); prog->setConstantSurface(&constantSurface.mockGfxAllocation); constantSurface.mockGfxAllocation.set32BitAllocation(true); uint32_t *constantSurfaceStorage = reinterpret_cast(constantSurface.getCpuAddress()); uint32_t sentinel = 0x17192329U; constantSurfaceStorage[0] = 0U; constantSurfaceStorage[1] = sentinel; buildAndDecodeProgramPatchList(); uint32_t expectedAddr = static_cast(constantSurface.getGraphicsAllocation()->getGpuAddressToPatch()); EXPECT_EQ(expectedAddr, constantSurfaceStorage[0]); EXPECT_EQ(sentinel, constantSurfaceStorage[1]); constantSurface.mockGfxAllocation.set32BitAllocation(false); prog->setConstantSurface(nullptr); } TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeGlobalPointerPatchTokensAreReadThenGlobalPointerOffsetIsPatchedWith32bitPointer) { cl_device_id device = pPlatform->getDevice(0); CreateProgramWithSource(pContext, &device, "CopyBuffer_simd8.cl"); ASSERT_NE(nullptr, pProgram); MockProgram *prog = static_cast(pProgram); // simulate case when constant surface was not allocated EXPECT_EQ(nullptr, prog->getConstantSurface()); SPatchGlobalPointerProgramBinaryInfo globalPointer; globalPointer.Token = PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO; globalPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo); globalPointer.GlobalBufferIndex = 0; globalPointer.GlobalPointerOffset = 0; globalPointer.BufferIndex = 0; globalPointer.BufferType = PROGRAM_SCOPE_GLOBAL_BUFFER; auto pGlobalPointer = std::unique_ptr(new char[globalPointer.Size]); memcpy_s(pGlobalPointer.get(), sizeof(SPatchGlobalPointerProgramBinaryInfo), &globalPointer, sizeof(SPatchGlobalPointerProgramBinaryInfo)); pProgramPatchList = (void *)pGlobalPointer.get(); programPatchListSize = globalPointer.Size; MockBuffer globalSurface; ASSERT_LT(8U, globalSurface.getSize()); prog->setGlobalSurface(&globalSurface.mockGfxAllocation); globalSurface.mockGfxAllocation.set32BitAllocation(true); uint32_t *globalSurfaceStorage = reinterpret_cast(globalSurface.getCpuAddress()); uint32_t sentinel = 0x17192329U; globalSurfaceStorage[0] = 0U; globalSurfaceStorage[1] = sentinel; buildAndDecodeProgramPatchList(); uint32_t expectedAddr = static_cast(globalSurface.getGraphicsAllocation()->getGpuAddressToPatch()); EXPECT_EQ(expectedAddr, globalSurfaceStorage[0]); EXPECT_EQ(sentinel, globalSurfaceStorage[1]); globalSurface.mockGfxAllocation.set32BitAllocation(false); prog->setGlobalSurface(nullptr); }