From: Lei Zhang Date: Fri, 20 Nov 2015 15:44:30 +0000 (-0500) Subject: Add more SPIR-V assembly tests based on compute shader. X-Git-Tag: upstream/0.1.0~812^2~445^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0e95062c203b163b84428f1e3781c0243c51bc29;p=platform%2Fupstream%2FVK-GL-CTS.git Add more SPIR-V assembly tests based on compute shader. - Multiple shaders in the same module. - Memory access bits. - OpCopyMemory. - OpCopyObject. - Decoration: NoContraction. - OpSpecConstantOp. --- diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp index 23872a5..d848695 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp @@ -91,11 +91,11 @@ void setMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocation* flushMappedMemoryRange(vkdi, device, destAlloc->getMemory(), destAlloc->getOffset(), numBytes); } -void clearMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocation* destAlloc, size_t numBytes) +void fillMemoryWithValue (const DeviceInterface& vkdi, const VkDevice& device, Allocation* destAlloc, size_t numBytes, deUint8 value) { void* const hostPtr = destAlloc->getHostPtr(); - deMemset((deUint8*)hostPtr, 0, numBytes); + deMemset((deUint8*)hostPtr, value, numBytes); flushMappedMemoryRange(vkdi, device, destAlloc->getMemory(), destAlloc->getOffset(), numBytes); } @@ -177,17 +177,38 @@ Move createDescriptorSet (const DeviceInterface& vkdi, const Vk /*--------------------------------------------------------------------*//*! * \brief Create a compute pipeline based on the given shader *//*--------------------------------------------------------------------*/ -Move createComputePipeline (const DeviceInterface& vkdi, const VkDevice& device, VkPipelineLayout pipelineLayout, VkShaderModule shader) +Move createComputePipeline (const DeviceInterface& vkdi, const VkDevice& device, VkPipelineLayout pipelineLayout, VkShaderModule shader, const char* entryPoint, const vector& specConstants) { + const deUint32 numSpecConstants = (deUint32)specConstants.size(); + vector entries; + VkSpecializationInfo specInfo; + + if (numSpecConstants != 0) + { + entries.reserve(numSpecConstants); + + for (deUint32 ndx = 0; ndx < numSpecConstants; ++ndx) + { + entries[ndx].constantID = ndx; + entries[ndx].offset = ndx * (deUint32)sizeof(deUint32); + entries[ndx].size = sizeof(deUint32); + } + + specInfo.mapEntryCount = numSpecConstants; + specInfo.pMapEntries = &entries[0]; + specInfo.dataSize = numSpecConstants * sizeof(deUint32); + specInfo.pData = specConstants.data(); + } + const VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType DE_NULL, // pNext - (VkPipelineShaderStageCreateFlags)0, + (VkPipelineShaderStageCreateFlags)0, // flags VK_SHADER_STAGE_COMPUTE_BIT, // stage - shader, // shader - "main", - DE_NULL, // pSpecializationInfo + shader, // module + entryPoint, // pName + (numSpecConstants == 0) ? DE_NULL : &specInfo, // pSpecializationInfo }; const VkComputePipelineCreateInfo pipelineCreateInfo = { @@ -313,7 +334,7 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void) const size_t numBytes = output->getNumBytes(); BufferHandleUp* buffer = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, allocator, numBytes, &alloc)); - clearMemory(vkdi, device, &*alloc, numBytes); + fillMemoryWithValue(vkdi, device, &*alloc, numBytes, 0xff); descriptorInfos.push_back(vk::makeDescriptorBufferInfo(**buffer, 0u, numBytes)); outputBuffers.push_back(BufferHandleSp(buffer)); outputAllocs.push_back(de::SharedPtr(alloc.release())); @@ -331,7 +352,7 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void) const ProgramBinary& binary = m_context.getBinaryCollection().get("compute"); Unique module (createShaderModule(vkdi, device, binary, (VkShaderModuleCreateFlags)0u)); - Unique computePipeline (createComputePipeline(vkdi, device, *pipelineLayout, *module)); + Unique computePipeline (createComputePipeline(vkdi, device, *pipelineLayout, *module, m_shaderSpec.entryPoint.c_str(), m_shaderSpec.specConstants)); // Create command buffer and record commands diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp index fbfa5c0..01af95d 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp @@ -78,7 +78,11 @@ private: std::vector m_elements; }; -typedef Buffer Float32Buffer; +DE_STATIC_ASSERT(sizeof(tcu::Vec4) == 4 * sizeof(float)); + +typedef Buffer Float32Buffer; +typedef Buffer Int32Buffer; +typedef Buffer Vec4Buffer; /*--------------------------------------------------------------------*//*! @@ -90,9 +94,11 @@ typedef Buffer Float32Buffer; struct ComputeShaderSpec { std::string assembly; + std::string entryPoint; std::vector inputs; std::vector outputs; tcu::IVec3 numWorkGroups; + std::vector specConstants; }; } // SpirVAssembly diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp index 56f74cf..20a28fa 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp @@ -57,6 +57,8 @@ #include "deUniquePtr.hpp" #include "tcuStringTemplate.hpp" +#include + #include "vktSpvAsmComputeShaderCase.hpp" #include "vktSpvAsmComputeShaderTestUtil.hpp" #include "vktTestCaseUtil.hpp" @@ -85,6 +87,7 @@ using tcu::TestStatus; using tcu::Vec4; using de::UniquePtr; using tcu::StringTemplate; +using tcu::Vec4; typedef Unique ModuleHandleUp; typedef de::SharedPtr ModuleHandleSp; @@ -92,7 +95,6 @@ typedef de::SharedPtr ModuleHandleSp; template T randomScalar (de::Random& rnd, T minValue, T maxValue); template<> inline float randomScalar (de::Random& rnd, float minValue, float maxValue) { return rnd.getFloat(minValue, maxValue); } template<> inline deInt32 randomScalar (de::Random& rnd, deInt32 minValue, deInt32 maxValue) { return rnd.getInt(minValue, maxValue); } -template<> inline deUint32 randomScalar (de::Random& rnd, deUint32 minValue, deUint32 maxValue) { return minValue + rnd.getUint32() % (maxValue - minValue + 1); } template static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0) @@ -102,6 +104,14 @@ static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* ds typedPtr[offset + ndx] = randomScalar(rnd, minValue, maxValue); } +struct CaseParameter +{ + const char* name; + string param; + + CaseParameter (const char* case_, const string& param_) : name(case_), param(param_) {} +}; + // Assembly code used for testing OpNop, OpConstant{Null|Composite}, Op[No]Line, OpSource[Continued], OpSourceExtension, OpUndef is based on GLSL source code: // // #version 430 @@ -207,6 +217,7 @@ tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNop appearing at different places", spec)); @@ -271,6 +282,7 @@ tcu::TestCaseGroup* createOpLineGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpLine appearing at different places", spec)); @@ -337,12 +349,399 @@ tcu::TestCaseGroup* createOpNoLineGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNoLine appearing at different places", spec)); return group.release(); } +tcu::TestCaseGroup* createNoContractionGroup (tcu::TestContext& testCtx) +{ + de::MovePtr group (new tcu::TestCaseGroup(testCtx, "nocontraction", "Test the NoContraction decoration")); + vector cases; + de::Random rnd (deStringHash(group->getName())); + const int numElements = 100; + vector inputFloats1 (numElements, 0); + vector inputFloats2 (numElements, 0); + vector outputFloats (numElements, 0); + const StringTemplate shaderTemplate ( + string(s_ShaderPreamble) + + + "OpName %main \"main\"\n" + "OpName %id \"gl_GlobalInvocationID\"\n" + + "OpDecorate %id BuiltIn GlobalInvocationId\n" + + "${DECORATION}\n" + + "OpDecorate %inbuf1 BufferBlock\n" + "OpDecorate %indata1 DescriptorSet 0\n" + "OpDecorate %indata1 Binding 0\n" + "OpDecorate %inbuf2 BufferBlock\n" + "OpDecorate %indata2 DescriptorSet 0\n" + "OpDecorate %indata2 Binding 1\n" + "OpDecorate %outbuf BufferBlock\n" + "OpDecorate %outdata DescriptorSet 0\n" + "OpDecorate %outdata Binding 2\n" + "OpDecorate %f32arr ArrayStride 4\n" + "OpMemberDecorate %inbuf1 0 Offset 0\n" + "OpMemberDecorate %inbuf2 0 Offset 0\n" + "OpMemberDecorate %outbuf 0 Offset 0\n" + + + string(s_CommonTypes) + + + "%inbuf1 = OpTypeStruct %f32arr\n" + "%inbufptr1 = OpTypePointer Uniform %inbuf1\n" + "%indata1 = OpVariable %inbufptr1 Uniform\n" + "%inbuf2 = OpTypeStruct %f32arr\n" + "%inbufptr2 = OpTypePointer Uniform %inbuf2\n" + "%indata2 = OpVariable %inbufptr2 Uniform\n" + "%outbuf = OpTypeStruct %f32arr\n" + "%outbufptr = OpTypePointer Uniform %outbuf\n" + "%outdata = OpVariable %outbufptr Uniform\n" + + "%id = OpVariable %uvec3ptr Input\n" + "%zero = OpConstant %i32 0\n" + "%c_f_m1 = OpConstant %f32 -1.\n" + + "%main = OpFunction %void None %voidf\n" + "%label = OpLabel\n" + "%idval = OpLoad %uvec3 %id\n" + "%x = OpCompositeExtract %u32 %idval 0\n" + "%inloc1 = OpAccessChain %f32ptr %indata1 %zero %x\n" + "%inval1 = OpLoad %f32 %inloc1\n" + "%inloc2 = OpAccessChain %f32ptr %indata2 %zero %x\n" + "%inval2 = OpLoad %f32 %inloc2\n" + "%mul = OpFMul %f32 %inval1 %inval2\n" + "%add = OpFAdd %f32 %mul %c_f_m1\n" + "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" + " OpStore %outloc %add\n" + " OpReturn\n" + " OpFunctionEnd\n"); + + cases.push_back(CaseParameter("multiplication", "OpDecorate %mul NoContraction")); + cases.push_back(CaseParameter("addition", "OpDecorate %add NoContraction")); + cases.push_back(CaseParameter("both", "OpDecorate %mul NoContraction\nOpDecorate %add NoContraction")); + + for (size_t ndx = 0; ndx < numElements; ++ndx) + { + inputFloats1[ndx] = 1.f + std::ldexp(1.f, -23); // 1 + 2^-23. + inputFloats2[ndx] = 1.f - std::ldexp(1.f, -23); // 1 - 2^-23. + // Result for (1 + 2^-23) * (1 - 2^-23) - 1. With NoContraction, the multiplication will be + // conducted separately and the result is rounded to 1. So the final result will be 0.f. + // If the operation is combined into a precise fused multiply-add, then the result would be + // 2^-46 (0xa8800000). + outputFloats[ndx] = 0.f; + } + + for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) + { + map specializations; + ComputeShaderSpec spec; + + specializations["DECORATION"] = cases[caseNdx].param; + spec.assembly = shaderTemplate.specialize(specializations); + spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1))); + spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2))); + spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); + spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; + + group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); + } + return group.release(); +} + +// Copy contents in the input buffer to the output buffer. +tcu::TestCaseGroup* createOpCopyMemoryGroup (tcu::TestContext& testCtx) +{ + de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opcopymemory", "Test the OpCopyMemory instruction")); + de::Random rnd (deStringHash(group->getName())); + const int numElements = 100; + + // The following case adds vec4(0., 0.5, 1.5, 2.5) to each of the elements in the input buffer and writes output to the output buffer. + ComputeShaderSpec spec1; + vector inputFloats1 (numElements); + vector outputFloats1 (numElements); + + fillRandomScalars(rnd, -200.f, 200.f, &inputFloats1[0], numElements * 4); + + for (size_t ndx = 0; ndx < numElements; ++ndx) + outputFloats1[ndx] = inputFloats1[ndx] + Vec4(0.f, 0.5f, 1.5f, 2.5f); + + spec1.assembly = + string(s_ShaderPreamble) + + + "OpName %main \"main\"\n" + "OpName %id \"gl_GlobalInvocationID\"\n" + + "OpDecorate %id BuiltIn GlobalInvocationId\n" + + + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + "%vec4 = OpTypeVector %f32 4\n" + "%vec4ptr_u = OpTypePointer Uniform %vec4\n" + "%vec4ptr_f = OpTypePointer Function %vec4\n" + "%vec4arr = OpTypeRuntimeArray %vec4\n" + "%inbuf = OpTypeStruct %vec4arr\n" + "%inbufptr = OpTypePointer Uniform %inbuf\n" + "%indata = OpVariable %inbufptr Uniform\n" + "%outbuf = OpTypeStruct %vec4arr\n" + "%outbufptr = OpTypePointer Uniform %outbuf\n" + "%outdata = OpVariable %outbufptr Uniform\n" + + "%id = OpVariable %uvec3ptr Input\n" + "%zero = OpConstant %i32 0\n" + "%c_f_0 = OpConstant %f32 0.\n" + "%c_f_0_5 = OpConstant %f32 0.5\n" + "%c_f_1_5 = OpConstant %f32 1.5\n" + "%c_f_2_5 = OpConstant %f32 2.5\n" + "%c_vec4 = OpConstantComposite %vec4 %c_f_0 %c_f_0_5 %c_f_1_5 %c_f_2_5\n" + + "%main = OpFunction %void None %voidf\n" + "%label = OpLabel\n" + "%v_vec4 = OpVariable %vec4ptr_f Function\n" + "%idval = OpLoad %uvec3 %id\n" + "%x = OpCompositeExtract %u32 %idval 0\n" + "%inloc = OpAccessChain %vec4ptr_u %indata %zero %x\n" + "%outloc = OpAccessChain %vec4ptr_u %outdata %zero %x\n" + " OpCopyMemory %v_vec4 %inloc\n" + "%v_vec4_val = OpLoad %vec4 %v_vec4\n" + "%add = OpFAdd %vec4 %v_vec4_val %c_vec4\n" + " OpStore %outloc %add\n" + " OpReturn\n" + " OpFunctionEnd\n"; + + spec1.inputs.push_back(BufferSp(new Vec4Buffer(inputFloats1))); + spec1.outputs.push_back(BufferSp(new Vec4Buffer(outputFloats1))); + spec1.numWorkGroups = IVec3(numElements, 1, 1); + spec1.entryPoint = "main"; + + group->addChild(new SpvAsmComputeShaderCase(testCtx, "vector", "OpCopyMemory elements of vector type", spec1)); + + // The following case copies a float[100] variable from the input buffer to the output buffer. + ComputeShaderSpec spec2; + vector inputFloats2 (numElements); + vector outputFloats2 (numElements); + + fillRandomScalars(rnd, -200.f, 200.f, &inputFloats2[0], numElements); + + for (size_t ndx = 0; ndx < numElements; ++ndx) + outputFloats2[ndx] = inputFloats2[ndx]; + + spec2.assembly = + string(s_ShaderPreamble) + + + "OpName %main \"main\"\n" + "OpName %id \"gl_GlobalInvocationID\"\n" + + "OpDecorate %id BuiltIn GlobalInvocationId\n" + + + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + "%hundred = OpConstant %u32 100\n" + "%f32arr100 = OpTypeArray %f32 %hundred\n" + "%f32arr100ptr_f = OpTypePointer Function %f32arr100\n" + "%f32arr100ptr_u = OpTypePointer Uniform %f32arr100\n" + "%inbuf = OpTypeStruct %f32arr100\n" + "%inbufptr = OpTypePointer Uniform %inbuf\n" + "%indata = OpVariable %inbufptr Uniform\n" + "%outbuf = OpTypeStruct %f32arr100\n" + "%outbufptr = OpTypePointer Uniform %outbuf\n" + "%outdata = OpVariable %outbufptr Uniform\n" + + "%id = OpVariable %uvec3ptr Input\n" + "%zero = OpConstant %i32 0\n" + + "%main = OpFunction %void None %voidf\n" + "%label = OpLabel\n" + "%var = OpVariable %f32arr100ptr_f Function\n" + "%inarr = OpAccessChain %f32arr100ptr_u %indata %zero\n" + "%outarr = OpAccessChain %f32arr100ptr_u %outdata %zero\n" + " OpCopyMemory %var %inarr\n" + " OpCopyMemory %outarr %var\n" + " OpReturn\n" + " OpFunctionEnd\n"; + + spec2.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2))); + spec2.outputs.push_back(BufferSp(new Float32Buffer(outputFloats2))); + spec2.numWorkGroups = IVec3(1, 1, 1); + spec2.entryPoint = "main"; + + group->addChild(new SpvAsmComputeShaderCase(testCtx, "array", "OpCopyMemory elements of array type", spec2)); + + // The following case copies a struct{vec4, vec4, vec4, vec4} variable from the input buffer to the output buffer. + ComputeShaderSpec spec3; + vector inputFloats3 (16); + vector outputFloats3 (16); + + fillRandomScalars(rnd, -200.f, 200.f, &inputFloats3[0], 16); + + for (size_t ndx = 0; ndx < 16; ++ndx) + outputFloats3[ndx] = -inputFloats3[ndx]; + + spec3.assembly = + string(s_ShaderPreamble) + + + "OpName %main \"main\"\n" + "OpName %id \"gl_GlobalInvocationID\"\n" + + "OpDecorate %id BuiltIn GlobalInvocationId\n" + + + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + "%vec4 = OpTypeVector %f32 4\n" + "%inbuf = OpTypeStruct %vec4 %vec4 %vec4 %vec4\n" + "%inbufptr = OpTypePointer Uniform %inbuf\n" + "%indata = OpVariable %inbufptr Uniform\n" + "%outbuf = OpTypeStruct %vec4 %vec4 %vec4 %vec4\n" + "%outbufptr = OpTypePointer Uniform %outbuf\n" + "%outdata = OpVariable %outbufptr Uniform\n" + "%vec4stptr = OpTypePointer Function %inbuf\n" + + "%id = OpVariable %uvec3ptr Input\n" + "%zero = OpConstant %i32 0\n" + + "%main = OpFunction %void None %voidf\n" + "%label = OpLabel\n" + "%var = OpVariable %vec4stptr Function\n" + " OpCopyMemory %var %indata\n" + " OpCopyMemory %outdata %var\n" + " OpReturn\n" + " OpFunctionEnd\n"; + + spec3.inputs.push_back(BufferSp(new Float32Buffer(inputFloats3))); + spec3.outputs.push_back(BufferSp(new Float32Buffer(outputFloats3))); + spec3.numWorkGroups = IVec3(1, 1, 1); + spec3.entryPoint = "main"; + + group->addChild(new SpvAsmComputeShaderCase(testCtx, "struct", "OpCopyMemory elements of struct type", spec3)); + + // The following case negates multiple float variables from the input buffer and stores the results to the output buffer. + ComputeShaderSpec spec4; + vector inputFloats4 (numElements); + vector outputFloats4 (numElements); + + fillRandomScalars(rnd, -200.f, 200.f, &inputFloats4[0], numElements); + + for (size_t ndx = 0; ndx < numElements; ++ndx) + outputFloats4[ndx] = -inputFloats4[ndx]; + + spec4.assembly = + string(s_ShaderPreamble) + + + "OpName %main \"main\"\n" + "OpName %id \"gl_GlobalInvocationID\"\n" + + "OpDecorate %id BuiltIn GlobalInvocationId\n" + + + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + "%f32ptr_f = OpTypePointer Function %f32\n" + "%id = OpVariable %uvec3ptr Input\n" + "%zero = OpConstant %i32 0\n" + + "%main = OpFunction %void None %voidf\n" + "%label = OpLabel\n" + "%var = OpVariable %f32ptr_f Function\n" + "%idval = OpLoad %uvec3 %id\n" + "%x = OpCompositeExtract %u32 %idval 0\n" + "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" + "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" + " OpCopyMemory %var %inloc\n" + "%val = OpLoad %f32 %var\n" + "%neg = OpFNegate %f32 %val\n" + " OpStore %outloc %neg\n" + " OpReturn\n" + " OpFunctionEnd\n"; + + spec4.inputs.push_back(BufferSp(new Float32Buffer(inputFloats4))); + spec4.outputs.push_back(BufferSp(new Float32Buffer(outputFloats4))); + spec4.numWorkGroups = IVec3(numElements, 1, 1); + spec4.entryPoint = "main"; + + group->addChild(new SpvAsmComputeShaderCase(testCtx, "float", "OpCopyMemory elements of float type", spec4)); + + return group.release(); +} + +tcu::TestCaseGroup* createOpCopyObjectGroup (tcu::TestContext& testCtx) +{ + de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opcopyobject", "Test the OpCopyObject instruction")); + ComputeShaderSpec spec; + de::Random rnd (deStringHash(group->getName())); + const int numElements = 100; + vector inputFloats (numElements, 0); + vector outputFloats (numElements, 0); + + fillRandomScalars(rnd, -200.f, 200.f, &inputFloats[0], numElements); + + for (size_t ndx = 0; ndx < numElements; ++ndx) + outputFloats[ndx] = inputFloats[ndx] + 7.5f; + + spec.assembly = + string(s_ShaderPreamble) + + + "OpName %main \"main\"\n" + "OpName %id \"gl_GlobalInvocationID\"\n" + + "OpDecorate %id BuiltIn GlobalInvocationId\n" + + + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + "%fvec3 = OpTypeVector %f32 3\n" + "%fmat = OpTypeMatrix %fvec3 3\n" + "%three = OpConstant %u32 3\n" + "%farr = OpTypeArray %f32 %three\n" + "%fst = OpTypeStruct %f32 %f32\n" + + + string(s_InputOutputBuffer) + + + "%id = OpVariable %uvec3ptr Input\n" + "%zero = OpConstant %i32 0\n" + "%c_f = OpConstant %f32 1.5\n" + "%c_fvec3 = OpConstantComposite %fvec3 %c_f %c_f %c_f\n" + "%c_fmat = OpConstantComposite %fmat %c_fvec3 %c_fvec3 %c_fvec3\n" + "%c_farr = OpConstantComposite %farr %c_f %c_f %c_f\n" + "%c_fst = OpConstantComposite %fst %c_f %c_f\n" + + "%main = OpFunction %void None %voidf\n" + "%label = OpLabel\n" + "%c_f_copy = OpCopyObject %f32 %c_f\n" + "%c_fvec3_copy = OpCopyObject %fvec3 %c_fvec3\n" + "%c_fmat_copy = OpCopyObject %fmat %c_fmat\n" + "%c_farr_copy = OpCopyObject %farr %c_farr\n" + "%c_fst_copy = OpCopyObject %fst %c_fst\n" + "%fvec3_elem = OpCompositeExtract %f32 %c_fvec3_copy 0\n" + "%fmat_elem = OpCompositeExtract %f32 %c_fmat_copy 1 2\n" + "%farr_elem = OpCompositeExtract %f32 %c_fmat_copy 2\n" + "%fst_elem = OpCompositeExtract %f32 %c_fmat_copy 1\n" + // Add up. 1.5 * 5 = 7.5. + "%add1 = OpFAdd %f32 %c_f_copy %fvec3_elem\n" + "%add2 = OpFAdd %f32 %add1 %fmat_elem\n" + "%add3 = OpFAdd %f32 %add2 %farr_elem\n" + "%add4 = OpFAdd %f32 %add3 %fst_elem\n" + + "%idval = OpLoad %uvec3 %id\n" + "%x = OpCompositeExtract %u32 %idval 0\n" + "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" + "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" + "%inval = OpLoad %f32 %inloc\n" + "%add = OpFAdd %f32 %add4 %inval\n" + " OpStore %outloc %add\n" + " OpReturn\n" + " OpFunctionEnd\n"; + spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); + spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); + spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; + + group->addChild(new SpvAsmComputeShaderCase(testCtx, "spotcheck", "OpCopyObject on different types", spec)); + + return group.release(); +} + // Assembly code used for testing OpUnreachable is based on GLSL source code: // // #version 430 @@ -488,6 +887,7 @@ tcu::TestCaseGroup* createOpUnreachableGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpUnreachable appearing at different places", spec)); @@ -649,13 +1049,238 @@ tcu::TestCaseGroup* createDecorationGroupGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats4))); spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "decoration group cases", spec)); return group.release(); } -tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx) +struct SpecConstantTwoIntCase +{ + const char* caseName; + const char* scDefinition0; + const char* scDefinition1; + const char* scResultType; + const char* scOperation; + deInt32 scActualValue0; + deInt32 scActualValue1; + const char* resultOperation; + vector expectedOutput; + + SpecConstantTwoIntCase (const char* name, + const char* definition0, + const char* definition1, + const char* resultType, + const char* operation, + deInt32 value0, + deInt32 value1, + const char* resultOp, + const vector& output) + : caseName (name) + , scDefinition0 (definition0) + , scDefinition1 (definition1) + , scResultType (resultType) + , scOperation (operation) + , scActualValue0 (value0) + , scActualValue1 (value1) + , resultOperation (resultOp) + , expectedOutput (output) {} +}; + +tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx) +{ + de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opspecconstantop", "Test the OpSpecConstantOp instruction")); + vector cases; + de::Random rnd (deStringHash(group->getName())); + const int numElements = 100; + vector inputInts (numElements, 0); + vector outputInts1 (numElements, 0); + vector outputInts2 (numElements, 0); + vector outputInts3 (numElements, 0); + vector outputInts4 (numElements, 0); + vector outputInts5 (numElements, 0); + const StringTemplate shaderTemplate ( + string(s_ShaderPreamble) + + + "OpName %main \"main\"\n" + "OpName %id \"gl_GlobalInvocationID\"\n" + + "OpDecorate %id BuiltIn GlobalInvocationId\n" + "OpDecorate %sc_0 SpecId 0\n" + "OpDecorate %sc_1 SpecId 1\n" + + + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + "%i32ptr = OpTypePointer Uniform %i32\n" + "%i32arr = OpTypeRuntimeArray %i32\n" + "%boolptr = OpTypePointer Uniform %bool\n" + "%boolarr = OpTypeRuntimeArray %bool\n" + "%inbuf = OpTypeStruct %i32arr\n" + "%inbufptr = OpTypePointer Uniform %inbuf\n" + "%indata = OpVariable %inbufptr Uniform\n" + "%outbuf = OpTypeStruct %i32arr\n" + "%outbufptr = OpTypePointer Uniform %outbuf\n" + "%outdata = OpVariable %outbufptr Uniform\n" + + "%id = OpVariable %uvec3ptr Input\n" + "%zero = OpConstant %i32 0\n" + + "%sc_0 = OpSpecConstant${SC_DEF0}\n" + "%sc_1 = OpSpecConstant${SC_DEF1}\n" + "%sc_final = OpSpecConstantOp ${SC_RESULT_TYPE} ${SC_OP}\n" + + "%main = OpFunction %void None %voidf\n" + "%label = OpLabel\n" + "%idval = OpLoad %uvec3 %id\n" + "%x = OpCompositeExtract %u32 %idval 0\n" + "%inloc = OpAccessChain %i32ptr %indata %zero %x\n" + "%inval = OpLoad %i32 %inloc\n" + "%final = ${GEN_RESULT}\n" + "%outloc = OpAccessChain %i32ptr %outdata %zero %x\n" + " OpStore %outloc %final\n" + " OpReturn\n" + " OpFunctionEnd\n"); + + fillRandomScalars(rnd, -65536, 65536, &inputInts[0], numElements); + + for (size_t ndx = 0; ndx < numElements; ++ndx) + { + outputInts1[ndx] = inputInts[ndx] + 42; + outputInts2[ndx] = inputInts[ndx]; + outputInts3[ndx] = inputInts[ndx] - 11200; + outputInts4[ndx] = inputInts[ndx] + 1; + outputInts5[ndx] = inputInts[ndx] - 2; + } + + const char addScToInput[] = "OpIAdd %i32 %inval %sc_final"; + const char selectTrueUsingSc[] = "OpSelect %i32 %sc_final %inval %zero"; + const char selectFalseUsingSc[] = "OpSelect %i32 %sc_final %zero %inval"; + + cases.push_back(SpecConstantTwoIntCase("iadd", " %i32 0", " %i32 0", "%i32", "IAdd %sc_0 %sc_1", 62, -20, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("isub", " %i32 0", " %i32 0", "%i32", "ISub %sc_0 %sc_1", 100, 58, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("imul", " %i32 0", " %i32 0", "%i32", "IMul %sc_0 %sc_1", -2, -21, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("sdiv", " %i32 0", " %i32 0", "%i32", "SDiv %sc_0 %sc_1", -126, -3, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("udiv", " %i32 0", " %i32 0", "%i32", "UDiv %sc_0 %sc_1", 126, 3, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("srem", " %i32 0", " %i32 0", "%i32", "SRem %sc_0 %sc_1", 7, -3, addScToInput, outputInts4)); + cases.push_back(SpecConstantTwoIntCase("smod", " %i32 0", " %i32 0", "%i32", "SMod %sc_0 %sc_1", 7, -3, addScToInput, outputInts5)); + cases.push_back(SpecConstantTwoIntCase("umod", " %i32 0", " %i32 0", "%i32", "UMod %sc_0 %sc_1", 342, 50, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("bitwiseand", " %i32 0", " %i32 0", "%i32", "BitwiseAnd %sc_0 %sc_1", 42, 63, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("bitwiseor", " %i32 0", " %i32 0", "%i32", "BitwiseOr %sc_0 %sc_1", 34, 8, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("bitwisexor", " %i32 0", " %i32 0", "%i32", "BitwiseAnd %sc_0 %sc_1", 18, 56, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("shiftrightlogical", " %i32 0", " %i32 0", "%i32", "ShiftRightLogical %sc_0 %sc_1", 168, 2, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("shiftrightarithmetic", " %i32 0", " %i32 0", "%i32", "ShiftRightArithmetic %sc_0 %sc_1", 168, 2, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("shiftleftlogical", " %i32 0", " %i32 0", "%i32", "ShiftLeftLogical %sc_0 %sc_1", 21, 1, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("slessthan", " %i32 0", " %i32 0", "%bool", "SLessThan %sc_0 %sc_1", -20, -10, selectTrueUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("ulessthan", " %i32 0", " %i32 0", "%bool", "ULessThan %sc_0 %sc_1", 10, 20, selectTrueUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("sgreaterthan", " %i32 0", " %i32 0", "%bool", "SGreaterThan %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("ugreaterthan", " %i32 0", " %i32 0", "%bool", "UGreaterThan %sc_0 %sc_1", 10, 5, selectTrueUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("slessthanequal", " %i32 0", " %i32 0", "%bool", "SLessThanEqual %sc_0 %sc_1", -10, -10, selectTrueUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("ulessthanequal", " %i32 0", " %i32 0", "%bool", "ULessThanEqual %sc_0 %sc_1", 50, 100, selectTrueUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("sgreaterthanequal", " %i32 0", " %i32 0", "%bool", "SGreaterThanEqual %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("ugreaterthanequal", " %i32 0", " %i32 0", "%bool", "UGreaterThanEqual %sc_0 %sc_1", 10, 10, selectTrueUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("iequal", " %i32 0", " %i32 0", "%bool", "IEqual %sc_0 %sc_1", 42, 24, selectFalseUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("logicaland", "True %bool", "True %bool", "%bool", "LogicalAnd %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("logicalor", "False %bool", "False %bool", "%bool", "LogicalOr %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("logicalequal", "True %bool", "True %bool", "%bool", "LogicalEqual %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("logicalnotequal", "False %bool", "False %bool", "%bool", "LogicalNotEqual %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("snegate", " %i32 0", " %i32 0", "%i32", "SNegate %sc_0", -42, 0, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("not", " %i32 0", " %i32 0", "%i32", "Not %sc_0", -43, 0, addScToInput, outputInts1)); + cases.push_back(SpecConstantTwoIntCase("logicalnot", "False %bool", "False %bool", "%bool", "LogicalNot %sc_0", 1, 0, selectFalseUsingSc, outputInts2)); + cases.push_back(SpecConstantTwoIntCase("select", "False %bool", " %i32 0", "%i32", "Select %sc_0 %sc_1 %zero", 1, 42, addScToInput, outputInts1)); + // OpSConvert, OpFConvert: these two instructions involve ints/floats of different bitwidths. + // \todo[2015-12-1 antiagainst] OpQuantizeToF16 + + for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) + { + map specializations; + ComputeShaderSpec spec; + + specializations["SC_DEF0"] = cases[caseNdx].scDefinition0; + specializations["SC_DEF1"] = cases[caseNdx].scDefinition1; + specializations["SC_RESULT_TYPE"] = cases[caseNdx].scResultType; + specializations["SC_OP"] = cases[caseNdx].scOperation; + specializations["GEN_RESULT"] = cases[caseNdx].resultOperation; + + spec.assembly = shaderTemplate.specialize(specializations); + spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts))); + spec.outputs.push_back(BufferSp(new Int32Buffer(cases[caseNdx].expectedOutput))); + spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; + spec.specConstants.push_back(cases[caseNdx].scActualValue0); + spec.specConstants.push_back(cases[caseNdx].scActualValue1); + + group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].caseName, cases[caseNdx].caseName, spec)); + } + + ComputeShaderSpec spec; + + spec.assembly = + string(s_ShaderPreamble) + + + "OpName %main \"main\"\n" + "OpName %id \"gl_GlobalInvocationID\"\n" + + "OpDecorate %id BuiltIn GlobalInvocationId\n" + "OpDecorate %sc_0 SpecId 0\n" + "OpDecorate %sc_1 SpecId 1\n" + "OpDecorate %sc_2 SpecId 2\n" + + + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + + + "%ivec3 = OpTypeVector %i32 3\n" + "%i32ptr = OpTypePointer Uniform %i32\n" + "%i32arr = OpTypeRuntimeArray %i32\n" + "%boolptr = OpTypePointer Uniform %bool\n" + "%boolarr = OpTypeRuntimeArray %bool\n" + "%inbuf = OpTypeStruct %i32arr\n" + "%inbufptr = OpTypePointer Uniform %inbuf\n" + "%indata = OpVariable %inbufptr Uniform\n" + "%outbuf = OpTypeStruct %i32arr\n" + "%outbufptr = OpTypePointer Uniform %outbuf\n" + "%outdata = OpVariable %outbufptr Uniform\n" + + "%id = OpVariable %uvec3ptr Input\n" + "%zero = OpConstant %i32 0\n" + "%ivec3_0 = OpConstantComposite %ivec3 %zero %zero %zero\n" + + "%sc_0 = OpSpecConstant %i32 0\n" + "%sc_1 = OpSpecConstant %i32 0\n" + "%sc_2 = OpSpecConstant %i32 0\n" + "%sc_vec3_0 = OpSpecConstantOp %ivec3 CompositeInsert %sc_0 %ivec3_0 0\n" // (sc_0, 0, 0) + "%sc_vec3_1 = OpSpecConstantOp %ivec3 CompositeInsert %sc_1 %ivec3_0 1\n" // (0, sc_1, 0) + "%sc_vec3_2 = OpSpecConstantOp %ivec3 CompositeInsert %sc_2 %ivec3_0 2\n" // (0, 0, sc_2) + "%sc_vec3_01 = OpSpecConstantOp %ivec3 VectorShuffle %sc_vec3_0 %sc_vec3_1 1 0 4\n" // (0, sc_0, sc_1) + "%sc_vec3_012 = OpSpecConstantOp %ivec3 VectorShuffle %sc_vec3_01 %sc_vec3_2 5 1 2\n" // (sc_2, sc_0, sc_1) + "%sc_ext_0 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 0\n" // sc_2 + "%sc_ext_1 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 1\n" // sc_0 + "%sc_ext_2 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 2\n" // sc_1 + "%sc_sub = OpSpecConstantOp %i32 ISub %sc_ext_0 %sc_ext_1\n" // (sc_2 - sc_0) + "%sc_final = OpSpecConstantOp %i32 IMul %sc_sub %sc_ext_2\n" // (sc_2 - sc_0) * sc_1 + + "%main = OpFunction %void None %voidf\n" + "%label = OpLabel\n" + "%idval = OpLoad %uvec3 %id\n" + "%x = OpCompositeExtract %u32 %idval 0\n" + "%inloc = OpAccessChain %i32ptr %indata %zero %x\n" + "%inval = OpLoad %i32 %inloc\n" + "%final = OpIAdd %i32 %inval %sc_final\n" + "%outloc = OpAccessChain %i32ptr %outdata %zero %x\n" + " OpStore %outloc %final\n" + " OpReturn\n" + " OpFunctionEnd\n"; + spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts))); + spec.outputs.push_back(BufferSp(new Int32Buffer(outputInts3))); + spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; + spec.specConstants.push_back(123); + spec.specConstants.push_back(56); + spec.specConstants.push_back(-77); + + group->addChild(new SpvAsmComputeShaderCase(testCtx, "vector_related", "VectorShuffle, CompositeExtract, & CompositeInsert", spec)); + + return group.release(); +} tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx) { de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opphi", "Test the OpPhi instruction")); ComputeShaderSpec spec; @@ -734,6 +1359,7 @@ tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpPhi corner cases", spec)); @@ -892,19 +1518,129 @@ tcu::TestCaseGroup* createBlockOrderGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "various out-of-order blocks", spec)); return group.release(); } -struct CaseParameter +tcu::TestCaseGroup* createMultipleShaderGroup (tcu::TestContext& testCtx) { - const char* name; - string param; + de::MovePtr group (new tcu::TestCaseGroup(testCtx, "multiple_shaders", "Test multiple shaders in the same module")); + ComputeShaderSpec spec1; + ComputeShaderSpec spec2; + de::Random rnd (deStringHash(group->getName())); + const int numElements = 100; + vector inputFloats (numElements, 0); + vector outputFloats1 (numElements, 0); + vector outputFloats2 (numElements, 0); - CaseParameter (const char* case_, const string& param_) : name(case_), param(param_) {} -}; + fillRandomScalars(rnd, -500.f, 500.f, &inputFloats[0], numElements); + + for (size_t ndx = 0; ndx < numElements; ++ndx) + { + outputFloats1[ndx] = inputFloats[ndx] + inputFloats[ndx]; + outputFloats2[ndx] = -inputFloats[ndx]; + } + + const string assembly = + "OpCapability Shader\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint GLCompute %comp_main1 \"entrypoint1\" %id\n" + "OpEntryPoint GLCompute %comp_main2 \"entrypoint2\" %id\n" + // A module cannot have two OpEntryPoint instructions with the same Execution Model and the same Name string. + "OpEntryPoint Vertex %vert_main \"entrypoint2\" %vert_builtins %vertexID %instanceID\n" + "OpExecutionMode %main LocalSize 1 1 1\n"; + + "OpName %comp_main1 \"entrypoint1\"\n" + "OpName %comp_main2 \"entrypoint2\"\n" + "OpName %vert_main \"entrypoint2\"\n" + "OpName %id \"gl_GlobalInvocationID\"\n" + "OpName %vert_builtin_st \"gl_PerVertex\"\n" + "OpName %vertexID \"gl_VertexID\"\n" + "OpName %instanceID \"gl_InstanceID\"\n" + "OpMemberName %vert_builtin_st 0 \"gl_Position\"\n" + "OpMemberName %vert_builtin_st 1 \"gl_PointSize\"\n" + "OpMemberName %vert_builtin_st 2 \"gl_ClipDistance\"\n" + + "OpDecorate %id BuiltIn GlobalInvocationId\n" + "OpDecorate %vertexID BuiltIn VertexId\n" + "OpDecorate %instanceID BuiltIn InstanceId\n" + "OpDecorate %vert_builtin_st Block\n" + "OpMemberDecorate %vert_builtin_st 0 BuiltIn Position\n" + "OpMemberDecorate %vert_builtin_st 1 BuiltIn PointSize\n" + "OpMemberDecorate %vert_builtin_st 2 BuiltIn ClipDistance\n" + + + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + "%i32ptr = OpTypePointer Input %i32\n" + "%vec4 = OpTypeVector %f32 4\n" + "%vec4ptr = OpTypePointer Output %vec4\n" + "%f32arr1 = OpTypeArray %f32 %one\n" + "%vert_builtin_st = OpTypeStruct %vec4 %f32 %f32arr1\n" + "%vert_builtin_st_ptr = OpTypePointer Output %vert_builtin_st\n" + "%vert_builtins = OpVariable %vert_builtin_st_ptr Output\n" + + "%id = OpVariable %uvec3ptr Input\n" + "%vertexID = OpVariable %i32ptr Input\n" + "%instanceID = OpVariable %i32ptr Input\n" + "%zero = OpConstant %i32 0\n" + "%one = OpConstant %u32 1\n" + "%c_f32_1 = OpConstant %f32 1\n" + "%c_vec4_1 = OpConstantComposite %vec4 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n" + + // gl_Position = vec4(1.); + "%vert_main = OpFunction %void None %voidf\n" + "%vert_entry = OpLabel\n" + "%position = OpAccessChain %vec4ptr %vert_builtins %zero\n" + " OpStore %position %c_vec4_1\n" + " OpReturn\n" + " OpFunctionEnd\n" + + // Double inputs. + "%comp_main1 = OpFunction %void None %voidf\n" + "%comp1_entry = OpLabel\n" + "%idval1 = OpLoad %uvec3 %id\n" + "%x1 = OpCompositeExtract %u32 %idval1 0\n" + "%inloc1 = OpAccessChain %f32ptr %indata %zero %x1\n" + "%inval1 = OpLoad %f32 %inloc1\n" + "%add = OpFAdd %f32 %inval1 %inval1\n" + "%outloc1 = OpAccessChain %f32ptr %outdata %zero %x1\n" + " OpStore %outloc1 %add\n" + " OpReturn\n" + " OpFunctionEnd\n" + + // Negate inputs. + "%comp_main2 = OpFunction %void None %voidf\n" + "%comp2_entry = OpLabel\n" + "%idval2 = OpLoad %uvec3 %id\n" + "%x2 = OpCompositeExtract %u32 %idval2 0\n" + "%inloc2 = OpAccessChain %f32ptr %indata %zero %x2\n" + "%inval2 = OpLoad %f32 %inloc2\n" + "%neg = OpFNegate %f32 %inval2\n" + "%outloc2 = OpAccessChain %f32ptr %outdata %zero %x2\n" + " OpStore %outloc2 %neg\n" + " OpReturn\n" + " OpFunctionEnd\n"; + + spec1.assembly = assembly; + spec1.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); + spec1.outputs.push_back(BufferSp(new Float32Buffer(outputFloats1))); + spec1.numWorkGroups = IVec3(numElements, 1, 1); + spec1.entryPoint = "entrypoint1"; + + spec2.assembly = assembly; + spec2.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); + spec2.outputs.push_back(BufferSp(new Float32Buffer(outputFloats2))); + spec2.numWorkGroups = IVec3(numElements, 1, 1); + spec2.entryPoint = "entrypoint2"; + + group->addChild(new SpvAsmComputeShaderCase(testCtx, "shader1", "multiple shaders in the same module", spec1)); + group->addChild(new SpvAsmComputeShaderCase(testCtx, "shader2", "multiple shaders in the same module", spec2)); + + return group.release(); +} tcu::TestCaseGroup* createOpSourceGroup (tcu::TestContext& testCtx) { @@ -995,6 +1731,7 @@ tcu::TestCaseGroup* createOpSourceGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); } @@ -1058,6 +1795,7 @@ tcu::TestCaseGroup* createOpSourceExtensionGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); } @@ -1132,6 +1870,7 @@ tcu::TestCaseGroup* createOpConstantNullGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); } @@ -1214,6 +1953,7 @@ tcu::TestCaseGroup* createOpConstantCompositeGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); } @@ -1306,6 +2046,7 @@ tcu::TestCaseGroup* createOpConstantUsageGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, "spotcheck", "Check that values constructed via OpConstantNull & OpConstantComposite can be used", spec)); @@ -1404,6 +2145,7 @@ tcu::TestCaseGroup* createLoopControlGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); } @@ -1496,6 +2238,7 @@ tcu::TestCaseGroup* createSelectionControlGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); } @@ -1588,6 +2331,78 @@ tcu::TestCaseGroup* createFunctionControlGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; + + group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); + } + + return group.release(); +} + +tcu::TestCaseGroup* createMemoryAccessGroup (tcu::TestContext& testCtx) +{ + de::MovePtr group (new tcu::TestCaseGroup(testCtx, "memory_access", "Tests memory access cases")); + vector cases; + de::Random rnd (deStringHash(group->getName())); + const int numElements = 100; + vector inputFloats (numElements, 0); + vector outputFloats (numElements, 0); + const StringTemplate shaderTemplate ( + string(s_ShaderPreamble) + + + "OpSource GLSL 430\n" + "OpName %main \"main\"\n" + "OpName %id \"gl_GlobalInvocationID\"\n" + + "OpDecorate %id BuiltIn GlobalInvocationId\n" + + + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + + + "%f32ptr_f = OpTypePointer Function %f32\n" + + "%id = OpVariable %uvec3ptr Input\n" + "%zero = OpConstant %i32 0\n" + "%four = OpConstant %i32 4\n" + + "%main = OpFunction %void None %voidf\n" + "%label = OpLabel\n" + "%copy = OpVariable %f32ptr_f Function\n" + "%idval = OpLoad %uvec3 %id ${ACCESS}\n" + "%x = OpCompositeExtract %u32 %idval 0\n" + "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" + "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" + " OpCopyMemory %copy %inloc ${ACCESS}\n" + "%val1 = OpLoad %f32 %copy\n" + "%val2 = OpLoad %f32 %inloc\n" + "%add = OpFAdd %f32 %val1 %val2\n" + " OpStore %outloc %add ${ACCESS}\n" + " OpReturn\n" + " OpFunctionEnd\n"); + + cases.push_back(CaseParameter("null", "")); + cases.push_back(CaseParameter("none", "None")); + cases.push_back(CaseParameter("volatile", "Volatile")); + cases.push_back(CaseParameter("aligned", "Aligned 4")); + cases.push_back(CaseParameter("nontemporal", "Nontemporal")); + cases.push_back(CaseParameter("aligned_nontemporal", "Aligned|Nontemporal 4")); + cases.push_back(CaseParameter("aligned_volatile", "Volatile|Aligned 4")); + + fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements); + + for (size_t ndx = 0; ndx < numElements; ++ndx) + outputFloats[ndx] = inputFloats[ndx] + inputFloats[ndx]; + + for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) + { + map specializations; + ComputeShaderSpec spec; + + specializations["ACCESS"] = cases[caseNdx].param; + spec.assembly = shaderTemplate.specialize(specializations); + spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); + spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); + spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); } @@ -1669,6 +2484,7 @@ tcu::TestCaseGroup* createOpUndefGroup (tcu::TestContext& testCtx) spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.entryPoint = "main"; group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); } @@ -3012,6 +3828,7 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx) instructionTests->addChild(createOpConstantNullGroup(testCtx)); instructionTests->addChild(createOpConstantCompositeGroup(testCtx)); instructionTests->addChild(createOpConstantUsageGroup(testCtx)); + instructionTests->addChild(createSpecConstantGroup(testCtx)); instructionTests->addChild(createOpSourceGroup(testCtx)); instructionTests->addChild(createOpSourceExtensionGroup(testCtx)); instructionTests->addChild(createDecorationGroupGroup(testCtx)); @@ -3020,6 +3837,11 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx) instructionTests->addChild(createFunctionControlGroup(testCtx)); instructionTests->addChild(createSelectionControlGroup(testCtx)); instructionTests->addChild(createBlockOrderGroup(testCtx)); + instructionTests->addChild(createMultipleShaderGroup(testCtx)); + instructionTests->addChild(createMemoryAccessGroup(testCtx)); + instructionTests->addChild(createOpCopyMemoryGroup(testCtx)); + instructionTests->addChild(createOpCopyObjectGroup(testCtx)); + instructionTests->addChild(createNoContractionGroup(testCtx)); instructionTests->addChild(createOpUndefGroup(testCtx)); instructionTests->addChild(createOpUnreachableGroup(testCtx));