diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index 6c7c1088d7..d7fcd14131 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -102,11 +102,27 @@ bool ModuleTranslationUnit::buildFromSpirV(const char *input, uint32_t inputSize NEO::TranslationInput inputArgs = {IGC::CodeType::spirV, IGC::CodeType::oclGenBin}; if (pConstants) { + NEO::SpecConstantInfo specConstInfo; + auto retVal = compilerInterface->getSpecConstantsInfo(*device->getNEODevice(), ArrayRef(input, inputSize), specConstInfo); + if (retVal != NEO::TranslationOutput::ErrorCode::Success) { + return false; + } for (uint32_t i = 0; i < pConstants->numConstants; i++) { uint64_t specConstantValue = 0; - memcpy_s(&specConstantValue, sizeof(uint64_t), - const_cast(pConstants->pConstantValues[i]), sizeof(uint64_t)); uint32_t specConstantId = pConstants->pConstantIds[i]; + auto atributeSize = 0u; + uint32_t j; + for (j = 0; j < specConstInfo.sizesBuffer->GetSize(); j++) { + if (specConstantId == specConstInfo.idsBuffer->GetMemory()[j]) { + atributeSize = specConstInfo.sizesBuffer->GetMemory()[j]; + break; + } + } + if (j == specConstInfo.sizesBuffer->GetSize()) { + return false; + } + memcpy_s(&specConstantValue, sizeof(uint64_t), + const_cast(pConstants->pConstantValues[i]), atributeSize); specConstantsValues[specConstantId] = specConstantValue; } } diff --git a/level_zero/core/test/unit_tests/mocks/mock_module.h b/level_zero/core/test/unit_tests/mocks/mock_module.h index d4d39d285b..9c708a7e51 100644 --- a/level_zero/core/test/unit_tests/mocks/mock_module.h +++ b/level_zero/core/test/unit_tests/mocks/mock_module.h @@ -91,7 +91,7 @@ struct MockCompilerInterface : public NEO::CompilerInterface { return NEO::TranslationOutput::ErrorCode::Success; } }; - +template struct MockCompilerInterfaceWithSpecConstants : public NEO::CompilerInterface { MockCompilerInterfaceWithSpecConstants(uint32_t moduleNumSpecConstants) : moduleNumSpecConstants(moduleNumSpecConstants) { } @@ -101,29 +101,25 @@ struct MockCompilerInterfaceWithSpecConstants : public NEO::CompilerInterface { EXPECT_EQ(moduleNumSpecConstants, input.specializedValues.size()); - for (uint32_t i = 0; i < moduleSpecConstantsIds.size(); i++) { - uint32_t specConstantId = moduleSpecConstantsIds[i]; - auto it = input.specializedValues.find(specConstantId); - EXPECT_NE(it, input.specializedValues.end()); - - uint64_t specConstantValue = moduleSpecConstantsValues[i]; - EXPECT_EQ(specConstantValue, it->second); - } - return NEO::TranslationOutput::ErrorCode::Success; } NEO::TranslationOutput::ErrorCode getSpecConstantsInfo(const NEO::Device &device, ArrayRef srcSpirV, NEO::SpecConstantInfo &output) override { output.idsBuffer.reset(new NEO::MockCIFBuffer()); + output.sizesBuffer.reset(new NEO::MockCIFBuffer()); for (uint32_t i = 0; i < moduleNumSpecConstants; i++) { output.idsBuffer->PushBackRawCopy(moduleSpecConstantsIds[i]); + output.sizesBuffer->PushBackRawCopy(moduleSpecConstantsSizes[i]); } return NEO::TranslationOutput::ErrorCode::Success; } uint32_t moduleNumSpecConstants = 0u; - const std::vector moduleSpecConstantsIds{0, 1, 2, 3}; - const std::vector moduleSpecConstantsValues{10, 20, 30, 40}; + const std::vector moduleSpecConstantsIds{2, 0, 1, 3, 5, 4}; + const std::vector moduleSpecConstantsValuesT1{10, 20, 30}; + const std::vector moduleSpecConstantsValuesT2{static_cast(std::numeric_limits::max()) + 60u, static_cast(std::numeric_limits::max()) + 50u, static_cast(std::numeric_limits::max()) + 40u}; + const std::vector moduleSpecConstantsSizes{sizeof(T2), sizeof(T1), sizeof(T2), sizeof(T1), sizeof(T2), sizeof(T1)}; + static_assert(sizeof(T1) < sizeof(T2)); }; } // namespace ult diff --git a/level_zero/core/test/unit_tests/sources/module/test_module.cpp b/level_zero/core/test/unit_tests/sources/module/test_module.cpp index 75887c15ad..94eb152819 100644 --- a/level_zero/core/test/unit_tests/sources/module/test_module.cpp +++ b/level_zero/core/test/unit_tests/sources/module/test_module.cpp @@ -229,13 +229,13 @@ HWTEST_F(ModuleTest, GivenIncorrectNameWhenCreatingKernelThenResultErrorInvalidA EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, res); } - +template struct ModuleSpecConstantsTests : public DeviceFixture, public ::testing::Test { void SetUp() override { DeviceFixture::SetUp(); - mockCompiler = new MockCompilerInterfaceWithSpecConstants(moduleNumSpecConstants); + mockCompiler = new MockCompilerInterfaceWithSpecConstants(moduleNumSpecConstants); auto rootDeviceEnvironment = neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0].get(); rootDeviceEnvironment->compilerInterface.reset(mockCompiler); @@ -246,17 +246,77 @@ struct ModuleSpecConstantsTests : public DeviceFixture, DeviceFixture::TearDown(); } - const uint32_t moduleNumSpecConstants = 4; + void runTest() { + std::string testFile; + retrieveBinaryKernelFilenameNoRevision(testFile, binaryFilename + "_", ".spv"); + + size_t size = 0; + auto src = loadDataFromFile(testFile.c_str(), size); + + ASSERT_NE(0u, size); + ASSERT_NE(nullptr, src); + + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = reinterpret_cast(src.get()); + moduleDesc.inputSize = size; + + specConstants.numConstants = mockCompiler->moduleNumSpecConstants; + for (uint32_t i = mockCompiler->moduleNumSpecConstants / 2; i > 0; i--) { + specConstantsPointerValues.push_back(&mockCompiler->moduleSpecConstantsValuesT1[i - 1]); + specConstantsPointerValues.push_back(&mockCompiler->moduleSpecConstantsValuesT2[i - 1]); + } + for (uint32_t i = mockCompiler->moduleNumSpecConstants; i > 0; i--) { + specConstantsPointerIds.push_back(mockCompiler->moduleSpecConstantsIds[i - 1]); + } + specConstants.pConstantIds = specConstantsPointerIds.data(); + specConstants.pConstantValues = specConstantsPointerValues.data(); + moduleDesc.pConstants = &specConstants; + + auto module = new Module(device, nullptr, ModuleType::User); + module->translationUnit.reset(mockTranslationUnit); + + bool success = module->initialize(&moduleDesc, neoDevice); + for (uint32_t i = 0; i < mockCompiler->moduleNumSpecConstants / 2; i++) { + EXPECT_EQ(static_cast(module->translationUnit->specConstantsValues[mockCompiler->moduleSpecConstantsIds[2 * i]]), static_cast(mockCompiler->moduleSpecConstantsValuesT2[i])); + EXPECT_EQ(static_cast(module->translationUnit->specConstantsValues[mockCompiler->moduleSpecConstantsIds[2 * i + 1]]), static_cast(mockCompiler->moduleSpecConstantsValuesT1[i])); + } + EXPECT_TRUE(success); + module->destroy(); + } + + const uint32_t moduleNumSpecConstants = 3 * 2; ze_module_constants_t specConstants; std::vector specConstantsPointerValues; + std::vector specConstantsPointerIds; const std::string binaryFilename = "test_kernel"; const std::string kernelName = "test"; - MockCompilerInterfaceWithSpecConstants *mockCompiler; + MockCompilerInterfaceWithSpecConstants *mockCompiler; MockModuleTranslationUnit *mockTranslationUnit; }; -HWTEST_F(ModuleSpecConstantsTests, givenSpecializationConstantsSetInDescriptorThenModuleCorrectlyPassesThemToTheCompiler) { +using ModuleSpecConstantsLongTests = ModuleSpecConstantsTests; +TEST_F(ModuleSpecConstantsLongTests, givenSpecializationConstantsSetWithLongSizeInDescriptorThenModuleCorrectlyPassesThemToTheCompiler) { + runTest(); +} +using ModuleSpecConstantsCharTests = ModuleSpecConstantsTests; +TEST_F(ModuleSpecConstantsCharTests, givenSpecializationConstantsSetWithCharSizeInDescriptorThenModuleCorrectlyPassesThemToTheCompiler) { + runTest(); +} + +TEST_F(ModuleSpecConstantsLongTests, givenSpecializationConstantsSetWhenCompilerReturnsErrorThenModuleInitFails) { + class FailingMockCompilerInterfaceWithSpecConstants : public MockCompilerInterfaceWithSpecConstants { + public: + FailingMockCompilerInterfaceWithSpecConstants(uint32_t moduleNumSpecConstants) : MockCompilerInterfaceWithSpecConstants(moduleNumSpecConstants) {} + NEO::TranslationOutput::ErrorCode getSpecConstantsInfo(const NEO::Device &device, + ArrayRef srcSpirV, NEO::SpecConstantInfo &output) override { + return NEO::TranslationOutput::ErrorCode::CompilerNotAvailable; + } + }; + mockCompiler = new FailingMockCompilerInterfaceWithSpecConstants(moduleNumSpecConstants); + auto rootDeviceEnvironment = neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0].get(); + rootDeviceEnvironment->compilerInterface.reset(mockCompiler); std::string testFile; retrieveBinaryKernelFilenameNoRevision(testFile, binaryFilename + "_", ".spv"); @@ -272,8 +332,9 @@ HWTEST_F(ModuleSpecConstantsTests, givenSpecializationConstantsSetInDescriptorTh moduleDesc.inputSize = size; specConstants.numConstants = mockCompiler->moduleNumSpecConstants; - for (uint32_t i = 0; i < mockCompiler->moduleNumSpecConstants; i++) { - specConstantsPointerValues.push_back(&mockCompiler->moduleSpecConstantsValues[i]); + for (uint32_t i = 0; i < mockCompiler->moduleNumSpecConstants / 2; i++) { + specConstantsPointerValues.push_back(&mockCompiler->moduleSpecConstantsValuesT2[i]); + specConstantsPointerValues.push_back(&mockCompiler->moduleSpecConstantsValuesT1[i]); } specConstants.pConstantIds = mockCompiler->moduleSpecConstantsIds.data(); @@ -284,7 +345,45 @@ HWTEST_F(ModuleSpecConstantsTests, givenSpecializationConstantsSetInDescriptorTh module->translationUnit.reset(mockTranslationUnit); bool success = module->initialize(&moduleDesc, neoDevice); - EXPECT_TRUE(success); + EXPECT_FALSE(success); + module->destroy(); +} + +TEST_F(ModuleSpecConstantsLongTests, givenSpecializationConstantsSetWhenUserPassTooMuchConstsIdsThenModuleInitFails) { + std::string testFile; + retrieveBinaryKernelFilenameNoRevision(testFile, binaryFilename + "_", ".spv"); + + size_t size = 0; + auto src = loadDataFromFile(testFile.c_str(), size); + + ASSERT_NE(0u, size); + ASSERT_NE(nullptr, src); + + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = reinterpret_cast(src.get()); + moduleDesc.inputSize = size; + + specConstants.numConstants = mockCompiler->moduleNumSpecConstants; + for (uint32_t i = mockCompiler->moduleNumSpecConstants / 2; i > 0; i--) { + specConstantsPointerValues.push_back(&mockCompiler->moduleSpecConstantsValuesT1[i - 1]); + specConstantsPointerValues.push_back(&mockCompiler->moduleSpecConstantsValuesT2[i - 1]); + } + for (uint32_t i = mockCompiler->moduleNumSpecConstants; i > 0; i--) { + specConstantsPointerIds.push_back(mockCompiler->moduleSpecConstantsIds[i - 1]); + } + specConstantsPointerIds.push_back(0x1000); + specConstants.numConstants += 1; + + specConstants.pConstantIds = specConstantsPointerIds.data(); + specConstants.pConstantValues = specConstantsPointerValues.data(); + moduleDesc.pConstants = &specConstants; + + auto module = new Module(device, nullptr, ModuleType::User); + module->translationUnit.reset(mockTranslationUnit); + + bool success = module->initialize(&moduleDesc, neoDevice); + EXPECT_FALSE(success); module->destroy(); }