/*------------------------------------------------------------------------ * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2015 The Khronos Group Inc. * Copyright (c) 2018 Advanced Micro Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Test cases for VK_KHR_shader_clock. Ensure that values are being read from the OpReadClockKHR OpCode. *//*--------------------------------------------------------------------*/ #include "vktShaderClockTests.hpp" #include "vktTestCaseUtil.hpp" #include "vktTestGroupUtil.hpp" #include "vktShaderExecutor.hpp" #include "vkQueryUtil.hpp" #include "tcuStringTemplate.hpp" #include "vktAtomicOperationTests.hpp" #include "vktShaderExecutor.hpp" #include "vkRefUtil.hpp" #include "vkMemUtil.hpp" #include "vkQueryUtil.hpp" #include "vktTestGroupUtil.hpp" #include "tcuTestLog.hpp" #include "tcuStringTemplate.hpp" #include "tcuResultCollector.hpp" #include "deStringUtil.hpp" #include "deSharedPtr.hpp" #include "deRandom.hpp" #include "deArrayUtil.hpp" #include #include namespace vkt { namespace shaderexecutor { namespace { enum { NUM_ELEMENTS = 32 }; enum clockType { SUBGROUP = 0, DEVICE }; enum bitType { BIT_32 = 0, BIT_64 }; struct testType { clockType testClockType; bitType testBitType; const char* testName; }; static inline void* getPtrOfVar(deUint64& var) { return &var; } using namespace vk; class ShaderClockTestInstance : public TestInstance { public: ShaderClockTestInstance(Context& context, const ShaderSpec& shaderSpec, glu::ShaderType shaderType) : TestInstance(context) , m_executor(createExecutor(m_context, shaderType, shaderSpec)) { } virtual tcu::TestStatus iterate(void) { const deUint64 initValue = 0xcdcdcdcd; std::vector outputs (NUM_ELEMENTS, initValue); std::vector outputPtr (NUM_ELEMENTS, nullptr); std::transform(std::begin(outputs), std::end(outputs), std::begin(outputPtr), getPtrOfVar); m_executor->execute(NUM_ELEMENTS, nullptr, outputPtr.data()); if (validateOutput(outputs)) return tcu::TestStatus::pass("Pass"); else return tcu::TestStatus::fail("Result comparison failed"); } private: bool validateOutput(std::vector& outputs) { // The shader will write a 1 in the output if the clock did not increase return (outputs.size() == deUint64(std::count(std::begin(outputs), std::end(outputs), 0))); } de::UniquePtr m_executor; }; class ShaderClockCase : public TestCase { public: ShaderClockCase(tcu::TestContext& testCtx, testType operation, glu::ShaderType shaderType) : TestCase(testCtx, operation.testName, operation.testName) , m_operation(operation) , m_shaderSpec() , m_shaderType(shaderType) { initShaderSpec(); } TestInstance* createInstance (Context& ctx) const override { return new ShaderClockTestInstance(ctx, m_shaderSpec, m_shaderType); } void initPrograms (vk::SourceCollections& programCollection) const override { generateSources(m_shaderType, m_shaderSpec, programCollection); } void checkSupport (Context& context) const override { context.requireDeviceFunctionality("VK_KHR_shader_clock"); if (m_operation.testBitType == BIT_64) context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_INT64); const auto& shaderClockFeatures = context.getShaderClockFeatures(); const auto realTimeTest = (m_operation.testClockType == DEVICE); if (realTimeTest && !shaderClockFeatures.shaderDeviceClock) TCU_THROW(NotSupportedError, "Shader device clock is not supported"); if (!realTimeTest && !shaderClockFeatures.shaderSubgroupClock) TCU_THROW(NotSupportedError, "Shader subgroup clock is not supported"); } private: void initShaderSpec() { std::stringstream extensions; std::stringstream source; if (m_operation.testBitType == BIT_64) { extensions << "#extension GL_ARB_gpu_shader_int64 : require \n"; source << "uint64_t time1 = " << m_operation.testName << "(); \n"; source << "uint64_t time2 = " << m_operation.testName << "(); \n"; source << "out0 = uvec2(0, 0); \n"; source << "if (time1 > time2) { \n"; source << " out0.x = 1; \n"; source << "} \n"; } else { source << "uvec2 time1 = " << m_operation.testName << "(); \n"; source << "uvec2 time2 = " << m_operation.testName << "(); \n"; source << "out0 = uvec2(0, 0); \n"; source << "if (time1.y > time2.y || (time1.y == time2.y && time1.x > time2.x)){ \n"; source << " out0.x = 1; \n"; source << "} \n"; } if (m_operation.testClockType == DEVICE) { extensions << "#extension GL_EXT_shader_realtime_clock : require \n"; } else { extensions << "#extension GL_ARB_shader_clock : enable \n"; } std::map specializations = { { "EXTENSIONS", extensions.str() }, { "SOURCE", source.str() } }; m_shaderSpec.globalDeclarations = tcu::StringTemplate("${EXTENSIONS}").specialize(specializations); m_shaderSpec.source = tcu::StringTemplate("${SOURCE} ").specialize(specializations); m_shaderSpec.outputs.push_back(Symbol("out0", glu::VarType(glu::TYPE_UINT_VEC2, glu::PRECISION_HIGHP))); } private: ShaderClockCase (const ShaderClockCase&); ShaderClockCase& operator= (const ShaderClockCase&); testType m_operation; ShaderSpec m_shaderSpec; glu::ShaderType m_shaderType; }; void addShaderClockTests (tcu::TestCaseGroup* testGroup) { static glu::ShaderType stages[] = { glu::SHADERTYPE_VERTEX, glu::SHADERTYPE_FRAGMENT, glu::SHADERTYPE_COMPUTE }; static testType operations[] = { {SUBGROUP, BIT_64, "clockARB"}, {SUBGROUP, BIT_32, "clock2x32ARB" }, {DEVICE, BIT_64, "clockRealtimeEXT"}, {DEVICE, BIT_32, "clockRealtime2x32EXT"} }; tcu::TestContext& testCtx = testGroup->getTestContext(); for (size_t i = 0; i != DE_LENGTH_OF_ARRAY(stages); ++i) { const char* stageName = (stages[i] == glu::SHADERTYPE_VERTEX) ? ("vertex") : (stages[i] == glu::SHADERTYPE_FRAGMENT) ? ("fragment") : (stages[i] == glu::SHADERTYPE_COMPUTE) ? ("compute") : (DE_NULL); const std::string setName = std::string() + stageName; de::MovePtr stageGroupTest(new tcu::TestCaseGroup(testCtx, setName.c_str(), "Shader Clock Tests")); for (size_t j = 0; j != DE_LENGTH_OF_ARRAY(operations); ++j) { stageGroupTest->addChild(new ShaderClockCase(testCtx, operations[j], stages[i])); } testGroup->addChild(stageGroupTest.release()); } } } // anonymous tcu::TestCaseGroup* createShaderClockTests(tcu::TestContext& testCtx) { return createTestGroup(testCtx, "shader_clock", "Shader Clock Tests", addShaderClockTests); } } // shaderexecutor } // vkt