blob: c7dc7013e5b86ff7c2f1e29f7443f9a732fcd6eb [file] [log] [blame]
/*-------------------------------------------------------------------------
* 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", "Tests OpVariable initialization in private storage class.");
vector<float> 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<string, string> 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 = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS;
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<string, string> fragments;
RGBA defaultColors[4];
VulkanFeatures features;
tcu::TestCaseGroup* privateGroup = new tcu::TestCaseGroup(testCtx, "private", "Tests OpVariable initialization in private storage class.");
const int numFloats = 128;
vector<float> 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<string> 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<string, string> 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<string, string> 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<string, string> fragments;
RGBA defaultColors[4];
tcu::TestCaseGroup* outputGroup = new tcu::TestCaseGroup(testCtx, "output", "Tests OpVariable initialization in output storage class.");
SpecConstants noSpecConstants;
PushConstants noPushConstants;
GraphicsInterfaces noInterfaces;
vector<string> extensions;
map<string, string> 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<float> 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<ShaderParams>(outputGroup,
testParams[paramIdx].name.c_str(),
"",
addShaderCodeOutput,
outputTest,
shaderParams);
}
}
}
} // anonymous
tcu::TestCaseGroup* createVariableInitComputeGroup (tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> 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<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "variable_init", "Graphics tests for OpVariable initialization."));
addGraphicsVariableInitPrivateTest(group.get());
addGraphicsVariableInitOutputTest(group.get());
return group.release();
}
} // SpirVAssembly
} // vkt