Home | History | Annotate | Download | only in spirv_assembly
      1 /*-------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2017 Google Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief SPIR-V Assembly Tests for UBO matrix padding.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "vktSpvAsmUboMatrixPaddingTests.hpp"
     25 #include "vktSpvAsmComputeShaderCase.hpp"
     26 #include "vktSpvAsmComputeShaderTestUtil.hpp"
     27 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
     28 
     29 namespace vkt
     30 {
     31 namespace SpirVAssembly
     32 {
     33 
     34 using namespace vk;
     35 using std::map;
     36 using std::string;
     37 using std::vector;
     38 using tcu::IVec3;
     39 using tcu::RGBA;
     40 using tcu::Vec4;
     41 
     42 namespace
     43 {
     44 
     45 void addComputeUboMatrixPaddingTest (tcu::TestCaseGroup* group)
     46 {
     47 	tcu::TestContext&	testCtx			= group->getTestContext();
     48 	de::Random			rnd				(deStringHash(group->getName()));
     49 	const int			numElements		= 128;
     50 
     51 	// Read input UBO containing and array of mat2x2 using no padding inside matrix. Output
     52 	// into output buffer containing floats. The input and output buffer data should match.
     53 	const string		shaderSource	=
     54 		"                       OpCapability Shader\n"
     55 		"                  %1 = OpExtInstImport \"GLSL.std.450\"\n"
     56 		"                       OpMemoryModel Logical GLSL450\n"
     57 		"                       OpEntryPoint GLCompute %main \"main\" %id\n"
     58 		"                       OpExecutionMode %main LocalSize 1 1 1\n"
     59 		"                       OpSource GLSL 430\n"
     60 		"                       OpDecorate %id BuiltIn GlobalInvocationId\n"
     61 		"                       OpDecorate %_arr_v4 ArrayStride 16\n"
     62 		"                       OpMemberDecorate %Output 0 Offset 0\n"
     63 		"                       OpDecorate %Output BufferBlock\n"
     64 		"                       OpDecorate %dataOutput DescriptorSet 0\n"
     65 		"                       OpDecorate %dataOutput Binding 1\n"
     66 		"                       OpDecorate %_arr_mat2v2 ArrayStride 16\n"
     67 		"                       OpMemberDecorate %Input 0 ColMajor\n"
     68 		"                       OpMemberDecorate %Input 0 Offset 0\n"
     69 		"                       OpMemberDecorate %Input 0 MatrixStride 8\n"
     70 		"                       OpDecorate %Input Block\n"
     71 		"                       OpDecorate %dataInput DescriptorSet 0\n"
     72 		"                       OpDecorate %dataInput Binding 0\n"
     73 		"               %void = OpTypeVoid\n"
     74 		"                  %3 = OpTypeFunction %void\n"
     75 		"                %u32 = OpTypeInt 32 0\n"
     76 		" %_ptr_Function_uint = OpTypePointer Function %u32\n"
     77 		"             %v3uint = OpTypeVector %u32 3\n"
     78 		"  %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
     79 		"                 %id = OpVariable %_ptr_Input_v3uint Input\n"
     80 		"                %i32 = OpTypeInt 32 1\n"
     81 		"              %int_0 = OpConstant %i32 0\n"
     82 		"              %int_1 = OpConstant %i32 1\n"
     83 		"             %uint_0 = OpConstant %u32 0\n"
     84 		"             %uint_1 = OpConstant %u32 1\n"
     85 		"             %uint_2 = OpConstant %u32 2\n"
     86 		"             %uint_3 = OpConstant %u32 3\n"
     87 		"    %_ptr_Input_uint = OpTypePointer Input %u32\n"
     88 		"                %f32 = OpTypeFloat 32\n"
     89 		"            %v4float = OpTypeVector %f32 4\n"
     90 		"           %uint_128 = OpConstant %u32 128\n"
     91 		"            %_arr_v4 = OpTypeArray %v4float %uint_128\n"
     92 		"             %Output = OpTypeStruct %_arr_v4\n"
     93 		"%_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
     94 		"         %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
     95 		"            %v2float = OpTypeVector %f32 2\n"
     96 		"        %mat2v2float = OpTypeMatrix %v2float 2\n"
     97 		"        %_arr_mat2v2 = OpTypeArray %mat2v2float %uint_128\n"
     98 		"              %Input = OpTypeStruct %_arr_mat2v2\n"
     99 		" %_ptr_Uniform_Input = OpTypePointer Uniform %Input\n"
    100 		"          %dataInput = OpVariable %_ptr_Uniform_Input Uniform\n"
    101 		" %_ptr_Uniform_float = OpTypePointer Uniform %f32\n"
    102 		"               %main = OpFunction %void None %3\n"
    103 		"                  %5 = OpLabel\n"
    104 		"                  %i = OpVariable %_ptr_Function_uint Function\n"
    105 		"                 %14 = OpAccessChain %_ptr_Input_uint %id %uint_0\n"
    106 		"                 %15 = OpLoad %u32 %14\n"
    107 		"                       OpStore %i %15\n"
    108 		"                %idx = OpLoad %u32 %i\n"
    109 		"                 %34 = OpAccessChain %_ptr_Uniform_float %dataInput %int_0 %idx %int_0 %uint_0\n"
    110 		"                 %35 = OpLoad %f32 %34\n"
    111 		"                 %36 = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %idx %uint_0\n"
    112 		"                       OpStore %36 %35\n"
    113 		"                 %40 = OpAccessChain %_ptr_Uniform_float %dataInput %int_0 %idx %int_0 %uint_1\n"
    114 		"                 %41 = OpLoad %f32 %40\n"
    115 		"                 %42 = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %idx %uint_1\n"
    116 		"                       OpStore %42 %41\n"
    117 		"                 %46 = OpAccessChain %_ptr_Uniform_float %dataInput %int_0 %idx %int_1 %uint_0\n"
    118 		"                 %47 = OpLoad %f32 %46\n"
    119 		"                 %49 = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %idx %uint_2\n"
    120 		"                       OpStore %49 %47\n"
    121 		"                 %52 = OpAccessChain %_ptr_Uniform_float %dataInput %int_0 %idx %int_1 %uint_1\n"
    122 		"                 %53 = OpLoad %f32 %52\n"
    123 		"                 %55 = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %idx %uint_3\n"
    124 		"                       OpStore %55 %53\n"
    125 		"                       OpReturn\n"
    126 		"                       OpFunctionEnd\n";
    127 
    128 		vector<tcu::Vec4>		inputData;
    129 		ComputeShaderSpec		spec;
    130 
    131 		inputData.reserve(numElements);
    132 		for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
    133 			inputData.push_back(tcu::Vec4(rnd.getFloat(), rnd.getFloat(), rnd.getFloat(), rnd.getFloat()));
    134 
    135 		spec.assembly			= shaderSource;
    136 		spec.numWorkGroups		= IVec3(numElements, 1, 1);
    137 		spec.inputTypes[0]		= VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    138 
    139 		spec.inputs.push_back(BufferSp(new Vec4Buffer(inputData)));
    140 		// Shader is expected to pass the input data by treating the input vec4 as mat2x2
    141 		spec.outputs.push_back(BufferSp(new Vec4Buffer(inputData)));
    142 
    143 		group->addChild(new SpvAsmComputeShaderCase(testCtx, "mat2x2", "Tests mat2x2 member in UBO struct without padding (treated as vec4).", spec));
    144 	}
    145 }
    146 
    147 void addGraphicsUboMatrixPaddingTest (tcu::TestCaseGroup* group)
    148 {
    149 	de::Random				rnd					(deStringHash(group->getName()));
    150 	map<string, string>		fragments;
    151 	const deUint32			numDataPoints		= 128;
    152 	RGBA					defaultColors[4];
    153 	GraphicsResources		resources;
    154 	vector<tcu::Vec4>		inputData;
    155 
    156 	inputData.reserve(numDataPoints);
    157 	for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
    158 		inputData.push_back(tcu::Vec4(rnd.getFloat(), rnd.getFloat(), rnd.getFloat(), rnd.getFloat()));
    159 
    160 	resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, BufferSp(new Vec4Buffer(inputData))));
    161 	// Shader is expected to pass the input data by treating the input vec4 as mat2x2
    162 	resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Vec4Buffer(inputData))));
    163 
    164 	getDefaultColors(defaultColors);
    165 
    166 	fragments["pre_main"]	=
    167 		"             %uint_128 = OpConstant %u32 128\n"
    168 		"    %_arr_v4f_uint_128 = OpTypeArray %v4f32 %uint_128\n"
    169 		"               %Output = OpTypeStruct %_arr_v4f_uint_128\n"
    170 		"  %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
    171 		"           %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
    172 		"              %mat2v2f = OpTypeMatrix %v2f32 2\n"
    173 		"%_arr_mat2v2f_uint_128 = OpTypeArray %mat2v2f %uint_128\n"
    174 		"                %Input = OpTypeStruct %_arr_mat2v2f_uint_128\n"
    175 		"   %_ptr_Uniform_Input = OpTypePointer Uniform %Input\n"
    176 		"            %dataInput = OpVariable %_ptr_Uniform_Input Uniform\n"
    177 		"       %_ptr_Uniform_f = OpTypePointer Uniform %f32\n"
    178 		"            %c_i32_128 = OpConstant %i32 128\n";
    179 
    180 	fragments["decoration"]	=
    181 		"                         OpDecorate %_arr_v4f_uint_128 ArrayStride 16\n"
    182 		"                         OpMemberDecorate %Output 0 Offset 0\n"
    183 		"                         OpDecorate %Output BufferBlock\n"
    184 		"                         OpDecorate %dataOutput DescriptorSet 0\n"
    185 		"                         OpDecorate %dataOutput Binding 1\n"
    186 		"                         OpDecorate %_arr_mat2v2f_uint_128 ArrayStride 16\n"
    187 		"                         OpMemberDecorate %Input 0 ColMajor\n"
    188 		"                         OpMemberDecorate %Input 0 Offset 0\n"
    189 		"                         OpMemberDecorate %Input 0 MatrixStride 8\n"
    190 		"                         OpDecorate %Input Block\n"
    191 		"                         OpDecorate %dataInput DescriptorSet 0\n"
    192 		"                         OpDecorate %dataInput Binding 0\n";
    193 
    194 	// Read input UBO containing and array of mat2x2 using no padding inside matrix. Output
    195 	// into output buffer containing floats. The input and output buffer data should match.
    196 	// The whole array is handled inside a for loop.
    197 	fragments["testfun"]	=
    198 		"            %test_code = OpFunction %v4f32 None %v4f32_function\n"
    199 		"                %param = OpFunctionParameter %v4f32\n"
    200 
    201 		"                %entry = OpLabel\n"
    202 		"                    %i = OpVariable %fp_i32 Function\n"
    203 		"                         OpStore %i %c_i32_0\n"
    204 		"                         OpBranch %loop\n"
    205 
    206 		"                 %loop = OpLabel\n"
    207 		"                   %15 = OpLoad %i32 %i\n"
    208 		"                   %lt = OpSLessThan %bool %15 %c_i32_128\n"
    209 		"                         OpLoopMerge %merge %inc None\n"
    210 		"                         OpBranchConditional %lt %write %merge\n"
    211 
    212 		"                %write = OpLabel\n"
    213 		"                   %30 = OpLoad %i32 %i\n"
    214 		"                   %34 = OpAccessChain %_ptr_Uniform_f %dataInput %c_i32_0 %30 %c_i32_0 %c_u32_0\n"
    215 		"                   %35 = OpLoad %f32 %34\n"
    216 		"                   %36 = OpAccessChain %_ptr_Uniform_f %dataOutput %c_i32_0 %30 %c_u32_0\n"
    217 		"                         OpStore %36 %35\n"
    218 		"                   %40 = OpAccessChain %_ptr_Uniform_f %dataInput %c_i32_0 %30 %c_i32_0 %c_u32_1\n"
    219 		"                   %41 = OpLoad %f32 %40\n"
    220 		"                   %42 = OpAccessChain %_ptr_Uniform_f %dataOutput %c_i32_0 %30 %c_u32_1\n"
    221 		"                         OpStore %42 %41\n"
    222 		"                   %46 = OpAccessChain %_ptr_Uniform_f %dataInput %c_i32_0 %30 %c_i32_1 %c_u32_0\n"
    223 		"                   %47 = OpLoad %f32 %46\n"
    224 		"                   %49 = OpAccessChain %_ptr_Uniform_f %dataOutput %c_i32_0 %30 %c_u32_2\n"
    225 		"                         OpStore %49 %47\n"
    226 		"                   %52 = OpAccessChain %_ptr_Uniform_f %dataInput %c_i32_0 %30 %c_i32_1 %c_u32_1\n"
    227 		"                   %53 = OpLoad %f32 %52\n"
    228 		"                   %55 = OpAccessChain %_ptr_Uniform_f %dataOutput %c_i32_0 %30 %c_u32_3\n"
    229 		"                         OpStore %55 %53\n"
    230 		"                         OpBranch %inc\n"
    231 
    232 		"                  %inc = OpLabel\n"
    233 		"                   %37 = OpLoad %i32 %i\n"
    234 		"                   %39 = OpIAdd %i32 %37 %c_i32_1\n"
    235 		"                         OpStore %i %39\n"
    236 		"                         OpBranch %loop\n"
    237 
    238 		"                %merge = OpLabel\n"
    239 		"                         OpReturnValue %param\n"
    240 
    241 		"                         OpFunctionEnd\n";
    242 
    243 	resources.inputs.back().first	= VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    244 
    245 	createTestsForAllStages("mat2x2", defaultColors, defaultColors, fragments, resources, vector<string>(), group);
    246 }
    247 
    248 tcu::TestCaseGroup* createUboMatrixPaddingComputeGroup (tcu::TestContext& testCtx)
    249 {
    250 	de::MovePtr<tcu::TestCaseGroup> group		(new tcu::TestCaseGroup(testCtx, "ubo_padding", "Compute tests for UBO struct member packing."));
    251 	addComputeUboMatrixPaddingTest(group.get());
    252 
    253 	return group.release();
    254 }
    255 
    256 tcu::TestCaseGroup* createUboMatrixPaddingGraphicsGroup (tcu::TestContext& testCtx)
    257 {
    258 	de::MovePtr<tcu::TestCaseGroup> group		(new tcu::TestCaseGroup(testCtx, "ubo_padding", "Graphics tests for UBO struct member packing."));
    259 	addGraphicsUboMatrixPaddingTest(group.get());
    260 
    261 	return group.release();
    262 }
    263 
    264 } // SpirVAssembly
    265 } // vkt
    266