Add clEnqueueNDRangeKernelINTEL API

Related-To: NEO-2712

Change-Id: If1d16d9d626871a9dc4b19282f9edc5786ffa398
Signed-off-by: Filip Hazubski <filip.hazubski@intel.com>
This commit is contained in:
Filip Hazubski
2019-11-19 16:54:47 +01:00
committed by sys_ocldev
parent 7be937c226
commit 82bc594af0
26 changed files with 764 additions and 14 deletions

View File

@@ -34,11 +34,11 @@ set(IGDRCL_SRCS_tests_command_queue
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_fixture.cpp
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_fixture.h
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_handler_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_kernel_1_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_kernel_2_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_kernel_event_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_kernel_global_offset_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_kernel_local_work_size_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_kernel_1_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_kernel_2_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_kernel_two_ioq_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_kernel_two_ooq_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/enqueue_kernel_two_walker_ioq_tests.cpp
@@ -89,6 +89,7 @@ set(IGDRCL_SRCS_tests_command_queue
${CMAKE_CURRENT_SOURCE_DIR}/ooq_task_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ooq_task_tests_mt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/read_write_buffer_cpu_copy.cpp
${CMAKE_CURRENT_SOURCE_DIR}/sync_buffer_handler_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/work_group_size_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/zero_size_enqueue_tests.cpp
)

View File

@@ -6,6 +6,7 @@
*/
#include "core/unit_tests/helpers/debug_manager_state_restore.h"
#include "runtime/api/api.h"
#include "runtime/built_ins/builtins_dispatch_builder.h"
#include "unit_tests/command_queue/enqueue_fixture.h"
#include "unit_tests/fixtures/hello_world_fixture.h"
@@ -187,6 +188,156 @@ TEST_F(EnqueueKernelTest, GivenInvalidWorkGroupSizeWhenEnqueuingKernelThenInvali
EXPECT_EQ(CL_INVALID_WORK_GROUP_SIZE, retVal);
}
TEST_F(EnqueueKernelTest, GivenNullKernelWhenEnqueuingKernelINTELThenInvalidKernelErrorIsReturned) {
size_t workgroupCount[3] = {1, 1, 1};
auto retVal = clEnqueueNDRangeKernelINTEL(
pCmdQ,
nullptr,
1,
nullptr,
workgroupCount,
nullptr,
0,
nullptr,
nullptr);
EXPECT_EQ(CL_INVALID_KERNEL, retVal);
}
TEST_F(EnqueueKernelTest, givenKernelWhenAllArgsAreSetThenClEnqueueNDRangeKernelINTELReturnsSuccess) {
const size_t n = 512;
size_t workgroupCount[3] = {2, 1, 1};
size_t localWorkSize[3] = {256, 1, 1};
cl_int retVal = CL_SUCCESS;
CommandQueue *pCmdQ2 = createCommandQueue(pDevice);
std::unique_ptr<Kernel> kernel(Kernel::create(pProgram, *pProgram->getKernelInfo("CopyBuffer"), &retVal));
EXPECT_EQ(CL_SUCCESS, retVal);
auto b0 = clCreateBuffer(context, 0, n * sizeof(float), nullptr, nullptr);
auto b1 = clCreateBuffer(context, 0, n * sizeof(float), nullptr, nullptr);
EXPECT_FALSE(kernel->isPatched());
retVal = clEnqueueNDRangeKernelINTEL(pCmdQ2, kernel.get(), 1, nullptr, workgroupCount, localWorkSize, 0, nullptr, nullptr);
EXPECT_EQ(CL_INVALID_KERNEL_ARGS, retVal);
retVal = clSetKernelArg(kernel.get(), 0, sizeof(cl_mem), &b0);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_FALSE(kernel->isPatched());
retVal = clEnqueueNDRangeKernelINTEL(pCmdQ2, kernel.get(), 1, nullptr, workgroupCount, localWorkSize, 0, nullptr, nullptr);
EXPECT_EQ(CL_INVALID_KERNEL_ARGS, retVal);
retVal = clSetKernelArg(kernel.get(), 1, sizeof(cl_mem), &b1);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_TRUE(kernel->isPatched());
retVal = clEnqueueNDRangeKernelINTEL(pCmdQ2, kernel.get(), 1, nullptr, workgroupCount, localWorkSize, 0, nullptr, nullptr);
EXPECT_EQ(CL_SUCCESS, retVal);
retVal = clReleaseMemObject(b0);
EXPECT_EQ(CL_SUCCESS, retVal);
retVal = clReleaseMemObject(b1);
EXPECT_EQ(CL_SUCCESS, retVal);
clReleaseCommandQueue(pCmdQ2);
EXPECT_EQ(CL_SUCCESS, retVal);
}
TEST_F(EnqueueKernelTest, givenKernelWhenNotAllArgsAreSetButSetKernelArgIsCalledTwiceThenClEnqueueNDRangeKernelINTELReturnsError) {
const size_t n = 512;
size_t workgroupCount[3] = {2, 1, 1};
size_t localWorkSize[3] = {256, 1, 1};
cl_int retVal = CL_SUCCESS;
CommandQueue *pCmdQ2 = createCommandQueue(pDevice);
std::unique_ptr<Kernel> kernel(Kernel::create(pProgram, *pProgram->getKernelInfo("CopyBuffer"), &retVal));
EXPECT_EQ(CL_SUCCESS, retVal);
auto b0 = clCreateBuffer(context, 0, n * sizeof(float), nullptr, nullptr);
auto b1 = clCreateBuffer(context, 0, n * sizeof(float), nullptr, nullptr);
EXPECT_FALSE(kernel->isPatched());
retVal = clEnqueueNDRangeKernelINTEL(pCmdQ2, kernel.get(), 1, nullptr, workgroupCount, localWorkSize, 0, nullptr, nullptr);
EXPECT_EQ(CL_INVALID_KERNEL_ARGS, retVal);
retVal = clSetKernelArg(kernel.get(), 0, sizeof(cl_mem), &b0);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_FALSE(kernel->isPatched());
retVal = clEnqueueNDRangeKernelINTEL(pCmdQ2, kernel.get(), 1, nullptr, workgroupCount, localWorkSize, 0, nullptr, nullptr);
EXPECT_EQ(CL_INVALID_KERNEL_ARGS, retVal);
retVal = clSetKernelArg(kernel.get(), 0, sizeof(cl_mem), &b1);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_FALSE(kernel->isPatched());
retVal = clEnqueueNDRangeKernelINTEL(pCmdQ2, kernel.get(), 1, nullptr, workgroupCount, localWorkSize, 0, nullptr, nullptr);
EXPECT_EQ(CL_INVALID_KERNEL_ARGS, retVal);
retVal = clReleaseMemObject(b0);
EXPECT_EQ(CL_SUCCESS, retVal);
retVal = clReleaseMemObject(b1);
EXPECT_EQ(CL_SUCCESS, retVal);
clReleaseCommandQueue(pCmdQ2);
EXPECT_EQ(CL_SUCCESS, retVal);
}
TEST_F(EnqueueKernelTest, givenKernelWhenSetKernelArgIsCalledForEachArgButAtLeastFailsThenClEnqueueNDRangeKernelINTELReturnsError) {
const size_t n = 512;
size_t workgroupCount[3] = {2, 1, 1};
size_t localWorkSize[3] = {256, 1, 1};
cl_int retVal = CL_SUCCESS;
CommandQueue *pCmdQ2 = createCommandQueue(pDevice);
std::unique_ptr<Kernel> kernel(Kernel::create(pProgram, *pProgram->getKernelInfo("CopyBuffer"), &retVal));
EXPECT_EQ(CL_SUCCESS, retVal);
auto b0 = clCreateBuffer(context, 0, n * sizeof(float), nullptr, nullptr);
auto b1 = clCreateBuffer(context, 0, n * sizeof(float), nullptr, nullptr);
EXPECT_FALSE(kernel->isPatched());
retVal = clEnqueueNDRangeKernelINTEL(pCmdQ2, kernel.get(), 1, nullptr, workgroupCount, localWorkSize, 0, nullptr, nullptr);
EXPECT_EQ(CL_INVALID_KERNEL_ARGS, retVal);
retVal = clSetKernelArg(kernel.get(), 0, sizeof(cl_mem), &b0);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_FALSE(kernel->isPatched());
retVal = clEnqueueNDRangeKernelINTEL(pCmdQ2, kernel.get(), 1, nullptr, workgroupCount, localWorkSize, 0, nullptr, nullptr);
EXPECT_EQ(CL_INVALID_KERNEL_ARGS, retVal);
retVal = clSetKernelArg(kernel.get(), 1, 2 * sizeof(cl_mem), &b1);
EXPECT_NE(CL_SUCCESS, retVal);
EXPECT_FALSE(kernel->isPatched());
retVal = clEnqueueNDRangeKernelINTEL(pCmdQ2, kernel.get(), 1, nullptr, workgroupCount, localWorkSize, 0, nullptr, nullptr);
EXPECT_EQ(CL_INVALID_KERNEL_ARGS, retVal);
retVal = clReleaseMemObject(b0);
EXPECT_EQ(CL_SUCCESS, retVal);
retVal = clReleaseMemObject(b1);
EXPECT_EQ(CL_SUCCESS, retVal);
clReleaseCommandQueue(pCmdQ2);
EXPECT_EQ(CL_SUCCESS, retVal);
}
TEST_F(EnqueueKernelTest, GivenInvalidEventListCountWhenEnqueuingKernelINTELThenInvalidEventWaitListErrorIsReturned) {
size_t workgroupCount[3] = {1, 1, 1};
auto retVal = clEnqueueNDRangeKernelINTEL(
pCmdQ,
pKernel,
1,
nullptr,
workgroupCount,
nullptr,
1,
nullptr,
nullptr);
EXPECT_EQ(CL_INVALID_EVENT_WAIT_LIST, retVal);
}
HWTEST_F(EnqueueKernelTest, bumpsTaskLevel) {
auto taskLevelBefore = pCmdQ->taskLevel;
callOneWorkItemNDRKernel();

View File

@@ -0,0 +1,167 @@
/*
* Copyright (C) 2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/program/sync_buffer_handler.h"
#include "runtime/api/api.h"
#include "test.h"
#include "unit_tests/fixtures/enqueue_handler_fixture.h"
#include "unit_tests/mocks/mock_command_queue.h"
#include "unit_tests/mocks/mock_kernel.h"
#include "unit_tests/mocks/mock_mdi.h"
using namespace NEO;
class MockSyncBufferHandler : public SyncBufferHandler {
public:
using SyncBufferHandler::bufferSize;
using SyncBufferHandler::graphicsAllocation;
using SyncBufferHandler::usedBufferSize;
};
class SyncBufferHandlerTest : public EnqueueHandlerTest {
public:
void SetUp() override {}
void TearDown() override {}
template <typename FamilyType>
void SetUpT() {
EnqueueHandlerTest::SetUp();
kernelInternals = std::make_unique<MockKernelWithInternals>(*pDevice, context);
kernel = kernelInternals->mockKernel;
commandQueue = reinterpret_cast<MockCommandQueue *>(new MockCommandQueueHw<FamilyType>(context, pDevice, 0));
}
template <typename FamilyType>
void TearDownT() {
commandQueue->release();
kernelInternals.reset();
EnqueueHandlerTest::TearDown();
}
void patchAllocateSyncBuffer() {
sPatchAllocateSyncBuffer.SurfaceStateHeapOffset = 0;
sPatchAllocateSyncBuffer.DataParamOffset = 0;
sPatchAllocateSyncBuffer.DataParamSize = sizeof(uint8_t);
kernelInternals->kernelInfo.patchInfo.pAllocateSyncBuffer = &sPatchAllocateSyncBuffer;
}
MockSyncBufferHandler *getSyncBufferHandler() {
return reinterpret_cast<MockSyncBufferHandler *>(pDevice->syncBufferHandler.get());
}
const cl_uint workDim = 1;
const size_t gwOffset[3] = {0, 0, 0};
const size_t lws[3] = {10, 1, 1};
size_t workgroupCount[3] = {10, 1, 1};
size_t workItemsCount = 10;
std::unique_ptr<MockKernelWithInternals> kernelInternals;
MockKernel *kernel;
MockCommandQueue *commandQueue;
SPatchAllocateSyncBuffer sPatchAllocateSyncBuffer;
};
HWTEST_TEMPLATED_F(SyncBufferHandlerTest, GivenAllocateSyncBufferPatchWhenEnqueuingKernelThenSyncBufferIsUsed) {
patchAllocateSyncBuffer();
clEnqueueNDRangeKernelINTEL(commandQueue, kernel, workDim, gwOffset, workgroupCount, lws, 0, nullptr, nullptr);
auto syncBufferHandler = getSyncBufferHandler();
EXPECT_EQ(workItemsCount, syncBufferHandler->usedBufferSize);
commandQueue->flush();
EXPECT_EQ(syncBufferHandler->graphicsAllocation->getTaskCount(
pDevice->getUltCommandStreamReceiver<FamilyType>().getOsContext().getContextId()),
pDevice->getUltCommandStreamReceiver<FamilyType>().latestSentTaskCount);
}
HWTEST_TEMPLATED_F(SyncBufferHandlerTest, GivenNoAllocateSyncBufferPatchWhenEnqueuingKernelThenSyncBufferIsNotUsedAndUsedBufferSizeIsNotUpdated) {
clEnqueueNDRangeKernelINTEL(commandQueue, kernel, workDim, gwOffset, workgroupCount, lws, 0, nullptr, nullptr);
auto syncBufferHandler = getSyncBufferHandler();
EXPECT_EQ(0u, syncBufferHandler->usedBufferSize);
}
HWTEST_TEMPLATED_F(SyncBufferHandlerTest, GivenMaxWorkgroupCountWhenEnqueuingKernelThenSuccessIsReturned) {
auto maxWorkGroupCount = kernel->getMaxWorkGroupCount(workDim, lws);
workgroupCount[0] = maxWorkGroupCount;
auto retVal = clEnqueueNDRangeKernelINTEL(commandQueue, kernel, workDim, gwOffset, workgroupCount, lws, 0, nullptr, nullptr);
EXPECT_EQ(CL_SUCCESS, retVal);
}
HWTEST_TEMPLATED_F(SyncBufferHandlerTest, GivenTooHighWorkgroupCountWhenEnqueuingKernelThenErrorIsReturned) {
size_t maxWorkGroupCount = kernel->getMaxWorkGroupCount(workDim, lws);
workgroupCount[0] = maxWorkGroupCount + 1;
auto retVal = clEnqueueNDRangeKernelINTEL(commandQueue, kernel, workDim, gwOffset, workgroupCount, lws, 0, nullptr, nullptr);
EXPECT_EQ(CL_INVALID_VALUE, retVal);
}
HWTEST_TEMPLATED_F(SyncBufferHandlerTest, GivenSyncBufferFullWhenEnqueuingKernelThenNewBufferIsAllocated) {
patchAllocateSyncBuffer();
clEnqueueNDRangeKernelINTEL(commandQueue, kernel, workDim, gwOffset, workgroupCount, lws, 0, nullptr, nullptr);
auto syncBufferHandler = getSyncBufferHandler();
syncBufferHandler->usedBufferSize = syncBufferHandler->bufferSize;
clEnqueueNDRangeKernelINTEL(commandQueue, kernel, workDim, gwOffset, workgroupCount, lws, 0, nullptr, nullptr);
EXPECT_EQ(workItemsCount, syncBufferHandler->usedBufferSize);
}
HWTEST_TEMPLATED_F(SyncBufferHandlerTest, GivenSshRequiredWhenPatchingSyncBufferThenSshIsProperlyPatched) {
using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE;
kernelInternals->kernelInfo.usesSsh = true;
kernelInternals->kernelInfo.requiresSshForBuffers = true;
patchAllocateSyncBuffer();
pDevice->allocateSyncBufferHandler();
auto syncBufferHandler = getSyncBufferHandler();
auto surfaceState = reinterpret_cast<const RENDER_SURFACE_STATE *>(ptrOffset(kernel->getSurfaceStateHeap(),
sPatchAllocateSyncBuffer.SurfaceStateHeapOffset));
auto surfaceAddress = surfaceState->getSurfaceBaseAddress();
auto bufferAddress = syncBufferHandler->graphicsAllocation->getGpuAddress();
EXPECT_NE(bufferAddress, surfaceAddress);
kernel->patchSyncBuffer(commandQueue->getDevice(), syncBufferHandler->graphicsAllocation, syncBufferHandler->usedBufferSize);
surfaceAddress = surfaceState->getSurfaceBaseAddress();
EXPECT_EQ(bufferAddress, surfaceAddress);
}
HWTEST_TEMPLATED_F(SyncBufferHandlerTest, GivenKernelUsingSyncBufferWhenUsingStandardEnqueueThenErrorIsReturned) {
patchAllocateSyncBuffer();
size_t globalWorkSize[3] = {workgroupCount[0] * lws[0], workgroupCount[1] * lws[1], workgroupCount[2] * lws[2]};
auto retVal = clEnqueueNDRangeKernel(commandQueue, kernel, workDim, gwOffset, globalWorkSize, lws, 0, nullptr, nullptr);
EXPECT_EQ(CL_INVALID_KERNEL, retVal);
}
TEST(SyncBufferHandlerDeviceTest, GivenRootDeviceWhenAllocateSyncBufferIsCalledTwiceThenTheObjectIsCreatedOnlyOnce) {
const size_t testUsedBufferSize = 100;
MockDevice rootDevice;
rootDevice.allocateSyncBufferHandler();
auto syncBufferHandler = reinterpret_cast<MockSyncBufferHandler *>(rootDevice.syncBufferHandler.get());
ASSERT_NE(syncBufferHandler->usedBufferSize, testUsedBufferSize);
syncBufferHandler->usedBufferSize = testUsedBufferSize;
rootDevice.allocateSyncBufferHandler();
syncBufferHandler = reinterpret_cast<MockSyncBufferHandler *>(rootDevice.syncBufferHandler.get());
EXPECT_EQ(testUsedBufferSize, syncBufferHandler->usedBufferSize);
}
TEST(SyncBufferHandlerDeviceTest, GivenSubDeviceWhenAllocateSyncBufferIsCalledTwiceThenTheObjectIsCreatedOnlyOnce) {
const size_t testUsedBufferSize = 100;
MockDevice rootDevice;
std::unique_ptr<MockSubDevice> subDevice{reinterpret_cast<MockSubDevice *>(rootDevice.createSubDevice(0))};
subDevice->allocateSyncBufferHandler();
auto syncBufferHandler = reinterpret_cast<MockSyncBufferHandler *>(subDevice->syncBufferHandler.get());
ASSERT_NE(syncBufferHandler->usedBufferSize, testUsedBufferSize);
syncBufferHandler->usedBufferSize = testUsedBufferSize;
subDevice->allocateSyncBufferHandler();
syncBufferHandler = reinterpret_cast<MockSyncBufferHandler *>(subDevice->syncBufferHandler.get());
EXPECT_EQ(testUsedBufferSize, syncBufferHandler->usedBufferSize);
}