blob: 8b4ac874eb8830908c3a9abb2d49405d0e9ed29e [file] [log] [blame]
/*-------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2017 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 OpBranchConditional instruction.
*//*--------------------------------------------------------------------*/
#include "vktSpvAsmConditionalBranchTests.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::RGBA;
using tcu::IVec3;
using tcu::StringTemplate;
namespace
{
static const string conditions[] = { "true", "false" };
void addComputeSameLabelsTest (tcu::TestCaseGroup* group)
{
tcu::TestContext& testCtx = group->getTestContext();
const int numItems = 128;
vector<deUint32> outputData;
outputData.reserve(numItems);
for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx)
outputData.push_back(numIdx);
for (int conditionIdx = 0; conditionIdx < DE_LENGTH_OF_ARRAY(conditions); ++conditionIdx)
{
ComputeShaderSpec spec;
map<string, string> specs;
string testName = string("same_labels_") + conditions[conditionIdx];
const StringTemplate shaderSource (
" OpCapability Shader\n"
" %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"
" OpDecorate %_arr_uint_uint_128 ArrayStride 4\n"
" OpMemberDecorate %Output 0 Offset 0\n"
" OpDecorate %Output BufferBlock\n"
" OpDecorate %dataOutput DescriptorSet 0\n"
" OpDecorate %dataOutput Binding 0\n"
" %void = OpTypeVoid\n"
" %3 = OpTypeFunction %void\n"
" %uint = OpTypeInt 32 0\n"
" %_ptr_Function_uint = OpTypePointer Function %uint\n"
" %v3uint = OpTypeVector %uint 3\n"
" %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
"%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
" %uint_0 = OpConstant %uint 0\n"
" %_ptr_Input_uint = OpTypePointer Input %uint\n"
" %bool = OpTypeBool\n"
" %true = OpConstantTrue %bool\n"
" %false = OpConstantFalse %bool\n"
" %uint_128 = OpConstant %uint 128\n"
" %_arr_uint_uint_128 = OpTypeArray %uint %uint_128\n"
" %Output = OpTypeStruct %_arr_uint_uint_128\n"
" %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
" %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
" %_ptr_Uniform_uint = OpTypePointer Uniform %uint\n"
" %uint_dummy = OpConstant %uint 2863311530\n"
" %main = OpFunction %void None %3\n"
" %5 = OpLabel\n"
" %i = OpVariable %_ptr_Function_uint Function\n"
" %14 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n"
" %15 = OpLoad %uint %14\n"
" OpStore %i %15\n"
" %uint_i = OpLoad %uint %i\n"
" OpSelectionMerge %merge None\n"
" OpBranchConditional %${condition} %live %live\n"
" %live = OpLabel\n"
" %31 = OpAccessChain %_ptr_Uniform_uint %dataOutput %uint_0 %uint_i\n"
" OpStore %31 %uint_i\n"
" OpBranch %merge\n"
" %dead = OpLabel\n"
" %35 = OpAccessChain %_ptr_Uniform_uint %dataOutput %uint_0 %uint_i\n"
" OpStore %35 %uint_dummy\n"
" OpBranch %merge\n"
" %merge = OpLabel\n"
" OpReturn\n"
" OpFunctionEnd\n");
specs["condition"] = conditions[conditionIdx];
spec.assembly = shaderSource.specialize(specs);
spec.numWorkGroups = IVec3(numItems, 1, 1);
spec.outputs.push_back(Resource(BufferSp(new Buffer<deUint32>(outputData))));
group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), "Tests both labels pointing to a same branch.", spec));
}
}
void addGraphicsSameLabelsTest (tcu::TestCaseGroup* group)
{
const deUint32 numItems = 128;
RGBA defaultColors[4];
GraphicsResources resources;
vector<deUint32> outputData;
VulkanFeatures features;
outputData.reserve(numItems);
for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx)
outputData.push_back(numIdx);
resources.outputs.push_back(Resource(BufferSp(new Buffer<deUint32>(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
features.coreFeatures.vertexPipelineStoresAndAtomics = true;
features.coreFeatures.fragmentStoresAndAtomics = true;
getDefaultColors(defaultColors);
for (int conditionIdx = 0; conditionIdx < DE_LENGTH_OF_ARRAY(conditions); ++conditionIdx)
{
map<string, string> fragments;
map<string, string> specs;
string testName = string("same_labels_") + conditions[conditionIdx];
fragments["pre_main"] =
" %c_u32_128 = OpConstant %u32 128\n"
" %true = OpConstantTrue %bool\n"
" %false = OpConstantFalse %bool\n"
" %_arr_uint_uint_128 = OpTypeArray %u32 %c_u32_128\n"
" %Output = OpTypeStruct %_arr_uint_uint_128\n"
"%_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
" %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
" %_ptr_Uniform_uint = OpTypePointer Uniform %u32\n"
" %fp_u32 = OpTypePointer Function %u32\n"
" %uint_dummy = OpConstant %u32 2863311530\n";
fragments["decoration"] =
" OpDecorate %_arr_uint_uint_128 ArrayStride 4\n"
" OpMemberDecorate %Output 0 Offset 0\n"
" OpDecorate %Output BufferBlock\n"
" OpDecorate %dataOutput DescriptorSet 0\n"
" OpDecorate %dataOutput Binding 0\n";
const StringTemplate testFun (
" %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
" %param = OpFunctionParameter %v4f32\n"
" %entry = OpLabel\n"
" %i = OpVariable %fp_u32 Function\n"
" OpStore %i %c_u32_0\n"
" OpBranch %loop\n"
" %loop = OpLabel\n"
" %15 = OpLoad %u32 %i\n"
" %lt = OpSLessThan %bool %15 %c_u32_128\n"
" OpLoopMerge %merge %inc None\n"
" OpBranchConditional %lt %write %merge\n"
" %write = OpLabel\n"
" %uint_i = OpLoad %u32 %i\n"
" OpSelectionMerge %condmerge None\n"
" OpBranchConditional %${condition} %live %live\n"
" %live = OpLabel\n"
" %31 = OpAccessChain %_ptr_Uniform_uint %dataOutput %c_u32_0 %uint_i\n"
" OpStore %31 %uint_i\n"
" OpBranch %condmerge\n"
" %dead = OpLabel\n"
" %35 = OpAccessChain %_ptr_Uniform_uint %dataOutput %c_u32_0 %uint_i\n"
" OpStore %35 %uint_dummy\n"
" OpBranch %condmerge\n"
" %condmerge = OpLabel\n"
" OpBranch %inc\n"
" %inc = OpLabel\n"
" %37 = OpLoad %u32 %i\n"
" %39 = OpIAdd %u32 %37 %c_u32_1\n"
" OpStore %i %39\n"
" OpBranch %loop\n"
" %merge = OpLabel\n"
" OpReturnValue %param\n"
" OpFunctionEnd\n");
specs["condition"] = conditions[conditionIdx];
fragments["testfun"] = testFun.specialize(specs);
createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, resources, vector<string>(), group, features);
}
}
} // anonymous
tcu::TestCaseGroup* createConditionalBranchComputeGroup (tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "conditional_branch", "Compute tests for OpBranchConditional."));
addComputeSameLabelsTest(group.get());
return group.release();
}
tcu::TestCaseGroup* createConditionalBranchGraphicsGroup (tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "conditional_branch", "Graphics tests for OpBranchConditional."));
addGraphicsSameLabelsTest(group.get());
return group.release();
}
} // SpirVAssembly
} // vkt