438 lines
15 KiB
C++
438 lines
15 KiB
C++
/*
|
|
* Copyright (c) 2017, 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 "hw_cmds.h"
|
|
#include "runtime/helpers/ptr_math.h"
|
|
#include "runtime/kernel/kernel.h"
|
|
#include "runtime/sampler/sampler.h"
|
|
#include "runtime/helpers/sampler_helpers.h"
|
|
#include "unit_tests/fixtures/device_fixture.h"
|
|
#include "test.h"
|
|
#include "unit_tests/mocks/mock_context.h"
|
|
#include "unit_tests/mocks/mock_kernel.h"
|
|
#include "unit_tests/mocks/mock_program.h"
|
|
|
|
using namespace OCLRT;
|
|
|
|
namespace OCLRT {
|
|
class Surface;
|
|
};
|
|
|
|
class SamplerSetArgFixture : public DeviceFixture {
|
|
public:
|
|
SamplerSetArgFixture()
|
|
|
|
{
|
|
memset(&kernelHeader, 0, sizeof(kernelHeader));
|
|
}
|
|
|
|
protected:
|
|
void SetUp() {
|
|
DeviceFixture::SetUp();
|
|
pKernelInfo = KernelInfo::create();
|
|
|
|
// define kernel info
|
|
kernelHeader.DynamicStateHeapSize = sizeof(samplerStateHeap);
|
|
pKernelInfo->heapInfo.pDsh = samplerStateHeap;
|
|
pKernelInfo->heapInfo.pKernelHeader = &kernelHeader;
|
|
|
|
// setup kernel arg offsets
|
|
pKernelInfo->kernelArgInfo.resize(2);
|
|
pKernelInfo->kernelArgInfo[0].offsetHeap = 0x40;
|
|
pKernelInfo->kernelArgInfo[0].isSampler = true;
|
|
|
|
pKernelInfo->kernelArgInfo[0].offsetObjectId = 0x0;
|
|
pKernelInfo->kernelArgInfo[0].offsetSamplerSnapWa = 0x4;
|
|
pKernelInfo->kernelArgInfo[0].offsetSamplerAddressingMode = 0x8;
|
|
pKernelInfo->kernelArgInfo[0].offsetSamplerNormalizedCoords = 0x10;
|
|
|
|
pKernelInfo->kernelArgInfo[1].offsetHeap = 0x40;
|
|
pKernelInfo->kernelArgInfo[1].isSampler = true;
|
|
|
|
pKernel = new MockKernel(&program, *pKernelInfo, *pDevice);
|
|
ASSERT_NE(nullptr, pKernel);
|
|
ASSERT_EQ(CL_SUCCESS, pKernel->initialize());
|
|
|
|
pKernel->setKernelArgHandler(0, &Kernel::setArgSampler);
|
|
pKernel->setKernelArgHandler(1, &Kernel::setArgSampler);
|
|
|
|
uint32_t crossThreadData[crossThreadDataSize] = {};
|
|
pKernel->setCrossThreadData(crossThreadData, sizeof(crossThreadData));
|
|
context = new MockContext(pDevice);
|
|
retVal = CL_INVALID_VALUE;
|
|
}
|
|
|
|
void TearDown() {
|
|
delete pKernelInfo;
|
|
delete sampler;
|
|
delete pKernel;
|
|
delete context;
|
|
DeviceFixture::TearDown();
|
|
}
|
|
|
|
bool crossThreadDataUnchanged() {
|
|
for (uint32_t i = 0; i < crossThreadDataSize; i++) {
|
|
if (pKernel->mockCrossThreadData[i] != 0u) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void createSampler() {
|
|
sampler = Sampler::create(
|
|
context,
|
|
CL_TRUE,
|
|
CL_ADDRESS_MIRRORED_REPEAT,
|
|
CL_FILTER_NEAREST,
|
|
retVal);
|
|
}
|
|
|
|
static const uint32_t crossThreadDataSize = 0x40;
|
|
|
|
// clang-format off
|
|
cl_int retVal = CL_SUCCESS;
|
|
MockProgram program;
|
|
MockKernel *pKernel = nullptr;
|
|
SKernelBinaryHeaderCommon kernelHeader;
|
|
KernelInfo *pKernelInfo = nullptr;
|
|
char samplerStateHeap[0x80];
|
|
MockContext *context;
|
|
Sampler *sampler = nullptr;
|
|
// clang-format on
|
|
};
|
|
|
|
typedef Test<SamplerSetArgFixture> SamplerSetArgTest;
|
|
HWTEST_F(SamplerSetArgTest, clSetKernelArgSampler) {
|
|
typedef typename FamilyType::SAMPLER_STATE SAMPLER_STATE;
|
|
createSampler();
|
|
|
|
cl_sampler samplerObj = sampler;
|
|
|
|
retVal = clSetKernelArg(
|
|
pKernel,
|
|
0,
|
|
sizeof(samplerObj),
|
|
&samplerObj);
|
|
ASSERT_EQ(CL_SUCCESS, retVal);
|
|
|
|
auto samplerState = reinterpret_cast<const SAMPLER_STATE *>(
|
|
ptrOffset(pKernel->getDynamicStateHeap(),
|
|
pKernelInfo->kernelArgInfo[0].offsetHeap));
|
|
EXPECT_EQ(static_cast<cl_bool>(CL_TRUE), static_cast<cl_bool>(!samplerState->getNonNormalizedCoordinateEnable()));
|
|
EXPECT_EQ(SAMPLER_STATE::TCX_ADDRESS_CONTROL_MODE_MIRROR, samplerState->getTcxAddressControlMode());
|
|
EXPECT_EQ(SAMPLER_STATE::TCY_ADDRESS_CONTROL_MODE_MIRROR, samplerState->getTcyAddressControlMode());
|
|
EXPECT_EQ(SAMPLER_STATE::TCZ_ADDRESS_CONTROL_MODE_MIRROR, samplerState->getTczAddressControlMode());
|
|
EXPECT_EQ(SAMPLER_STATE::MIN_MODE_FILTER_NEAREST, samplerState->getMinModeFilter());
|
|
EXPECT_EQ(SAMPLER_STATE::MAG_MODE_FILTER_NEAREST, samplerState->getMagModeFilter());
|
|
EXPECT_EQ(SAMPLER_STATE::MIP_MODE_FILTER_NEAREST, samplerState->getMipModeFilter());
|
|
|
|
std::vector<Surface *> surfaces;
|
|
pKernel->getResidency(surfaces);
|
|
EXPECT_EQ(0u, surfaces.size());
|
|
}
|
|
|
|
HWTEST_F(SamplerSetArgTest, getKernelArgShouldReturnSampler) {
|
|
createSampler();
|
|
cl_sampler samplerObj = sampler;
|
|
|
|
retVal = pKernel->setArg(
|
|
0,
|
|
sizeof(samplerObj),
|
|
&samplerObj);
|
|
ASSERT_EQ(CL_SUCCESS, retVal);
|
|
|
|
EXPECT_EQ(samplerObj, pKernel->getKernelArg(0));
|
|
}
|
|
|
|
HWTEST_F(SamplerSetArgTest, WithFilteringNearestAndAddressingClClampSetAsKernelArgumentSetsConstantBuffer) {
|
|
|
|
sampler = Sampler::create(
|
|
context,
|
|
CL_TRUE,
|
|
CL_ADDRESS_CLAMP,
|
|
CL_FILTER_NEAREST,
|
|
retVal);
|
|
|
|
cl_sampler samplerObj = sampler;
|
|
|
|
retVal = pKernel->setArg(
|
|
0,
|
|
sizeof(samplerObj),
|
|
&samplerObj);
|
|
ASSERT_EQ(CL_SUCCESS, retVal);
|
|
|
|
EXPECT_EQ(samplerObj, pKernel->getKernelArg(0));
|
|
|
|
auto crossThreadData = reinterpret_cast<uint32_t *>(pKernel->getCrossThreadData());
|
|
auto snapWaCrossThreadData = ptrOffset(crossThreadData, 0x4);
|
|
|
|
unsigned int snapWaValue = 0xffffffff;
|
|
unsigned int objectId = SAMPLER_OBJECT_ID_SHIFT + pKernelInfo->kernelArgInfo[0].offsetHeap;
|
|
|
|
EXPECT_EQ(snapWaValue, *snapWaCrossThreadData);
|
|
EXPECT_EQ(objectId, *crossThreadData);
|
|
}
|
|
|
|
HWTEST_F(SamplerSetArgTest, GIVENkernelWithoutObjIdOffsetWHENsetArgTHENdoesntPatchObjId) {
|
|
|
|
sampler = Sampler::create(
|
|
context,
|
|
CL_TRUE,
|
|
CL_ADDRESS_CLAMP,
|
|
CL_FILTER_NEAREST,
|
|
retVal);
|
|
|
|
cl_sampler samplerObj = sampler;
|
|
|
|
retVal = pKernel->setArg(
|
|
1,
|
|
sizeof(samplerObj),
|
|
&samplerObj);
|
|
ASSERT_EQ(CL_SUCCESS, retVal);
|
|
|
|
EXPECT_EQ(samplerObj, pKernel->getKernelArg(1));
|
|
EXPECT_TRUE(crossThreadDataUnchanged());
|
|
}
|
|
|
|
HWTEST_F(SamplerSetArgTest, setKernelArgWithNullptrSampler) {
|
|
createSampler();
|
|
cl_sampler samplerObj = sampler;
|
|
|
|
retVal = pKernel->setArg(
|
|
0,
|
|
sizeof(samplerObj),
|
|
nullptr);
|
|
ASSERT_EQ(CL_INVALID_SAMPLER, retVal);
|
|
}
|
|
|
|
HWTEST_F(SamplerSetArgTest, setKernelArgWithInvalidSampler) {
|
|
createSampler();
|
|
cl_sampler samplerObj = sampler;
|
|
|
|
const void *notASampler = reinterpret_cast<const void *>(pKernel);
|
|
|
|
retVal = pKernel->setArg(
|
|
0,
|
|
sizeof(samplerObj),
|
|
notASampler);
|
|
ASSERT_EQ(CL_INVALID_SAMPLER, retVal);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
struct NormalizedTest
|
|
: public SamplerSetArgFixture,
|
|
public ::testing::TestWithParam<uint32_t /*cl_bool*/> {
|
|
void SetUp() override {
|
|
SamplerSetArgFixture::SetUp();
|
|
}
|
|
void TearDown() override {
|
|
SamplerSetArgFixture::TearDown();
|
|
}
|
|
};
|
|
|
|
HWTEST_P(NormalizedTest, setKernelArgSampler) {
|
|
typedef typename FamilyType::SAMPLER_STATE SAMPLER_STATE;
|
|
auto normalizedCoordinates = GetParam();
|
|
sampler = Sampler::create(
|
|
context,
|
|
normalizedCoordinates,
|
|
CL_ADDRESS_MIRRORED_REPEAT,
|
|
CL_FILTER_NEAREST,
|
|
retVal);
|
|
|
|
cl_sampler samplerObj = sampler;
|
|
|
|
retVal = pKernel->setArg(
|
|
0,
|
|
sizeof(samplerObj),
|
|
&samplerObj);
|
|
ASSERT_EQ(CL_SUCCESS, retVal);
|
|
|
|
auto samplerState = reinterpret_cast<const SAMPLER_STATE *>(
|
|
ptrOffset(pKernel->getDynamicStateHeap(),
|
|
pKernelInfo->kernelArgInfo[0].offsetHeap));
|
|
|
|
EXPECT_EQ(normalizedCoordinates, static_cast<cl_bool>(!samplerState->getNonNormalizedCoordinateEnable()));
|
|
|
|
auto crossThreadData = reinterpret_cast<uint32_t *>(pKernel->getCrossThreadData());
|
|
auto normalizedCoordsAddress = ptrOffset(crossThreadData, 0x10);
|
|
unsigned int normalizedCoordsValue = GetNormCoordsEnum(normalizedCoordinates);
|
|
|
|
EXPECT_EQ(normalizedCoordsValue, *normalizedCoordsAddress);
|
|
}
|
|
|
|
cl_bool normalizedCoordinatesCases[] = {
|
|
CL_FALSE,
|
|
CL_TRUE};
|
|
|
|
INSTANTIATE_TEST_CASE_P(SamplerSetArg,
|
|
NormalizedTest,
|
|
::testing::ValuesIn(normalizedCoordinatesCases));
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
struct AddressingModeTest
|
|
: public SamplerSetArgFixture,
|
|
public ::testing::TestWithParam<uint32_t /*cl_addressing_mode*/> {
|
|
void SetUp() override {
|
|
SamplerSetArgFixture::SetUp();
|
|
}
|
|
void TearDown() override {
|
|
SamplerSetArgFixture::TearDown();
|
|
}
|
|
};
|
|
|
|
HWTEST_P(AddressingModeTest, setKernelArgSampler) {
|
|
typedef typename FamilyType::SAMPLER_STATE SAMPLER_STATE;
|
|
auto addressingMode = GetParam();
|
|
sampler = Sampler::create(
|
|
context,
|
|
CL_TRUE,
|
|
addressingMode,
|
|
CL_FILTER_NEAREST,
|
|
retVal);
|
|
|
|
cl_sampler samplerObj = sampler;
|
|
|
|
retVal = pKernel->setArg(
|
|
0,
|
|
sizeof(samplerObj),
|
|
&samplerObj);
|
|
ASSERT_EQ(CL_SUCCESS, retVal);
|
|
|
|
auto samplerState = reinterpret_cast<const SAMPLER_STATE *>(
|
|
ptrOffset(pKernel->getDynamicStateHeap(),
|
|
pKernelInfo->kernelArgInfo[0].offsetHeap));
|
|
|
|
auto expectedModeX = SAMPLER_STATE::TCX_ADDRESS_CONTROL_MODE_MIRROR;
|
|
auto expectedModeY = SAMPLER_STATE::TCY_ADDRESS_CONTROL_MODE_MIRROR;
|
|
auto expectedModeZ = SAMPLER_STATE::TCZ_ADDRESS_CONTROL_MODE_MIRROR;
|
|
|
|
// clang-format off
|
|
switch (addressingMode) {
|
|
case CL_ADDRESS_NONE:
|
|
case CL_ADDRESS_CLAMP:
|
|
expectedModeX = SAMPLER_STATE::TCX_ADDRESS_CONTROL_MODE_CLAMP_BORDER;
|
|
expectedModeY = SAMPLER_STATE::TCY_ADDRESS_CONTROL_MODE_CLAMP_BORDER;
|
|
expectedModeZ = SAMPLER_STATE::TCZ_ADDRESS_CONTROL_MODE_CLAMP_BORDER;
|
|
break;
|
|
case CL_ADDRESS_CLAMP_TO_EDGE:
|
|
expectedModeX = SAMPLER_STATE::TCX_ADDRESS_CONTROL_MODE_CLAMP;
|
|
expectedModeY = SAMPLER_STATE::TCY_ADDRESS_CONTROL_MODE_CLAMP;
|
|
expectedModeZ = SAMPLER_STATE::TCZ_ADDRESS_CONTROL_MODE_CLAMP;
|
|
break;
|
|
case CL_ADDRESS_MIRRORED_REPEAT:
|
|
expectedModeX = SAMPLER_STATE::TCX_ADDRESS_CONTROL_MODE_MIRROR;
|
|
expectedModeY = SAMPLER_STATE::TCY_ADDRESS_CONTROL_MODE_MIRROR;
|
|
expectedModeZ = SAMPLER_STATE::TCZ_ADDRESS_CONTROL_MODE_MIRROR;
|
|
break;
|
|
case CL_ADDRESS_REPEAT:
|
|
expectedModeX = SAMPLER_STATE::TCX_ADDRESS_CONTROL_MODE_WRAP;
|
|
expectedModeY = SAMPLER_STATE::TCY_ADDRESS_CONTROL_MODE_WRAP;
|
|
expectedModeZ = SAMPLER_STATE::TCZ_ADDRESS_CONTROL_MODE_WRAP;
|
|
break;
|
|
}
|
|
// clang-format on
|
|
|
|
EXPECT_EQ(expectedModeX, samplerState->getTcxAddressControlMode());
|
|
EXPECT_EQ(expectedModeY, samplerState->getTcyAddressControlMode());
|
|
EXPECT_EQ(expectedModeZ, samplerState->getTczAddressControlMode());
|
|
|
|
auto crossThreadData = reinterpret_cast<uint32_t *>(pKernel->getCrossThreadData());
|
|
auto addressingModeAddress = ptrOffset(crossThreadData, 0x8);
|
|
|
|
unsigned int addresingValue = GetAddrModeEnum(addressingMode);
|
|
|
|
EXPECT_EQ(addresingValue, *addressingModeAddress);
|
|
}
|
|
|
|
cl_addressing_mode addressingModeCases[] = {
|
|
CL_ADDRESS_NONE,
|
|
CL_ADDRESS_CLAMP_TO_EDGE,
|
|
CL_ADDRESS_CLAMP,
|
|
CL_ADDRESS_REPEAT,
|
|
CL_ADDRESS_MIRRORED_REPEAT};
|
|
|
|
INSTANTIATE_TEST_CASE_P(SamplerSetArg,
|
|
AddressingModeTest,
|
|
::testing::ValuesIn(addressingModeCases));
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
struct FilterModeTest
|
|
: public SamplerSetArgFixture,
|
|
public ::testing::TestWithParam<uint32_t /*cl_filter_mode*/> {
|
|
void SetUp() override {
|
|
SamplerSetArgFixture::SetUp();
|
|
}
|
|
void TearDown() override {
|
|
SamplerSetArgFixture::TearDown();
|
|
}
|
|
};
|
|
|
|
HWTEST_P(FilterModeTest, setKernelArgSampler) {
|
|
typedef typename FamilyType::SAMPLER_STATE SAMPLER_STATE;
|
|
auto filterMode = GetParam();
|
|
sampler = Sampler::create(
|
|
context,
|
|
CL_TRUE,
|
|
CL_ADDRESS_MIRRORED_REPEAT,
|
|
filterMode,
|
|
retVal);
|
|
|
|
auto samplerState = reinterpret_cast<const SAMPLER_STATE *>(
|
|
ptrOffset(pKernel->getDynamicStateHeap(),
|
|
pKernelInfo->kernelArgInfo[0].offsetHeap));
|
|
|
|
sampler->setArg(const_cast<SAMPLER_STATE *>(samplerState));
|
|
|
|
if (CL_FILTER_NEAREST == filterMode) {
|
|
EXPECT_EQ(SAMPLER_STATE::MIN_MODE_FILTER_NEAREST, samplerState->getMinModeFilter());
|
|
EXPECT_EQ(SAMPLER_STATE::MAG_MODE_FILTER_NEAREST, samplerState->getMagModeFilter());
|
|
EXPECT_EQ(SAMPLER_STATE::MIP_MODE_FILTER_NEAREST, samplerState->getMipModeFilter());
|
|
EXPECT_FALSE(samplerState->getUAddressMinFilterRoundingEnable());
|
|
EXPECT_FALSE(samplerState->getUAddressMagFilterRoundingEnable());
|
|
EXPECT_FALSE(samplerState->getVAddressMinFilterRoundingEnable());
|
|
EXPECT_FALSE(samplerState->getVAddressMagFilterRoundingEnable());
|
|
EXPECT_FALSE(samplerState->getRAddressMagFilterRoundingEnable());
|
|
EXPECT_FALSE(samplerState->getRAddressMinFilterRoundingEnable());
|
|
} else {
|
|
EXPECT_EQ(SAMPLER_STATE::MIN_MODE_FILTER_LINEAR, samplerState->getMinModeFilter());
|
|
EXPECT_EQ(SAMPLER_STATE::MAG_MODE_FILTER_LINEAR, samplerState->getMagModeFilter());
|
|
EXPECT_EQ(SAMPLER_STATE::MIP_MODE_FILTER_LINEAR, samplerState->getMipModeFilter());
|
|
EXPECT_TRUE(samplerState->getUAddressMinFilterRoundingEnable());
|
|
EXPECT_TRUE(samplerState->getUAddressMagFilterRoundingEnable());
|
|
EXPECT_TRUE(samplerState->getVAddressMinFilterRoundingEnable());
|
|
EXPECT_TRUE(samplerState->getVAddressMagFilterRoundingEnable());
|
|
EXPECT_TRUE(samplerState->getRAddressMagFilterRoundingEnable());
|
|
EXPECT_TRUE(samplerState->getRAddressMinFilterRoundingEnable());
|
|
}
|
|
}
|
|
|
|
cl_filter_mode filterModeCase[] = {
|
|
CL_FILTER_NEAREST,
|
|
CL_FILTER_LINEAR};
|
|
|
|
INSTANTIATE_TEST_CASE_P(SamplerSetArg,
|
|
FilterModeTest,
|
|
::testing::ValuesIn(filterModeCase));
|