/*------------------------------------------------------------------------- * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2018 Google 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 SPIR-V Assembly Tests for OpVariable initializer *//*--------------------------------------------------------------------*/ #include "vktSpvAsmVariableInitTests.hpp" #include "vktSpvAsmComputeShaderCase.hpp" #include "vktSpvAsmComputeShaderTestUtil.hpp" #include "vktSpvAsmGraphicsShaderTestUtil.hpp" #include "tcuStringTemplate.hpp" namespace vkt { namespace SpirVAssembly { using namespace vk; using std::map; using std::string; using std::vector; using tcu::IVec3; using tcu::Vec4; using tcu::RGBA; using tcu::StringTemplate; namespace { enum InitializationSource { INITIALIZATION_SOURCE_CONSTANT, // Variable is initialized from a constant value INITIALIZATION_SOURCE_GLOBAL, // Variable is initialized from a global variable, which in turn is initialized from a constant }; struct TestParams { string name; string type; int numComponents; InitializationSource initializationSource; }; struct ShaderParams { InstanceContext context; string type; }; const TestParams testParams[] = { { "float", "f32", 1, INITIALIZATION_SOURCE_CONSTANT }, { "vec4", "v4f32", 4, INITIALIZATION_SOURCE_CONSTANT }, { "matrix", "matrix", 2 * 4, INITIALIZATION_SOURCE_CONSTANT }, { "floatarray", "floatArray", 8, INITIALIZATION_SOURCE_CONSTANT }, { "struct", "struct", 2 * 4 + 4 + 4, INITIALIZATION_SOURCE_CONSTANT }, { "float_from_workgroup", "f32", 1, INITIALIZATION_SOURCE_GLOBAL }, { "vec4_from_workgroup", "v4f32", 4, INITIALIZATION_SOURCE_GLOBAL }, { "matrix_from_workgroup", "matrix", 2 * 4, INITIALIZATION_SOURCE_GLOBAL }, { "floatarray_from_workgroup", "floatArray", 8, INITIALIZATION_SOURCE_GLOBAL }, { "struct_from_workgroup", "struct", 2 * 4 + 4 + 4, INITIALIZATION_SOURCE_GLOBAL } }; const string common = " %f32_1 = OpConstant %f32 1\n" " %v4f32_1 = OpConstantComposite %v4f32 %f32_1 %f32_1 %f32_1 %f32_1\n" " %matrix = OpTypeMatrix %v4f32 2\n" " %matrix_1 = OpConstantComposite %matrix %v4f32_1 %v4f32_1\n" " %struct = OpTypeStruct %matrix %v4f32 %f32 %f32 %f32 %f32\n" " %struct_1 = OpConstantComposite %struct %matrix_1 %v4f32_1 %f32_1 %f32_1 %f32_1 %f32_1\n" " %c_u32_8 = OpConstant %u32 8\n" " %floatArray = OpTypeArray %f32 %c_u32_8\n" " %floatArray_1 = OpConstantComposite %floatArray %f32_1 %f32_1 %f32_1 %f32_1 %f32_1 %f32_1 %f32_1 %f32_1\n" " %numElements = OpConstant %u32 ${count}\n" " %outputArray = OpTypeArray %${type} %numElements\n" " %Output = OpTypeStruct %outputArray\n" " %_ptr_Output = OpTypePointer StorageBuffer %Output\n" " %sbPtr = OpTypePointer StorageBuffer %${type}\n" " %dataOutput = OpVariable %_ptr_Output StorageBuffer\n"; const string globals = " %_ptr_${type}_global = OpTypePointer Workgroup %${type}\n" " %${type}_global_1 = OpVariable %_ptr_${type}_global Workgroup\n"; const string decorations = "${arrayStrideDecoration}" " OpMemberDecorate %Output 0 Offset 0\n" " OpDecorate %Output Block\n" " OpDecorate %dataOutput DescriptorSet 0\n" " OpDecorate %dataOutput Binding 0\n" "${extraDecorations:opt}" " OpDecorate %floatArray ArrayStride 4\n" " OpMemberDecorate %struct 0 ColMajor\n" " OpMemberDecorate %struct 0 Offset 0\n" " OpMemberDecorate %struct 0 MatrixStride 16\n" " OpMemberDecorate %struct 1 Offset 32\n" " OpMemberDecorate %struct 2 Offset 48\n" " OpMemberDecorate %struct 3 Offset 52\n" " OpMemberDecorate %struct 4 Offset 56\n" " OpMemberDecorate %struct 5 Offset 60\n"; void addComputeVariableInitPrivateTest (tcu::TestCaseGroup* group) { tcu::TestContext& testCtx = group->getTestContext(); const int numFloats = 128; tcu::TestCaseGroup* privateGroup = new tcu::TestCaseGroup(testCtx, "private"); vector expectedOutput (numFloats, 1.0f); group->addChild(privateGroup); for (int paramIdx = 0; paramIdx < DE_LENGTH_OF_ARRAY(testParams); paramIdx++) { ComputeShaderSpec spec; spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput))); map shaderSpec; const int numComponents = testParams[paramIdx].numComponents; const int numElements = numFloats / numComponents; const string type = testParams[paramIdx].type; const StringTemplate shaderSourceTemplate ( string( " OpCapability Shader\n" "${capabilities:opt}" " OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n" "${extensions:opt}" " %1 = OpExtInstImport \"GLSL.std.450\"\n" " OpMemoryModel Logical GLSL450\n" " OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n" " OpExecutionMode %main LocalSize 1 1 1\n" " OpSource GLSL 430\n" " OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n") + decorations + string( " %void = OpTypeVoid\n" " %voidFunc = OpTypeFunction %void\n" " %f32 = OpTypeFloat 32\n" " %u32 = OpTypeInt 32 0\n" " %c_u32_0 = OpConstant %u32 0\n" " %v4f32 = OpTypeVector %f32 4\n") + common + (testParams[paramIdx].initializationSource == INITIALIZATION_SOURCE_GLOBAL ? globals : "") + string( " %dataPtr = OpTypePointer Private %${type}\n" " %_ptr_Function_uint = OpTypePointer Function %u32\n" " %v3uint = OpTypeVector %u32 3\n" " %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n" "%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n" " %_ptr_Input_uint = OpTypePointer Input %u32\n" " %int = OpTypeInt 32 1\n" " %int_0 = OpConstant %int 0\n" "${variableInit}" " %main = OpFunction %void None %voidFunc\n" " %entry = OpLabel\n" " %invocationPtr = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %c_u32_0\n" " %invocation = OpLoad %u32 %invocationPtr\n" "${dataLoad}" " %outputPtr = OpAccessChain %sbPtr %dataOutput %int_0 %invocation\n" " OpStore %outputPtr %outputData\n" " OpReturn\n" " OpFunctionEnd\n")); shaderSpec["type"] = type; shaderSpec["arrayStrideDecoration"] = "OpDecorate %outputArray ArrayStride " + de::toString(numComponents * 4) + "\n"; shaderSpec["count"] = de::toString(numElements); shaderSpec["constData"] = type + "_1"; switch(testParams[paramIdx].initializationSource) { case INITIALIZATION_SOURCE_CONSTANT: shaderSpec["variableInit"] = " %f1 = OpVariable %dataPtr Private %" + type + "_1\n"; shaderSpec["dataLoad"] = " %outputData = OpLoad %" + type + " %f1\n"; break; default: DE_ASSERT(testParams[paramIdx].initializationSource == INITIALIZATION_SOURCE_GLOBAL); shaderSpec["capabilities"] = " OpCapability VariablePointers\n"; shaderSpec["extensions"] = " OpExtension \"SPV_KHR_variable_pointers\"\n"; shaderSpec["variableInit"] = " %dataPtrPtr = OpTypePointer Private %_ptr_" + type + "_global\n" " %f1 = OpVariable %dataPtrPtr Private %" + type + "_global_1\n"; shaderSpec["dataLoad"] = " %outputDataPtr = OpLoad %_ptr_" + type + "_global %f1\n" " OpStore %" + type + "_global_1 %" + type + "_1\n" " %outputData = OpLoad %" + type + " %outputDataPtr\n"; spec.requestedVulkanFeatures.extVariablePointers.variablePointers = true; spec.extensions.push_back("VK_KHR_variable_pointers"); break; } if (testParams[paramIdx].type == "matrix") { shaderSpec["extraDecorations"] += " OpMemberDecorate %Output 0 ColMajor\n" " OpMemberDecorate %Output 0 MatrixStride 16\n"; } spec.assembly = shaderSourceTemplate.specialize(shaderSpec); spec.numWorkGroups = IVec3(numElements, 1, 1); spec.extensions.push_back("VK_KHR_storage_buffer_storage_class"); privateGroup->addChild(new SpvAsmComputeShaderCase(testCtx, testParams[paramIdx].name.c_str(), spec)); } } void addGraphicsVariableInitPrivateTest (tcu::TestCaseGroup* group) { tcu::TestContext& testCtx = group->getTestContext(); map fragments; RGBA defaultColors[4]; VulkanFeatures features; tcu::TestCaseGroup* privateGroup = new tcu::TestCaseGroup(testCtx, "private"); const int numFloats = 128; vector expectedOutput (numFloats, 1.0f); group->addChild(privateGroup); getDefaultColors(defaultColors); features.coreFeatures.vertexPipelineStoresAndAtomics = true; features.coreFeatures.fragmentStoresAndAtomics = true; for (int paramIdx = 0; paramIdx < DE_LENGTH_OF_ARRAY(testParams); paramIdx++) { if (testParams[paramIdx].initializationSource != INITIALIZATION_SOURCE_CONSTANT) continue; GraphicsResources resources; vector extensions; resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)); extensions.push_back("VK_KHR_storage_buffer_storage_class"); map shaderSpec; const int numComponents = testParams[paramIdx].numComponents; const int numElements = numFloats / numComponents; const string type = testParams[paramIdx].type; StringTemplate preMain ( common + string( " %dataPtr = OpTypePointer Private %${type}\n" "${variableInit}" )); StringTemplate decoration (decorations); StringTemplate testFun ( " %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n" " %param = OpFunctionParameter %v4f32\n" " %entry = OpLabel\n" " %i = OpVariable %fp_i32 Function\n" "${dataLoad}" " OpStore %i %c_i32_0\n" " OpBranch %loop\n" " %loop = OpLabel\n" " %15 = OpLoad %i32 %i\n" " %lt = OpSLessThan %bool %15 %numElements\n" " OpLoopMerge %merge %inc None\n" " OpBranchConditional %lt %write %merge\n" " %write = OpLabel\n" " %30 = OpLoad %i32 %i\n" " %outputPtr = OpAccessChain %sbPtr %dataOutput %c_i32_0 %30\n" " OpStore %outputPtr %outputData\n" " OpBranch %inc\n" " %inc = OpLabel\n" " %37 = OpLoad %i32 %i\n" " %39 = OpIAdd %i32 %37 %c_i32_1\n" " OpStore %i %39\n" " OpBranch %loop\n" " %merge = OpLabel\n" " OpReturnValue %param\n" " OpFunctionEnd\n"); shaderSpec["type"] = type; shaderSpec["arrayStrideDecoration"] = "OpDecorate %outputArray ArrayStride " + de::toString(numComponents * 4) + "\n"; shaderSpec["count"] = de::toString(numElements); shaderSpec["constData"] = type + "_1"; shaderSpec["variableInit"] = " %f1 = OpVariable %dataPtr Private %" + type + "_1\n"; shaderSpec["dataLoad"] = " %outputData = OpLoad %" + type + " %f1\n"; if (testParams[paramIdx].type == "matrix") { shaderSpec["extraDecorations"] += " OpMemberDecorate %Output 0 ColMajor\n" " OpMemberDecorate %Output 0 MatrixStride 16\n"; } fragments["extension"] += "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"; fragments["pre_main"] = preMain.specialize(shaderSpec); fragments["decoration"] = decoration.specialize(shaderSpec); fragments["testfun"] = testFun.specialize(shaderSpec); createTestsForAllStages(testParams[paramIdx].name, defaultColors, defaultColors, fragments, resources, extensions, privateGroup, features); } } tcu::TestStatus outputTest (Context& context, ShaderParams params) { return runAndVerifyDefaultPipeline(context, params.context); } void addShaderCodeOutput (vk::SourceCollections& dst, ShaderParams params) { SpirvVersion targetSpirvVersion = params.context.resources.spirvVersion; map spec; const deUint32 vulkanVersion = dst.usedVulkanVersion; spec["type"] = params.type; spec["initSource"] = params.type + "_1"; if (params.type == "struct") { // Output structure of matrix, vec4, and four floats all having values of 1. const StringTemplate vertexShader ( " OpCapability Shader\n" " %1 = OpExtInstImport \"GLSL.std.450\"\n" " OpMemoryModel Logical GLSL450\n" " OpEntryPoint Vertex %main \"main\" %_ %position %vtxColor %color %outData\n" " OpSource GLSL 430\n" " OpMemberDecorate %gl_PerVertex 0 BuiltIn Position\n" " OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize\n" " OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance\n" " OpDecorate %gl_PerVertex Block\n" " OpDecorate %position Location 0\n" " OpDecorate %vtxColor Location 1\n" " OpDecorate %color Location 1\n" " OpDecorate %outData Location 2\n" " OpMemberDecorate %Data 0 ColMajor\n" " OpMemberDecorate %Data 0 Offset 0\n" " OpMemberDecorate %Data 0 MatrixStride 16\n" " OpMemberDecorate %Data 1 Offset 32\n" " OpMemberDecorate %Data 2 Offset 48\n" " OpMemberDecorate %Data 3 Offset 52\n" " OpMemberDecorate %Data 4 Offset 56\n" " OpMemberDecorate %Data 5 Offset 60\n" " OpMemberDecorate %DataOutput 0 Offset 0\n" " %void = OpTypeVoid\n" " %voidFunc = OpTypeFunction %void\n" " %float = OpTypeFloat 32\n" " %v4float = OpTypeVector %float 4\n" " %uint = OpTypeInt 32 0\n" " %uint_1 = OpConstant %uint 1\n" " %_arr_float_uint_1 = OpTypeArray %float %uint_1\n" " %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1\n" "%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex\n" " %_ = OpVariable %_ptr_Output_gl_PerVertex Output\n" " %int = OpTypeInt 32 1\n" " %int_0 = OpConstant %int 0\n" " %_ptr_Input_v4float = OpTypePointer Input %v4float\n" " %position = OpVariable %_ptr_Input_v4float Input\n" " %_ptr_Output_v4float = OpTypePointer Output %v4float\n" " %vtxColor = OpVariable %_ptr_Output_v4float Output\n" " %color = OpVariable %_ptr_Input_v4float Input\n" " %mat2v4float = OpTypeMatrix %v4float 2\n" " %Data = OpTypeStruct %mat2v4float %v4float %float %float %float %float\n" " %DataOutput = OpTypeStruct %Data\n" " %_ptr_Output_DataOutput = OpTypePointer Output %DataOutput\n" " %float_1 = OpConstant %float 1\n" " %vec4_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1\n" " %matrix_1 = OpConstantComposite %mat2v4float %vec4_1 %vec4_1\n" " %_ptr_Output_mat2v4float = OpTypePointer Output %mat2v4float\n" " %_ptr_Output_float = OpTypePointer Output %float\n" " %data_1 = OpConstantComposite %Data %matrix_1 %vec4_1 %float_1 %float_1 %float_1 %float_1\n" " %struct_1 = OpConstantComposite %DataOutput %data_1\n" " %_ptr_struct_private = OpTypePointer Private %DataOutput\n" " %struct_global_1 = OpVariable %_ptr_struct_private Private %struct_1\n" " %outData = OpVariable %_ptr_Output_DataOutput Output %${initSource}\n" " %main = OpFunction %void None %voidFunc\n" " %entry = OpLabel\n" " %posData = OpLoad %v4float %position\n" " %posPtr = OpAccessChain %_ptr_Output_v4float %_ %int_0\n" " OpStore %posPtr %posData\n" " %colorData = OpLoad %v4float %color\n" " OpStore %vtxColor %colorData\n" " OpReturn\n" " OpFunctionEnd\n"); // Pass the incoming input struct into buffer. const string fragmentShader = " OpCapability Shader\n" " OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n" " %1 = OpExtInstImport \"GLSL.std.450\"\n" " OpMemoryModel Logical GLSL450\n" " OpEntryPoint Fragment %main \"main\" %fragColor %vtxColor %inData\n" " OpExecutionMode %main OriginUpperLeft\n" " OpSource GLSL 430\n" " OpDecorate %fragColor Location 0\n" " OpDecorate %vtxColor Location 1\n" " OpMemberDecorate %Data 0 ColMajor\n" " OpMemberDecorate %Data 0 Offset 0\n" " OpMemberDecorate %Data 0 MatrixStride 16\n" " OpMemberDecorate %Data 1 Offset 32\n" " OpMemberDecorate %Data 2 Offset 48\n" " OpMemberDecorate %Data 3 Offset 52\n" " OpMemberDecorate %Data 4 Offset 56\n" " OpMemberDecorate %Data 5 Offset 60\n" " OpMemberDecorate %Output 0 Offset 0\n" " OpDecorate %Output Block\n" " OpDecorate %dataOutput DescriptorSet 0\n" " OpDecorate %dataOutput Binding 0\n" " OpDecorate %inData Location 2\n" " %void = OpTypeVoid\n" " %voidFunc = OpTypeFunction %void\n" " %float = OpTypeFloat 32\n" " %v4float = OpTypeVector %float 4\n" " %_ptr_Output_v4float = OpTypePointer Output %v4float\n" " %fragColor = OpVariable %_ptr_Output_v4float Output\n" " %_ptr_Input_v4float = OpTypePointer Input %v4float\n" " %vtxColor = OpVariable %_ptr_Input_v4float Input\n" " %mat2v4float = OpTypeMatrix %v4float 2\n" " %Data = OpTypeStruct %mat2v4float %v4float %float %float %float %float\n" " %Output = OpTypeStruct %Data\n" " %_ptr_Output = OpTypePointer StorageBuffer %Output\n" " %dataOutput = OpVariable %_ptr_Output StorageBuffer\n" " %int = OpTypeInt 32 1\n" " %int_0 = OpConstant %int 0\n" " %DataInput = OpTypeStruct %Data\n" " %_ptr_Input_DataInput = OpTypePointer Input %DataInput\n" " %inData = OpVariable %_ptr_Input_DataInput Input\n" " %_ptr_Input_Data = OpTypePointer Input %Data\n" " %_ptr_Data = OpTypePointer StorageBuffer %Data\n" " %main = OpFunction %void None %voidFunc\n" " %entry = OpLabel\n" " %colorData = OpLoad %v4float %vtxColor\n" " OpStore %fragColor %colorData\n" " %inputDataPtr = OpAccessChain %_ptr_Input_Data %inData %int_0\n" " %inputData = OpLoad %Data %inputDataPtr\n" " %outputDataPtr = OpAccessChain %_ptr_Data %dataOutput %int_0\n" " OpStore %outputDataPtr %inputData\n" " OpReturn\n" " OpFunctionEnd\n"; dst.spirvAsmSources.add("vert", DE_NULL) << vertexShader.specialize(spec) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion); dst.spirvAsmSources.add("frag", DE_NULL) << fragmentShader << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion); } else { // Needed for preventing duplicate pointer declarations. if (params.type == "v4f32") { spec["vec4ptrDeclOutput"] = ""; spec["vec4ptrOutput"] = "outputPtr"; spec["vec4ptrDeclInput"] = ""; spec["vec4ptrInput"] = "inputPtr"; } else { spec["vec4ptrDeclOutput"] = " %_ptr_Output_v4f32 = OpTypePointer Output %v4f32\n"; spec["vec4ptrOutput"] = "_ptr_Output_v4f32"; spec["vec4ptrDeclInput"] = " %_ptr_Input_v4f32 = OpTypePointer Input %v4f32\n"; spec["vec4ptrInput"] = "_ptr_Input_v4f32"; } const string types = " %u32 = OpTypeInt 32 0\n" " %f32 = OpTypeFloat 32\n" " %v4f32 = OpTypeVector %f32 4\n" " %matrix = OpTypeMatrix %v4f32 2\n" " %c_u32_0 = OpConstant %u32 0\n" " %c_u32_8 = OpConstant %u32 8\n" " %floatArray = OpTypeArray %f32 %c_u32_8\n"; if (params.type == "matrix") { spec["extraDecorations"] = " OpMemberDecorate %Output 0 ColMajor\n" " OpMemberDecorate %Output 0 MatrixStride 16\n"; } // Output selected data type with all components having value one. const StringTemplate vertexShader ( string( " OpCapability Shader\n" " %1 = OpExtInstImport \"GLSL.std.450\"\n" " OpMemoryModel Logical GLSL450\n" " OpEntryPoint Vertex %main \"main\" %_ %position %vtxColor %color %outData\n" " OpSource GLSL 430\n" " OpMemberDecorate %gl_PerVertex 0 BuiltIn Position\n" " OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize\n" " OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance\n" " OpDecorate %gl_PerVertex Block\n" " OpDecorate %position Location 0\n" " OpDecorate %vtxColor Location 1\n" " OpDecorate %color Location 1\n" " OpDecorate %outData Location 2\n" " OpDecorate %floatArray ArrayStride 4\n" " %void = OpTypeVoid\n" " %3 = OpTypeFunction %void\n") + types + string( " %f32_1 = OpConstant %f32 1\n" " %_ptr_f32_private = OpTypePointer Private %f32\n" " %f32_global_1 = OpVariable %_ptr_f32_private Private %f32_1\n" " %v4f32_1 = OpConstantComposite %v4f32 %f32_1 %f32_1 %f32_1 %f32_1\n" " %_ptr_v4f32_private = OpTypePointer Private %v4f32\n" " %v4f32_global_1 = OpVariable %_ptr_v4f32_private Private %v4f32_1\n" " %matrix_1 = OpConstantComposite %matrix %v4f32_1 %v4f32_1\n" " %_ptr_matrix_private = OpTypePointer Private %matrix\n" " %matrix_global_1 = OpVariable %_ptr_matrix_private Private %matrix_1\n" " %floatArray_1 = OpConstantComposite %floatArray %f32_1 %f32_1 %f32_1 %f32_1 %f32_1 %f32_1 %f32_1 %f32_1\n" " %_ptr_floatArray_private = OpTypePointer Private %floatArray\n" " %floatArray_global_1 = OpVariable %_ptr_floatArray_private Private %floatArray_1\n" " %c_u32_1 = OpConstant %u32 1\n" " %_arr_f32_u32_1 = OpTypeArray %f32 %c_u32_1\n" " %gl_PerVertex = OpTypeStruct %v4f32 %f32 %_arr_f32_u32_1\n" "%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex\n" " %_ = OpVariable %_ptr_Output_gl_PerVertex Output\n" " %outputPtr = OpTypePointer Output %${type}\n" " %outData = OpVariable %outputPtr Output %${initSource}\n" " %_ptr_Input_v4f32 = OpTypePointer Input %v4f32\n" " %position = OpVariable %_ptr_Input_v4f32 Input\n" "${vec4ptrDeclOutput}" " %vtxColor = OpVariable %${vec4ptrOutput} Output\n" " %color = OpVariable %_ptr_Input_v4f32 Input\n" " %main = OpFunction %void None %3\n" " %entry = OpLabel\n" " %posData = OpLoad %v4f32 %position\n" " %posOutputPtr = OpAccessChain %${vec4ptrOutput} %_ %c_u32_0\n" " OpStore %posOutputPtr %posData\n" " %colorData = OpLoad %v4f32 %color\n" " OpStore %vtxColor %colorData\n" " OpReturn\n" " OpFunctionEnd\n")); // Pass incoming data into buffer const StringTemplate fragmentShader ( string( " OpCapability Shader\n" " OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n" " %1 = OpExtInstImport \"GLSL.std.450\"\n" " OpMemoryModel Logical GLSL450\n" " OpEntryPoint Fragment %main \"main\" %fragColor %vtxColor %inData\n" " OpExecutionMode %main OriginUpperLeft\n" " OpSource GLSL 430\n" " OpDecorate %fragColor Location 0\n" " OpDecorate %vtxColor Location 1\n" " OpMemberDecorate %Output 0 Offset 0\n" " OpDecorate %Output Block\n" " OpDecorate %dataOutput DescriptorSet 0\n" " OpDecorate %dataOutput Binding 0\n" " OpDecorate %inData Location 2\n" " OpDecorate %floatArray ArrayStride 4\n" "${extraDecorations:opt}" " %void = OpTypeVoid\n" " %3 = OpTypeFunction %void\n") + types + string( " %inputPtr = OpTypePointer Input %${type}\n" " %inData = OpVariable %inputPtr Input\n" " %_ptr_Output_v4f32 = OpTypePointer Output %v4f32\n" " %fragColor = OpVariable %_ptr_Output_v4f32 Output\n" "${vec4ptrDeclInput}" " %vtxColor = OpVariable %${vec4ptrInput} Input\n" " %Output = OpTypeStruct %${type}\n" " %_ptr_Output = OpTypePointer StorageBuffer %Output\n" " %dataOutput = OpVariable %_ptr_Output StorageBuffer\n" " %outputPtr = OpTypePointer StorageBuffer %${type}\n" " %main = OpFunction %void None %3\n" " %entry = OpLabel\n" " %colorData = OpLoad %v4f32 %vtxColor\n" " OpStore %fragColor %colorData\n" " %inputData = OpLoad %${type} %inData\n" " %outputDataPtr = OpAccessChain %outputPtr %dataOutput %c_u32_0\n" " OpStore %outputDataPtr %inputData\n" " OpReturn\n" " OpFunctionEnd\n")); dst.spirvAsmSources.add("vert", DE_NULL) << vertexShader.specialize(spec) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion); dst.spirvAsmSources.add("frag", DE_NULL) << fragmentShader.specialize(spec) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion); } } void addGraphicsVariableInitOutputTest (tcu::TestCaseGroup* group) { tcu::TestContext& testCtx = group->getTestContext(); map fragments; RGBA defaultColors[4]; // Tests OpVariable initialization in output storage class. tcu::TestCaseGroup* outputGroup = new tcu::TestCaseGroup(testCtx, "output"); SpecConstants noSpecConstants; PushConstants noPushConstants; GraphicsInterfaces noInterfaces; vector extensions; map noFragments; StageToSpecConstantMap specConstantMap; const ShaderElement pipelineStages[] = { ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), }; specConstantMap[VK_SHADER_STAGE_VERTEX_BIT] = noSpecConstants; specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT] = noSpecConstants; getDefaultColors(defaultColors); group->addChild(outputGroup); VulkanFeatures requiredFeatures; requiredFeatures.coreFeatures.fragmentStoresAndAtomics = VK_TRUE; extensions.push_back("VK_KHR_storage_buffer_storage_class"); for (int paramIdx = 0; paramIdx < DE_LENGTH_OF_ARRAY(testParams); paramIdx++) { if (testParams[paramIdx].initializationSource == INITIALIZATION_SOURCE_GLOBAL) continue; GraphicsResources resources; vector expectedOutput (testParams[paramIdx].numComponents, 1.0f); resources.outputs.push_back(Resource(BufferSp(new Float32Buffer(expectedOutput)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)); { const InstanceContext& instanceContext = createInstanceContext(pipelineStages, defaultColors, defaultColors, noFragments, specConstantMap, noPushConstants, resources, noInterfaces, extensions, requiredFeatures, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, QP_TEST_RESULT_FAIL, string()); const ShaderParams shaderParams = { instanceContext, testParams[paramIdx].type }; addFunctionCaseWithPrograms(outputGroup, testParams[paramIdx].name.c_str(), addShaderCodeOutput, outputTest, shaderParams); } } } } // anonymous tcu::TestCaseGroup* createVariableInitComputeGroup (tcu::TestContext& testCtx) { de::MovePtr group(new tcu::TestCaseGroup(testCtx, "variable_init", "Compute tests for OpVariable initialization.")); addComputeVariableInitPrivateTest(group.get()); return group.release(); } tcu::TestCaseGroup* createVariableInitGraphicsGroup (tcu::TestContext& testCtx) { de::MovePtr group(new tcu::TestCaseGroup(testCtx, "variable_init", "Graphics tests for OpVariable initialization.")); addGraphicsVariableInitPrivateTest(group.get()); addGraphicsVariableInitOutputTest(group.get()); return group.release(); } } // SpirVAssembly } // vkt