service read_only memory passed to CreateBuffer
- only when cl_mem_flags allows for read only memory and USE_HOST_PTR is used Change-Id: Id023f9cb551f7d81ec680de9cc546005980e6f75
This commit is contained in:
parent
385fcdb7ca
commit
76dd4ac1f3
|
@ -132,6 +132,12 @@ Buffer *Buffer::create(Context *context,
|
|||
//Host ptr was not created with clSVMAlloc - create graphic allocation
|
||||
memory = memoryManager->createGraphicsAllocationWithRequiredBitness(size, hostPtr, true);
|
||||
}
|
||||
if (!memory && Buffer::isReadOnlyMemoryPermittedByFlags(flags)) {
|
||||
memory = memoryManager->createGraphicsAllocationWithRequiredBitness(size, nullptr, true);
|
||||
zeroCopy = false;
|
||||
copyMemoryFromHostPtr = true;
|
||||
allocateMemory = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!memory) {
|
||||
|
@ -229,6 +235,14 @@ void Buffer::checkMemory(cl_mem_flags flags,
|
|||
return;
|
||||
}
|
||||
|
||||
bool Buffer::isReadOnlyMemoryPermittedByFlags(cl_mem_flags flags) {
|
||||
// Host won't access or will only read and kernel will only read
|
||||
if ((flags & (CL_MEM_HOST_NO_ACCESS | CL_MEM_HOST_READ_ONLY)) && (flags & CL_MEM_READ_ONLY)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Buffer *Buffer::createSubBuffer(cl_mem_flags flags,
|
||||
const cl_buffer_region *region,
|
||||
cl_int &errcodeRet) {
|
||||
|
|
|
@ -127,6 +127,8 @@ class Buffer : public MemObj {
|
|||
bool ©MemoryFromHostPtr,
|
||||
MemoryManager *memMngr);
|
||||
|
||||
static bool isReadOnlyMemoryPermittedByFlags(cl_mem_flags flags);
|
||||
|
||||
void transferData(void *dst, void *src, size_t copySize, size_t copyOffset);
|
||||
};
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ class MemoryManager {
|
|||
return createGraphicsAllocationWithRequiredBitness(size, ptr, false);
|
||||
}
|
||||
|
||||
GraphicsAllocation *createGraphicsAllocationWithRequiredBitness(size_t size, void *ptr, bool forcePin) {
|
||||
MOCKABLE_VIRTUAL GraphicsAllocation *createGraphicsAllocationWithRequiredBitness(size_t size, void *ptr, bool forcePin) {
|
||||
if (force32bitAllocations && is64bit) {
|
||||
return allocate32BitGraphicsMemory(size, ptr, MemoryType::EXTERNAL_ALLOCATION);
|
||||
} else {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#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/gen_common/matchers.h"
|
||||
#include "unit_tests/helpers/debug_manager_state_restore.h"
|
||||
#include "unit_tests/helpers/memory_management.h"
|
||||
#include "unit_tests/mocks/mock_context.h"
|
||||
|
@ -66,6 +67,158 @@ TEST(Buffer, givenBufferWhenAskedForPtrLengthThenReturnCorrectValue) {
|
|||
EXPECT_EQ(size[0], retOffset);
|
||||
}
|
||||
|
||||
TEST(Buffer, givenReadOnlySetOfInputFlagsWhenPassedToisReadOnlyMemoryPermittedByFlagsThenTrueIsReturned) {
|
||||
class MockBuffer : public Buffer {
|
||||
public:
|
||||
using Buffer::isReadOnlyMemoryPermittedByFlags;
|
||||
};
|
||||
cl_mem_flags flags = CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_ONLY;
|
||||
EXPECT_TRUE(MockBuffer::isReadOnlyMemoryPermittedByFlags(flags));
|
||||
|
||||
flags = CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY;
|
||||
EXPECT_TRUE(MockBuffer::isReadOnlyMemoryPermittedByFlags(flags));
|
||||
}
|
||||
|
||||
class BufferReadOnlyTest : public testing::TestWithParam<uint64_t> {
|
||||
};
|
||||
|
||||
TEST_P(BufferReadOnlyTest, givenNonReadOnlySetOfInputFlagsWhenPassedToisReadOnlyMemoryPermittedByFlagsThenFalseIsReturned) {
|
||||
class MockBuffer : public Buffer {
|
||||
public:
|
||||
using Buffer::isReadOnlyMemoryPermittedByFlags;
|
||||
};
|
||||
|
||||
cl_mem_flags flags = GetParam() | CL_MEM_USE_HOST_PTR;
|
||||
EXPECT_FALSE(MockBuffer::isReadOnlyMemoryPermittedByFlags(flags));
|
||||
}
|
||||
static cl_mem_flags nonReadOnlyFlags[] = {
|
||||
CL_MEM_READ_WRITE | CL_MEM_HOST_READ_ONLY,
|
||||
CL_MEM_WRITE_ONLY,
|
||||
CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY,
|
||||
CL_MEM_HOST_READ_ONLY,
|
||||
CL_MEM_HOST_WRITE_ONLY,
|
||||
CL_MEM_HOST_NO_ACCESS,
|
||||
CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY,
|
||||
CL_MEM_HOST_WRITE_ONLY | CL_MEM_WRITE_ONLY,
|
||||
0};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
nonReadOnlyFlags,
|
||||
BufferReadOnlyTest,
|
||||
testing::ValuesIn(nonReadOnlyFlags));
|
||||
|
||||
class GMockMemoryManagerFailFirstAllocation : public MockMemoryManager {
|
||||
public:
|
||||
MOCK_METHOD3(createGraphicsAllocationWithRequiredBitness, GraphicsAllocation *(size_t size, void *ptr, bool forcePin));
|
||||
GraphicsAllocation *baseCreateGraphicsAllocationWithRequiredBitness(size_t size, void *ptr, bool forcePin) {
|
||||
return MockMemoryManager::createGraphicsAllocationWithRequiredBitness(size, ptr, forcePin);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Buffer, givenReadOnlyHostPtrMemoryWhenBufferIsCreatedWithReadOnlyFlagsThenBufferHasAllocatedNewMemoryStorageAndBufferIsNotZeroCopy) {
|
||||
void *memory = alignedMalloc(MemoryConstants::pageSize, MemoryConstants::pageSize);
|
||||
ASSERT_NE(nullptr, memory);
|
||||
|
||||
memset(memory, 0xAA, MemoryConstants::pageSize);
|
||||
|
||||
std::unique_ptr<MockDevice> device(DeviceHelper<>::create(nullptr));
|
||||
::testing::NiceMock<GMockMemoryManagerFailFirstAllocation> *memoryManager = new ::testing::NiceMock<GMockMemoryManagerFailFirstAllocation>;
|
||||
|
||||
device->injectMemoryManager(memoryManager);
|
||||
MockContext ctx(device.get());
|
||||
|
||||
// First fail in createGraphicsAllocation simulates error for read only memory allocation
|
||||
EXPECT_CALL(*memoryManager, createGraphicsAllocationWithRequiredBitness(MemoryConstants::pageSize, (void *)memory, true))
|
||||
.WillOnce(::testing::Return(nullptr));
|
||||
|
||||
EXPECT_CALL(*memoryManager, createGraphicsAllocationWithRequiredBitness(::testing::_, nullptr, ::testing::_))
|
||||
.WillRepeatedly(::testing::Invoke(memoryManager, &GMockMemoryManagerFailFirstAllocation::baseCreateGraphicsAllocationWithRequiredBitness));
|
||||
|
||||
cl_int retVal;
|
||||
cl_mem_flags flags = CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR;
|
||||
|
||||
std::unique_ptr<Buffer> buffer(Buffer::create(&ctx, flags, MemoryConstants::pageSize, (void *)memory, retVal));
|
||||
|
||||
EXPECT_FALSE(buffer->isMemObjZeroCopy());
|
||||
void *memoryStorage = buffer->getCpuAddressForMemoryTransfer();
|
||||
EXPECT_NE((void *)memory, memoryStorage);
|
||||
EXPECT_THAT(buffer->getCpuAddressForMemoryTransfer(), MemCompare(memory, MemoryConstants::pageSize));
|
||||
|
||||
alignedFree(memory);
|
||||
}
|
||||
|
||||
TEST(Buffer, givenReadOnlyHostPtrMemoryWhenBufferIsCreatedWithReadOnlyFlagsAndSecondAllocationFailsThenNullptrIsReturned) {
|
||||
void *memory = alignedMalloc(MemoryConstants::pageSize, MemoryConstants::pageSize);
|
||||
ASSERT_NE(nullptr, memory);
|
||||
|
||||
memset(memory, 0xAA, MemoryConstants::pageSize);
|
||||
|
||||
std::unique_ptr<MockDevice> device(DeviceHelper<>::create(nullptr));
|
||||
::testing::NiceMock<GMockMemoryManagerFailFirstAllocation> *memoryManager = new ::testing::NiceMock<GMockMemoryManagerFailFirstAllocation>;
|
||||
|
||||
device->injectMemoryManager(memoryManager);
|
||||
MockContext ctx(device.get());
|
||||
|
||||
// First fail in createGraphicsAllocation simulates error for read only memory allocation
|
||||
EXPECT_CALL(*memoryManager, createGraphicsAllocationWithRequiredBitness(MemoryConstants::pageSize, (void *)memory, true))
|
||||
.WillOnce(::testing::Return(nullptr));
|
||||
|
||||
EXPECT_CALL(*memoryManager, createGraphicsAllocationWithRequiredBitness(::testing::_, nullptr, ::testing::_))
|
||||
.WillOnce(::testing::Return(nullptr));
|
||||
|
||||
cl_int retVal;
|
||||
cl_mem_flags flags = CL_MEM_HOST_READ_ONLY | CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR;
|
||||
|
||||
std::unique_ptr<Buffer> buffer(Buffer::create(&ctx, flags, MemoryConstants::pageSize, (void *)memory, retVal));
|
||||
|
||||
EXPECT_EQ(nullptr, buffer.get());
|
||||
alignedFree(memory);
|
||||
}
|
||||
|
||||
TEST(Buffer, givenReadOnlyHostPtrMemoryWhenBufferIsCreatedWithKernelWriteFlagThenBufferAllocationFailsAndReturnsNullptr) {
|
||||
void *memory = alignedMalloc(MemoryConstants::pageSize, MemoryConstants::pageSize);
|
||||
ASSERT_NE(nullptr, memory);
|
||||
|
||||
memset(memory, 0xAA, MemoryConstants::pageSize);
|
||||
|
||||
std::unique_ptr<MockDevice> device(DeviceHelper<>::create(nullptr));
|
||||
::testing::NiceMock<GMockMemoryManagerFailFirstAllocation> *memoryManager = new ::testing::NiceMock<GMockMemoryManagerFailFirstAllocation>;
|
||||
|
||||
device->injectMemoryManager(memoryManager);
|
||||
MockContext ctx(device.get());
|
||||
|
||||
// First fail in createGraphicsAllocation simulates error for read only memory allocation
|
||||
EXPECT_CALL(*memoryManager, createGraphicsAllocationWithRequiredBitness(MemoryConstants::pageSize, (void *)memory, true))
|
||||
.WillOnce(::testing::Return(nullptr));
|
||||
|
||||
cl_int retVal;
|
||||
cl_mem_flags flags = CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR;
|
||||
|
||||
std::unique_ptr<Buffer> buffer(Buffer::create(&ctx, flags, MemoryConstants::pageSize, (void *)memory, retVal));
|
||||
|
||||
EXPECT_EQ(nullptr, buffer.get());
|
||||
alignedFree(memory);
|
||||
}
|
||||
|
||||
TEST(Buffer, givenNullPtrWhenBufferIsCreatedWithKernelReadOnlyFlagsThenBufferAllocationFailsAndReturnsNullptr) {
|
||||
std::unique_ptr<MockDevice> device(DeviceHelper<>::create(nullptr));
|
||||
::testing::NiceMock<GMockMemoryManagerFailFirstAllocation> *memoryManager = new ::testing::NiceMock<GMockMemoryManagerFailFirstAllocation>;
|
||||
|
||||
device->injectMemoryManager(memoryManager);
|
||||
MockContext ctx(device.get());
|
||||
|
||||
// First fail in createGraphicsAllocation simulates error for read only memory allocation
|
||||
EXPECT_CALL(*memoryManager, createGraphicsAllocationWithRequiredBitness(::testing::_, nullptr, ::testing::_))
|
||||
.WillOnce(::testing::Return(nullptr));
|
||||
|
||||
cl_int retVal;
|
||||
cl_mem_flags flags = CL_MEM_HOST_READ_ONLY | CL_MEM_WRITE_ONLY;
|
||||
|
||||
std::unique_ptr<Buffer> buffer(Buffer::create(&ctx, flags, MemoryConstants::pageSize, nullptr, retVal));
|
||||
|
||||
EXPECT_EQ(nullptr, buffer.get());
|
||||
}
|
||||
|
||||
class BufferTest : public DeviceFixture,
|
||||
public testing::TestWithParam<uint64_t /*cl_mem_flags*/> {
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue