enable create subBuffer from pooled buffer

Allow creating subBuffer from buffer from buffer pool allocator
by redirecting the call to the pool buffer and adjusting offset

Related-To: NEO-7332

Signed-off-by: Dominik Dabek <dominik.dabek@intel.com>
This commit is contained in:
Dominik Dabek 2022-10-18 08:39:46 +00:00 committed by Compute-Runtime-Automation
parent f06df021b5
commit d1a6054af9
6 changed files with 106 additions and 8 deletions

View File

@ -786,14 +786,16 @@ cl_mem CL_API_CALL clCreateSubBuffer(cl_mem buffer,
break;
}
if (parentBuffer->isSubBuffer() == true) {
if (!parentBuffer->getContext()->getBufferPoolAllocator().isPoolBuffer(parentBuffer->getAssociatedMemObject()) || parentBuffer->isSubBufferFromPool) {
retVal = CL_INVALID_MEM_OBJECT;
break;
}
}
cl_mem_flags parentFlags = parentBuffer->getFlags();
cl_mem_flags_intel parentFlagsIntel = parentBuffer->getFlagsIntel();
if (parentBuffer->isSubBuffer() == true) {
retVal = CL_INVALID_MEM_OBJECT;
break;
}
/* Check whether flag is valid. */
if (((flags & CL_MEM_HOST_READ_ONLY) && (flags & CL_MEM_HOST_NO_ACCESS)) ||
((flags & CL_MEM_HOST_READ_ONLY) && (flags & CL_MEM_HOST_WRITE_ONLY)) ||

View File

@ -514,7 +514,7 @@ Buffer *Context::BufferPoolAllocator::allocateBufferFromPool(const MemoryPropert
}
bool Context::BufferPoolAllocator::isPoolBuffer(const MemObj *buffer) const {
return this->mainStorage == buffer;
return buffer != nullptr && this->mainStorage == buffer;
}
void Context::BufferPoolAllocator::tryFreeFromPoolBuffer(MemObj *possiblePoolBuffer, size_t offset, size_t size) {

View File

@ -613,6 +613,14 @@ Buffer *Buffer::createSubBuffer(cl_mem_flags flags,
const cl_buffer_region *region,
cl_int &errcodeRet) {
DEBUG_BREAK_IF(nullptr == createFunction);
if (this->context->getBufferPoolAllocator().isPoolBuffer(associatedMemObject)) {
Buffer *poolBuffer = static_cast<Buffer *>(associatedMemObject);
auto regionWithAdditionalOffset = *region;
regionWithAdditionalOffset.origin += this->offset;
auto buffer = poolBuffer->createSubBuffer(flags, flagsIntel, &regionWithAdditionalOffset, errcodeRet);
buffer->isSubBufferFromPool = true;
return buffer;
}
MemoryProperties memoryProperties =
ClMemoryPropertiesHelper::createMemoryProperties(flags, flagsIntel, 0, &this->context->getDevice(0)->getDevice());

View File

@ -62,6 +62,7 @@ class Buffer : public MemObj {
constexpr static cl_ulong maskMagic = 0xFFFFFFFFFFFFFFFFLL;
constexpr static cl_ulong objectMagic = MemObj::objectMagic | 0x02;
bool forceDisallowCPUCopy = false;
bool isSubBufferFromPool = false;
~Buffer() override;

View File

@ -156,6 +156,9 @@ class MemObj : public BaseObject<_cl_mem> {
}
return associatedMemObject->getHighestRootMemObj();
}
MemObj *getAssociatedMemObject() {
return associatedMemObject;
}
protected:
void getOsSpecificMemObjectInfo(const cl_mem_info &paramName, size_t *srcParamSize, void **srcParam);

View File

@ -325,8 +325,6 @@ TEST_F(aggregatedSmallBuffersEnabledApiTest, givenSubBufferNotFromPoolAndAggrega
}
TEST_F(aggregatedSmallBuffersEnabledApiTest, givenCopyHostPointerWhenCreatingBufferThenUsePoolAndCopyHostPointer) {
DebugManagerStateRestore restore;
DebugManager.flags.ExperimentalSmallBufferPoolAllocator.set(1);
flags |= CL_MEM_COPY_HOST_PTR;
unsigned char dataToCopy[PoolAllocator::smallBufferThreshold];
dataToCopy[0] = 123;
@ -355,4 +353,90 @@ TEST_F(aggregatedSmallBuffersEnabledApiTest, givenCopyHostPointerWhenCreatingBuf
EXPECT_EQ(clReleaseContext(context), CL_SUCCESS);
}
using aggregatedSmallBuffersSubBufferApiTest = aggregatedSmallBuffersEnabledApiTest;
TEST_F(aggregatedSmallBuffersSubBufferApiTest, givenBufferFromPoolWhenCreateSubBufferCalledThenItSucceeds) {
cl_mem notUsedBuffer = clCreateBuffer(clContext, flags, size, hostPtr, &retVal);
EXPECT_EQ(retVal, CL_SUCCESS);
EXPECT_NE(notUsedBuffer, nullptr);
cl_mem buffer = clCreateBuffer(clContext, flags, size, hostPtr, &retVal);
EXPECT_EQ(retVal, CL_SUCCESS);
ASSERT_NE(buffer, nullptr);
MockBuffer *mockBuffer = static_cast<MockBuffer *>(buffer);
EXPECT_GT(mockBuffer->offset, 0u);
cl_buffer_region region{};
region.size = 1;
region.origin = size / 2;
cl_mem subBuffer = clCreateSubBuffer(buffer, flags, CL_BUFFER_CREATE_TYPE_REGION, &region, &retVal);
EXPECT_EQ(retVal, CL_SUCCESS);
ASSERT_NE(subBuffer, nullptr);
MockBuffer *mockSubBuffer = static_cast<MockBuffer *>(subBuffer);
EXPECT_EQ(mockSubBuffer->offset, mockBuffer->offset + region.origin);
MockBufferPoolAllocator *mockBufferPoolAllocator = static_cast<MockBufferPoolAllocator *>(&context->getBufferPoolAllocator());
EXPECT_EQ(mockSubBuffer->associatedMemObject, mockBufferPoolAllocator->mainStorage);
retVal = clReleaseMemObject(subBuffer);
EXPECT_EQ(retVal, CL_SUCCESS);
retVal = clReleaseMemObject(buffer);
EXPECT_EQ(retVal, CL_SUCCESS);
retVal = clReleaseMemObject(notUsedBuffer);
EXPECT_EQ(retVal, CL_SUCCESS);
EXPECT_EQ(clReleaseContext(context), CL_SUCCESS);
}
TEST_F(aggregatedSmallBuffersSubBufferApiTest, givenBufferFromPoolWhenCreateSubBufferCalledWithRegionOutsideBufferThenItFails) {
cl_mem buffer = clCreateBuffer(clContext, flags, size, hostPtr, &retVal);
EXPECT_EQ(retVal, CL_SUCCESS);
ASSERT_NE(buffer, nullptr);
cl_buffer_region region{};
region.size = size + 1;
region.origin = 0;
cl_mem subBuffer = clCreateSubBuffer(buffer, flags, CL_BUFFER_CREATE_TYPE_REGION, &region, &retVal);
EXPECT_EQ(retVal, CL_INVALID_VALUE);
EXPECT_EQ(subBuffer, nullptr);
region.size = 1;
region.origin = PoolAllocator::smallBufferThreshold;
subBuffer = clCreateSubBuffer(buffer, flags, CL_BUFFER_CREATE_TYPE_REGION, &region, &retVal);
EXPECT_EQ(retVal, CL_INVALID_VALUE);
EXPECT_EQ(subBuffer, nullptr);
retVal = clReleaseMemObject(buffer);
EXPECT_EQ(retVal, CL_SUCCESS);
EXPECT_EQ(clReleaseContext(context), CL_SUCCESS);
}
TEST_F(aggregatedSmallBuffersSubBufferApiTest, givenSubBufferFromBufferFromPoolWhenCreateSubBufferCalledThenItFails) {
cl_mem buffer = clCreateBuffer(clContext, flags, size, hostPtr, &retVal);
EXPECT_EQ(retVal, CL_SUCCESS);
ASSERT_NE(buffer, nullptr);
cl_buffer_region region{};
region.size = 1;
region.origin = size / 2;
cl_mem subBuffer = clCreateSubBuffer(buffer, flags, CL_BUFFER_CREATE_TYPE_REGION, &region, &retVal);
EXPECT_EQ(retVal, CL_SUCCESS);
ASSERT_NE(subBuffer, nullptr);
region.origin = 0;
cl_mem subSubBuffer = clCreateSubBuffer(subBuffer, flags, CL_BUFFER_CREATE_TYPE_REGION, &region, &retVal);
EXPECT_EQ(retVal, CL_INVALID_MEM_OBJECT);
EXPECT_EQ(subSubBuffer, nullptr);
retVal = clReleaseMemObject(subBuffer);
EXPECT_EQ(retVal, CL_SUCCESS);
retVal = clReleaseMemObject(buffer);
EXPECT_EQ(retVal, CL_SUCCESS);
EXPECT_EQ(clReleaseContext(context), CL_SUCCESS);
}
} // namespace Ult