From: Lei Zhang Date: Thu, 9 Mar 2017 14:59:22 +0000 (-0500) Subject: Move graphics pipeline related code to their own files X-Git-Tag: upstream/0.1.0~471 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=56bd1576eb438e10e8ccb22e17b08354fbf3bac7;p=platform%2Fupstream%2FVK-GL-CTS.git Move graphics pipeline related code to their own files This is just refactoring work. No logic change. Affects: dEQP-VK.spirv_assembly.* Component: Vulkan Change-Id: If0585dc6e62c415fd04e3bd39f5e0ca9659a267d (cherry picked from commit f7c283abbd4c94260bbeb2dfed0f709a0b48a509) --- diff --git a/AndroidGen.mk b/AndroidGen.mk index dc82a25..b72494b 100644 --- a/AndroidGen.mk +++ b/AndroidGen.mk @@ -195,6 +195,7 @@ LOCAL_SRC_FILES := \ external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesTestsUtil.cpp \ external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp \ external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp \ + external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp \ external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp \ external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmTests.cpp \ external/vulkancts/modules/vulkan/ssbo/vktSSBOLayoutCase.cpp \ diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt b/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt index 1dbd6d6..c871c9e 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt @@ -7,6 +7,8 @@ set(DEQP_VK_SPIRV_ASSEMBLY_SRCS vktSpvAsmComputeShaderCase.hpp vktSpvAsmComputeShaderTestUtil.cpp vktSpvAsmComputeShaderTestUtil.hpp + vktSpvAsmGraphicsShaderTestUtil.cpp + vktSpvAsmGraphicsShaderTestUtil.hpp vktSpvAsmInstructionTests.cpp vktSpvAsmInstructionTests.hpp vktSpvAsmTests.cpp diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp index 5727fb5..dc908c4 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp @@ -23,4 +23,49 @@ #include "vktSpvAsmComputeShaderTestUtil.hpp" -DE_EMPTY_CPP_FILE +namespace vkt +{ +namespace SpirVAssembly +{ + +const char* const s_ShaderPreamble = + "OpCapability Shader\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint GLCompute %main \"main\" %id\n" + "OpExecutionMode %main LocalSize 1 1 1\n"; + +const char* const s_CommonTypes = + "%bool = OpTypeBool\n" + "%void = OpTypeVoid\n" + "%voidf = OpTypeFunction %void\n" + "%u32 = OpTypeInt 32 0\n" + "%i32 = OpTypeInt 32 1\n" + "%f32 = OpTypeFloat 32\n" + "%uvec3 = OpTypeVector %u32 3\n" + "%fvec3 = OpTypeVector %f32 3\n" + "%uvec3ptr = OpTypePointer Input %uvec3\n" + "%i32ptr = OpTypePointer Uniform %i32\n" + "%f32ptr = OpTypePointer Uniform %f32\n" + "%i32arr = OpTypeRuntimeArray %i32\n" + "%f32arr = OpTypeRuntimeArray %f32\n"; + +// Declares two uniform variables (indata, outdata) of type "struct { float[] }". Depends on type "f32arr" (for "float[]"). +const char* const s_InputOutputBuffer = + "%buf = OpTypeStruct %f32arr\n" + "%bufptr = OpTypePointer Uniform %buf\n" + "%indata = OpVariable %bufptr Uniform\n" + "%outdata = OpVariable %bufptr Uniform\n"; + +// Declares buffer type and layout for uniform variables indata and outdata. Both of them are SSBO bounded to descriptor set 0. +// indata is at binding point 0, while outdata is at 1. +const char* const s_InputOutputBufferTraits = + "OpDecorate %buf BufferBlock\n" + "OpDecorate %indata DescriptorSet 0\n" + "OpDecorate %indata Binding 0\n" + "OpDecorate %outdata DescriptorSet 0\n" + "OpDecorate %outdata Binding 1\n" + "OpDecorate %f32arr ArrayStride 4\n" + "OpMemberDecorate %buf 0 Offset 0\n"; + +} // SpirVAssembly +} // vkt diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp index 1f0551d..2182906 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp @@ -111,6 +111,11 @@ struct ComputeShaderSpec {} }; +extern const char* const s_ShaderPreamble; +extern const char* const s_CommonTypes; +extern const char* const s_InputOutputBuffer; +extern const char* const s_InputOutputBufferTraits; + } // SpirVAssembly } // vkt diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp new file mode 100644 index 0000000..688cc27 --- /dev/null +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp @@ -0,0 +1,2189 @@ +/*------------------------------------------------------------------------- + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2017 The Khronos Group 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 Graphics pipeline for SPIR-V assembly tests + *//*--------------------------------------------------------------------*/ + +#include "vktSpvAsmGraphicsShaderTestUtil.hpp" + +#include "tcuStringTemplate.hpp" + +#include "vkDefs.hpp" +#include "vkMemUtil.hpp" +#include "vkQueryUtil.hpp" +#include "vkRefUtil.hpp" +#include "vkTypeUtil.hpp" + +#include "deRandom.hpp" + +namespace vkt +{ +namespace SpirVAssembly +{ + +using namespace vk; +using std::map; +using std::string; +using std::vector; +using tcu::IVec3; +using tcu::IVec4; +using tcu::RGBA; +using tcu::TestLog; +using tcu::TestStatus; +using tcu::Vec4; +using de::UniquePtr; +using tcu::StringTemplate; +using tcu::Vec4; + +InstanceContext::InstanceContext (const RGBA (&inputs)[4], + const RGBA (&outputs)[4], + const map& testCodeFragments_, + const StageToSpecConstantMap& specConstants_) + : testCodeFragments (testCodeFragments_) + , specConstants (specConstants_) + , hasTessellation (false) + , requiredStages (static_cast(0)) + , failResult (QP_TEST_RESULT_FAIL) + , failMessageTemplate ("${reason}") +{ + inputColors[0] = inputs[0]; + inputColors[1] = inputs[1]; + inputColors[2] = inputs[2]; + inputColors[3] = inputs[3]; + + outputColors[0] = outputs[0]; + outputColors[1] = outputs[1]; + outputColors[2] = outputs[2]; + outputColors[3] = outputs[3]; +} + +InstanceContext::InstanceContext (const InstanceContext& other) + : moduleMap (other.moduleMap) + , testCodeFragments (other.testCodeFragments) + , specConstants (other.specConstants) + , hasTessellation (other.hasTessellation) + , requiredStages (other.requiredStages) + , failResult (other.failResult) + , failMessageTemplate (other.failMessageTemplate) +{ + inputColors[0] = other.inputColors[0]; + inputColors[1] = other.inputColors[1]; + inputColors[2] = other.inputColors[2]; + inputColors[3] = other.inputColors[3]; + + outputColors[0] = other.outputColors[0]; + outputColors[1] = other.outputColors[1]; + outputColors[2] = other.outputColors[2]; + outputColors[3] = other.outputColors[3]; +} + +string InstanceContext::getSpecializedFailMessage (const string& failureReason) +{ + map parameters; + parameters["reason"] = failureReason; + return StringTemplate(failMessageTemplate).specialize(parameters); +} + +ShaderElement::ShaderElement (const string& moduleName_, + const string& entryPoint_, + VkShaderStageFlagBits shaderStage_) + : moduleName(moduleName_) + , entryName(entryPoint_) + , stage(shaderStage_) +{ +} + +void getDefaultColors (RGBA (&colors)[4]) +{ + colors[0] = RGBA::white(); + colors[1] = RGBA::red(); + colors[2] = RGBA::green(); + colors[3] = RGBA::blue(); +} + +void getHalfColorsFullAlpha (RGBA (&colors)[4]) +{ + colors[0] = RGBA(127, 127, 127, 255); + colors[1] = RGBA(127, 0, 0, 255); + colors[2] = RGBA(0, 127, 0, 255); + colors[3] = RGBA(0, 0, 127, 255); +} + +void getInvertedDefaultColors (RGBA (&colors)[4]) +{ + colors[0] = RGBA(0, 0, 0, 255); + colors[1] = RGBA(0, 255, 255, 255); + colors[2] = RGBA(255, 0, 255, 255); + colors[3] = RGBA(255, 255, 0, 255); +} + +// For the current InstanceContext, constructs the required modules and shader stage create infos. +void createPipelineShaderStages (const DeviceInterface& vk, + const VkDevice vkDevice, + InstanceContext& instance, + Context& context, + vector& modules, + vector& createInfos) +{ + for (ModuleMap::const_iterator moduleNdx = instance.moduleMap.begin(); moduleNdx != instance.moduleMap.end(); ++moduleNdx) + { + const ModuleHandleSp mod(new Unique(createShaderModule(vk, vkDevice, context.getBinaryCollection().get(moduleNdx->first), 0))); + modules.push_back(ModuleHandleSp(mod)); + for (vector::const_iterator shaderNdx = moduleNdx->second.begin(); shaderNdx != moduleNdx->second.end(); ++shaderNdx) + { + const EntryToStage& stage = *shaderNdx; + const VkPipelineShaderStageCreateInfo shaderParam = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, + stage.second, // VkShaderStageFlagBits stage; + **modules.back(), // VkShaderModule module; + stage.first.c_str(), // const char* pName; + (const VkSpecializationInfo*)DE_NULL, + }; + createInfos.push_back(shaderParam); + } + } +} + +#define SPIRV_ASSEMBLY_TYPES \ + "%void = OpTypeVoid\n" \ + "%bool = OpTypeBool\n" \ + \ + "%i32 = OpTypeInt 32 1\n" \ + "%u32 = OpTypeInt 32 0\n" \ + \ + "%f32 = OpTypeFloat 32\n" \ + "%v3f32 = OpTypeVector %f32 3\n" \ + "%v4i32 = OpTypeVector %i32 4\n" \ + "%v4f32 = OpTypeVector %f32 4\n" \ + "%v4bool = OpTypeVector %bool 4\n" \ + \ + "%v4f32_function = OpTypeFunction %v4f32 %v4f32\n" \ + "%fun = OpTypeFunction %void\n" \ + \ + "%ip_f32 = OpTypePointer Input %f32\n" \ + "%ip_i32 = OpTypePointer Input %i32\n" \ + "%ip_v3f32 = OpTypePointer Input %v3f32\n" \ + "%ip_v4f32 = OpTypePointer Input %v4f32\n" \ + \ + "%op_f32 = OpTypePointer Output %f32\n" \ + "%op_v4f32 = OpTypePointer Output %v4f32\n" \ + \ + "%fp_f32 = OpTypePointer Function %f32\n" \ + "%fp_i32 = OpTypePointer Function %i32\n" \ + "%fp_v4f32 = OpTypePointer Function %v4f32\n" + +#define SPIRV_ASSEMBLY_CONSTANTS \ + "%c_f32_1 = OpConstant %f32 1.0\n" \ + "%c_f32_0 = OpConstant %f32 0.0\n" \ + "%c_f32_0_5 = OpConstant %f32 0.5\n" \ + "%c_f32_n1 = OpConstant %f32 -1.\n" \ + "%c_f32_7 = OpConstant %f32 7.0\n" \ + "%c_f32_8 = OpConstant %f32 8.0\n" \ + "%c_i32_0 = OpConstant %i32 0\n" \ + "%c_i32_1 = OpConstant %i32 1\n" \ + "%c_i32_2 = OpConstant %i32 2\n" \ + "%c_i32_3 = OpConstant %i32 3\n" \ + "%c_i32_4 = OpConstant %i32 4\n" \ + "%c_u32_0 = OpConstant %u32 0\n" \ + "%c_u32_1 = OpConstant %u32 1\n" \ + "%c_u32_2 = OpConstant %u32 2\n" \ + "%c_u32_3 = OpConstant %u32 3\n" \ + "%c_u32_32 = OpConstant %u32 32\n" \ + "%c_u32_4 = OpConstant %u32 4\n" \ + "%c_u32_31_bits = OpConstant %u32 0x7FFFFFFF\n" \ + "%c_v4f32_1_1_1_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n" \ + "%c_v4f32_1_0_0_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_1\n" \ + "%c_v4f32_0_5_0_5_0_5_0_5 = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5\n" + +#define SPIRV_ASSEMBLY_ARRAYS \ + "%a1f32 = OpTypeArray %f32 %c_u32_1\n" \ + "%a2f32 = OpTypeArray %f32 %c_u32_2\n" \ + "%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n" \ + "%a4f32 = OpTypeArray %f32 %c_u32_4\n" \ + "%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n" \ + "%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n" \ + "%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n" \ + "%op_a2f32 = OpTypePointer Output %a2f32\n" \ + "%op_a3v4f32 = OpTypePointer Output %a3v4f32\n" \ + "%op_a4f32 = OpTypePointer Output %a4f32\n" + +// Creates vertex-shader assembly by specializing a boilerplate StringTemplate +// on fragments, which must (at least) map "testfun" to an OpFunction definition +// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed +// with "BP_" to avoid collisions with fragments. +// +// It corresponds roughly to this GLSL: +//; +// layout(location = 0) in vec4 position; +// layout(location = 1) in vec4 color; +// layout(location = 1) out highp vec4 vtxColor; +// void main (void) { gl_Position = position; vtxColor = test_func(color); } +string makeVertexShaderAssembly(const map& fragments) +{ +// \todo [2015-11-23 awoloszyn] Remove OpName once these have stabalized + static const char vertexShaderBoilerplate[] = + "OpCapability Shader\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint Vertex %main \"main\" %BP_stream %BP_position %BP_vtx_color %BP_color %BP_gl_VertexIndex %BP_gl_InstanceIndex\n" + "${debug:opt}\n" + "OpName %main \"main\"\n" + "OpName %BP_gl_PerVertex \"gl_PerVertex\"\n" + "OpMemberName %BP_gl_PerVertex 0 \"gl_Position\"\n" + "OpMemberName %BP_gl_PerVertex 1 \"gl_PointSize\"\n" + "OpMemberName %BP_gl_PerVertex 2 \"gl_ClipDistance\"\n" + "OpMemberName %BP_gl_PerVertex 3 \"gl_CullDistance\"\n" + "OpName %test_code \"testfun(vf4;\"\n" + "OpName %BP_stream \"\"\n" + "OpName %BP_position \"position\"\n" + "OpName %BP_vtx_color \"vtxColor\"\n" + "OpName %BP_color \"color\"\n" + "OpName %BP_gl_VertexIndex \"gl_VertexIndex\"\n" + "OpName %BP_gl_InstanceIndex \"gl_InstanceIndex\"\n" + "OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n" + "OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n" + "OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n" + "OpDecorate %BP_gl_PerVertex Block\n" + "OpDecorate %BP_position Location 0\n" + "OpDecorate %BP_vtx_color Location 1\n" + "OpDecorate %BP_color Location 1\n" + "OpDecorate %BP_gl_VertexIndex BuiltIn VertexIndex\n" + "OpDecorate %BP_gl_InstanceIndex BuiltIn InstanceIndex\n" + "${decoration:opt}\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%BP_op_gl_PerVertex = OpTypePointer Output %BP_gl_PerVertex\n" + "%BP_stream = OpVariable %BP_op_gl_PerVertex Output\n" + "%BP_position = OpVariable %ip_v4f32 Input\n" + "%BP_vtx_color = OpVariable %op_v4f32 Output\n" + "%BP_color = OpVariable %ip_v4f32 Input\n" + "%BP_gl_VertexIndex = OpVariable %ip_i32 Input\n" + "%BP_gl_InstanceIndex = OpVariable %ip_i32 Input\n" + "${pre_main:opt}\n" + "%main = OpFunction %void None %fun\n" + "%BP_label = OpLabel\n" + "%BP_pos = OpLoad %v4f32 %BP_position\n" + "%BP_gl_pos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n" + "OpStore %BP_gl_pos %BP_pos\n" + "%BP_col = OpLoad %v4f32 %BP_color\n" + "%BP_col_transformed = OpFunctionCall %v4f32 %test_code %BP_col\n" + "OpStore %BP_vtx_color %BP_col_transformed\n" + "OpReturn\n" + "OpFunctionEnd\n" + "${testfun}\n"; + return tcu::StringTemplate(vertexShaderBoilerplate).specialize(fragments); +} + +// Creates tess-control-shader assembly by specializing a boilerplate +// StringTemplate on fragments, which must (at least) map "testfun" to an +// OpFunction definition for %test_code that takes and returns a %v4f32. +// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments. +// +// It roughly corresponds to the following GLSL. +// +// #version 450 +// layout(vertices = 3) out; +// layout(location = 1) in vec4 in_color[]; +// layout(location = 1) out vec4 out_color[]; +// +// void main() { +// out_color[gl_InvocationID] = testfun(in_color[gl_InvocationID]); +// gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; +// if (gl_InvocationID == 0) { +// gl_TessLevelOuter[0] = 1.0; +// gl_TessLevelOuter[1] = 1.0; +// gl_TessLevelOuter[2] = 1.0; +// gl_TessLevelInner[0] = 1.0; +// } +// } +string makeTessControlShaderAssembly (const map& fragments) +{ + static const char tessControlShaderBoilerplate[] = + "OpCapability Tessellation\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint TessellationControl %BP_main \"main\" %BP_out_color %BP_gl_InvocationID %BP_in_color %BP_gl_out %BP_gl_in %BP_gl_TessLevelOuter %BP_gl_TessLevelInner\n" + "OpExecutionMode %BP_main OutputVertices 3\n" + "${debug:opt}\n" + "OpName %BP_main \"main\"\n" + "OpName %test_code \"testfun(vf4;\"\n" + "OpName %BP_out_color \"out_color\"\n" + "OpName %BP_gl_InvocationID \"gl_InvocationID\"\n" + "OpName %BP_in_color \"in_color\"\n" + "OpName %BP_gl_PerVertex \"gl_PerVertex\"\n" + "OpMemberName %BP_gl_PerVertex 0 \"gl_Position\"\n" + "OpMemberName %BP_gl_PerVertex 1 \"gl_PointSize\"\n" + "OpMemberName %BP_gl_PerVertex 2 \"gl_ClipDistance\"\n" + "OpMemberName %BP_gl_PerVertex 3 \"gl_CullDistance\"\n" + "OpName %BP_gl_out \"gl_out\"\n" + "OpName %BP_gl_PVOut \"gl_PerVertex\"\n" + "OpMemberName %BP_gl_PVOut 0 \"gl_Position\"\n" + "OpMemberName %BP_gl_PVOut 1 \"gl_PointSize\"\n" + "OpMemberName %BP_gl_PVOut 2 \"gl_ClipDistance\"\n" + "OpMemberName %BP_gl_PVOut 3 \"gl_CullDistance\"\n" + "OpName %BP_gl_in \"gl_in\"\n" + "OpName %BP_gl_TessLevelOuter \"gl_TessLevelOuter\"\n" + "OpName %BP_gl_TessLevelInner \"gl_TessLevelInner\"\n" + "OpDecorate %BP_out_color Location 1\n" + "OpDecorate %BP_gl_InvocationID BuiltIn InvocationId\n" + "OpDecorate %BP_in_color Location 1\n" + "OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n" + "OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n" + "OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n" + "OpDecorate %BP_gl_PerVertex Block\n" + "OpMemberDecorate %BP_gl_PVOut 0 BuiltIn Position\n" + "OpMemberDecorate %BP_gl_PVOut 1 BuiltIn PointSize\n" + "OpMemberDecorate %BP_gl_PVOut 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %BP_gl_PVOut 3 BuiltIn CullDistance\n" + "OpDecorate %BP_gl_PVOut Block\n" + "OpDecorate %BP_gl_TessLevelOuter Patch\n" + "OpDecorate %BP_gl_TessLevelOuter BuiltIn TessLevelOuter\n" + "OpDecorate %BP_gl_TessLevelInner Patch\n" + "OpDecorate %BP_gl_TessLevelInner BuiltIn TessLevelInner\n" + "${decoration:opt}\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%BP_out_color = OpVariable %op_a3v4f32 Output\n" + "%BP_gl_InvocationID = OpVariable %ip_i32 Input\n" + "%BP_in_color = OpVariable %ip_a32v4f32 Input\n" + "%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%BP_a3_gl_PerVertex = OpTypeArray %BP_gl_PerVertex %c_u32_3\n" + "%BP_op_a3_gl_PerVertex = OpTypePointer Output %BP_a3_gl_PerVertex\n" + "%BP_gl_out = OpVariable %BP_op_a3_gl_PerVertex Output\n" + "%BP_gl_PVOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%BP_a32_gl_PVOut = OpTypeArray %BP_gl_PVOut %c_u32_32\n" + "%BP_ip_a32_gl_PVOut = OpTypePointer Input %BP_a32_gl_PVOut\n" + "%BP_gl_in = OpVariable %BP_ip_a32_gl_PVOut Input\n" + "%BP_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" + "%BP_gl_TessLevelInner = OpVariable %op_a2f32 Output\n" + "${pre_main:opt}\n" + + "%BP_main = OpFunction %void None %fun\n" + "%BP_label = OpLabel\n" + + "%BP_gl_Invoc = OpLoad %i32 %BP_gl_InvocationID\n" + + "%BP_in_col_loc = OpAccessChain %ip_v4f32 %BP_in_color %BP_gl_Invoc\n" + "%BP_out_col_loc = OpAccessChain %op_v4f32 %BP_out_color %BP_gl_Invoc\n" + "%BP_in_col_val = OpLoad %v4f32 %BP_in_col_loc\n" + "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_in_col_val\n" + "OpStore %BP_out_col_loc %BP_clr_transformed\n" + + "%BP_in_pos_loc = OpAccessChain %ip_v4f32 %BP_gl_in %BP_gl_Invoc %c_i32_0\n" + "%BP_out_pos_loc = OpAccessChain %op_v4f32 %BP_gl_out %BP_gl_Invoc %c_i32_0\n" + "%BP_in_pos_val = OpLoad %v4f32 %BP_in_pos_loc\n" + "OpStore %BP_out_pos_loc %BP_in_pos_val\n" + + "%BP_cmp = OpIEqual %bool %BP_gl_Invoc %c_i32_0\n" + "OpSelectionMerge %BP_merge_label None\n" + "OpBranchConditional %BP_cmp %BP_if_label %BP_merge_label\n" + "%BP_if_label = OpLabel\n" + "%BP_gl_TessLevelOuterPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_0\n" + "%BP_gl_TessLevelOuterPos_1 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_1\n" + "%BP_gl_TessLevelOuterPos_2 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_2\n" + "%BP_gl_TessLevelInnerPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelInner %c_i32_0\n" + "OpStore %BP_gl_TessLevelOuterPos_0 %c_f32_1\n" + "OpStore %BP_gl_TessLevelOuterPos_1 %c_f32_1\n" + "OpStore %BP_gl_TessLevelOuterPos_2 %c_f32_1\n" + "OpStore %BP_gl_TessLevelInnerPos_0 %c_f32_1\n" + "OpBranch %BP_merge_label\n" + "%BP_merge_label = OpLabel\n" + "OpReturn\n" + "OpFunctionEnd\n" + "${testfun}\n"; + return tcu::StringTemplate(tessControlShaderBoilerplate).specialize(fragments); +} + +// Creates tess-evaluation-shader assembly by specializing a boilerplate +// StringTemplate on fragments, which must (at least) map "testfun" to an +// OpFunction definition for %test_code that takes and returns a %v4f32. +// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments. +// +// It roughly corresponds to the following glsl. +// +// #version 450 +// +// layout(triangles, equal_spacing, ccw) in; +// layout(location = 1) in vec4 in_color[]; +// layout(location = 1) out vec4 out_color; +// +// #define interpolate(val) +// vec4(gl_TessCoord.x) * val[0] + vec4(gl_TessCoord.y) * val[1] + +// vec4(gl_TessCoord.z) * val[2] +// +// void main() { +// gl_Position = vec4(gl_TessCoord.x) * gl_in[0].gl_Position + +// vec4(gl_TessCoord.y) * gl_in[1].gl_Position + +// vec4(gl_TessCoord.z) * gl_in[2].gl_Position; +// out_color = testfun(interpolate(in_color)); +// } +string makeTessEvalShaderAssembly(const map& fragments) +{ + static const char tessEvalBoilerplate[] = + "OpCapability Tessellation\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint TessellationEvaluation %BP_main \"main\" %BP_stream %BP_gl_TessCoord %BP_gl_in %BP_out_color %BP_in_color\n" + "OpExecutionMode %BP_main Triangles\n" + "OpExecutionMode %BP_main SpacingEqual\n" + "OpExecutionMode %BP_main VertexOrderCcw\n" + "${debug:opt}\n" + "OpName %BP_main \"main\"\n" + "OpName %test_code \"testfun(vf4;\"\n" + "OpName %BP_gl_PerVertexOut \"gl_PerVertex\"\n" + "OpMemberName %BP_gl_PerVertexOut 0 \"gl_Position\"\n" + "OpMemberName %BP_gl_PerVertexOut 1 \"gl_PointSize\"\n" + "OpMemberName %BP_gl_PerVertexOut 2 \"gl_ClipDistance\"\n" + "OpMemberName %BP_gl_PerVertexOut 3 \"gl_CullDistance\"\n" + "OpName %BP_stream \"\"\n" + "OpName %BP_gl_TessCoord \"gl_TessCoord\"\n" + "OpName %BP_gl_PerVertexIn \"gl_PerVertex\"\n" + "OpMemberName %BP_gl_PerVertexIn 0 \"gl_Position\"\n" + "OpMemberName %BP_gl_PerVertexIn 1 \"gl_PointSize\"\n" + "OpMemberName %BP_gl_PerVertexIn 2 \"gl_ClipDistance\"\n" + "OpMemberName %BP_gl_PerVertexIn 3 \"gl_CullDistance\"\n" + "OpName %BP_gl_in \"gl_in\"\n" + "OpName %BP_out_color \"out_color\"\n" + "OpName %BP_in_color \"in_color\"\n" + "OpMemberDecorate %BP_gl_PerVertexOut 0 BuiltIn Position\n" + "OpMemberDecorate %BP_gl_PerVertexOut 1 BuiltIn PointSize\n" + "OpMemberDecorate %BP_gl_PerVertexOut 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %BP_gl_PerVertexOut 3 BuiltIn CullDistance\n" + "OpDecorate %BP_gl_PerVertexOut Block\n" + "OpDecorate %BP_gl_TessCoord BuiltIn TessCoord\n" + "OpMemberDecorate %BP_gl_PerVertexIn 0 BuiltIn Position\n" + "OpMemberDecorate %BP_gl_PerVertexIn 1 BuiltIn PointSize\n" + "OpMemberDecorate %BP_gl_PerVertexIn 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %BP_gl_PerVertexIn 3 BuiltIn CullDistance\n" + "OpDecorate %BP_gl_PerVertexIn Block\n" + "OpDecorate %BP_out_color Location 1\n" + "OpDecorate %BP_in_color Location 1\n" + "${decoration:opt}\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%BP_gl_PerVertexOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%BP_op_gl_PerVertexOut = OpTypePointer Output %BP_gl_PerVertexOut\n" + "%BP_stream = OpVariable %BP_op_gl_PerVertexOut Output\n" + "%BP_gl_TessCoord = OpVariable %ip_v3f32 Input\n" + "%BP_gl_PerVertexIn = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%BP_a32_gl_PerVertexIn = OpTypeArray %BP_gl_PerVertexIn %c_u32_32\n" + "%BP_ip_a32_gl_PerVertexIn = OpTypePointer Input %BP_a32_gl_PerVertexIn\n" + "%BP_gl_in = OpVariable %BP_ip_a32_gl_PerVertexIn Input\n" + "%BP_out_color = OpVariable %op_v4f32 Output\n" + "%BP_in_color = OpVariable %ip_a32v4f32 Input\n" + "${pre_main:opt}\n" + "%BP_main = OpFunction %void None %fun\n" + "%BP_label = OpLabel\n" + "%BP_gl_TC_0 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_0\n" + "%BP_gl_TC_1 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_1\n" + "%BP_gl_TC_2 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_2\n" + "%BP_gl_in_gl_Pos_0 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n" + "%BP_gl_in_gl_Pos_1 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n" + "%BP_gl_in_gl_Pos_2 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n" + + "%BP_gl_OPos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n" + "%BP_in_color_0 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n" + "%BP_in_color_1 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n" + "%BP_in_color_2 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n" + + "%BP_TC_W_0 = OpLoad %f32 %BP_gl_TC_0\n" + "%BP_TC_W_1 = OpLoad %f32 %BP_gl_TC_1\n" + "%BP_TC_W_2 = OpLoad %f32 %BP_gl_TC_2\n" + "%BP_v4f32_TC_0 = OpCompositeConstruct %v4f32 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0\n" + "%BP_v4f32_TC_1 = OpCompositeConstruct %v4f32 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1\n" + "%BP_v4f32_TC_2 = OpCompositeConstruct %v4f32 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2\n" + + "%BP_gl_IP_0 = OpLoad %v4f32 %BP_gl_in_gl_Pos_0\n" + "%BP_gl_IP_1 = OpLoad %v4f32 %BP_gl_in_gl_Pos_1\n" + "%BP_gl_IP_2 = OpLoad %v4f32 %BP_gl_in_gl_Pos_2\n" + + "%BP_IP_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_gl_IP_0\n" + "%BP_IP_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_gl_IP_1\n" + "%BP_IP_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_gl_IP_2\n" + + "%BP_pos_sum_0 = OpFAdd %v4f32 %BP_IP_W_0 %BP_IP_W_1\n" + "%BP_pos_sum_1 = OpFAdd %v4f32 %BP_pos_sum_0 %BP_IP_W_2\n" + + "OpStore %BP_gl_OPos %BP_pos_sum_1\n" + + "%BP_IC_0 = OpLoad %v4f32 %BP_in_color_0\n" + "%BP_IC_1 = OpLoad %v4f32 %BP_in_color_1\n" + "%BP_IC_2 = OpLoad %v4f32 %BP_in_color_2\n" + + "%BP_IC_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_IC_0\n" + "%BP_IC_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_IC_1\n" + "%BP_IC_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_IC_2\n" + + "%BP_col_sum_0 = OpFAdd %v4f32 %BP_IC_W_0 %BP_IC_W_1\n" + "%BP_col_sum_1 = OpFAdd %v4f32 %BP_col_sum_0 %BP_IC_W_2\n" + + "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_col_sum_1\n" + + "OpStore %BP_out_color %BP_clr_transformed\n" + "OpReturn\n" + "OpFunctionEnd\n" + "${testfun}\n"; + return tcu::StringTemplate(tessEvalBoilerplate).specialize(fragments); +} + +// Creates geometry-shader assembly by specializing a boilerplate StringTemplate +// on fragments, which must (at least) map "testfun" to an OpFunction definition +// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed +// with "BP_" to avoid collisions with fragments. +// +// Derived from this GLSL: +// +// #version 450 +// layout(triangles) in; +// layout(triangle_strip, max_vertices = 3) out; +// +// layout(location = 1) in vec4 in_color[]; +// layout(location = 1) out vec4 out_color; +// +// void main() { +// gl_Position = gl_in[0].gl_Position; +// out_color = test_fun(in_color[0]); +// EmitVertex(); +// gl_Position = gl_in[1].gl_Position; +// out_color = test_fun(in_color[1]); +// EmitVertex(); +// gl_Position = gl_in[2].gl_Position; +// out_color = test_fun(in_color[2]); +// EmitVertex(); +// EndPrimitive(); +// } +string makeGeometryShaderAssembly(const map& fragments) +{ + static const char geometryShaderBoilerplate[] = + "OpCapability Geometry\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint Geometry %BP_main \"main\" %BP_out_gl_position %BP_gl_in %BP_out_color %BP_in_color\n" + "OpExecutionMode %BP_main Triangles\n" + "OpExecutionMode %BP_main OutputTriangleStrip\n" + "OpExecutionMode %BP_main OutputVertices 3\n" + "${debug:opt}\n" + "OpName %BP_main \"main\"\n" + "OpName %BP_per_vertex_in \"gl_PerVertex\"\n" + "OpMemberName %BP_per_vertex_in 0 \"gl_Position\"\n" + "OpMemberName %BP_per_vertex_in 1 \"gl_PointSize\"\n" + "OpMemberName %BP_per_vertex_in 2 \"gl_ClipDistance\"\n" + "OpMemberName %BP_per_vertex_in 3 \"gl_CullDistance\"\n" + "OpName %BP_gl_in \"gl_in\"\n" + "OpName %BP_out_color \"out_color\"\n" + "OpName %BP_in_color \"in_color\"\n" + "OpName %test_code \"testfun(vf4;\"\n" + "OpDecorate %BP_out_gl_position BuiltIn Position\n" + "OpMemberDecorate %BP_per_vertex_in 0 BuiltIn Position\n" + "OpMemberDecorate %BP_per_vertex_in 1 BuiltIn PointSize\n" + "OpMemberDecorate %BP_per_vertex_in 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %BP_per_vertex_in 3 BuiltIn CullDistance\n" + "OpDecorate %BP_per_vertex_in Block\n" + "OpDecorate %BP_out_color Location 1\n" + "OpDecorate %BP_in_color Location 1\n" + "${decoration:opt}\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%BP_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%BP_a3_per_vertex_in = OpTypeArray %BP_per_vertex_in %c_u32_3\n" + "%BP_ip_a3_per_vertex_in = OpTypePointer Input %BP_a3_per_vertex_in\n" + + "%BP_gl_in = OpVariable %BP_ip_a3_per_vertex_in Input\n" + "%BP_out_color = OpVariable %op_v4f32 Output\n" + "%BP_in_color = OpVariable %ip_a3v4f32 Input\n" + "%BP_out_gl_position = OpVariable %op_v4f32 Output\n" + "${pre_main:opt}\n" + + "%BP_main = OpFunction %void None %fun\n" + "%BP_label = OpLabel\n" + "%BP_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n" + "%BP_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n" + "%BP_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n" + + "%BP_in_position_0 = OpLoad %v4f32 %BP_gl_in_0_gl_position\n" + "%BP_in_position_1 = OpLoad %v4f32 %BP_gl_in_1_gl_position\n" + "%BP_in_position_2 = OpLoad %v4f32 %BP_gl_in_2_gl_position \n" + + "%BP_in_color_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n" + "%BP_in_color_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n" + "%BP_in_color_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n" + + "%BP_in_color_0 = OpLoad %v4f32 %BP_in_color_0_ptr\n" + "%BP_in_color_1 = OpLoad %v4f32 %BP_in_color_1_ptr\n" + "%BP_in_color_2 = OpLoad %v4f32 %BP_in_color_2_ptr\n" + + "%BP_transformed_in_color_0 = OpFunctionCall %v4f32 %test_code %BP_in_color_0\n" + "%BP_transformed_in_color_1 = OpFunctionCall %v4f32 %test_code %BP_in_color_1\n" + "%BP_transformed_in_color_2 = OpFunctionCall %v4f32 %test_code %BP_in_color_2\n" + + + "OpStore %BP_out_gl_position %BP_in_position_0\n" + "OpStore %BP_out_color %BP_transformed_in_color_0\n" + "OpEmitVertex\n" + + "OpStore %BP_out_gl_position %BP_in_position_1\n" + "OpStore %BP_out_color %BP_transformed_in_color_1\n" + "OpEmitVertex\n" + + "OpStore %BP_out_gl_position %BP_in_position_2\n" + "OpStore %BP_out_color %BP_transformed_in_color_2\n" + "OpEmitVertex\n" + + "OpEndPrimitive\n" + "OpReturn\n" + "OpFunctionEnd\n" + "${testfun}\n"; + return tcu::StringTemplate(geometryShaderBoilerplate).specialize(fragments); +} + +// Creates fragment-shader assembly by specializing a boilerplate StringTemplate +// on fragments, which must (at least) map "testfun" to an OpFunction definition +// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed +// with "BP_" to avoid collisions with fragments. +// +// Derived from this GLSL: +// +// layout(location = 1) in highp vec4 vtxColor; +// layout(location = 0) out highp vec4 fragColor; +// highp vec4 testfun(highp vec4 x) { return x; } +// void main(void) { fragColor = testfun(vtxColor); } +// +// with modifications including passing vtxColor by value and ripping out +// testfun() definition. +string makeFragmentShaderAssembly(const map& fragments) +{ + static const char fragmentShaderBoilerplate[] = + "OpCapability Shader\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint Fragment %BP_main \"main\" %BP_vtxColor %BP_fragColor\n" + "OpExecutionMode %BP_main OriginUpperLeft\n" + "${debug:opt}\n" + "OpName %BP_main \"main\"\n" + "OpName %BP_fragColor \"fragColor\"\n" + "OpName %BP_vtxColor \"vtxColor\"\n" + "OpName %test_code \"testfun(vf4;\"\n" + "OpDecorate %BP_fragColor Location 0\n" + "OpDecorate %BP_vtxColor Location 1\n" + "${decoration:opt}\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%BP_fragColor = OpVariable %op_v4f32 Output\n" + "%BP_vtxColor = OpVariable %ip_v4f32 Input\n" + "${pre_main:opt}\n" + "%BP_main = OpFunction %void None %fun\n" + "%BP_label_main = OpLabel\n" + "%BP_tmp1 = OpLoad %v4f32 %BP_vtxColor\n" + "%BP_tmp2 = OpFunctionCall %v4f32 %test_code %BP_tmp1\n" + "OpStore %BP_fragColor %BP_tmp2\n" + "OpReturn\n" + "OpFunctionEnd\n" + "${testfun}\n"; + return tcu::StringTemplate(fragmentShaderBoilerplate).specialize(fragments); +} + +map passthruFragments(void) +{ + map fragments; + fragments["testfun"] = + // A %test_code function that returns its argument unchanged. + "%test_code = OpFunction %v4f32 None %v4f32_function\n" + "%param1 = OpFunctionParameter %v4f32\n" + "%label_testfun = OpLabel\n" + "OpReturnValue %param1\n" + "OpFunctionEnd\n"; + return fragments; +} + +// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. +// Vertex shader gets custom code from context, the rest are pass-through. +void addShaderCodeCustomVertex(vk::SourceCollections& dst, InstanceContext context) +{ + map passthru = passthruFragments(); + dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(context.testCodeFragments); + dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); +} + +// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. +// Tessellation control shader gets custom code from context, the rest are +// pass-through. +void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext context) +{ + map passthru = passthruFragments(); + dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); + dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(context.testCodeFragments); + dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru); + dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); +} + +// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. +// Tessellation evaluation shader gets custom code from context, the rest are +// pass-through. +void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext context) +{ + map passthru = passthruFragments(); + dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); + dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru); + dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(context.testCodeFragments); + dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); +} + +// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. +// Geometry shader gets custom code from context, the rest are pass-through. +void addShaderCodeCustomGeometry(vk::SourceCollections& dst, InstanceContext context) +{ + map passthru = passthruFragments(); + dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); + dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(context.testCodeFragments); + dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); +} + +// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. +// Fragment shader gets custom code from context, the rest are pass-through. +void addShaderCodeCustomFragment(vk::SourceCollections& dst, InstanceContext context) +{ + map passthru = passthruFragments(); + dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); + dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(context.testCodeFragments); +} + +void createCombinedModule(vk::SourceCollections& dst, InstanceContext) +{ + // \todo [2015-12-07 awoloszyn] Make tessellation / geometry conditional + // \todo [2015-12-07 awoloszyn] Remove OpName and OpMemberName at some point + dst.spirvAsmSources.add("module") << + "OpCapability Shader\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "OpCapability Geometry\n" + "OpCapability Tessellation\n" + "OpMemoryModel Logical GLSL450\n" + + "OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_vtxPosition %vert_vertex_id %vert_instance_id\n" + "OpEntryPoint Geometry %geom_main \"main\" %geom_out_gl_position %geom_gl_in %geom_out_color %geom_in_color\n" + "OpEntryPoint TessellationControl %tessc_main \"main\" %tessc_out_color %tessc_gl_InvocationID %tessc_in_color %tessc_out_position %tessc_in_position %tessc_gl_TessLevelOuter %tessc_gl_TessLevelInner\n" + "OpEntryPoint TessellationEvaluation %tesse_main \"main\" %tesse_stream %tesse_gl_tessCoord %tesse_in_position %tesse_out_color %tesse_in_color \n" + "OpEntryPoint Fragment %frag_main \"main\" %frag_vtxColor %frag_fragColor\n" + + "OpExecutionMode %geom_main Triangles\n" + "OpExecutionMode %geom_main OutputTriangleStrip\n" + "OpExecutionMode %geom_main OutputVertices 3\n" + + "OpExecutionMode %tessc_main OutputVertices 3\n" + + "OpExecutionMode %tesse_main Triangles\n" + "OpExecutionMode %tesse_main SpacingEqual\n" + "OpExecutionMode %tesse_main VertexOrderCcw\n" + + "OpExecutionMode %frag_main OriginUpperLeft\n" + + "OpName %vert_main \"main\"\n" + "OpName %vert_vtxPosition \"vtxPosition\"\n" + "OpName %vert_Position \"position\"\n" + "OpName %vert_vtxColor \"vtxColor\"\n" + "OpName %vert_color \"color\"\n" + "OpName %vert_vertex_id \"gl_VertexIndex\"\n" + "OpName %vert_instance_id \"gl_InstanceIndex\"\n" + "OpName %geom_main \"main\"\n" + "OpName %geom_per_vertex_in \"gl_PerVertex\"\n" + "OpMemberName %geom_per_vertex_in 0 \"gl_Position\"\n" + "OpMemberName %geom_per_vertex_in 1 \"gl_PointSize\"\n" + "OpMemberName %geom_per_vertex_in 2 \"gl_ClipDistance\"\n" + "OpMemberName %geom_per_vertex_in 3 \"gl_CullDistance\"\n" + "OpName %geom_gl_in \"gl_in\"\n" + "OpName %geom_out_color \"out_color\"\n" + "OpName %geom_in_color \"in_color\"\n" + "OpName %tessc_main \"main\"\n" + "OpName %tessc_out_color \"out_color\"\n" + "OpName %tessc_gl_InvocationID \"gl_InvocationID\"\n" + "OpName %tessc_in_color \"in_color\"\n" + "OpName %tessc_out_position \"out_position\"\n" + "OpName %tessc_in_position \"in_position\"\n" + "OpName %tessc_gl_TessLevelOuter \"gl_TessLevelOuter\"\n" + "OpName %tessc_gl_TessLevelInner \"gl_TessLevelInner\"\n" + "OpName %tesse_main \"main\"\n" + "OpName %tesse_per_vertex_out \"gl_PerVertex\"\n" + "OpMemberName %tesse_per_vertex_out 0 \"gl_Position\"\n" + "OpMemberName %tesse_per_vertex_out 1 \"gl_PointSize\"\n" + "OpMemberName %tesse_per_vertex_out 2 \"gl_ClipDistance\"\n" + "OpMemberName %tesse_per_vertex_out 3 \"gl_CullDistance\"\n" + "OpName %tesse_stream \"\"\n" + "OpName %tesse_gl_tessCoord \"gl_TessCoord\"\n" + "OpName %tesse_in_position \"in_position\"\n" + "OpName %tesse_out_color \"out_color\"\n" + "OpName %tesse_in_color \"in_color\"\n" + "OpName %frag_main \"main\"\n" + "OpName %frag_fragColor \"fragColor\"\n" + "OpName %frag_vtxColor \"vtxColor\"\n" + + "; Vertex decorations\n" + "OpDecorate %vert_vtxPosition Location 2\n" + "OpDecorate %vert_Position Location 0\n" + "OpDecorate %vert_vtxColor Location 1\n" + "OpDecorate %vert_color Location 1\n" + "OpDecorate %vert_vertex_id BuiltIn VertexIndex\n" + "OpDecorate %vert_instance_id BuiltIn InstanceIndex\n" + + "; Geometry decorations\n" + "OpDecorate %geom_out_gl_position BuiltIn Position\n" + "OpMemberDecorate %geom_per_vertex_in 0 BuiltIn Position\n" + "OpMemberDecorate %geom_per_vertex_in 1 BuiltIn PointSize\n" + "OpMemberDecorate %geom_per_vertex_in 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %geom_per_vertex_in 3 BuiltIn CullDistance\n" + "OpDecorate %geom_per_vertex_in Block\n" + "OpDecorate %geom_out_color Location 1\n" + "OpDecorate %geom_in_color Location 1\n" + + "; Tessellation Control decorations\n" + "OpDecorate %tessc_out_color Location 1\n" + "OpDecorate %tessc_gl_InvocationID BuiltIn InvocationId\n" + "OpDecorate %tessc_in_color Location 1\n" + "OpDecorate %tessc_out_position Location 2\n" + "OpDecorate %tessc_in_position Location 2\n" + "OpDecorate %tessc_gl_TessLevelOuter Patch\n" + "OpDecorate %tessc_gl_TessLevelOuter BuiltIn TessLevelOuter\n" + "OpDecorate %tessc_gl_TessLevelInner Patch\n" + "OpDecorate %tessc_gl_TessLevelInner BuiltIn TessLevelInner\n" + + "; Tessellation Evaluation decorations\n" + "OpMemberDecorate %tesse_per_vertex_out 0 BuiltIn Position\n" + "OpMemberDecorate %tesse_per_vertex_out 1 BuiltIn PointSize\n" + "OpMemberDecorate %tesse_per_vertex_out 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %tesse_per_vertex_out 3 BuiltIn CullDistance\n" + "OpDecorate %tesse_per_vertex_out Block\n" + "OpDecorate %tesse_gl_tessCoord BuiltIn TessCoord\n" + "OpDecorate %tesse_in_position Location 2\n" + "OpDecorate %tesse_out_color Location 1\n" + "OpDecorate %tesse_in_color Location 1\n" + + "; Fragment decorations\n" + "OpDecorate %frag_fragColor Location 0\n" + "OpDecorate %frag_vtxColor Location 1\n" + + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + + "; Vertex Variables\n" + "%vert_vtxPosition = OpVariable %op_v4f32 Output\n" + "%vert_Position = OpVariable %ip_v4f32 Input\n" + "%vert_vtxColor = OpVariable %op_v4f32 Output\n" + "%vert_color = OpVariable %ip_v4f32 Input\n" + "%vert_vertex_id = OpVariable %ip_i32 Input\n" + "%vert_instance_id = OpVariable %ip_i32 Input\n" + + "; Geometry Variables\n" + "%geom_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%geom_a3_per_vertex_in = OpTypeArray %geom_per_vertex_in %c_u32_3\n" + "%geom_ip_a3_per_vertex_in = OpTypePointer Input %geom_a3_per_vertex_in\n" + "%geom_gl_in = OpVariable %geom_ip_a3_per_vertex_in Input\n" + "%geom_out_color = OpVariable %op_v4f32 Output\n" + "%geom_in_color = OpVariable %ip_a3v4f32 Input\n" + "%geom_out_gl_position = OpVariable %op_v4f32 Output\n" + + "; Tessellation Control Variables\n" + "%tessc_out_color = OpVariable %op_a3v4f32 Output\n" + "%tessc_gl_InvocationID = OpVariable %ip_i32 Input\n" + "%tessc_in_color = OpVariable %ip_a32v4f32 Input\n" + "%tessc_out_position = OpVariable %op_a3v4f32 Output\n" + "%tessc_in_position = OpVariable %ip_a32v4f32 Input\n" + "%tessc_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" + "%tessc_gl_TessLevelInner = OpVariable %op_a2f32 Output\n" + + "; Tessellation Evaluation Decorations\n" + "%tesse_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%tesse_op_per_vertex_out = OpTypePointer Output %tesse_per_vertex_out\n" + "%tesse_stream = OpVariable %tesse_op_per_vertex_out Output\n" + "%tesse_gl_tessCoord = OpVariable %ip_v3f32 Input\n" + "%tesse_in_position = OpVariable %ip_a32v4f32 Input\n" + "%tesse_out_color = OpVariable %op_v4f32 Output\n" + "%tesse_in_color = OpVariable %ip_a32v4f32 Input\n" + + "; Fragment Variables\n" + "%frag_fragColor = OpVariable %op_v4f32 Output\n" + "%frag_vtxColor = OpVariable %ip_v4f32 Input\n" + + "; Vertex Entry\n" + "%vert_main = OpFunction %void None %fun\n" + "%vert_label = OpLabel\n" + "%vert_tmp_position = OpLoad %v4f32 %vert_Position\n" + "OpStore %vert_vtxPosition %vert_tmp_position\n" + "%vert_tmp_color = OpLoad %v4f32 %vert_color\n" + "OpStore %vert_vtxColor %vert_tmp_color\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "; Geometry Entry\n" + "%geom_main = OpFunction %void None %fun\n" + "%geom_label = OpLabel\n" + "%geom_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_0 %c_i32_0\n" + "%geom_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_1 %c_i32_0\n" + "%geom_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_2 %c_i32_0\n" + "%geom_in_position_0 = OpLoad %v4f32 %geom_gl_in_0_gl_position\n" + "%geom_in_position_1 = OpLoad %v4f32 %geom_gl_in_1_gl_position\n" + "%geom_in_position_2 = OpLoad %v4f32 %geom_gl_in_2_gl_position \n" + "%geom_in_color_0_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_0\n" + "%geom_in_color_1_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_1\n" + "%geom_in_color_2_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_2\n" + "%geom_in_color_0 = OpLoad %v4f32 %geom_in_color_0_ptr\n" + "%geom_in_color_1 = OpLoad %v4f32 %geom_in_color_1_ptr\n" + "%geom_in_color_2 = OpLoad %v4f32 %geom_in_color_2_ptr\n" + "OpStore %geom_out_gl_position %geom_in_position_0\n" + "OpStore %geom_out_color %geom_in_color_0\n" + "OpEmitVertex\n" + "OpStore %geom_out_gl_position %geom_in_position_1\n" + "OpStore %geom_out_color %geom_in_color_1\n" + "OpEmitVertex\n" + "OpStore %geom_out_gl_position %geom_in_position_2\n" + "OpStore %geom_out_color %geom_in_color_2\n" + "OpEmitVertex\n" + "OpEndPrimitive\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "; Tessellation Control Entry\n" + "%tessc_main = OpFunction %void None %fun\n" + "%tessc_label = OpLabel\n" + "%tessc_invocation_id = OpLoad %i32 %tessc_gl_InvocationID\n" + "%tessc_in_color_ptr = OpAccessChain %ip_v4f32 %tessc_in_color %tessc_invocation_id\n" + "%tessc_in_position_ptr = OpAccessChain %ip_v4f32 %tessc_in_position %tessc_invocation_id\n" + "%tessc_in_color_val = OpLoad %v4f32 %tessc_in_color_ptr\n" + "%tessc_in_position_val = OpLoad %v4f32 %tessc_in_position_ptr\n" + "%tessc_out_color_ptr = OpAccessChain %op_v4f32 %tessc_out_color %tessc_invocation_id\n" + "%tessc_out_position_ptr = OpAccessChain %op_v4f32 %tessc_out_position %tessc_invocation_id\n" + "OpStore %tessc_out_color_ptr %tessc_in_color_val\n" + "OpStore %tessc_out_position_ptr %tessc_in_position_val\n" + "%tessc_is_first_invocation = OpIEqual %bool %tessc_invocation_id %c_i32_0\n" + "OpSelectionMerge %tessc_merge_label None\n" + "OpBranchConditional %tessc_is_first_invocation %tessc_first_invocation %tessc_merge_label\n" + "%tessc_first_invocation = OpLabel\n" + "%tessc_tess_outer_0 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_0\n" + "%tessc_tess_outer_1 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_1\n" + "%tessc_tess_outer_2 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_2\n" + "%tessc_tess_inner = OpAccessChain %op_f32 %tessc_gl_TessLevelInner %c_i32_0\n" + "OpStore %tessc_tess_outer_0 %c_f32_1\n" + "OpStore %tessc_tess_outer_1 %c_f32_1\n" + "OpStore %tessc_tess_outer_2 %c_f32_1\n" + "OpStore %tessc_tess_inner %c_f32_1\n" + "OpBranch %tessc_merge_label\n" + "%tessc_merge_label = OpLabel\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "; Tessellation Evaluation Entry\n" + "%tesse_main = OpFunction %void None %fun\n" + "%tesse_label = OpLabel\n" + "%tesse_tc_0_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_0\n" + "%tesse_tc_1_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_1\n" + "%tesse_tc_2_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_2\n" + "%tesse_tc_0 = OpLoad %f32 %tesse_tc_0_ptr\n" + "%tesse_tc_1 = OpLoad %f32 %tesse_tc_1_ptr\n" + "%tesse_tc_2 = OpLoad %f32 %tesse_tc_2_ptr\n" + "%tesse_in_pos_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_0\n" + "%tesse_in_pos_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_1\n" + "%tesse_in_pos_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_2\n" + "%tesse_in_pos_0 = OpLoad %v4f32 %tesse_in_pos_0_ptr\n" + "%tesse_in_pos_1 = OpLoad %v4f32 %tesse_in_pos_1_ptr\n" + "%tesse_in_pos_2 = OpLoad %v4f32 %tesse_in_pos_2_ptr\n" + "%tesse_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_0 %tesse_tc_0\n" + "%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_1 %tesse_tc_1\n" + "%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_2 %tesse_tc_2\n" + "%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n" + "%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n" + "%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n" + "OpStore %tesse_out_pos_ptr %tesse_computed_out\n" + "%tesse_in_clr_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_0\n" + "%tesse_in_clr_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_1\n" + "%tesse_in_clr_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_2\n" + "%tesse_in_clr_0 = OpLoad %v4f32 %tesse_in_clr_0_ptr\n" + "%tesse_in_clr_1 = OpLoad %v4f32 %tesse_in_clr_1_ptr\n" + "%tesse_in_clr_2 = OpLoad %v4f32 %tesse_in_clr_2_ptr\n" + "%tesse_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_0 %tesse_tc_0\n" + "%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_1 %tesse_tc_1\n" + "%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_2 %tesse_tc_2\n" + "%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n" + "%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n" + "OpStore %tesse_out_color %tesse_computed_clr\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "; Fragment Entry\n" + "%frag_main = OpFunction %void None %fun\n" + "%frag_label_main = OpLabel\n" + "%frag_tmp1 = OpLoad %v4f32 %frag_vtxColor\n" + "OpStore %frag_fragColor %frag_tmp1\n" + "OpReturn\n" + "OpFunctionEnd\n"; +} + +void createMultipleEntries(vk::SourceCollections& dst, InstanceContext) +{ + dst.spirvAsmSources.add("vert") << + // This module contains 2 vertex shaders. One that is a passthrough + // and a second that inverts the color of the output (1.0 - color). + "OpCapability Shader\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint Vertex %main \"vert1\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n" + "OpEntryPoint Vertex %main2 \"vert2\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n" + + "OpName %main \"vert1\"\n" + "OpName %main2 \"vert2\"\n" + "OpName %vtxPosition \"vtxPosition\"\n" + "OpName %Position \"position\"\n" + "OpName %vtxColor \"vtxColor\"\n" + "OpName %color \"color\"\n" + "OpName %vertex_id \"gl_VertexIndex\"\n" + "OpName %instance_id \"gl_InstanceIndex\"\n" + + "OpDecorate %vtxPosition Location 2\n" + "OpDecorate %Position Location 0\n" + "OpDecorate %vtxColor Location 1\n" + "OpDecorate %color Location 1\n" + "OpDecorate %vertex_id BuiltIn VertexIndex\n" + "OpDecorate %instance_id BuiltIn InstanceIndex\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" + "%vtxPosition = OpVariable %op_v4f32 Output\n" + "%Position = OpVariable %ip_v4f32 Input\n" + "%vtxColor = OpVariable %op_v4f32 Output\n" + "%color = OpVariable %ip_v4f32 Input\n" + "%vertex_id = OpVariable %ip_i32 Input\n" + "%instance_id = OpVariable %ip_i32 Input\n" + + "%main = OpFunction %void None %fun\n" + "%label = OpLabel\n" + "%tmp_position = OpLoad %v4f32 %Position\n" + "OpStore %vtxPosition %tmp_position\n" + "%tmp_color = OpLoad %v4f32 %color\n" + "OpStore %vtxColor %tmp_color\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "%main2 = OpFunction %void None %fun\n" + "%label2 = OpLabel\n" + "%tmp_position2 = OpLoad %v4f32 %Position\n" + "OpStore %vtxPosition %tmp_position2\n" + "%tmp_color2 = OpLoad %v4f32 %color\n" + "%tmp_color3 = OpFSub %v4f32 %cval %tmp_color2\n" + "%tmp_color4 = OpVectorInsertDynamic %v4f32 %tmp_color3 %c_f32_1 %c_i32_3\n" + "OpStore %vtxColor %tmp_color4\n" + "OpReturn\n" + "OpFunctionEnd\n"; + + dst.spirvAsmSources.add("frag") << + // This is a single module that contains 2 fragment shaders. + // One that passes color through and the other that inverts the output + // color (1.0 - color). + "OpCapability Shader\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint Fragment %main \"frag1\" %vtxColor %fragColor\n" + "OpEntryPoint Fragment %main2 \"frag2\" %vtxColor %fragColor\n" + "OpExecutionMode %main OriginUpperLeft\n" + "OpExecutionMode %main2 OriginUpperLeft\n" + + "OpName %main \"frag1\"\n" + "OpName %main2 \"frag2\"\n" + "OpName %fragColor \"fragColor\"\n" + "OpName %vtxColor \"vtxColor\"\n" + "OpDecorate %fragColor Location 0\n" + "OpDecorate %vtxColor Location 1\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" + "%fragColor = OpVariable %op_v4f32 Output\n" + "%vtxColor = OpVariable %ip_v4f32 Input\n" + + "%main = OpFunction %void None %fun\n" + "%label_main = OpLabel\n" + "%tmp1 = OpLoad %v4f32 %vtxColor\n" + "OpStore %fragColor %tmp1\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "%main2 = OpFunction %void None %fun\n" + "%label_main2 = OpLabel\n" + "%tmp2 = OpLoad %v4f32 %vtxColor\n" + "%tmp3 = OpFSub %v4f32 %cval %tmp2\n" + "%tmp4 = OpVectorInsertDynamic %v4f32 %tmp3 %c_f32_1 %c_i32_3\n" + "OpStore %fragColor %tmp4\n" + "OpReturn\n" + "OpFunctionEnd\n"; + + dst.spirvAsmSources.add("geom") << + "OpCapability Geometry\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint Geometry %geom1_main \"geom1\" %out_gl_position %gl_in %out_color %in_color\n" + "OpEntryPoint Geometry %geom2_main \"geom2\" %out_gl_position %gl_in %out_color %in_color\n" + "OpExecutionMode %geom1_main Triangles\n" + "OpExecutionMode %geom2_main Triangles\n" + "OpExecutionMode %geom1_main OutputTriangleStrip\n" + "OpExecutionMode %geom2_main OutputTriangleStrip\n" + "OpExecutionMode %geom1_main OutputVertices 3\n" + "OpExecutionMode %geom2_main OutputVertices 3\n" + "OpName %geom1_main \"geom1\"\n" + "OpName %geom2_main \"geom2\"\n" + "OpName %per_vertex_in \"gl_PerVertex\"\n" + "OpMemberName %per_vertex_in 0 \"gl_Position\"\n" + "OpMemberName %per_vertex_in 1 \"gl_PointSize\"\n" + "OpMemberName %per_vertex_in 2 \"gl_ClipDistance\"\n" + "OpMemberName %per_vertex_in 3 \"gl_CullDistance\"\n" + "OpName %gl_in \"gl_in\"\n" + "OpName %out_color \"out_color\"\n" + "OpName %in_color \"in_color\"\n" + "OpDecorate %out_gl_position BuiltIn Position\n" + "OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n" + "OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n" + "OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n" + "OpDecorate %per_vertex_in Block\n" + "OpDecorate %out_color Location 1\n" + "OpDecorate %in_color Location 1\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" + "%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n" + "%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n" + "%gl_in = OpVariable %ip_a3_per_vertex_in Input\n" + "%out_color = OpVariable %op_v4f32 Output\n" + "%in_color = OpVariable %ip_a3v4f32 Input\n" + "%out_gl_position = OpVariable %op_v4f32 Output\n" + + "%geom1_main = OpFunction %void None %fun\n" + "%geom1_label = OpLabel\n" + "%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n" + "%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n" + "%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n" + "%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n" + "%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n" + "%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n" + "%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" + "%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" + "%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" + "%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n" + "%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n" + "%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n" + "OpStore %out_gl_position %geom1_in_position_0\n" + "OpStore %out_color %geom1_in_color_0\n" + "OpEmitVertex\n" + "OpStore %out_gl_position %geom1_in_position_1\n" + "OpStore %out_color %geom1_in_color_1\n" + "OpEmitVertex\n" + "OpStore %out_gl_position %geom1_in_position_2\n" + "OpStore %out_color %geom1_in_color_2\n" + "OpEmitVertex\n" + "OpEndPrimitive\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "%geom2_main = OpFunction %void None %fun\n" + "%geom2_label = OpLabel\n" + "%geom2_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n" + "%geom2_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n" + "%geom2_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n" + "%geom2_in_position_0 = OpLoad %v4f32 %geom2_gl_in_0_gl_position\n" + "%geom2_in_position_1 = OpLoad %v4f32 %geom2_gl_in_1_gl_position\n" + "%geom2_in_position_2 = OpLoad %v4f32 %geom2_gl_in_2_gl_position \n" + "%geom2_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" + "%geom2_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" + "%geom2_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" + "%geom2_in_color_0 = OpLoad %v4f32 %geom2_in_color_0_ptr\n" + "%geom2_in_color_1 = OpLoad %v4f32 %geom2_in_color_1_ptr\n" + "%geom2_in_color_2 = OpLoad %v4f32 %geom2_in_color_2_ptr\n" + "%geom2_transformed_in_color_0 = OpFSub %v4f32 %cval %geom2_in_color_0\n" + "%geom2_transformed_in_color_1 = OpFSub %v4f32 %cval %geom2_in_color_1\n" + "%geom2_transformed_in_color_2 = OpFSub %v4f32 %cval %geom2_in_color_2\n" + "%geom2_transformed_in_color_0_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_0 %c_f32_1 %c_i32_3\n" + "%geom2_transformed_in_color_1_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_1 %c_f32_1 %c_i32_3\n" + "%geom2_transformed_in_color_2_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_2 %c_f32_1 %c_i32_3\n" + "OpStore %out_gl_position %geom2_in_position_0\n" + "OpStore %out_color %geom2_transformed_in_color_0_a\n" + "OpEmitVertex\n" + "OpStore %out_gl_position %geom2_in_position_1\n" + "OpStore %out_color %geom2_transformed_in_color_1_a\n" + "OpEmitVertex\n" + "OpStore %out_gl_position %geom2_in_position_2\n" + "OpStore %out_color %geom2_transformed_in_color_2_a\n" + "OpEmitVertex\n" + "OpEndPrimitive\n" + "OpReturn\n" + "OpFunctionEnd\n"; + + dst.spirvAsmSources.add("tessc") << + "OpCapability Tessellation\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint TessellationControl %tessc1_main \"tessc1\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n" + "OpEntryPoint TessellationControl %tessc2_main \"tessc2\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n" + "OpExecutionMode %tessc1_main OutputVertices 3\n" + "OpExecutionMode %tessc2_main OutputVertices 3\n" + "OpName %tessc1_main \"tessc1\"\n" + "OpName %tessc2_main \"tessc2\"\n" + "OpName %out_color \"out_color\"\n" + "OpName %gl_InvocationID \"gl_InvocationID\"\n" + "OpName %in_color \"in_color\"\n" + "OpName %out_position \"out_position\"\n" + "OpName %in_position \"in_position\"\n" + "OpName %gl_TessLevelOuter \"gl_TessLevelOuter\"\n" + "OpName %gl_TessLevelInner \"gl_TessLevelInner\"\n" + "OpDecorate %out_color Location 1\n" + "OpDecorate %gl_InvocationID BuiltIn InvocationId\n" + "OpDecorate %in_color Location 1\n" + "OpDecorate %out_position Location 2\n" + "OpDecorate %in_position Location 2\n" + "OpDecorate %gl_TessLevelOuter Patch\n" + "OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n" + "OpDecorate %gl_TessLevelInner Patch\n" + "OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" + "%out_color = OpVariable %op_a3v4f32 Output\n" + "%gl_InvocationID = OpVariable %ip_i32 Input\n" + "%in_color = OpVariable %ip_a32v4f32 Input\n" + "%out_position = OpVariable %op_a3v4f32 Output\n" + "%in_position = OpVariable %ip_a32v4f32 Input\n" + "%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" + "%gl_TessLevelInner = OpVariable %op_a2f32 Output\n" + + "%tessc1_main = OpFunction %void None %fun\n" + "%tessc1_label = OpLabel\n" + "%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n" + "%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n" + "%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n" + "%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n" + "%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n" + "%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n" + "%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n" + "OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n" + "OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n" + "%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n" + "OpSelectionMerge %tessc1_merge_label None\n" + "OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n" + "%tessc1_first_invocation = OpLabel\n" + "%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n" + "%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n" + "%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n" + "%tessc1_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n" + "OpStore %tessc1_tess_outer_0 %c_f32_1\n" + "OpStore %tessc1_tess_outer_1 %c_f32_1\n" + "OpStore %tessc1_tess_outer_2 %c_f32_1\n" + "OpStore %tessc1_tess_inner %c_f32_1\n" + "OpBranch %tessc1_merge_label\n" + "%tessc1_merge_label = OpLabel\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "%tessc2_main = OpFunction %void None %fun\n" + "%tessc2_label = OpLabel\n" + "%tessc2_invocation_id = OpLoad %i32 %gl_InvocationID\n" + "%tessc2_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc2_invocation_id\n" + "%tessc2_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc2_invocation_id\n" + "%tessc2_in_color_val = OpLoad %v4f32 %tessc2_in_color_ptr\n" + "%tessc2_in_position_val = OpLoad %v4f32 %tessc2_in_position_ptr\n" + "%tessc2_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc2_invocation_id\n" + "%tessc2_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc2_invocation_id\n" + "%tessc2_transformed_color = OpFSub %v4f32 %cval %tessc2_in_color_val\n" + "%tessc2_transformed_color_a = OpVectorInsertDynamic %v4f32 %tessc2_transformed_color %c_f32_1 %c_i32_3\n" + "OpStore %tessc2_out_color_ptr %tessc2_transformed_color_a\n" + "OpStore %tessc2_out_position_ptr %tessc2_in_position_val\n" + "%tessc2_is_first_invocation = OpIEqual %bool %tessc2_invocation_id %c_i32_0\n" + "OpSelectionMerge %tessc2_merge_label None\n" + "OpBranchConditional %tessc2_is_first_invocation %tessc2_first_invocation %tessc2_merge_label\n" + "%tessc2_first_invocation = OpLabel\n" + "%tessc2_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n" + "%tessc2_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n" + "%tessc2_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n" + "%tessc2_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n" + "OpStore %tessc2_tess_outer_0 %c_f32_1\n" + "OpStore %tessc2_tess_outer_1 %c_f32_1\n" + "OpStore %tessc2_tess_outer_2 %c_f32_1\n" + "OpStore %tessc2_tess_inner %c_f32_1\n" + "OpBranch %tessc2_merge_label\n" + "%tessc2_merge_label = OpLabel\n" + "OpReturn\n" + "OpFunctionEnd\n"; + + dst.spirvAsmSources.add("tesse") << + "OpCapability Tessellation\n" + "OpCapability ClipDistance\n" + "OpCapability CullDistance\n" + "OpMemoryModel Logical GLSL450\n" + "OpEntryPoint TessellationEvaluation %tesse1_main \"tesse1\" %stream %gl_tessCoord %in_position %out_color %in_color \n" + "OpEntryPoint TessellationEvaluation %tesse2_main \"tesse2\" %stream %gl_tessCoord %in_position %out_color %in_color \n" + "OpExecutionMode %tesse1_main Triangles\n" + "OpExecutionMode %tesse1_main SpacingEqual\n" + "OpExecutionMode %tesse1_main VertexOrderCcw\n" + "OpExecutionMode %tesse2_main Triangles\n" + "OpExecutionMode %tesse2_main SpacingEqual\n" + "OpExecutionMode %tesse2_main VertexOrderCcw\n" + "OpName %tesse1_main \"tesse1\"\n" + "OpName %tesse2_main \"tesse2\"\n" + "OpName %per_vertex_out \"gl_PerVertex\"\n" + "OpMemberName %per_vertex_out 0 \"gl_Position\"\n" + "OpMemberName %per_vertex_out 1 \"gl_PointSize\"\n" + "OpMemberName %per_vertex_out 2 \"gl_ClipDistance\"\n" + "OpMemberName %per_vertex_out 3 \"gl_CullDistance\"\n" + "OpName %stream \"\"\n" + "OpName %gl_tessCoord \"gl_TessCoord\"\n" + "OpName %in_position \"in_position\"\n" + "OpName %out_color \"out_color\"\n" + "OpName %in_color \"in_color\"\n" + "OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n" + "OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n" + "OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n" + "OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n" + "OpDecorate %per_vertex_out Block\n" + "OpDecorate %gl_tessCoord BuiltIn TessCoord\n" + "OpDecorate %in_position Location 2\n" + "OpDecorate %out_color Location 1\n" + "OpDecorate %in_color Location 1\n" + SPIRV_ASSEMBLY_TYPES + SPIRV_ASSEMBLY_CONSTANTS + SPIRV_ASSEMBLY_ARRAYS + "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" + "%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" + "%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n" + "%stream = OpVariable %op_per_vertex_out Output\n" + "%gl_tessCoord = OpVariable %ip_v3f32 Input\n" + "%in_position = OpVariable %ip_a32v4f32 Input\n" + "%out_color = OpVariable %op_v4f32 Output\n" + "%in_color = OpVariable %ip_a32v4f32 Input\n" + + "%tesse1_main = OpFunction %void None %fun\n" + "%tesse1_label = OpLabel\n" + "%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n" + "%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n" + "%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n" + "%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n" + "%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n" + "%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n" + "%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n" + "%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n" + "%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n" + "%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n" + "%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n" + "%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n" + "%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_0 %tesse1_tc_0\n" + "%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_1 %tesse1_tc_1\n" + "%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_2 %tesse1_tc_2\n" + "%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n" + "%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n" + "%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n" + "OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n" + "%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" + "%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" + "%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" + "%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n" + "%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n" + "%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n" + "%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_0 %tesse1_tc_0\n" + "%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_1 %tesse1_tc_1\n" + "%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_2 %tesse1_tc_2\n" + "%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n" + "%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n" + "OpStore %out_color %tesse1_computed_clr\n" + "OpReturn\n" + "OpFunctionEnd\n" + + "%tesse2_main = OpFunction %void None %fun\n" + "%tesse2_label = OpLabel\n" + "%tesse2_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n" + "%tesse2_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n" + "%tesse2_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n" + "%tesse2_tc_0 = OpLoad %f32 %tesse2_tc_0_ptr\n" + "%tesse2_tc_1 = OpLoad %f32 %tesse2_tc_1_ptr\n" + "%tesse2_tc_2 = OpLoad %f32 %tesse2_tc_2_ptr\n" + "%tesse2_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n" + "%tesse2_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n" + "%tesse2_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n" + "%tesse2_in_pos_0 = OpLoad %v4f32 %tesse2_in_pos_0_ptr\n" + "%tesse2_in_pos_1 = OpLoad %v4f32 %tesse2_in_pos_1_ptr\n" + "%tesse2_in_pos_2 = OpLoad %v4f32 %tesse2_in_pos_2_ptr\n" + "%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_0 %tesse2_tc_0\n" + "%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_1 %tesse2_tc_1\n" + "%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_2 %tesse2_tc_2\n" + "%tesse2_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n" + "%tesse2_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse2_in_pos_0_weighted %tesse2_in_pos_1_weighted\n" + "%tesse2_computed_out = OpFAdd %v4f32 %tesse2_in_pos_0_plus_pos_1 %tesse2_in_pos_2_weighted\n" + "OpStore %tesse2_out_pos_ptr %tesse2_computed_out\n" + "%tesse2_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" + "%tesse2_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" + "%tesse2_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" + "%tesse2_in_clr_0 = OpLoad %v4f32 %tesse2_in_clr_0_ptr\n" + "%tesse2_in_clr_1 = OpLoad %v4f32 %tesse2_in_clr_1_ptr\n" + "%tesse2_in_clr_2 = OpLoad %v4f32 %tesse2_in_clr_2_ptr\n" + "%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_0 %tesse2_tc_0\n" + "%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_1 %tesse2_tc_1\n" + "%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_2 %tesse2_tc_2\n" + "%tesse2_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse2_in_clr_0_weighted %tesse2_in_clr_1_weighted\n" + "%tesse2_computed_clr = OpFAdd %v4f32 %tesse2_in_clr_0_plus_col_1 %tesse2_in_clr_2_weighted\n" + "%tesse2_clr_transformed = OpFSub %v4f32 %cval %tesse2_computed_clr\n" + "%tesse2_clr_transformed_a = OpVectorInsertDynamic %v4f32 %tesse2_clr_transformed %c_f32_1 %c_i32_3\n" + "OpStore %out_color %tesse2_clr_transformed_a\n" + "OpReturn\n" + "OpFunctionEnd\n"; +} + +TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance) +{ + const VkDevice vkDevice = context.getDevice(); + const DeviceInterface& vk = context.getDeviceInterface(); + const VkQueue queue = context.getUniversalQueue(); + const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); + const tcu::UVec2 renderSize (256, 256); + vector modules; + map moduleByStage; + const int testSpecificSeed = 31354125; + const int seed = context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed; + bool supportsGeometry = false; + bool supportsTessellation = false; + bool hasTessellation = false; + + const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures(); + supportsGeometry = features.geometryShader == VK_TRUE; + supportsTessellation = features.tessellationShader == VK_TRUE; + hasTessellation = (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) || + (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); + + if (hasTessellation && !supportsTessellation) + { + throw tcu::NotSupportedError(std::string("Tessellation not supported")); + } + + if ((instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT) && + !supportsGeometry) + { + throw tcu::NotSupportedError(std::string("Geometry not supported")); + } + + de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4); + de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4); + const Vec4 vertexData[] = + { + // Upper left corner: + Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(), + Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(), + Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(), + + // Upper right corner: + Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(), + Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(), + Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(), + + // Lower left corner: + Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(), + Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(), + Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(), + + // Lower right corner: + Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(), + Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(), + Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec() + }; + const size_t singleVertexDataSize = 2 * sizeof(Vec4); + const size_t vertexCount = sizeof(vertexData) / singleVertexDataSize; + + const VkBufferCreateInfo vertexBufferParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size; + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyCount; + &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; + }; + const Unique vertexBuffer (createBuffer(vk, vkDevice, &vertexBufferParams)); + const UniquePtr vertexBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible)); + + VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset())); + + const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y()); + const VkBufferCreateInfo readImageBufferParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + imageSizeBytes, // VkDeviceSize size; + VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyCount; + &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; + }; + const Unique readImageBuffer (createBuffer(vk, vkDevice, &readImageBufferParams)); + const UniquePtr readImageBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible)); + + VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset())); + + const VkImageCreateInfo imageParams = + { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkImageCreateFlags flags; + VK_IMAGE_TYPE_2D, // VkImageType imageType; + VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; + { renderSize.x(), renderSize.y(), 1 }, // VkExtent3D extent; + 1u, // deUint32 mipLevels; + 1u, // deUint32 arraySize; + VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyCount; + &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + }; + + const Unique image (createImage(vk, vkDevice, &imageParams)); + const UniquePtr imageMemory (context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any)); + + VK_CHECK(vk.bindImageMemory(vkDevice, *image, imageMemory->getMemory(), imageMemory->getOffset())); + + const VkAttachmentDescription colorAttDesc = + { + 0u, // VkAttachmentDescriptionFlags flags; + VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; + VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; + }; + const VkAttachmentReference colorAttRef = + { + 0u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; + }; + const VkSubpassDescription subpassDesc = + { + 0u, // VkSubpassDescriptionFlags flags; + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; + 0u, // deUint32 inputCount; + DE_NULL, // const VkAttachmentReference* pInputAttachments; + 1u, // deUint32 colorCount; + &colorAttRef, // const VkAttachmentReference* pColorAttachments; + DE_NULL, // const VkAttachmentReference* pResolveAttachments; + DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; + 0u, // deUint32 preserveCount; + DE_NULL, // const VkAttachmentReference* pPreserveAttachments; + + }; + const VkRenderPassCreateInfo renderPassParams = + { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkRenderPassCreateFlags)0, + 1u, // deUint32 attachmentCount; + &colorAttDesc, // const VkAttachmentDescription* pAttachments; + 1u, // deUint32 subpassCount; + &subpassDesc, // const VkSubpassDescription* pSubpasses; + 0u, // deUint32 dependencyCount; + DE_NULL, // const VkSubpassDependency* pDependencies; + }; + const Unique renderPass (createRenderPass(vk, vkDevice, &renderPassParams)); + + const VkImageViewCreateInfo colorAttViewParams = + { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkImageViewCreateFlags flags; + *image, // VkImage image; + VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; + VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; + { + VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A + }, // VkChannelMapping channels; + { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; + 0u, // deUint32 baseMipLevel; + 1u, // deUint32 mipLevels; + 0u, // deUint32 baseArrayLayer; + 1u, // deUint32 arraySize; + }, // VkImageSubresourceRange subresourceRange; + }; + const Unique colorAttView (createImageView(vk, vkDevice, &colorAttViewParams)); + + + // Pipeline layout + const VkPipelineLayoutCreateInfo pipelineLayoutParams = + { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineLayoutCreateFlags)0, + 0u, // deUint32 descriptorSetCount; + DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; + 0u, // deUint32 pushConstantRangeCount; + DE_NULL, // const VkPushConstantRange* pPushConstantRanges; + }; + const Unique pipelineLayout (createPipelineLayout(vk, vkDevice, &pipelineLayoutParams)); + + // Pipeline + vector shaderStageParams; + // We need these vectors to make sure that information about specialization constants for each stage can outlive createGraphicsPipeline(). + vector > specConstantEntries; + vector specializationInfos; + createPipelineShaderStages(vk, vkDevice, instance, context, modules, shaderStageParams); + + // And we don't want the reallocation of these vectors to invalidate pointers pointing to their contents. + specConstantEntries.reserve(shaderStageParams.size()); + specializationInfos.reserve(shaderStageParams.size()); + + // Patch the specialization info field in PipelineShaderStageCreateInfos. + for (vector::iterator stageInfo = shaderStageParams.begin(); stageInfo != shaderStageParams.end(); ++stageInfo) + { + const StageToSpecConstantMap::const_iterator stageIt = instance.specConstants.find(stageInfo->stage); + + if (stageIt != instance.specConstants.end()) + { + const size_t numSpecConstants = stageIt->second.size(); + vector entries; + VkSpecializationInfo specInfo; + + entries.resize(numSpecConstants); + + // Only support 32-bit integers as spec constants now. And their constant IDs are numbered sequentially starting from 0. + for (size_t ndx = 0; ndx < numSpecConstants; ++ndx) + { + entries[ndx].constantID = (deUint32)ndx; + entries[ndx].offset = deUint32(ndx * sizeof(deInt32)); + entries[ndx].size = sizeof(deInt32); + } + + specConstantEntries.push_back(entries); + + specInfo.mapEntryCount = (deUint32)numSpecConstants; + specInfo.pMapEntries = specConstantEntries.back().data(); + specInfo.dataSize = numSpecConstants * sizeof(deInt32); + specInfo.pData = stageIt->second.data(); + specializationInfos.push_back(specInfo); + + stageInfo->pSpecializationInfo = &specializationInfos.back(); + } + } + const VkPipelineDepthStencilStateCreateInfo depthStencilParams = + { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineDepthStencilStateCreateFlags)0, + DE_FALSE, // deUint32 depthTestEnable; + DE_FALSE, // deUint32 depthWriteEnable; + VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp; + DE_FALSE, // deUint32 depthBoundsTestEnable; + DE_FALSE, // deUint32 stencilTestEnable; + { + VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp; + VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp; + VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp; + VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp; + 0u, // deUint32 stencilCompareMask; + 0u, // deUint32 stencilWriteMask; + 0u, // deUint32 stencilReference; + }, // VkStencilOpState front; + { + VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp; + VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp; + VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp; + VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp; + 0u, // deUint32 stencilCompareMask; + 0u, // deUint32 stencilWriteMask; + 0u, // deUint32 stencilReference; + }, // VkStencilOpState back; + -1.0f, // float minDepthBounds; + +1.0f, // float maxDepthBounds; + }; + const VkViewport viewport0 = + { + 0.0f, // float originX; + 0.0f, // float originY; + (float)renderSize.x(), // float width; + (float)renderSize.y(), // float height; + 0.0f, // float minDepth; + 1.0f, // float maxDepth; + }; + const VkRect2D scissor0 = + { + { + 0u, // deInt32 x; + 0u, // deInt32 y; + }, // VkOffset2D offset; + { + renderSize.x(), // deInt32 width; + renderSize.y(), // deInt32 height; + }, // VkExtent2D extent; + }; + const VkPipelineViewportStateCreateInfo viewportParams = + { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineViewportStateCreateFlags)0, + 1u, // deUint32 viewportCount; + &viewport0, + 1u, + &scissor0 + }; + const VkSampleMask sampleMask = ~0u; + const VkPipelineMultisampleStateCreateInfo multisampleParams = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineMultisampleStateCreateFlags)0, + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterSamples; + DE_FALSE, // deUint32 sampleShadingEnable; + 0.0f, // float minSampleShading; + &sampleMask, // const VkSampleMask* pSampleMask; + DE_FALSE, // VkBool32 alphaToCoverageEnable; + DE_FALSE, // VkBool32 alphaToOneEnable; + }; + const VkPipelineRasterizationStateCreateInfo rasterParams = + { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineRasterizationStateCreateFlags)0, + DE_TRUE, // deUint32 depthClipEnable; + DE_FALSE, // deUint32 rasterizerDiscardEnable; + VK_POLYGON_MODE_FILL, // VkFillMode fillMode; + VK_CULL_MODE_NONE, // VkCullMode cullMode; + VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; + VK_FALSE, // VkBool32 depthBiasEnable; + 0.0f, // float depthBias; + 0.0f, // float depthBiasClamp; + 0.0f, // float slopeScaledDepthBias; + 1.0f, // float lineWidth; + }; + const VkPrimitiveTopology topology = hasTessellation? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams = + { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineInputAssemblyStateCreateFlags)0, + topology, // VkPrimitiveTopology topology; + DE_FALSE, // deUint32 primitiveRestartEnable; + }; + const VkVertexInputBindingDescription vertexBinding0 = + { + 0u, // deUint32 binding; + deUint32(singleVertexDataSize), // deUint32 strideInBytes; + VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate; + }; + const VkVertexInputAttributeDescription vertexAttrib0[2] = + { + { + 0u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + 0u // deUint32 offsetInBytes; + }, + { + 1u, // deUint32 location; + 0u, // deUint32 binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + sizeof(Vec4), // deUint32 offsetInBytes; + } + }; + + const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineVertexInputStateCreateFlags)0, + 1u, // deUint32 bindingCount; + &vertexBinding0, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + 2u, // deUint32 attributeCount; + vertexAttrib0, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + const VkPipelineColorBlendAttachmentState attBlendParams = + { + DE_FALSE, // deUint32 blendEnable; + VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor; + VK_BLEND_FACTOR_ZERO, // VkBlend destBlendColor; + VK_BLEND_OP_ADD, // VkBlendOp blendOpColor; + VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha; + VK_BLEND_FACTOR_ZERO, // VkBlend destBlendAlpha; + VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha; + (VK_COLOR_COMPONENT_R_BIT| + VK_COLOR_COMPONENT_G_BIT| + VK_COLOR_COMPONENT_B_BIT| + VK_COLOR_COMPONENT_A_BIT), // VkChannelFlags channelWriteMask; + }; + const VkPipelineColorBlendStateCreateInfo blendParams = + { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineColorBlendStateCreateFlags)0, + DE_FALSE, // VkBool32 logicOpEnable; + VK_LOGIC_OP_COPY, // VkLogicOp logicOp; + 1u, // deUint32 attachmentCount; + &attBlendParams, // const VkPipelineColorBlendAttachmentState* pAttachments; + { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4]; + }; + const VkPipelineTessellationStateCreateInfo tessellationState = + { + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, + DE_NULL, + (VkPipelineTessellationStateCreateFlags)0, + 3u + }; + + const VkPipelineTessellationStateCreateInfo* tessellationInfo = hasTessellation ? &tessellationState: DE_NULL; + const VkGraphicsPipelineCreateInfo pipelineParams = + { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkPipelineCreateFlags flags; + (deUint32)shaderStageParams.size(), // deUint32 stageCount; + &shaderStageParams[0], // const VkPipelineShaderStageCreateInfo* pStages; + &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + &inputAssemblyParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + tessellationInfo, // const VkPipelineTessellationStateCreateInfo* pTessellationState; + &viewportParams, // const VkPipelineViewportStateCreateInfo* pViewportState; + &rasterParams, // const VkPipelineRasterStateCreateInfo* pRasterState; + &multisampleParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + &depthStencilParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + &blendParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; + *pipelineLayout, // VkPipelineLayout layout; + *renderPass, // VkRenderPass renderPass; + 0u, // deUint32 subpass; + DE_NULL, // VkPipeline basePipelineHandle; + 0u, // deInt32 basePipelineIndex; + }; + + const Unique pipeline (createGraphicsPipeline(vk, vkDevice, DE_NULL, &pipelineParams)); + + // Framebuffer + const VkFramebufferCreateInfo framebufferParams = + { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkFramebufferCreateFlags)0, + *renderPass, // VkRenderPass renderPass; + 1u, // deUint32 attachmentCount; + &*colorAttView, // const VkImageView* pAttachments; + (deUint32)renderSize.x(), // deUint32 width; + (deUint32)renderSize.y(), // deUint32 height; + 1u, // deUint32 layers; + }; + const Unique framebuffer (createFramebuffer(vk, vkDevice, &framebufferParams)); + + const Unique cmdPool (createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); + + // Command buffer + const Unique cmdBuf (allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); + + const VkCommandBufferBeginInfo cmdBufBeginParams = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkCommandBufferUsageFlags)0, + (const VkCommandBufferInheritanceInfo*)DE_NULL, + }; + + // Record commands + VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginParams)); + + { + const VkMemoryBarrier vertFlushBarrier = + { + VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_HOST_WRITE_BIT, // VkMemoryOutputFlags outputMask; + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkMemoryInputFlags inputMask; + }; + const VkImageMemoryBarrier colorAttBarrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkMemoryOutputFlags outputMask; + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryInputFlags inputMask; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; + queueFamilyIndex, // deUint32 srcQueueFamilyIndex; + queueFamilyIndex, // deUint32 destQueueFamilyIndex; + *image, // VkImage image; + { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect; + 0u, // deUint32 baseMipLevel; + 1u, // deUint32 mipLevels; + 0u, // deUint32 baseArraySlice; + 1u, // deUint32 arraySize; + } // VkImageSubresourceRange subresourceRange; + }; + vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &colorAttBarrier); + } + + { + const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f); + const VkRenderPassBeginInfo passBeginParams = + { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + *renderPass, // VkRenderPass renderPass; + *framebuffer, // VkFramebuffer framebuffer; + { { 0, 0 }, { renderSize.x(), renderSize.y() } }, // VkRect2D renderArea; + 1u, // deUint32 clearValueCount; + &clearValue, // const VkClearValue* pClearValues; + }; + vk.cmdBeginRenderPass(*cmdBuf, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE); + } + + vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); + { + const VkDeviceSize bindingOffset = 0; + vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset); + } + vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/); + vk.cmdEndRenderPass(*cmdBuf); + + { + const VkImageMemoryBarrier renderFinishBarrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryOutputFlags outputMask; + VK_ACCESS_TRANSFER_READ_BIT, // VkMemoryInputFlags inputMask; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; + queueFamilyIndex, // deUint32 srcQueueFamilyIndex; + queueFamilyIndex, // deUint32 destQueueFamilyIndex; + *image, // VkImage image; + { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; + 0u, // deUint32 baseMipLevel; + 1u, // deUint32 mipLevels; + 0u, // deUint32 baseArraySlice; + 1u, // deUint32 arraySize; + } // VkImageSubresourceRange subresourceRange; + }; + vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &renderFinishBarrier); + } + + { + const VkBufferImageCopy copyParams = + { + (VkDeviceSize)0u, // VkDeviceSize bufferOffset; + (deUint32)renderSize.x(), // deUint32 bufferRowLength; + (deUint32)renderSize.y(), // deUint32 bufferImageHeight; + { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect; + 0u, // deUint32 mipLevel; + 0u, // deUint32 arrayLayer; + 1u, // deUint32 arraySize; + }, // VkImageSubresourceCopy imageSubresource; + { 0u, 0u, 0u }, // VkOffset3D imageOffset; + { renderSize.x(), renderSize.y(), 1u } // VkExtent3D imageExtent; + }; + vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params); + } + + { + const VkBufferMemoryBarrier copyFinishBarrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkMemoryOutputFlags outputMask; + VK_ACCESS_HOST_READ_BIT, // VkMemoryInputFlags inputMask; + queueFamilyIndex, // deUint32 srcQueueFamilyIndex; + queueFamilyIndex, // deUint32 destQueueFamilyIndex; + *readImageBuffer, // VkBuffer buffer; + 0u, // VkDeviceSize offset; + imageSizeBytes // VkDeviceSize size; + }; + vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©FinishBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); + } + + VK_CHECK(vk.endCommandBuffer(*cmdBuf)); + + // Upload vertex data + { + const VkMappedMemoryRange range = + { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; + DE_NULL, // const void* pNext; + vertexBufferMemory->getMemory(), // VkDeviceMemory mem; + 0, // VkDeviceSize offset; + (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size; + }; + void* vertexBufPtr = vertexBufferMemory->getHostPtr(); + + deMemcpy(vertexBufPtr, &vertexData[0], sizeof(vertexData)); + VK_CHECK(vk.flushMappedMemoryRanges(vkDevice, 1u, &range)); + } + + // Submit & wait for completion + { + const Unique fence (createFence(vk, vkDevice)); + const VkSubmitInfo submitInfo = + { + VK_STRUCTURE_TYPE_SUBMIT_INFO, + DE_NULL, + 0u, + (const VkSemaphore*)DE_NULL, + (const VkPipelineStageFlags*)DE_NULL, + 1u, + &cmdBuf.get(), + 0u, + (const VkSemaphore*)DE_NULL, + }; + + VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence)); + VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull)); + } + + const void* imagePtr = readImageBufferMemory->getHostPtr(); + const tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), + renderSize.x(), renderSize.y(), 1, imagePtr); + // Log image + { + const VkMappedMemoryRange range = + { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; + DE_NULL, // const void* pNext; + readImageBufferMemory->getMemory(), // VkDeviceMemory mem; + 0, // VkDeviceSize offset; + imageSizeBytes, // VkDeviceSize size; + }; + + VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range)); + context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer); + } + + const RGBA threshold(1, 1, 1, 1); + const RGBA upperLeft(pixelBuffer.getPixel(1, 1)); + if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold)) + return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper left corner mismatch")); + + const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1)); + if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold)) + return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper right corner mismatch")); + + const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1)); + if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold)) + return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower left corner mismatch")); + + const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1)); + if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold)) + return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower right corner mismatch")); + + return TestStatus::pass("Rendered output matches input"); +} + +void createTestsForAllStages (const std::string& name, + const RGBA (&inputColors)[4], + const RGBA (&outputColors)[4], + const map& testCodeFragments, + const vector& specConstants, + tcu::TestCaseGroup* tests, + const qpTestResult failResult, + const string& failMessageTemplate) +{ + const ShaderElement vertFragPipelineStages[] = + { + ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), + ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), + }; + + const ShaderElement tessPipelineStages[] = + { + ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), + ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), + ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), + ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), + }; + + const ShaderElement geomPipelineStages[] = + { + ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), + ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT), + ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), + }; + + StageToSpecConstantMap specConstantMap; + + specConstantMap[VK_SHADER_STAGE_VERTEX_BIT] = specConstants; + addFunctionCaseWithPrograms(tests, name + "_vert", "", addShaderCodeCustomVertex, runAndVerifyDefaultPipeline, + createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap, failResult, failMessageTemplate)); + + specConstantMap.clear(); + specConstantMap[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT] = specConstants; + addFunctionCaseWithPrograms(tests, name + "_tessc", "", addShaderCodeCustomTessControl, runAndVerifyDefaultPipeline, + createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap, failResult, failMessageTemplate)); + + specConstantMap.clear(); + specConstantMap[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = specConstants; + addFunctionCaseWithPrograms(tests, name + "_tesse", "", addShaderCodeCustomTessEval, runAndVerifyDefaultPipeline, + createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap, failResult, failMessageTemplate)); + + specConstantMap.clear(); + specConstantMap[VK_SHADER_STAGE_GEOMETRY_BIT] = specConstants; + addFunctionCaseWithPrograms(tests, name + "_geom", "", addShaderCodeCustomGeometry, runAndVerifyDefaultPipeline, + createInstanceContext(geomPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap, failResult, failMessageTemplate)); + + specConstantMap.clear(); + specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT] = specConstants; + addFunctionCaseWithPrograms(tests, name + "_frag", "", addShaderCodeCustomFragment, runAndVerifyDefaultPipeline, + createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap, failResult, failMessageTemplate)); +} + +void addTessCtrlTest(tcu::TestCaseGroup* group, const char* name, const map& fragments) +{ + RGBA defaultColors[4]; + getDefaultColors(defaultColors); + const ShaderElement pipelineStages[] = + { + ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), + ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), + ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), + ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), + }; + + addFunctionCaseWithPrograms(group, name, "", addShaderCodeCustomTessControl, + runAndVerifyDefaultPipeline, createInstanceContext( + pipelineStages, defaultColors, defaultColors, fragments, StageToSpecConstantMap())); +} + +} // SpirVAssembly +} // vkt diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.hpp new file mode 100644 index 0000000..432fb0f --- /dev/null +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.hpp @@ -0,0 +1,209 @@ +#ifndef _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP +#define _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP +/*------------------------------------------------------------------------- + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2017 The Khronos Group 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 Graphics pipeline and helper functions for SPIR-V assembly tests + *//*--------------------------------------------------------------------*/ + +#include "tcuCommandLine.hpp" +#include "tcuRGBA.hpp" + +#include "vkPrograms.hpp" +#include "vktTestCaseUtil.hpp" + +#include "deRandom.hpp" +#include "deSharedPtr.hpp" + +#include +#include +#include +#include + +namespace vkt +{ +namespace SpirVAssembly +{ + +typedef vk::Unique ModuleHandleUp; +typedef de::SharedPtr ModuleHandleSp; +typedef std::pair EntryToStage; +typedef std::map > ModuleMap; +typedef std::map > StageToSpecConstantMap; + +// Context for a specific test instantiation. For example, an instantiation +// may test colors yellow/magenta/cyan/mauve in a tesselation shader +// with an entry point named 'main_to_the_main' +struct InstanceContext +{ + // Map of modules to what entry_points we care to use from those modules. + ModuleMap moduleMap; + tcu::RGBA inputColors[4]; + tcu::RGBA outputColors[4]; + // Concrete SPIR-V code to test via boilerplate specialization. + std::map testCodeFragments; + StageToSpecConstantMap specConstants; + bool hasTessellation; + vk::VkShaderStageFlagBits requiredStages; + qpTestResult failResult; + std::string failMessageTemplate; //!< ${reason} in the template will be replaced with a detailed failure message + + InstanceContext (const tcu::RGBA (&inputs)[4], + const tcu::RGBA (&outputs)[4], + const std::map& testCodeFragments_, + const StageToSpecConstantMap& specConstants_); + + InstanceContext (const InstanceContext& other); + + std::string getSpecializedFailMessage (const std::string& failureReason); +}; + +// A description of a shader to be used for a single stage of the graphics pipeline. +struct ShaderElement +{ + // The module that contains this shader entrypoint. + std::string moduleName; + + // The name of the entrypoint. + std::string entryName; + + // Which shader stage this entry point represents. + vk::VkShaderStageFlagBits stage; + + ShaderElement (const std::string& moduleName_, const std::string& entryPoint_, vk::VkShaderStageFlagBits shaderStage_); +}; + +template +const std::string numberToString (T number) +{ + std::stringstream ss; + ss << number; + return ss.str(); +} + +// Performs a bitwise copy of source to the destination type Dest. +template +Dest bitwiseCast(Src source) +{ + Dest dest; + DE_STATIC_ASSERT(sizeof(source) == sizeof(dest)); + deMemcpy(&dest, &source, sizeof(dest)); + return dest; +} + +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); } + + +void getDefaultColors (tcu::RGBA (&colors)[4]); + +void getHalfColorsFullAlpha (tcu::RGBA (&colors)[4]); + +void getInvertedDefaultColors (tcu::RGBA (&colors)[4]); + +// Creates fragments that specialize into a simple pass-through shader (of any kind). +std::map passthruFragments(void); + +void createCombinedModule(vk::SourceCollections& dst, InstanceContext); + +// This has two shaders of each stage. The first +// is a passthrough, the second inverts the color. +void createMultipleEntries(vk::SourceCollections& dst, InstanceContext); + +// Turns a statically sized array of ShaderElements into an instance-context +// by setting up the mapping of modules to their contained shaders and stages. +// The inputs and expected outputs are given by inputColors and outputColors +template +InstanceContext createInstanceContext (const ShaderElement (&elements)[N], + const tcu::RGBA (&inputColors)[4], + const tcu::RGBA (&outputColors)[4], + const std::map& testCodeFragments, + const StageToSpecConstantMap& specConstants, + const qpTestResult failResult = QP_TEST_RESULT_FAIL, + const std::string& failMessageTemplate = std::string()) +{ + InstanceContext ctx (inputColors, outputColors, testCodeFragments, specConstants); + for (size_t i = 0; i < N; ++i) + { + ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage)); + ctx.requiredStages = static_cast(ctx.requiredStages | elements[i].stage); + } + ctx.failResult = failResult; + if (!failMessageTemplate.empty()) + ctx.failMessageTemplate = failMessageTemplate; + return ctx; +} + +template +inline InstanceContext createInstanceContext (const ShaderElement (&elements)[N], + tcu::RGBA (&inputColors)[4], + const tcu::RGBA (&outputColors)[4], + const std::map& testCodeFragments) +{ + return createInstanceContext(elements, inputColors, outputColors, testCodeFragments, StageToSpecConstantMap()); +} + +// The same as createInstanceContext above, but with default colors. +template +InstanceContext createInstanceContext (const ShaderElement (&elements)[N], + const std::map& testCodeFragments) +{ + tcu::RGBA defaultColors[4]; + getDefaultColors(defaultColors); + return createInstanceContext(elements, defaultColors, defaultColors, testCodeFragments); +} + +void createTestsForAllStages (const std::string& name, + const tcu::RGBA (&inputColors)[4], + const tcu::RGBA (&outputColors)[4], + const std::map& testCodeFragments, + const std::vector& specConstants, + tcu::TestCaseGroup* tests, + const qpTestResult failResult = QP_TEST_RESULT_FAIL, + const std::string& failMessageTemplate = std::string()); + +inline void createTestsForAllStages (const std::string& name, + const tcu::RGBA (&inputColors)[4], + const tcu::RGBA (&outputColors)[4], + const std::map& testCodeFragments, + tcu::TestCaseGroup* tests, + const qpTestResult failResult = QP_TEST_RESULT_FAIL, + const std::string& failMessageTemplate = std::string()) +{ + std::vector noSpecConstants; + createTestsForAllStages(name, inputColors, outputColors, testCodeFragments, noSpecConstants, tests, failResult, failMessageTemplate); +} + +// Sets up and runs a Vulkan pipeline, then spot-checks the resulting image. +// Feeds the pipeline a set of colored triangles, which then must occur in the +// rendered image. The surface is cleared before executing the pipeline, so +// whatever the shaders draw can be directly spot-checked. +tcu::TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance); + +// Adds a new test to group using custom fragments for the tessellation-control +// stage and passthrough fragments for all other stages. Uses default colors +// for input and expected output. +void addTessCtrlTest(tcu::TestCaseGroup* group, const char* name, const std::map& fragments); + +} // SpirVAssembly +} // vkt + +#endif // _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp index 63498be..e2f3684 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp @@ -51,6 +51,7 @@ #include "vktSpvAsmComputeShaderCase.hpp" #include "vktSpvAsmComputeShaderTestUtil.hpp" +#include "vktSpvAsmGraphicsShaderTestUtil.hpp" #include "vktTestCaseUtil.hpp" #include @@ -82,13 +83,6 @@ using de::UniquePtr; using tcu::StringTemplate; using tcu::Vec4; -typedef Unique ModuleHandleUp; -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 static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0) { @@ -156,45 +150,6 @@ struct CaseParameter // output_data.elements[x] = -input_data.elements[x]; // } -static const char* const s_ShaderPreamble = - "OpCapability Shader\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint GLCompute %main \"main\" %id\n" - "OpExecutionMode %main LocalSize 1 1 1\n"; - -static const char* const s_CommonTypes = - "%bool = OpTypeBool\n" - "%void = OpTypeVoid\n" - "%voidf = OpTypeFunction %void\n" - "%u32 = OpTypeInt 32 0\n" - "%i32 = OpTypeInt 32 1\n" - "%f32 = OpTypeFloat 32\n" - "%uvec3 = OpTypeVector %u32 3\n" - "%fvec3 = OpTypeVector %f32 3\n" - "%uvec3ptr = OpTypePointer Input %uvec3\n" - "%i32ptr = OpTypePointer Uniform %i32\n" - "%f32ptr = OpTypePointer Uniform %f32\n" - "%i32arr = OpTypeRuntimeArray %i32\n" - "%f32arr = OpTypeRuntimeArray %f32\n"; - -// Declares two uniform variables (indata, outdata) of type "struct { float[] }". Depends on type "f32arr" (for "float[]"). -static const char* const s_InputOutputBuffer = - "%buf = OpTypeStruct %f32arr\n" - "%bufptr = OpTypePointer Uniform %buf\n" - "%indata = OpVariable %bufptr Uniform\n" - "%outdata = OpVariable %bufptr Uniform\n"; - -// Declares buffer type and layout for uniform variables indata and outdata. Both of them are SSBO bounded to descriptor set 0. -// indata is at binding point 0, while outdata is at 1. -static const char* const s_InputOutputBufferTraits = - "OpDecorate %buf BufferBlock\n" - "OpDecorate %indata DescriptorSet 0\n" - "OpDecorate %indata Binding 0\n" - "OpDecorate %outdata DescriptorSet 0\n" - "OpDecorate %outdata Binding 1\n" - "OpDecorate %f32arr ArrayStride 4\n" - "OpMemberDecorate %buf 0 Offset 0\n"; - tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx) { de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opnop", "Test the OpNop instruction")); @@ -2965,16 +2920,6 @@ tcu::TestCaseGroup* createOpQuantizeToF16Group (tcu::TestContext& testCtx) return group.release(); } -// Performs a bitwise copy of source to the destination type Dest. -template -Dest bitwiseCast(Src source) -{ - Dest dest; - DE_STATIC_ASSERT(sizeof(source) == sizeof(dest)); - deMemcpy(&dest, &source, sizeof(dest)); - return dest; -} - tcu::TestCaseGroup* createSpecConstantOpQuantizeToF16Group (tcu::TestContext& testCtx) { de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opspecconstantop_opquantize", "Tests the OpQuantizeToF16 opcode for the OpSpecConstantOp instruction")); @@ -3711,2208 +3656,6 @@ tcu::TestCaseGroup* createOpUndefGroup (tcu::TestContext& testCtx) return group.release(); } -typedef std::pair EntryToStage; -typedef map > ModuleMap; -typedef map > StageToSpecConstantMap; - -// Context for a specific test instantiation. For example, an instantiation -// may test colors yellow/magenta/cyan/mauve in a tesselation shader -// with an entry point named 'main_to_the_main' -struct InstanceContext -{ - // Map of modules to what entry_points we care to use from those modules. - ModuleMap moduleMap; - RGBA inputColors[4]; - RGBA outputColors[4]; - // Concrete SPIR-V code to test via boilerplate specialization. - map testCodeFragments; - StageToSpecConstantMap specConstants; - bool hasTessellation; - VkShaderStageFlagBits requiredStages; - qpTestResult failResult; - string failMessageTemplate; //!< ${reason} in the template will be replaced with a detailed failure message - - InstanceContext (const RGBA (&inputs)[4], const RGBA (&outputs)[4], const map& testCodeFragments_, const StageToSpecConstantMap& specConstants_) - : testCodeFragments (testCodeFragments_) - , specConstants (specConstants_) - , hasTessellation (false) - , requiredStages (static_cast(0)) - , failResult (QP_TEST_RESULT_FAIL) - , failMessageTemplate ("${reason}") - { - inputColors[0] = inputs[0]; - inputColors[1] = inputs[1]; - inputColors[2] = inputs[2]; - inputColors[3] = inputs[3]; - - outputColors[0] = outputs[0]; - outputColors[1] = outputs[1]; - outputColors[2] = outputs[2]; - outputColors[3] = outputs[3]; - } - - InstanceContext (const InstanceContext& other) - : moduleMap (other.moduleMap) - , testCodeFragments (other.testCodeFragments) - , specConstants (other.specConstants) - , hasTessellation (other.hasTessellation) - , requiredStages (other.requiredStages) - , failResult (other.failResult) - , failMessageTemplate (other.failMessageTemplate) - { - inputColors[0] = other.inputColors[0]; - inputColors[1] = other.inputColors[1]; - inputColors[2] = other.inputColors[2]; - inputColors[3] = other.inputColors[3]; - - outputColors[0] = other.outputColors[0]; - outputColors[1] = other.outputColors[1]; - outputColors[2] = other.outputColors[2]; - outputColors[3] = other.outputColors[3]; - } - - string getSpecializedFailMessage (const string& failureReason) - { - map parameters; - parameters["reason"] = failureReason; - return StringTemplate(failMessageTemplate).specialize(parameters); - } -}; - -// A description of a shader to be used for a single stage of the graphics pipeline. -struct ShaderElement -{ - // The module that contains this shader entrypoint. - string moduleName; - - // The name of the entrypoint. - string entryName; - - // Which shader stage this entry point represents. - VkShaderStageFlagBits stage; - - ShaderElement (const string& moduleName_, const string& entryPoint_, VkShaderStageFlagBits shaderStage_) - : moduleName(moduleName_) - , entryName(entryPoint_) - , stage(shaderStage_) - { - } -}; - -void getDefaultColors (RGBA (&colors)[4]) -{ - colors[0] = RGBA::white(); - colors[1] = RGBA::red(); - colors[2] = RGBA::green(); - colors[3] = RGBA::blue(); -} - -void getHalfColorsFullAlpha (RGBA (&colors)[4]) -{ - colors[0] = RGBA(127, 127, 127, 255); - colors[1] = RGBA(127, 0, 0, 255); - colors[2] = RGBA(0, 127, 0, 255); - colors[3] = RGBA(0, 0, 127, 255); -} - -void getInvertedDefaultColors (RGBA (&colors)[4]) -{ - colors[0] = RGBA(0, 0, 0, 255); - colors[1] = RGBA(0, 255, 255, 255); - colors[2] = RGBA(255, 0, 255, 255); - colors[3] = RGBA(255, 255, 0, 255); -} - -// Turns a statically sized array of ShaderElements into an instance-context -// by setting up the mapping of modules to their contained shaders and stages. -// The inputs and expected outputs are given by inputColors and outputColors -template -InstanceContext createInstanceContext (const ShaderElement (&elements)[N], - const RGBA (&inputColors)[4], - const RGBA (&outputColors)[4], - const map& testCodeFragments, - const StageToSpecConstantMap& specConstants, - const qpTestResult failResult = QP_TEST_RESULT_FAIL, - const string& failMessageTemplate = string()) -{ - InstanceContext ctx (inputColors, outputColors, testCodeFragments, specConstants); - for (size_t i = 0; i < N; ++i) - { - ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage)); - ctx.requiredStages = static_cast(ctx.requiredStages | elements[i].stage); - } - ctx.failResult = failResult; - if (!failMessageTemplate.empty()) - ctx.failMessageTemplate = failMessageTemplate; - return ctx; -} - -template -inline InstanceContext createInstanceContext (const ShaderElement (&elements)[N], - RGBA (&inputColors)[4], - const RGBA (&outputColors)[4], - const map& testCodeFragments) -{ - return createInstanceContext(elements, inputColors, outputColors, testCodeFragments, StageToSpecConstantMap()); -} - -// The same as createInstanceContext above, but with default colors. -template -InstanceContext createInstanceContext (const ShaderElement (&elements)[N], - const map& testCodeFragments) -{ - RGBA defaultColors[4]; - getDefaultColors(defaultColors); - return createInstanceContext(elements, defaultColors, defaultColors, testCodeFragments); -} - -// For the current InstanceContext, constructs the required modules and shader stage create infos. -void createPipelineShaderStages (const DeviceInterface& vk, const VkDevice vkDevice, InstanceContext& instance, Context& context, vector& modules, vector& createInfos) -{ - for (ModuleMap::const_iterator moduleNdx = instance.moduleMap.begin(); moduleNdx != instance.moduleMap.end(); ++moduleNdx) - { - const ModuleHandleSp mod(new Unique(createShaderModule(vk, vkDevice, context.getBinaryCollection().get(moduleNdx->first), 0))); - modules.push_back(ModuleHandleSp(mod)); - for (vector::const_iterator shaderNdx = moduleNdx->second.begin(); shaderNdx != moduleNdx->second.end(); ++shaderNdx) - { - const EntryToStage& stage = *shaderNdx; - const VkPipelineShaderStageCreateInfo shaderParam = - { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineShaderStageCreateFlags)0, - stage.second, // VkShaderStageFlagBits stage; - **modules.back(), // VkShaderModule module; - stage.first.c_str(), // const char* pName; - (const VkSpecializationInfo*)DE_NULL, - }; - createInfos.push_back(shaderParam); - } - } -} - -#define SPIRV_ASSEMBLY_TYPES \ - "%void = OpTypeVoid\n" \ - "%bool = OpTypeBool\n" \ - \ - "%i32 = OpTypeInt 32 1\n" \ - "%u32 = OpTypeInt 32 0\n" \ - \ - "%f32 = OpTypeFloat 32\n" \ - "%v3f32 = OpTypeVector %f32 3\n" \ - "%v4i32 = OpTypeVector %i32 4\n" \ - "%v4f32 = OpTypeVector %f32 4\n" \ - "%v4bool = OpTypeVector %bool 4\n" \ - \ - "%v4f32_function = OpTypeFunction %v4f32 %v4f32\n" \ - "%fun = OpTypeFunction %void\n" \ - \ - "%ip_f32 = OpTypePointer Input %f32\n" \ - "%ip_i32 = OpTypePointer Input %i32\n" \ - "%ip_v3f32 = OpTypePointer Input %v3f32\n" \ - "%ip_v4f32 = OpTypePointer Input %v4f32\n" \ - \ - "%op_f32 = OpTypePointer Output %f32\n" \ - "%op_v4f32 = OpTypePointer Output %v4f32\n" \ - \ - "%fp_f32 = OpTypePointer Function %f32\n" \ - "%fp_i32 = OpTypePointer Function %i32\n" \ - "%fp_v4f32 = OpTypePointer Function %v4f32\n" - -#define SPIRV_ASSEMBLY_CONSTANTS \ - "%c_f32_1 = OpConstant %f32 1.0\n" \ - "%c_f32_0 = OpConstant %f32 0.0\n" \ - "%c_f32_0_5 = OpConstant %f32 0.5\n" \ - "%c_f32_n1 = OpConstant %f32 -1.\n" \ - "%c_f32_7 = OpConstant %f32 7.0\n" \ - "%c_f32_8 = OpConstant %f32 8.0\n" \ - "%c_i32_0 = OpConstant %i32 0\n" \ - "%c_i32_1 = OpConstant %i32 1\n" \ - "%c_i32_2 = OpConstant %i32 2\n" \ - "%c_i32_3 = OpConstant %i32 3\n" \ - "%c_i32_4 = OpConstant %i32 4\n" \ - "%c_u32_0 = OpConstant %u32 0\n" \ - "%c_u32_1 = OpConstant %u32 1\n" \ - "%c_u32_2 = OpConstant %u32 2\n" \ - "%c_u32_3 = OpConstant %u32 3\n" \ - "%c_u32_32 = OpConstant %u32 32\n" \ - "%c_u32_4 = OpConstant %u32 4\n" \ - "%c_u32_31_bits = OpConstant %u32 0x7FFFFFFF\n" \ - "%c_v4f32_1_1_1_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n" \ - "%c_v4f32_1_0_0_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_1\n" \ - "%c_v4f32_0_5_0_5_0_5_0_5 = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5\n" - -#define SPIRV_ASSEMBLY_ARRAYS \ - "%a1f32 = OpTypeArray %f32 %c_u32_1\n" \ - "%a2f32 = OpTypeArray %f32 %c_u32_2\n" \ - "%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n" \ - "%a4f32 = OpTypeArray %f32 %c_u32_4\n" \ - "%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n" \ - "%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n" \ - "%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n" \ - "%op_a2f32 = OpTypePointer Output %a2f32\n" \ - "%op_a3v4f32 = OpTypePointer Output %a3v4f32\n" \ - "%op_a4f32 = OpTypePointer Output %a4f32\n" - -// Creates vertex-shader assembly by specializing a boilerplate StringTemplate -// on fragments, which must (at least) map "testfun" to an OpFunction definition -// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed -// with "BP_" to avoid collisions with fragments. -// -// It corresponds roughly to this GLSL: -//; -// layout(location = 0) in vec4 position; -// layout(location = 1) in vec4 color; -// layout(location = 1) out highp vec4 vtxColor; -// void main (void) { gl_Position = position; vtxColor = test_func(color); } -string makeVertexShaderAssembly(const map& fragments) -{ -// \todo [2015-11-23 awoloszyn] Remove OpName once these have stabalized - static const char vertexShaderBoilerplate[] = - "OpCapability Shader\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Vertex %main \"main\" %BP_stream %BP_position %BP_vtx_color %BP_color %BP_gl_VertexIndex %BP_gl_InstanceIndex\n" - "${debug:opt}\n" - "OpName %main \"main\"\n" - "OpName %BP_gl_PerVertex \"gl_PerVertex\"\n" - "OpMemberName %BP_gl_PerVertex 0 \"gl_Position\"\n" - "OpMemberName %BP_gl_PerVertex 1 \"gl_PointSize\"\n" - "OpMemberName %BP_gl_PerVertex 2 \"gl_ClipDistance\"\n" - "OpMemberName %BP_gl_PerVertex 3 \"gl_CullDistance\"\n" - "OpName %test_code \"testfun(vf4;\"\n" - "OpName %BP_stream \"\"\n" - "OpName %BP_position \"position\"\n" - "OpName %BP_vtx_color \"vtxColor\"\n" - "OpName %BP_color \"color\"\n" - "OpName %BP_gl_VertexIndex \"gl_VertexIndex\"\n" - "OpName %BP_gl_InstanceIndex \"gl_InstanceIndex\"\n" - "OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n" - "OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n" - "OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n" - "OpDecorate %BP_gl_PerVertex Block\n" - "OpDecorate %BP_position Location 0\n" - "OpDecorate %BP_vtx_color Location 1\n" - "OpDecorate %BP_color Location 1\n" - "OpDecorate %BP_gl_VertexIndex BuiltIn VertexIndex\n" - "OpDecorate %BP_gl_InstanceIndex BuiltIn InstanceIndex\n" - "${decoration:opt}\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%BP_op_gl_PerVertex = OpTypePointer Output %BP_gl_PerVertex\n" - "%BP_stream = OpVariable %BP_op_gl_PerVertex Output\n" - "%BP_position = OpVariable %ip_v4f32 Input\n" - "%BP_vtx_color = OpVariable %op_v4f32 Output\n" - "%BP_color = OpVariable %ip_v4f32 Input\n" - "%BP_gl_VertexIndex = OpVariable %ip_i32 Input\n" - "%BP_gl_InstanceIndex = OpVariable %ip_i32 Input\n" - "${pre_main:opt}\n" - "%main = OpFunction %void None %fun\n" - "%BP_label = OpLabel\n" - "%BP_pos = OpLoad %v4f32 %BP_position\n" - "%BP_gl_pos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n" - "OpStore %BP_gl_pos %BP_pos\n" - "%BP_col = OpLoad %v4f32 %BP_color\n" - "%BP_col_transformed = OpFunctionCall %v4f32 %test_code %BP_col\n" - "OpStore %BP_vtx_color %BP_col_transformed\n" - "OpReturn\n" - "OpFunctionEnd\n" - "${testfun}\n"; - return tcu::StringTemplate(vertexShaderBoilerplate).specialize(fragments); -} - -// Creates tess-control-shader assembly by specializing a boilerplate -// StringTemplate on fragments, which must (at least) map "testfun" to an -// OpFunction definition for %test_code that takes and returns a %v4f32. -// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments. -// -// It roughly corresponds to the following GLSL. -// -// #version 450 -// layout(vertices = 3) out; -// layout(location = 1) in vec4 in_color[]; -// layout(location = 1) out vec4 out_color[]; -// -// void main() { -// out_color[gl_InvocationID] = testfun(in_color[gl_InvocationID]); -// gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; -// if (gl_InvocationID == 0) { -// gl_TessLevelOuter[0] = 1.0; -// gl_TessLevelOuter[1] = 1.0; -// gl_TessLevelOuter[2] = 1.0; -// gl_TessLevelInner[0] = 1.0; -// } -// } -string makeTessControlShaderAssembly (const map& fragments) -{ - static const char tessControlShaderBoilerplate[] = - "OpCapability Tessellation\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint TessellationControl %BP_main \"main\" %BP_out_color %BP_gl_InvocationID %BP_in_color %BP_gl_out %BP_gl_in %BP_gl_TessLevelOuter %BP_gl_TessLevelInner\n" - "OpExecutionMode %BP_main OutputVertices 3\n" - "${debug:opt}\n" - "OpName %BP_main \"main\"\n" - "OpName %test_code \"testfun(vf4;\"\n" - "OpName %BP_out_color \"out_color\"\n" - "OpName %BP_gl_InvocationID \"gl_InvocationID\"\n" - "OpName %BP_in_color \"in_color\"\n" - "OpName %BP_gl_PerVertex \"gl_PerVertex\"\n" - "OpMemberName %BP_gl_PerVertex 0 \"gl_Position\"\n" - "OpMemberName %BP_gl_PerVertex 1 \"gl_PointSize\"\n" - "OpMemberName %BP_gl_PerVertex 2 \"gl_ClipDistance\"\n" - "OpMemberName %BP_gl_PerVertex 3 \"gl_CullDistance\"\n" - "OpName %BP_gl_out \"gl_out\"\n" - "OpName %BP_gl_PVOut \"gl_PerVertex\"\n" - "OpMemberName %BP_gl_PVOut 0 \"gl_Position\"\n" - "OpMemberName %BP_gl_PVOut 1 \"gl_PointSize\"\n" - "OpMemberName %BP_gl_PVOut 2 \"gl_ClipDistance\"\n" - "OpMemberName %BP_gl_PVOut 3 \"gl_CullDistance\"\n" - "OpName %BP_gl_in \"gl_in\"\n" - "OpName %BP_gl_TessLevelOuter \"gl_TessLevelOuter\"\n" - "OpName %BP_gl_TessLevelInner \"gl_TessLevelInner\"\n" - "OpDecorate %BP_out_color Location 1\n" - "OpDecorate %BP_gl_InvocationID BuiltIn InvocationId\n" - "OpDecorate %BP_in_color Location 1\n" - "OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n" - "OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n" - "OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n" - "OpDecorate %BP_gl_PerVertex Block\n" - "OpMemberDecorate %BP_gl_PVOut 0 BuiltIn Position\n" - "OpMemberDecorate %BP_gl_PVOut 1 BuiltIn PointSize\n" - "OpMemberDecorate %BP_gl_PVOut 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %BP_gl_PVOut 3 BuiltIn CullDistance\n" - "OpDecorate %BP_gl_PVOut Block\n" - "OpDecorate %BP_gl_TessLevelOuter Patch\n" - "OpDecorate %BP_gl_TessLevelOuter BuiltIn TessLevelOuter\n" - "OpDecorate %BP_gl_TessLevelInner Patch\n" - "OpDecorate %BP_gl_TessLevelInner BuiltIn TessLevelInner\n" - "${decoration:opt}\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%BP_out_color = OpVariable %op_a3v4f32 Output\n" - "%BP_gl_InvocationID = OpVariable %ip_i32 Input\n" - "%BP_in_color = OpVariable %ip_a32v4f32 Input\n" - "%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%BP_a3_gl_PerVertex = OpTypeArray %BP_gl_PerVertex %c_u32_3\n" - "%BP_op_a3_gl_PerVertex = OpTypePointer Output %BP_a3_gl_PerVertex\n" - "%BP_gl_out = OpVariable %BP_op_a3_gl_PerVertex Output\n" - "%BP_gl_PVOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%BP_a32_gl_PVOut = OpTypeArray %BP_gl_PVOut %c_u32_32\n" - "%BP_ip_a32_gl_PVOut = OpTypePointer Input %BP_a32_gl_PVOut\n" - "%BP_gl_in = OpVariable %BP_ip_a32_gl_PVOut Input\n" - "%BP_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" - "%BP_gl_TessLevelInner = OpVariable %op_a2f32 Output\n" - "${pre_main:opt}\n" - - "%BP_main = OpFunction %void None %fun\n" - "%BP_label = OpLabel\n" - - "%BP_gl_Invoc = OpLoad %i32 %BP_gl_InvocationID\n" - - "%BP_in_col_loc = OpAccessChain %ip_v4f32 %BP_in_color %BP_gl_Invoc\n" - "%BP_out_col_loc = OpAccessChain %op_v4f32 %BP_out_color %BP_gl_Invoc\n" - "%BP_in_col_val = OpLoad %v4f32 %BP_in_col_loc\n" - "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_in_col_val\n" - "OpStore %BP_out_col_loc %BP_clr_transformed\n" - - "%BP_in_pos_loc = OpAccessChain %ip_v4f32 %BP_gl_in %BP_gl_Invoc %c_i32_0\n" - "%BP_out_pos_loc = OpAccessChain %op_v4f32 %BP_gl_out %BP_gl_Invoc %c_i32_0\n" - "%BP_in_pos_val = OpLoad %v4f32 %BP_in_pos_loc\n" - "OpStore %BP_out_pos_loc %BP_in_pos_val\n" - - "%BP_cmp = OpIEqual %bool %BP_gl_Invoc %c_i32_0\n" - "OpSelectionMerge %BP_merge_label None\n" - "OpBranchConditional %BP_cmp %BP_if_label %BP_merge_label\n" - "%BP_if_label = OpLabel\n" - "%BP_gl_TessLevelOuterPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_0\n" - "%BP_gl_TessLevelOuterPos_1 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_1\n" - "%BP_gl_TessLevelOuterPos_2 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_2\n" - "%BP_gl_TessLevelInnerPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelInner %c_i32_0\n" - "OpStore %BP_gl_TessLevelOuterPos_0 %c_f32_1\n" - "OpStore %BP_gl_TessLevelOuterPos_1 %c_f32_1\n" - "OpStore %BP_gl_TessLevelOuterPos_2 %c_f32_1\n" - "OpStore %BP_gl_TessLevelInnerPos_0 %c_f32_1\n" - "OpBranch %BP_merge_label\n" - "%BP_merge_label = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n" - "${testfun}\n"; - return tcu::StringTemplate(tessControlShaderBoilerplate).specialize(fragments); -} - -// Creates tess-evaluation-shader assembly by specializing a boilerplate -// StringTemplate on fragments, which must (at least) map "testfun" to an -// OpFunction definition for %test_code that takes and returns a %v4f32. -// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments. -// -// It roughly corresponds to the following glsl. -// -// #version 450 -// -// layout(triangles, equal_spacing, ccw) in; -// layout(location = 1) in vec4 in_color[]; -// layout(location = 1) out vec4 out_color; -// -// #define interpolate(val) -// vec4(gl_TessCoord.x) * val[0] + vec4(gl_TessCoord.y) * val[1] + -// vec4(gl_TessCoord.z) * val[2] -// -// void main() { -// gl_Position = vec4(gl_TessCoord.x) * gl_in[0].gl_Position + -// vec4(gl_TessCoord.y) * gl_in[1].gl_Position + -// vec4(gl_TessCoord.z) * gl_in[2].gl_Position; -// out_color = testfun(interpolate(in_color)); -// } -string makeTessEvalShaderAssembly(const map& fragments) -{ - static const char tessEvalBoilerplate[] = - "OpCapability Tessellation\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint TessellationEvaluation %BP_main \"main\" %BP_stream %BP_gl_TessCoord %BP_gl_in %BP_out_color %BP_in_color\n" - "OpExecutionMode %BP_main Triangles\n" - "OpExecutionMode %BP_main SpacingEqual\n" - "OpExecutionMode %BP_main VertexOrderCcw\n" - "${debug:opt}\n" - "OpName %BP_main \"main\"\n" - "OpName %test_code \"testfun(vf4;\"\n" - "OpName %BP_gl_PerVertexOut \"gl_PerVertex\"\n" - "OpMemberName %BP_gl_PerVertexOut 0 \"gl_Position\"\n" - "OpMemberName %BP_gl_PerVertexOut 1 \"gl_PointSize\"\n" - "OpMemberName %BP_gl_PerVertexOut 2 \"gl_ClipDistance\"\n" - "OpMemberName %BP_gl_PerVertexOut 3 \"gl_CullDistance\"\n" - "OpName %BP_stream \"\"\n" - "OpName %BP_gl_TessCoord \"gl_TessCoord\"\n" - "OpName %BP_gl_PerVertexIn \"gl_PerVertex\"\n" - "OpMemberName %BP_gl_PerVertexIn 0 \"gl_Position\"\n" - "OpMemberName %BP_gl_PerVertexIn 1 \"gl_PointSize\"\n" - "OpMemberName %BP_gl_PerVertexIn 2 \"gl_ClipDistance\"\n" - "OpMemberName %BP_gl_PerVertexIn 3 \"gl_CullDistance\"\n" - "OpName %BP_gl_in \"gl_in\"\n" - "OpName %BP_out_color \"out_color\"\n" - "OpName %BP_in_color \"in_color\"\n" - "OpMemberDecorate %BP_gl_PerVertexOut 0 BuiltIn Position\n" - "OpMemberDecorate %BP_gl_PerVertexOut 1 BuiltIn PointSize\n" - "OpMemberDecorate %BP_gl_PerVertexOut 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %BP_gl_PerVertexOut 3 BuiltIn CullDistance\n" - "OpDecorate %BP_gl_PerVertexOut Block\n" - "OpDecorate %BP_gl_TessCoord BuiltIn TessCoord\n" - "OpMemberDecorate %BP_gl_PerVertexIn 0 BuiltIn Position\n" - "OpMemberDecorate %BP_gl_PerVertexIn 1 BuiltIn PointSize\n" - "OpMemberDecorate %BP_gl_PerVertexIn 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %BP_gl_PerVertexIn 3 BuiltIn CullDistance\n" - "OpDecorate %BP_gl_PerVertexIn Block\n" - "OpDecorate %BP_out_color Location 1\n" - "OpDecorate %BP_in_color Location 1\n" - "${decoration:opt}\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%BP_gl_PerVertexOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%BP_op_gl_PerVertexOut = OpTypePointer Output %BP_gl_PerVertexOut\n" - "%BP_stream = OpVariable %BP_op_gl_PerVertexOut Output\n" - "%BP_gl_TessCoord = OpVariable %ip_v3f32 Input\n" - "%BP_gl_PerVertexIn = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%BP_a32_gl_PerVertexIn = OpTypeArray %BP_gl_PerVertexIn %c_u32_32\n" - "%BP_ip_a32_gl_PerVertexIn = OpTypePointer Input %BP_a32_gl_PerVertexIn\n" - "%BP_gl_in = OpVariable %BP_ip_a32_gl_PerVertexIn Input\n" - "%BP_out_color = OpVariable %op_v4f32 Output\n" - "%BP_in_color = OpVariable %ip_a32v4f32 Input\n" - "${pre_main:opt}\n" - "%BP_main = OpFunction %void None %fun\n" - "%BP_label = OpLabel\n" - "%BP_gl_TC_0 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_0\n" - "%BP_gl_TC_1 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_1\n" - "%BP_gl_TC_2 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_2\n" - "%BP_gl_in_gl_Pos_0 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n" - "%BP_gl_in_gl_Pos_1 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n" - "%BP_gl_in_gl_Pos_2 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n" - - "%BP_gl_OPos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n" - "%BP_in_color_0 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n" - "%BP_in_color_1 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n" - "%BP_in_color_2 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n" - - "%BP_TC_W_0 = OpLoad %f32 %BP_gl_TC_0\n" - "%BP_TC_W_1 = OpLoad %f32 %BP_gl_TC_1\n" - "%BP_TC_W_2 = OpLoad %f32 %BP_gl_TC_2\n" - "%BP_v4f32_TC_0 = OpCompositeConstruct %v4f32 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0\n" - "%BP_v4f32_TC_1 = OpCompositeConstruct %v4f32 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1\n" - "%BP_v4f32_TC_2 = OpCompositeConstruct %v4f32 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2\n" - - "%BP_gl_IP_0 = OpLoad %v4f32 %BP_gl_in_gl_Pos_0\n" - "%BP_gl_IP_1 = OpLoad %v4f32 %BP_gl_in_gl_Pos_1\n" - "%BP_gl_IP_2 = OpLoad %v4f32 %BP_gl_in_gl_Pos_2\n" - - "%BP_IP_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_gl_IP_0\n" - "%BP_IP_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_gl_IP_1\n" - "%BP_IP_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_gl_IP_2\n" - - "%BP_pos_sum_0 = OpFAdd %v4f32 %BP_IP_W_0 %BP_IP_W_1\n" - "%BP_pos_sum_1 = OpFAdd %v4f32 %BP_pos_sum_0 %BP_IP_W_2\n" - - "OpStore %BP_gl_OPos %BP_pos_sum_1\n" - - "%BP_IC_0 = OpLoad %v4f32 %BP_in_color_0\n" - "%BP_IC_1 = OpLoad %v4f32 %BP_in_color_1\n" - "%BP_IC_2 = OpLoad %v4f32 %BP_in_color_2\n" - - "%BP_IC_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_IC_0\n" - "%BP_IC_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_IC_1\n" - "%BP_IC_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_IC_2\n" - - "%BP_col_sum_0 = OpFAdd %v4f32 %BP_IC_W_0 %BP_IC_W_1\n" - "%BP_col_sum_1 = OpFAdd %v4f32 %BP_col_sum_0 %BP_IC_W_2\n" - - "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_col_sum_1\n" - - "OpStore %BP_out_color %BP_clr_transformed\n" - "OpReturn\n" - "OpFunctionEnd\n" - "${testfun}\n"; - return tcu::StringTemplate(tessEvalBoilerplate).specialize(fragments); -} - -// Creates geometry-shader assembly by specializing a boilerplate StringTemplate -// on fragments, which must (at least) map "testfun" to an OpFunction definition -// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed -// with "BP_" to avoid collisions with fragments. -// -// Derived from this GLSL: -// -// #version 450 -// layout(triangles) in; -// layout(triangle_strip, max_vertices = 3) out; -// -// layout(location = 1) in vec4 in_color[]; -// layout(location = 1) out vec4 out_color; -// -// void main() { -// gl_Position = gl_in[0].gl_Position; -// out_color = test_fun(in_color[0]); -// EmitVertex(); -// gl_Position = gl_in[1].gl_Position; -// out_color = test_fun(in_color[1]); -// EmitVertex(); -// gl_Position = gl_in[2].gl_Position; -// out_color = test_fun(in_color[2]); -// EmitVertex(); -// EndPrimitive(); -// } -string makeGeometryShaderAssembly(const map& fragments) -{ - static const char geometryShaderBoilerplate[] = - "OpCapability Geometry\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Geometry %BP_main \"main\" %BP_out_gl_position %BP_gl_in %BP_out_color %BP_in_color\n" - "OpExecutionMode %BP_main Triangles\n" - "OpExecutionMode %BP_main OutputTriangleStrip\n" - "OpExecutionMode %BP_main OutputVertices 3\n" - "${debug:opt}\n" - "OpName %BP_main \"main\"\n" - "OpName %BP_per_vertex_in \"gl_PerVertex\"\n" - "OpMemberName %BP_per_vertex_in 0 \"gl_Position\"\n" - "OpMemberName %BP_per_vertex_in 1 \"gl_PointSize\"\n" - "OpMemberName %BP_per_vertex_in 2 \"gl_ClipDistance\"\n" - "OpMemberName %BP_per_vertex_in 3 \"gl_CullDistance\"\n" - "OpName %BP_gl_in \"gl_in\"\n" - "OpName %BP_out_color \"out_color\"\n" - "OpName %BP_in_color \"in_color\"\n" - "OpName %test_code \"testfun(vf4;\"\n" - "OpDecorate %BP_out_gl_position BuiltIn Position\n" - "OpMemberDecorate %BP_per_vertex_in 0 BuiltIn Position\n" - "OpMemberDecorate %BP_per_vertex_in 1 BuiltIn PointSize\n" - "OpMemberDecorate %BP_per_vertex_in 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %BP_per_vertex_in 3 BuiltIn CullDistance\n" - "OpDecorate %BP_per_vertex_in Block\n" - "OpDecorate %BP_out_color Location 1\n" - "OpDecorate %BP_in_color Location 1\n" - "${decoration:opt}\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%BP_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%BP_a3_per_vertex_in = OpTypeArray %BP_per_vertex_in %c_u32_3\n" - "%BP_ip_a3_per_vertex_in = OpTypePointer Input %BP_a3_per_vertex_in\n" - - "%BP_gl_in = OpVariable %BP_ip_a3_per_vertex_in Input\n" - "%BP_out_color = OpVariable %op_v4f32 Output\n" - "%BP_in_color = OpVariable %ip_a3v4f32 Input\n" - "%BP_out_gl_position = OpVariable %op_v4f32 Output\n" - "${pre_main:opt}\n" - - "%BP_main = OpFunction %void None %fun\n" - "%BP_label = OpLabel\n" - "%BP_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n" - "%BP_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n" - "%BP_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n" - - "%BP_in_position_0 = OpLoad %v4f32 %BP_gl_in_0_gl_position\n" - "%BP_in_position_1 = OpLoad %v4f32 %BP_gl_in_1_gl_position\n" - "%BP_in_position_2 = OpLoad %v4f32 %BP_gl_in_2_gl_position \n" - - "%BP_in_color_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n" - "%BP_in_color_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n" - "%BP_in_color_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n" - - "%BP_in_color_0 = OpLoad %v4f32 %BP_in_color_0_ptr\n" - "%BP_in_color_1 = OpLoad %v4f32 %BP_in_color_1_ptr\n" - "%BP_in_color_2 = OpLoad %v4f32 %BP_in_color_2_ptr\n" - - "%BP_transformed_in_color_0 = OpFunctionCall %v4f32 %test_code %BP_in_color_0\n" - "%BP_transformed_in_color_1 = OpFunctionCall %v4f32 %test_code %BP_in_color_1\n" - "%BP_transformed_in_color_2 = OpFunctionCall %v4f32 %test_code %BP_in_color_2\n" - - - "OpStore %BP_out_gl_position %BP_in_position_0\n" - "OpStore %BP_out_color %BP_transformed_in_color_0\n" - "OpEmitVertex\n" - - "OpStore %BP_out_gl_position %BP_in_position_1\n" - "OpStore %BP_out_color %BP_transformed_in_color_1\n" - "OpEmitVertex\n" - - "OpStore %BP_out_gl_position %BP_in_position_2\n" - "OpStore %BP_out_color %BP_transformed_in_color_2\n" - "OpEmitVertex\n" - - "OpEndPrimitive\n" - "OpReturn\n" - "OpFunctionEnd\n" - "${testfun}\n"; - return tcu::StringTemplate(geometryShaderBoilerplate).specialize(fragments); -} - -// Creates fragment-shader assembly by specializing a boilerplate StringTemplate -// on fragments, which must (at least) map "testfun" to an OpFunction definition -// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed -// with "BP_" to avoid collisions with fragments. -// -// Derived from this GLSL: -// -// layout(location = 1) in highp vec4 vtxColor; -// layout(location = 0) out highp vec4 fragColor; -// highp vec4 testfun(highp vec4 x) { return x; } -// void main(void) { fragColor = testfun(vtxColor); } -// -// with modifications including passing vtxColor by value and ripping out -// testfun() definition. -string makeFragmentShaderAssembly(const map& fragments) -{ - static const char fragmentShaderBoilerplate[] = - "OpCapability Shader\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Fragment %BP_main \"main\" %BP_vtxColor %BP_fragColor\n" - "OpExecutionMode %BP_main OriginUpperLeft\n" - "${debug:opt}\n" - "OpName %BP_main \"main\"\n" - "OpName %BP_fragColor \"fragColor\"\n" - "OpName %BP_vtxColor \"vtxColor\"\n" - "OpName %test_code \"testfun(vf4;\"\n" - "OpDecorate %BP_fragColor Location 0\n" - "OpDecorate %BP_vtxColor Location 1\n" - "${decoration:opt}\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%BP_fragColor = OpVariable %op_v4f32 Output\n" - "%BP_vtxColor = OpVariable %ip_v4f32 Input\n" - "${pre_main:opt}\n" - "%BP_main = OpFunction %void None %fun\n" - "%BP_label_main = OpLabel\n" - "%BP_tmp1 = OpLoad %v4f32 %BP_vtxColor\n" - "%BP_tmp2 = OpFunctionCall %v4f32 %test_code %BP_tmp1\n" - "OpStore %BP_fragColor %BP_tmp2\n" - "OpReturn\n" - "OpFunctionEnd\n" - "${testfun}\n"; - return tcu::StringTemplate(fragmentShaderBoilerplate).specialize(fragments); -} - -// Creates fragments that specialize into a simple pass-through shader (of any kind). -map passthruFragments(void) -{ - map fragments; - fragments["testfun"] = - // A %test_code function that returns its argument unchanged. - "%test_code = OpFunction %v4f32 None %v4f32_function\n" - "%param1 = OpFunctionParameter %v4f32\n" - "%label_testfun = OpLabel\n" - "OpReturnValue %param1\n" - "OpFunctionEnd\n"; - return fragments; -} - -// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. -// Vertex shader gets custom code from context, the rest are pass-through. -void addShaderCodeCustomVertex(vk::SourceCollections& dst, InstanceContext context) -{ - map passthru = passthruFragments(); - dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(context.testCodeFragments); - dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); -} - -// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. -// Tessellation control shader gets custom code from context, the rest are -// pass-through. -void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext context) -{ - map passthru = passthruFragments(); - dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); - dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(context.testCodeFragments); - dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru); - dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); -} - -// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. -// Tessellation evaluation shader gets custom code from context, the rest are -// pass-through. -void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext context) -{ - map passthru = passthruFragments(); - dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); - dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru); - dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(context.testCodeFragments); - dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); -} - -// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. -// Geometry shader gets custom code from context, the rest are pass-through. -void addShaderCodeCustomGeometry(vk::SourceCollections& dst, InstanceContext context) -{ - map passthru = passthruFragments(); - dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); - dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(context.testCodeFragments); - dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); -} - -// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. -// Fragment shader gets custom code from context, the rest are pass-through. -void addShaderCodeCustomFragment(vk::SourceCollections& dst, InstanceContext context) -{ - map passthru = passthruFragments(); - dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); - dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(context.testCodeFragments); -} - -void createCombinedModule(vk::SourceCollections& dst, InstanceContext) -{ - // \todo [2015-12-07 awoloszyn] Make tessellation / geometry conditional - // \todo [2015-12-07 awoloszyn] Remove OpName and OpMemberName at some point - dst.spirvAsmSources.add("module") << - "OpCapability Shader\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpCapability Geometry\n" - "OpCapability Tessellation\n" - "OpMemoryModel Logical GLSL450\n" - - "OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_vtxPosition %vert_vertex_id %vert_instance_id\n" - "OpEntryPoint Geometry %geom_main \"main\" %geom_out_gl_position %geom_gl_in %geom_out_color %geom_in_color\n" - "OpEntryPoint TessellationControl %tessc_main \"main\" %tessc_out_color %tessc_gl_InvocationID %tessc_in_color %tessc_out_position %tessc_in_position %tessc_gl_TessLevelOuter %tessc_gl_TessLevelInner\n" - "OpEntryPoint TessellationEvaluation %tesse_main \"main\" %tesse_stream %tesse_gl_tessCoord %tesse_in_position %tesse_out_color %tesse_in_color \n" - "OpEntryPoint Fragment %frag_main \"main\" %frag_vtxColor %frag_fragColor\n" - - "OpExecutionMode %geom_main Triangles\n" - "OpExecutionMode %geom_main OutputTriangleStrip\n" - "OpExecutionMode %geom_main OutputVertices 3\n" - - "OpExecutionMode %tessc_main OutputVertices 3\n" - - "OpExecutionMode %tesse_main Triangles\n" - "OpExecutionMode %tesse_main SpacingEqual\n" - "OpExecutionMode %tesse_main VertexOrderCcw\n" - - "OpExecutionMode %frag_main OriginUpperLeft\n" - - "OpName %vert_main \"main\"\n" - "OpName %vert_vtxPosition \"vtxPosition\"\n" - "OpName %vert_Position \"position\"\n" - "OpName %vert_vtxColor \"vtxColor\"\n" - "OpName %vert_color \"color\"\n" - "OpName %vert_vertex_id \"gl_VertexIndex\"\n" - "OpName %vert_instance_id \"gl_InstanceIndex\"\n" - "OpName %geom_main \"main\"\n" - "OpName %geom_per_vertex_in \"gl_PerVertex\"\n" - "OpMemberName %geom_per_vertex_in 0 \"gl_Position\"\n" - "OpMemberName %geom_per_vertex_in 1 \"gl_PointSize\"\n" - "OpMemberName %geom_per_vertex_in 2 \"gl_ClipDistance\"\n" - "OpMemberName %geom_per_vertex_in 3 \"gl_CullDistance\"\n" - "OpName %geom_gl_in \"gl_in\"\n" - "OpName %geom_out_color \"out_color\"\n" - "OpName %geom_in_color \"in_color\"\n" - "OpName %tessc_main \"main\"\n" - "OpName %tessc_out_color \"out_color\"\n" - "OpName %tessc_gl_InvocationID \"gl_InvocationID\"\n" - "OpName %tessc_in_color \"in_color\"\n" - "OpName %tessc_out_position \"out_position\"\n" - "OpName %tessc_in_position \"in_position\"\n" - "OpName %tessc_gl_TessLevelOuter \"gl_TessLevelOuter\"\n" - "OpName %tessc_gl_TessLevelInner \"gl_TessLevelInner\"\n" - "OpName %tesse_main \"main\"\n" - "OpName %tesse_per_vertex_out \"gl_PerVertex\"\n" - "OpMemberName %tesse_per_vertex_out 0 \"gl_Position\"\n" - "OpMemberName %tesse_per_vertex_out 1 \"gl_PointSize\"\n" - "OpMemberName %tesse_per_vertex_out 2 \"gl_ClipDistance\"\n" - "OpMemberName %tesse_per_vertex_out 3 \"gl_CullDistance\"\n" - "OpName %tesse_stream \"\"\n" - "OpName %tesse_gl_tessCoord \"gl_TessCoord\"\n" - "OpName %tesse_in_position \"in_position\"\n" - "OpName %tesse_out_color \"out_color\"\n" - "OpName %tesse_in_color \"in_color\"\n" - "OpName %frag_main \"main\"\n" - "OpName %frag_fragColor \"fragColor\"\n" - "OpName %frag_vtxColor \"vtxColor\"\n" - - "; Vertex decorations\n" - "OpDecorate %vert_vtxPosition Location 2\n" - "OpDecorate %vert_Position Location 0\n" - "OpDecorate %vert_vtxColor Location 1\n" - "OpDecorate %vert_color Location 1\n" - "OpDecorate %vert_vertex_id BuiltIn VertexIndex\n" - "OpDecorate %vert_instance_id BuiltIn InstanceIndex\n" - - "; Geometry decorations\n" - "OpDecorate %geom_out_gl_position BuiltIn Position\n" - "OpMemberDecorate %geom_per_vertex_in 0 BuiltIn Position\n" - "OpMemberDecorate %geom_per_vertex_in 1 BuiltIn PointSize\n" - "OpMemberDecorate %geom_per_vertex_in 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %geom_per_vertex_in 3 BuiltIn CullDistance\n" - "OpDecorate %geom_per_vertex_in Block\n" - "OpDecorate %geom_out_color Location 1\n" - "OpDecorate %geom_in_color Location 1\n" - - "; Tessellation Control decorations\n" - "OpDecorate %tessc_out_color Location 1\n" - "OpDecorate %tessc_gl_InvocationID BuiltIn InvocationId\n" - "OpDecorate %tessc_in_color Location 1\n" - "OpDecorate %tessc_out_position Location 2\n" - "OpDecorate %tessc_in_position Location 2\n" - "OpDecorate %tessc_gl_TessLevelOuter Patch\n" - "OpDecorate %tessc_gl_TessLevelOuter BuiltIn TessLevelOuter\n" - "OpDecorate %tessc_gl_TessLevelInner Patch\n" - "OpDecorate %tessc_gl_TessLevelInner BuiltIn TessLevelInner\n" - - "; Tessellation Evaluation decorations\n" - "OpMemberDecorate %tesse_per_vertex_out 0 BuiltIn Position\n" - "OpMemberDecorate %tesse_per_vertex_out 1 BuiltIn PointSize\n" - "OpMemberDecorate %tesse_per_vertex_out 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %tesse_per_vertex_out 3 BuiltIn CullDistance\n" - "OpDecorate %tesse_per_vertex_out Block\n" - "OpDecorate %tesse_gl_tessCoord BuiltIn TessCoord\n" - "OpDecorate %tesse_in_position Location 2\n" - "OpDecorate %tesse_out_color Location 1\n" - "OpDecorate %tesse_in_color Location 1\n" - - "; Fragment decorations\n" - "OpDecorate %frag_fragColor Location 0\n" - "OpDecorate %frag_vtxColor Location 1\n" - - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - - "; Vertex Variables\n" - "%vert_vtxPosition = OpVariable %op_v4f32 Output\n" - "%vert_Position = OpVariable %ip_v4f32 Input\n" - "%vert_vtxColor = OpVariable %op_v4f32 Output\n" - "%vert_color = OpVariable %ip_v4f32 Input\n" - "%vert_vertex_id = OpVariable %ip_i32 Input\n" - "%vert_instance_id = OpVariable %ip_i32 Input\n" - - "; Geometry Variables\n" - "%geom_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%geom_a3_per_vertex_in = OpTypeArray %geom_per_vertex_in %c_u32_3\n" - "%geom_ip_a3_per_vertex_in = OpTypePointer Input %geom_a3_per_vertex_in\n" - "%geom_gl_in = OpVariable %geom_ip_a3_per_vertex_in Input\n" - "%geom_out_color = OpVariable %op_v4f32 Output\n" - "%geom_in_color = OpVariable %ip_a3v4f32 Input\n" - "%geom_out_gl_position = OpVariable %op_v4f32 Output\n" - - "; Tessellation Control Variables\n" - "%tessc_out_color = OpVariable %op_a3v4f32 Output\n" - "%tessc_gl_InvocationID = OpVariable %ip_i32 Input\n" - "%tessc_in_color = OpVariable %ip_a32v4f32 Input\n" - "%tessc_out_position = OpVariable %op_a3v4f32 Output\n" - "%tessc_in_position = OpVariable %ip_a32v4f32 Input\n" - "%tessc_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" - "%tessc_gl_TessLevelInner = OpVariable %op_a2f32 Output\n" - - "; Tessellation Evaluation Decorations\n" - "%tesse_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%tesse_op_per_vertex_out = OpTypePointer Output %tesse_per_vertex_out\n" - "%tesse_stream = OpVariable %tesse_op_per_vertex_out Output\n" - "%tesse_gl_tessCoord = OpVariable %ip_v3f32 Input\n" - "%tesse_in_position = OpVariable %ip_a32v4f32 Input\n" - "%tesse_out_color = OpVariable %op_v4f32 Output\n" - "%tesse_in_color = OpVariable %ip_a32v4f32 Input\n" - - "; Fragment Variables\n" - "%frag_fragColor = OpVariable %op_v4f32 Output\n" - "%frag_vtxColor = OpVariable %ip_v4f32 Input\n" - - "; Vertex Entry\n" - "%vert_main = OpFunction %void None %fun\n" - "%vert_label = OpLabel\n" - "%vert_tmp_position = OpLoad %v4f32 %vert_Position\n" - "OpStore %vert_vtxPosition %vert_tmp_position\n" - "%vert_tmp_color = OpLoad %v4f32 %vert_color\n" - "OpStore %vert_vtxColor %vert_tmp_color\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "; Geometry Entry\n" - "%geom_main = OpFunction %void None %fun\n" - "%geom_label = OpLabel\n" - "%geom_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_0 %c_i32_0\n" - "%geom_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_1 %c_i32_0\n" - "%geom_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_2 %c_i32_0\n" - "%geom_in_position_0 = OpLoad %v4f32 %geom_gl_in_0_gl_position\n" - "%geom_in_position_1 = OpLoad %v4f32 %geom_gl_in_1_gl_position\n" - "%geom_in_position_2 = OpLoad %v4f32 %geom_gl_in_2_gl_position \n" - "%geom_in_color_0_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_0\n" - "%geom_in_color_1_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_1\n" - "%geom_in_color_2_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_2\n" - "%geom_in_color_0 = OpLoad %v4f32 %geom_in_color_0_ptr\n" - "%geom_in_color_1 = OpLoad %v4f32 %geom_in_color_1_ptr\n" - "%geom_in_color_2 = OpLoad %v4f32 %geom_in_color_2_ptr\n" - "OpStore %geom_out_gl_position %geom_in_position_0\n" - "OpStore %geom_out_color %geom_in_color_0\n" - "OpEmitVertex\n" - "OpStore %geom_out_gl_position %geom_in_position_1\n" - "OpStore %geom_out_color %geom_in_color_1\n" - "OpEmitVertex\n" - "OpStore %geom_out_gl_position %geom_in_position_2\n" - "OpStore %geom_out_color %geom_in_color_2\n" - "OpEmitVertex\n" - "OpEndPrimitive\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "; Tessellation Control Entry\n" - "%tessc_main = OpFunction %void None %fun\n" - "%tessc_label = OpLabel\n" - "%tessc_invocation_id = OpLoad %i32 %tessc_gl_InvocationID\n" - "%tessc_in_color_ptr = OpAccessChain %ip_v4f32 %tessc_in_color %tessc_invocation_id\n" - "%tessc_in_position_ptr = OpAccessChain %ip_v4f32 %tessc_in_position %tessc_invocation_id\n" - "%tessc_in_color_val = OpLoad %v4f32 %tessc_in_color_ptr\n" - "%tessc_in_position_val = OpLoad %v4f32 %tessc_in_position_ptr\n" - "%tessc_out_color_ptr = OpAccessChain %op_v4f32 %tessc_out_color %tessc_invocation_id\n" - "%tessc_out_position_ptr = OpAccessChain %op_v4f32 %tessc_out_position %tessc_invocation_id\n" - "OpStore %tessc_out_color_ptr %tessc_in_color_val\n" - "OpStore %tessc_out_position_ptr %tessc_in_position_val\n" - "%tessc_is_first_invocation = OpIEqual %bool %tessc_invocation_id %c_i32_0\n" - "OpSelectionMerge %tessc_merge_label None\n" - "OpBranchConditional %tessc_is_first_invocation %tessc_first_invocation %tessc_merge_label\n" - "%tessc_first_invocation = OpLabel\n" - "%tessc_tess_outer_0 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_0\n" - "%tessc_tess_outer_1 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_1\n" - "%tessc_tess_outer_2 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_2\n" - "%tessc_tess_inner = OpAccessChain %op_f32 %tessc_gl_TessLevelInner %c_i32_0\n" - "OpStore %tessc_tess_outer_0 %c_f32_1\n" - "OpStore %tessc_tess_outer_1 %c_f32_1\n" - "OpStore %tessc_tess_outer_2 %c_f32_1\n" - "OpStore %tessc_tess_inner %c_f32_1\n" - "OpBranch %tessc_merge_label\n" - "%tessc_merge_label = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "; Tessellation Evaluation Entry\n" - "%tesse_main = OpFunction %void None %fun\n" - "%tesse_label = OpLabel\n" - "%tesse_tc_0_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_0\n" - "%tesse_tc_1_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_1\n" - "%tesse_tc_2_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_2\n" - "%tesse_tc_0 = OpLoad %f32 %tesse_tc_0_ptr\n" - "%tesse_tc_1 = OpLoad %f32 %tesse_tc_1_ptr\n" - "%tesse_tc_2 = OpLoad %f32 %tesse_tc_2_ptr\n" - "%tesse_in_pos_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_0\n" - "%tesse_in_pos_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_1\n" - "%tesse_in_pos_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_2\n" - "%tesse_in_pos_0 = OpLoad %v4f32 %tesse_in_pos_0_ptr\n" - "%tesse_in_pos_1 = OpLoad %v4f32 %tesse_in_pos_1_ptr\n" - "%tesse_in_pos_2 = OpLoad %v4f32 %tesse_in_pos_2_ptr\n" - "%tesse_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_0 %tesse_tc_0\n" - "%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_1 %tesse_tc_1\n" - "%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_2 %tesse_tc_2\n" - "%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n" - "%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n" - "%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n" - "OpStore %tesse_out_pos_ptr %tesse_computed_out\n" - "%tesse_in_clr_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_0\n" - "%tesse_in_clr_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_1\n" - "%tesse_in_clr_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_2\n" - "%tesse_in_clr_0 = OpLoad %v4f32 %tesse_in_clr_0_ptr\n" - "%tesse_in_clr_1 = OpLoad %v4f32 %tesse_in_clr_1_ptr\n" - "%tesse_in_clr_2 = OpLoad %v4f32 %tesse_in_clr_2_ptr\n" - "%tesse_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_0 %tesse_tc_0\n" - "%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_1 %tesse_tc_1\n" - "%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_2 %tesse_tc_2\n" - "%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n" - "%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n" - "OpStore %tesse_out_color %tesse_computed_clr\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "; Fragment Entry\n" - "%frag_main = OpFunction %void None %fun\n" - "%frag_label_main = OpLabel\n" - "%frag_tmp1 = OpLoad %v4f32 %frag_vtxColor\n" - "OpStore %frag_fragColor %frag_tmp1\n" - "OpReturn\n" - "OpFunctionEnd\n"; -} - -// This has two shaders of each stage. The first -// is a passthrough, the second inverts the color. -void createMultipleEntries(vk::SourceCollections& dst, InstanceContext) -{ - dst.spirvAsmSources.add("vert") << - // This module contains 2 vertex shaders. One that is a passthrough - // and a second that inverts the color of the output (1.0 - color). - "OpCapability Shader\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Vertex %main \"vert1\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n" - "OpEntryPoint Vertex %main2 \"vert2\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n" - - "OpName %main \"vert1\"\n" - "OpName %main2 \"vert2\"\n" - "OpName %vtxPosition \"vtxPosition\"\n" - "OpName %Position \"position\"\n" - "OpName %vtxColor \"vtxColor\"\n" - "OpName %color \"color\"\n" - "OpName %vertex_id \"gl_VertexIndex\"\n" - "OpName %instance_id \"gl_InstanceIndex\"\n" - - "OpDecorate %vtxPosition Location 2\n" - "OpDecorate %Position Location 0\n" - "OpDecorate %vtxColor Location 1\n" - "OpDecorate %color Location 1\n" - "OpDecorate %vertex_id BuiltIn VertexIndex\n" - "OpDecorate %instance_id BuiltIn InstanceIndex\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" - "%vtxPosition = OpVariable %op_v4f32 Output\n" - "%Position = OpVariable %ip_v4f32 Input\n" - "%vtxColor = OpVariable %op_v4f32 Output\n" - "%color = OpVariable %ip_v4f32 Input\n" - "%vertex_id = OpVariable %ip_i32 Input\n" - "%instance_id = OpVariable %ip_i32 Input\n" - - "%main = OpFunction %void None %fun\n" - "%label = OpLabel\n" - "%tmp_position = OpLoad %v4f32 %Position\n" - "OpStore %vtxPosition %tmp_position\n" - "%tmp_color = OpLoad %v4f32 %color\n" - "OpStore %vtxColor %tmp_color\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "%main2 = OpFunction %void None %fun\n" - "%label2 = OpLabel\n" - "%tmp_position2 = OpLoad %v4f32 %Position\n" - "OpStore %vtxPosition %tmp_position2\n" - "%tmp_color2 = OpLoad %v4f32 %color\n" - "%tmp_color3 = OpFSub %v4f32 %cval %tmp_color2\n" - "%tmp_color4 = OpVectorInsertDynamic %v4f32 %tmp_color3 %c_f32_1 %c_i32_3\n" - "OpStore %vtxColor %tmp_color4\n" - "OpReturn\n" - "OpFunctionEnd\n"; - - dst.spirvAsmSources.add("frag") << - // This is a single module that contains 2 fragment shaders. - // One that passes color through and the other that inverts the output - // color (1.0 - color). - "OpCapability Shader\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Fragment %main \"frag1\" %vtxColor %fragColor\n" - "OpEntryPoint Fragment %main2 \"frag2\" %vtxColor %fragColor\n" - "OpExecutionMode %main OriginUpperLeft\n" - "OpExecutionMode %main2 OriginUpperLeft\n" - - "OpName %main \"frag1\"\n" - "OpName %main2 \"frag2\"\n" - "OpName %fragColor \"fragColor\"\n" - "OpName %vtxColor \"vtxColor\"\n" - "OpDecorate %fragColor Location 0\n" - "OpDecorate %vtxColor Location 1\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" - "%fragColor = OpVariable %op_v4f32 Output\n" - "%vtxColor = OpVariable %ip_v4f32 Input\n" - - "%main = OpFunction %void None %fun\n" - "%label_main = OpLabel\n" - "%tmp1 = OpLoad %v4f32 %vtxColor\n" - "OpStore %fragColor %tmp1\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "%main2 = OpFunction %void None %fun\n" - "%label_main2 = OpLabel\n" - "%tmp2 = OpLoad %v4f32 %vtxColor\n" - "%tmp3 = OpFSub %v4f32 %cval %tmp2\n" - "%tmp4 = OpVectorInsertDynamic %v4f32 %tmp3 %c_f32_1 %c_i32_3\n" - "OpStore %fragColor %tmp4\n" - "OpReturn\n" - "OpFunctionEnd\n"; - - dst.spirvAsmSources.add("geom") << - "OpCapability Geometry\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint Geometry %geom1_main \"geom1\" %out_gl_position %gl_in %out_color %in_color\n" - "OpEntryPoint Geometry %geom2_main \"geom2\" %out_gl_position %gl_in %out_color %in_color\n" - "OpExecutionMode %geom1_main Triangles\n" - "OpExecutionMode %geom2_main Triangles\n" - "OpExecutionMode %geom1_main OutputTriangleStrip\n" - "OpExecutionMode %geom2_main OutputTriangleStrip\n" - "OpExecutionMode %geom1_main OutputVertices 3\n" - "OpExecutionMode %geom2_main OutputVertices 3\n" - "OpName %geom1_main \"geom1\"\n" - "OpName %geom2_main \"geom2\"\n" - "OpName %per_vertex_in \"gl_PerVertex\"\n" - "OpMemberName %per_vertex_in 0 \"gl_Position\"\n" - "OpMemberName %per_vertex_in 1 \"gl_PointSize\"\n" - "OpMemberName %per_vertex_in 2 \"gl_ClipDistance\"\n" - "OpMemberName %per_vertex_in 3 \"gl_CullDistance\"\n" - "OpName %gl_in \"gl_in\"\n" - "OpName %out_color \"out_color\"\n" - "OpName %in_color \"in_color\"\n" - "OpDecorate %out_gl_position BuiltIn Position\n" - "OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n" - "OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n" - "OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n" - "OpDecorate %per_vertex_in Block\n" - "OpDecorate %out_color Location 1\n" - "OpDecorate %in_color Location 1\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" - "%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n" - "%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n" - "%gl_in = OpVariable %ip_a3_per_vertex_in Input\n" - "%out_color = OpVariable %op_v4f32 Output\n" - "%in_color = OpVariable %ip_a3v4f32 Input\n" - "%out_gl_position = OpVariable %op_v4f32 Output\n" - - "%geom1_main = OpFunction %void None %fun\n" - "%geom1_label = OpLabel\n" - "%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n" - "%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n" - "%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n" - "%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n" - "%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n" - "%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n" - "%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" - "%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" - "%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" - "%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n" - "%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n" - "%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n" - "OpStore %out_gl_position %geom1_in_position_0\n" - "OpStore %out_color %geom1_in_color_0\n" - "OpEmitVertex\n" - "OpStore %out_gl_position %geom1_in_position_1\n" - "OpStore %out_color %geom1_in_color_1\n" - "OpEmitVertex\n" - "OpStore %out_gl_position %geom1_in_position_2\n" - "OpStore %out_color %geom1_in_color_2\n" - "OpEmitVertex\n" - "OpEndPrimitive\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "%geom2_main = OpFunction %void None %fun\n" - "%geom2_label = OpLabel\n" - "%geom2_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n" - "%geom2_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n" - "%geom2_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n" - "%geom2_in_position_0 = OpLoad %v4f32 %geom2_gl_in_0_gl_position\n" - "%geom2_in_position_1 = OpLoad %v4f32 %geom2_gl_in_1_gl_position\n" - "%geom2_in_position_2 = OpLoad %v4f32 %geom2_gl_in_2_gl_position \n" - "%geom2_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" - "%geom2_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" - "%geom2_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" - "%geom2_in_color_0 = OpLoad %v4f32 %geom2_in_color_0_ptr\n" - "%geom2_in_color_1 = OpLoad %v4f32 %geom2_in_color_1_ptr\n" - "%geom2_in_color_2 = OpLoad %v4f32 %geom2_in_color_2_ptr\n" - "%geom2_transformed_in_color_0 = OpFSub %v4f32 %cval %geom2_in_color_0\n" - "%geom2_transformed_in_color_1 = OpFSub %v4f32 %cval %geom2_in_color_1\n" - "%geom2_transformed_in_color_2 = OpFSub %v4f32 %cval %geom2_in_color_2\n" - "%geom2_transformed_in_color_0_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_0 %c_f32_1 %c_i32_3\n" - "%geom2_transformed_in_color_1_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_1 %c_f32_1 %c_i32_3\n" - "%geom2_transformed_in_color_2_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_2 %c_f32_1 %c_i32_3\n" - "OpStore %out_gl_position %geom2_in_position_0\n" - "OpStore %out_color %geom2_transformed_in_color_0_a\n" - "OpEmitVertex\n" - "OpStore %out_gl_position %geom2_in_position_1\n" - "OpStore %out_color %geom2_transformed_in_color_1_a\n" - "OpEmitVertex\n" - "OpStore %out_gl_position %geom2_in_position_2\n" - "OpStore %out_color %geom2_transformed_in_color_2_a\n" - "OpEmitVertex\n" - "OpEndPrimitive\n" - "OpReturn\n" - "OpFunctionEnd\n"; - - dst.spirvAsmSources.add("tessc") << - "OpCapability Tessellation\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint TessellationControl %tessc1_main \"tessc1\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n" - "OpEntryPoint TessellationControl %tessc2_main \"tessc2\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n" - "OpExecutionMode %tessc1_main OutputVertices 3\n" - "OpExecutionMode %tessc2_main OutputVertices 3\n" - "OpName %tessc1_main \"tessc1\"\n" - "OpName %tessc2_main \"tessc2\"\n" - "OpName %out_color \"out_color\"\n" - "OpName %gl_InvocationID \"gl_InvocationID\"\n" - "OpName %in_color \"in_color\"\n" - "OpName %out_position \"out_position\"\n" - "OpName %in_position \"in_position\"\n" - "OpName %gl_TessLevelOuter \"gl_TessLevelOuter\"\n" - "OpName %gl_TessLevelInner \"gl_TessLevelInner\"\n" - "OpDecorate %out_color Location 1\n" - "OpDecorate %gl_InvocationID BuiltIn InvocationId\n" - "OpDecorate %in_color Location 1\n" - "OpDecorate %out_position Location 2\n" - "OpDecorate %in_position Location 2\n" - "OpDecorate %gl_TessLevelOuter Patch\n" - "OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n" - "OpDecorate %gl_TessLevelInner Patch\n" - "OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" - "%out_color = OpVariable %op_a3v4f32 Output\n" - "%gl_InvocationID = OpVariable %ip_i32 Input\n" - "%in_color = OpVariable %ip_a32v4f32 Input\n" - "%out_position = OpVariable %op_a3v4f32 Output\n" - "%in_position = OpVariable %ip_a32v4f32 Input\n" - "%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" - "%gl_TessLevelInner = OpVariable %op_a2f32 Output\n" - - "%tessc1_main = OpFunction %void None %fun\n" - "%tessc1_label = OpLabel\n" - "%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n" - "%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n" - "%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n" - "%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n" - "%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n" - "%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n" - "%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n" - "OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n" - "OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n" - "%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n" - "OpSelectionMerge %tessc1_merge_label None\n" - "OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n" - "%tessc1_first_invocation = OpLabel\n" - "%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n" - "%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n" - "%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n" - "%tessc1_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n" - "OpStore %tessc1_tess_outer_0 %c_f32_1\n" - "OpStore %tessc1_tess_outer_1 %c_f32_1\n" - "OpStore %tessc1_tess_outer_2 %c_f32_1\n" - "OpStore %tessc1_tess_inner %c_f32_1\n" - "OpBranch %tessc1_merge_label\n" - "%tessc1_merge_label = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "%tessc2_main = OpFunction %void None %fun\n" - "%tessc2_label = OpLabel\n" - "%tessc2_invocation_id = OpLoad %i32 %gl_InvocationID\n" - "%tessc2_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc2_invocation_id\n" - "%tessc2_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc2_invocation_id\n" - "%tessc2_in_color_val = OpLoad %v4f32 %tessc2_in_color_ptr\n" - "%tessc2_in_position_val = OpLoad %v4f32 %tessc2_in_position_ptr\n" - "%tessc2_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc2_invocation_id\n" - "%tessc2_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc2_invocation_id\n" - "%tessc2_transformed_color = OpFSub %v4f32 %cval %tessc2_in_color_val\n" - "%tessc2_transformed_color_a = OpVectorInsertDynamic %v4f32 %tessc2_transformed_color %c_f32_1 %c_i32_3\n" - "OpStore %tessc2_out_color_ptr %tessc2_transformed_color_a\n" - "OpStore %tessc2_out_position_ptr %tessc2_in_position_val\n" - "%tessc2_is_first_invocation = OpIEqual %bool %tessc2_invocation_id %c_i32_0\n" - "OpSelectionMerge %tessc2_merge_label None\n" - "OpBranchConditional %tessc2_is_first_invocation %tessc2_first_invocation %tessc2_merge_label\n" - "%tessc2_first_invocation = OpLabel\n" - "%tessc2_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n" - "%tessc2_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n" - "%tessc2_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n" - "%tessc2_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n" - "OpStore %tessc2_tess_outer_0 %c_f32_1\n" - "OpStore %tessc2_tess_outer_1 %c_f32_1\n" - "OpStore %tessc2_tess_outer_2 %c_f32_1\n" - "OpStore %tessc2_tess_inner %c_f32_1\n" - "OpBranch %tessc2_merge_label\n" - "%tessc2_merge_label = OpLabel\n" - "OpReturn\n" - "OpFunctionEnd\n"; - - dst.spirvAsmSources.add("tesse") << - "OpCapability Tessellation\n" - "OpCapability ClipDistance\n" - "OpCapability CullDistance\n" - "OpMemoryModel Logical GLSL450\n" - "OpEntryPoint TessellationEvaluation %tesse1_main \"tesse1\" %stream %gl_tessCoord %in_position %out_color %in_color \n" - "OpEntryPoint TessellationEvaluation %tesse2_main \"tesse2\" %stream %gl_tessCoord %in_position %out_color %in_color \n" - "OpExecutionMode %tesse1_main Triangles\n" - "OpExecutionMode %tesse1_main SpacingEqual\n" - "OpExecutionMode %tesse1_main VertexOrderCcw\n" - "OpExecutionMode %tesse2_main Triangles\n" - "OpExecutionMode %tesse2_main SpacingEqual\n" - "OpExecutionMode %tesse2_main VertexOrderCcw\n" - "OpName %tesse1_main \"tesse1\"\n" - "OpName %tesse2_main \"tesse2\"\n" - "OpName %per_vertex_out \"gl_PerVertex\"\n" - "OpMemberName %per_vertex_out 0 \"gl_Position\"\n" - "OpMemberName %per_vertex_out 1 \"gl_PointSize\"\n" - "OpMemberName %per_vertex_out 2 \"gl_ClipDistance\"\n" - "OpMemberName %per_vertex_out 3 \"gl_CullDistance\"\n" - "OpName %stream \"\"\n" - "OpName %gl_tessCoord \"gl_TessCoord\"\n" - "OpName %in_position \"in_position\"\n" - "OpName %out_color \"out_color\"\n" - "OpName %in_color \"in_color\"\n" - "OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n" - "OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n" - "OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n" - "OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n" - "OpDecorate %per_vertex_out Block\n" - "OpDecorate %gl_tessCoord BuiltIn TessCoord\n" - "OpDecorate %in_position Location 2\n" - "OpDecorate %out_color Location 1\n" - "OpDecorate %in_color Location 1\n" - SPIRV_ASSEMBLY_TYPES - SPIRV_ASSEMBLY_CONSTANTS - SPIRV_ASSEMBLY_ARRAYS - "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" - "%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" - "%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n" - "%stream = OpVariable %op_per_vertex_out Output\n" - "%gl_tessCoord = OpVariable %ip_v3f32 Input\n" - "%in_position = OpVariable %ip_a32v4f32 Input\n" - "%out_color = OpVariable %op_v4f32 Output\n" - "%in_color = OpVariable %ip_a32v4f32 Input\n" - - "%tesse1_main = OpFunction %void None %fun\n" - "%tesse1_label = OpLabel\n" - "%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n" - "%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n" - "%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n" - "%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n" - "%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n" - "%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n" - "%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n" - "%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n" - "%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n" - "%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n" - "%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n" - "%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n" - "%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_0 %tesse1_tc_0\n" - "%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_1 %tesse1_tc_1\n" - "%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_2 %tesse1_tc_2\n" - "%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n" - "%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n" - "%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n" - "OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n" - "%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" - "%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" - "%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" - "%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n" - "%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n" - "%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n" - "%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_0 %tesse1_tc_0\n" - "%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_1 %tesse1_tc_1\n" - "%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_2 %tesse1_tc_2\n" - "%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n" - "%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n" - "OpStore %out_color %tesse1_computed_clr\n" - "OpReturn\n" - "OpFunctionEnd\n" - - "%tesse2_main = OpFunction %void None %fun\n" - "%tesse2_label = OpLabel\n" - "%tesse2_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n" - "%tesse2_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n" - "%tesse2_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n" - "%tesse2_tc_0 = OpLoad %f32 %tesse2_tc_0_ptr\n" - "%tesse2_tc_1 = OpLoad %f32 %tesse2_tc_1_ptr\n" - "%tesse2_tc_2 = OpLoad %f32 %tesse2_tc_2_ptr\n" - "%tesse2_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n" - "%tesse2_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n" - "%tesse2_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n" - "%tesse2_in_pos_0 = OpLoad %v4f32 %tesse2_in_pos_0_ptr\n" - "%tesse2_in_pos_1 = OpLoad %v4f32 %tesse2_in_pos_1_ptr\n" - "%tesse2_in_pos_2 = OpLoad %v4f32 %tesse2_in_pos_2_ptr\n" - "%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_0 %tesse2_tc_0\n" - "%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_1 %tesse2_tc_1\n" - "%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_2 %tesse2_tc_2\n" - "%tesse2_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n" - "%tesse2_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse2_in_pos_0_weighted %tesse2_in_pos_1_weighted\n" - "%tesse2_computed_out = OpFAdd %v4f32 %tesse2_in_pos_0_plus_pos_1 %tesse2_in_pos_2_weighted\n" - "OpStore %tesse2_out_pos_ptr %tesse2_computed_out\n" - "%tesse2_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" - "%tesse2_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" - "%tesse2_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" - "%tesse2_in_clr_0 = OpLoad %v4f32 %tesse2_in_clr_0_ptr\n" - "%tesse2_in_clr_1 = OpLoad %v4f32 %tesse2_in_clr_1_ptr\n" - "%tesse2_in_clr_2 = OpLoad %v4f32 %tesse2_in_clr_2_ptr\n" - "%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_0 %tesse2_tc_0\n" - "%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_1 %tesse2_tc_1\n" - "%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_2 %tesse2_tc_2\n" - "%tesse2_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse2_in_clr_0_weighted %tesse2_in_clr_1_weighted\n" - "%tesse2_computed_clr = OpFAdd %v4f32 %tesse2_in_clr_0_plus_col_1 %tesse2_in_clr_2_weighted\n" - "%tesse2_clr_transformed = OpFSub %v4f32 %cval %tesse2_computed_clr\n" - "%tesse2_clr_transformed_a = OpVectorInsertDynamic %v4f32 %tesse2_clr_transformed %c_f32_1 %c_i32_3\n" - "OpStore %out_color %tesse2_clr_transformed_a\n" - "OpReturn\n" - "OpFunctionEnd\n"; -} - -// Sets up and runs a Vulkan pipeline, then spot-checks the resulting image. -// Feeds the pipeline a set of colored triangles, which then must occur in the -// rendered image. The surface is cleared before executing the pipeline, so -// whatever the shaders draw can be directly spot-checked. -TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance) -{ - const VkDevice vkDevice = context.getDevice(); - const DeviceInterface& vk = context.getDeviceInterface(); - const VkQueue queue = context.getUniversalQueue(); - const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); - const tcu::UVec2 renderSize (256, 256); - vector modules; - map moduleByStage; - const int testSpecificSeed = 31354125; - const int seed = context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed; - bool supportsGeometry = false; - bool supportsTessellation = false; - bool hasTessellation = false; - - const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures(); - supportsGeometry = features.geometryShader == VK_TRUE; - supportsTessellation = features.tessellationShader == VK_TRUE; - hasTessellation = (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) || - (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); - - if (hasTessellation && !supportsTessellation) - { - throw tcu::NotSupportedError(std::string("Tessellation not supported")); - } - - if ((instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT) && - !supportsGeometry) - { - throw tcu::NotSupportedError(std::string("Geometry not supported")); - } - - de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4); - de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4); - const Vec4 vertexData[] = - { - // Upper left corner: - Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(), - Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(), - Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(), - - // Upper right corner: - Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(), - Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(), - Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(), - - // Lower left corner: - Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(), - Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(), - Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(), - - // Lower right corner: - Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(), - Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(), - Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec() - }; - const size_t singleVertexDataSize = 2 * sizeof(Vec4); - const size_t vertexCount = sizeof(vertexData) / singleVertexDataSize; - - const VkBufferCreateInfo vertexBufferParams = - { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - 0u, // VkBufferCreateFlags flags; - (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size; - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; - 1u, // deUint32 queueFamilyCount; - &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; - }; - const Unique vertexBuffer (createBuffer(vk, vkDevice, &vertexBufferParams)); - const UniquePtr vertexBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible)); - - VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset())); - - const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y()); - const VkBufferCreateInfo readImageBufferParams = - { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - 0u, // VkBufferCreateFlags flags; - imageSizeBytes, // VkDeviceSize size; - VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage; - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; - 1u, // deUint32 queueFamilyCount; - &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; - }; - const Unique readImageBuffer (createBuffer(vk, vkDevice, &readImageBufferParams)); - const UniquePtr readImageBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible)); - - VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset())); - - const VkImageCreateInfo imageParams = - { - VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - 0u, // VkImageCreateFlags flags; - VK_IMAGE_TYPE_2D, // VkImageType imageType; - VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; - { renderSize.x(), renderSize.y(), 1 }, // VkExtent3D extent; - 1u, // deUint32 mipLevels; - 1u, // deUint32 arraySize; - VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; - VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; - VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; - 1u, // deUint32 queueFamilyCount; - &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; - }; - - const Unique image (createImage(vk, vkDevice, &imageParams)); - const UniquePtr imageMemory (context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any)); - - VK_CHECK(vk.bindImageMemory(vkDevice, *image, imageMemory->getMemory(), imageMemory->getOffset())); - - const VkAttachmentDescription colorAttDesc = - { - 0u, // VkAttachmentDescriptionFlags flags; - VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; - VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; - VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; - VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; - VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; - VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; - }; - const VkAttachmentReference colorAttRef = - { - 0u, // deUint32 attachment; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; - }; - const VkSubpassDescription subpassDesc = - { - 0u, // VkSubpassDescriptionFlags flags; - VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; - 0u, // deUint32 inputCount; - DE_NULL, // const VkAttachmentReference* pInputAttachments; - 1u, // deUint32 colorCount; - &colorAttRef, // const VkAttachmentReference* pColorAttachments; - DE_NULL, // const VkAttachmentReference* pResolveAttachments; - DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; - 0u, // deUint32 preserveCount; - DE_NULL, // const VkAttachmentReference* pPreserveAttachments; - - }; - const VkRenderPassCreateInfo renderPassParams = - { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkRenderPassCreateFlags)0, - 1u, // deUint32 attachmentCount; - &colorAttDesc, // const VkAttachmentDescription* pAttachments; - 1u, // deUint32 subpassCount; - &subpassDesc, // const VkSubpassDescription* pSubpasses; - 0u, // deUint32 dependencyCount; - DE_NULL, // const VkSubpassDependency* pDependencies; - }; - const Unique renderPass (createRenderPass(vk, vkDevice, &renderPassParams)); - - const VkImageViewCreateInfo colorAttViewParams = - { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - 0u, // VkImageViewCreateFlags flags; - *image, // VkImage image; - VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; - VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; - { - VK_COMPONENT_SWIZZLE_R, - VK_COMPONENT_SWIZZLE_G, - VK_COMPONENT_SWIZZLE_B, - VK_COMPONENT_SWIZZLE_A - }, // VkChannelMapping channels; - { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; - 0u, // deUint32 baseMipLevel; - 1u, // deUint32 mipLevels; - 0u, // deUint32 baseArrayLayer; - 1u, // deUint32 arraySize; - }, // VkImageSubresourceRange subresourceRange; - }; - const Unique colorAttView (createImageView(vk, vkDevice, &colorAttViewParams)); - - - // Pipeline layout - const VkPipelineLayoutCreateInfo pipelineLayoutParams = - { - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineLayoutCreateFlags)0, - 0u, // deUint32 descriptorSetCount; - DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; - 0u, // deUint32 pushConstantRangeCount; - DE_NULL, // const VkPushConstantRange* pPushConstantRanges; - }; - const Unique pipelineLayout (createPipelineLayout(vk, vkDevice, &pipelineLayoutParams)); - - // Pipeline - vector shaderStageParams; - // We need these vectors to make sure that information about specialization constants for each stage can outlive createGraphicsPipeline(). - vector > specConstantEntries; - vector specializationInfos; - createPipelineShaderStages(vk, vkDevice, instance, context, modules, shaderStageParams); - - // And we don't want the reallocation of these vectors to invalidate pointers pointing to their contents. - specConstantEntries.reserve(shaderStageParams.size()); - specializationInfos.reserve(shaderStageParams.size()); - - // Patch the specialization info field in PipelineShaderStageCreateInfos. - for (vector::iterator stageInfo = shaderStageParams.begin(); stageInfo != shaderStageParams.end(); ++stageInfo) - { - const StageToSpecConstantMap::const_iterator stageIt = instance.specConstants.find(stageInfo->stage); - - if (stageIt != instance.specConstants.end()) - { - const size_t numSpecConstants = stageIt->second.size(); - vector entries; - VkSpecializationInfo specInfo; - - entries.resize(numSpecConstants); - - // Only support 32-bit integers as spec constants now. And their constant IDs are numbered sequentially starting from 0. - for (size_t ndx = 0; ndx < numSpecConstants; ++ndx) - { - entries[ndx].constantID = (deUint32)ndx; - entries[ndx].offset = deUint32(ndx * sizeof(deInt32)); - entries[ndx].size = sizeof(deInt32); - } - - specConstantEntries.push_back(entries); - - specInfo.mapEntryCount = (deUint32)numSpecConstants; - specInfo.pMapEntries = specConstantEntries.back().data(); - specInfo.dataSize = numSpecConstants * sizeof(deInt32); - specInfo.pData = stageIt->second.data(); - specializationInfos.push_back(specInfo); - - stageInfo->pSpecializationInfo = &specializationInfos.back(); - } - } - const VkPipelineDepthStencilStateCreateInfo depthStencilParams = - { - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineDepthStencilStateCreateFlags)0, - DE_FALSE, // deUint32 depthTestEnable; - DE_FALSE, // deUint32 depthWriteEnable; - VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp; - DE_FALSE, // deUint32 depthBoundsTestEnable; - DE_FALSE, // deUint32 stencilTestEnable; - { - VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp; - VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp; - VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp; - VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp; - 0u, // deUint32 stencilCompareMask; - 0u, // deUint32 stencilWriteMask; - 0u, // deUint32 stencilReference; - }, // VkStencilOpState front; - { - VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp; - VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp; - VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp; - VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp; - 0u, // deUint32 stencilCompareMask; - 0u, // deUint32 stencilWriteMask; - 0u, // deUint32 stencilReference; - }, // VkStencilOpState back; - -1.0f, // float minDepthBounds; - +1.0f, // float maxDepthBounds; - }; - const VkViewport viewport0 = - { - 0.0f, // float originX; - 0.0f, // float originY; - (float)renderSize.x(), // float width; - (float)renderSize.y(), // float height; - 0.0f, // float minDepth; - 1.0f, // float maxDepth; - }; - const VkRect2D scissor0 = - { - { - 0u, // deInt32 x; - 0u, // deInt32 y; - }, // VkOffset2D offset; - { - renderSize.x(), // deInt32 width; - renderSize.y(), // deInt32 height; - }, // VkExtent2D extent; - }; - const VkPipelineViewportStateCreateInfo viewportParams = - { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineViewportStateCreateFlags)0, - 1u, // deUint32 viewportCount; - &viewport0, - 1u, - &scissor0 - }; - const VkSampleMask sampleMask = ~0u; - const VkPipelineMultisampleStateCreateInfo multisampleParams = - { - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineMultisampleStateCreateFlags)0, - VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterSamples; - DE_FALSE, // deUint32 sampleShadingEnable; - 0.0f, // float minSampleShading; - &sampleMask, // const VkSampleMask* pSampleMask; - DE_FALSE, // VkBool32 alphaToCoverageEnable; - DE_FALSE, // VkBool32 alphaToOneEnable; - }; - const VkPipelineRasterizationStateCreateInfo rasterParams = - { - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineRasterizationStateCreateFlags)0, - DE_TRUE, // deUint32 depthClipEnable; - DE_FALSE, // deUint32 rasterizerDiscardEnable; - VK_POLYGON_MODE_FILL, // VkFillMode fillMode; - VK_CULL_MODE_NONE, // VkCullMode cullMode; - VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; - VK_FALSE, // VkBool32 depthBiasEnable; - 0.0f, // float depthBias; - 0.0f, // float depthBiasClamp; - 0.0f, // float slopeScaledDepthBias; - 1.0f, // float lineWidth; - }; - const VkPrimitiveTopology topology = hasTessellation? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams = - { - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineInputAssemblyStateCreateFlags)0, - topology, // VkPrimitiveTopology topology; - DE_FALSE, // deUint32 primitiveRestartEnable; - }; - const VkVertexInputBindingDescription vertexBinding0 = - { - 0u, // deUint32 binding; - deUint32(singleVertexDataSize), // deUint32 strideInBytes; - VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate; - }; - const VkVertexInputAttributeDescription vertexAttrib0[2] = - { - { - 0u, // deUint32 location; - 0u, // deUint32 binding; - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; - 0u // deUint32 offsetInBytes; - }, - { - 1u, // deUint32 location; - 0u, // deUint32 binding; - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; - sizeof(Vec4), // deUint32 offsetInBytes; - } - }; - - const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = - { - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineVertexInputStateCreateFlags)0, - 1u, // deUint32 bindingCount; - &vertexBinding0, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; - 2u, // deUint32 attributeCount; - vertexAttrib0, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; - }; - const VkPipelineColorBlendAttachmentState attBlendParams = - { - DE_FALSE, // deUint32 blendEnable; - VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor; - VK_BLEND_FACTOR_ZERO, // VkBlend destBlendColor; - VK_BLEND_OP_ADD, // VkBlendOp blendOpColor; - VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha; - VK_BLEND_FACTOR_ZERO, // VkBlend destBlendAlpha; - VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha; - (VK_COLOR_COMPONENT_R_BIT| - VK_COLOR_COMPONENT_G_BIT| - VK_COLOR_COMPONENT_B_BIT| - VK_COLOR_COMPONENT_A_BIT), // VkChannelFlags channelWriteMask; - }; - const VkPipelineColorBlendStateCreateInfo blendParams = - { - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkPipelineColorBlendStateCreateFlags)0, - DE_FALSE, // VkBool32 logicOpEnable; - VK_LOGIC_OP_COPY, // VkLogicOp logicOp; - 1u, // deUint32 attachmentCount; - &attBlendParams, // const VkPipelineColorBlendAttachmentState* pAttachments; - { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4]; - }; - const VkPipelineTessellationStateCreateInfo tessellationState = - { - VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, - DE_NULL, - (VkPipelineTessellationStateCreateFlags)0, - 3u - }; - - const VkPipelineTessellationStateCreateInfo* tessellationInfo = hasTessellation ? &tessellationState: DE_NULL; - const VkGraphicsPipelineCreateInfo pipelineParams = - { - VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - 0u, // VkPipelineCreateFlags flags; - (deUint32)shaderStageParams.size(), // deUint32 stageCount; - &shaderStageParams[0], // const VkPipelineShaderStageCreateInfo* pStages; - &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; - &inputAssemblyParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; - tessellationInfo, // const VkPipelineTessellationStateCreateInfo* pTessellationState; - &viewportParams, // const VkPipelineViewportStateCreateInfo* pViewportState; - &rasterParams, // const VkPipelineRasterStateCreateInfo* pRasterState; - &multisampleParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; - &depthStencilParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; - &blendParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; - (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; - *pipelineLayout, // VkPipelineLayout layout; - *renderPass, // VkRenderPass renderPass; - 0u, // deUint32 subpass; - DE_NULL, // VkPipeline basePipelineHandle; - 0u, // deInt32 basePipelineIndex; - }; - - const Unique pipeline (createGraphicsPipeline(vk, vkDevice, DE_NULL, &pipelineParams)); - - // Framebuffer - const VkFramebufferCreateInfo framebufferParams = - { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkFramebufferCreateFlags)0, - *renderPass, // VkRenderPass renderPass; - 1u, // deUint32 attachmentCount; - &*colorAttView, // const VkImageView* pAttachments; - (deUint32)renderSize.x(), // deUint32 width; - (deUint32)renderSize.y(), // deUint32 height; - 1u, // deUint32 layers; - }; - const Unique framebuffer (createFramebuffer(vk, vkDevice, &framebufferParams)); - - const Unique cmdPool (createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); - - // Command buffer - const Unique cmdBuf (allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); - - const VkCommandBufferBeginInfo cmdBufBeginParams = - { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - (VkCommandBufferUsageFlags)0, - (const VkCommandBufferInheritanceInfo*)DE_NULL, - }; - - // Record commands - VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginParams)); - - { - const VkMemoryBarrier vertFlushBarrier = - { - VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType; - DE_NULL, // const void* pNext; - VK_ACCESS_HOST_WRITE_BIT, // VkMemoryOutputFlags outputMask; - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkMemoryInputFlags inputMask; - }; - const VkImageMemoryBarrier colorAttBarrier = - { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; - DE_NULL, // const void* pNext; - 0u, // VkMemoryOutputFlags outputMask; - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryInputFlags inputMask; - VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; - queueFamilyIndex, // deUint32 srcQueueFamilyIndex; - queueFamilyIndex, // deUint32 destQueueFamilyIndex; - *image, // VkImage image; - { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect; - 0u, // deUint32 baseMipLevel; - 1u, // deUint32 mipLevels; - 0u, // deUint32 baseArraySlice; - 1u, // deUint32 arraySize; - } // VkImageSubresourceRange subresourceRange; - }; - vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &colorAttBarrier); - } - - { - const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f); - const VkRenderPassBeginInfo passBeginParams = - { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; - DE_NULL, // const void* pNext; - *renderPass, // VkRenderPass renderPass; - *framebuffer, // VkFramebuffer framebuffer; - { { 0, 0 }, { renderSize.x(), renderSize.y() } }, // VkRect2D renderArea; - 1u, // deUint32 clearValueCount; - &clearValue, // const VkClearValue* pClearValues; - }; - vk.cmdBeginRenderPass(*cmdBuf, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE); - } - - vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); - { - const VkDeviceSize bindingOffset = 0; - vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset); - } - vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/); - vk.cmdEndRenderPass(*cmdBuf); - - { - const VkImageMemoryBarrier renderFinishBarrier = - { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; - DE_NULL, // const void* pNext; - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryOutputFlags outputMask; - VK_ACCESS_TRANSFER_READ_BIT, // VkMemoryInputFlags inputMask; - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; - queueFamilyIndex, // deUint32 srcQueueFamilyIndex; - queueFamilyIndex, // deUint32 destQueueFamilyIndex; - *image, // VkImage image; - { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; - 0u, // deUint32 baseMipLevel; - 1u, // deUint32 mipLevels; - 0u, // deUint32 baseArraySlice; - 1u, // deUint32 arraySize; - } // VkImageSubresourceRange subresourceRange; - }; - vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &renderFinishBarrier); - } - - { - const VkBufferImageCopy copyParams = - { - (VkDeviceSize)0u, // VkDeviceSize bufferOffset; - (deUint32)renderSize.x(), // deUint32 bufferRowLength; - (deUint32)renderSize.y(), // deUint32 bufferImageHeight; - { - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect; - 0u, // deUint32 mipLevel; - 0u, // deUint32 arrayLayer; - 1u, // deUint32 arraySize; - }, // VkImageSubresourceCopy imageSubresource; - { 0u, 0u, 0u }, // VkOffset3D imageOffset; - { renderSize.x(), renderSize.y(), 1u } // VkExtent3D imageExtent; - }; - vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params); - } - - { - const VkBufferMemoryBarrier copyFinishBarrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; - DE_NULL, // const void* pNext; - VK_ACCESS_TRANSFER_WRITE_BIT, // VkMemoryOutputFlags outputMask; - VK_ACCESS_HOST_READ_BIT, // VkMemoryInputFlags inputMask; - queueFamilyIndex, // deUint32 srcQueueFamilyIndex; - queueFamilyIndex, // deUint32 destQueueFamilyIndex; - *readImageBuffer, // VkBuffer buffer; - 0u, // VkDeviceSize offset; - imageSizeBytes // VkDeviceSize size; - }; - vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©FinishBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); - } - - VK_CHECK(vk.endCommandBuffer(*cmdBuf)); - - // Upload vertex data - { - const VkMappedMemoryRange range = - { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; - DE_NULL, // const void* pNext; - vertexBufferMemory->getMemory(), // VkDeviceMemory mem; - 0, // VkDeviceSize offset; - (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size; - }; - void* vertexBufPtr = vertexBufferMemory->getHostPtr(); - - deMemcpy(vertexBufPtr, &vertexData[0], sizeof(vertexData)); - VK_CHECK(vk.flushMappedMemoryRanges(vkDevice, 1u, &range)); - } - - // Submit & wait for completion - { - const Unique fence (createFence(vk, vkDevice)); - const VkSubmitInfo submitInfo = - { - VK_STRUCTURE_TYPE_SUBMIT_INFO, - DE_NULL, - 0u, - (const VkSemaphore*)DE_NULL, - (const VkPipelineStageFlags*)DE_NULL, - 1u, - &cmdBuf.get(), - 0u, - (const VkSemaphore*)DE_NULL, - }; - - VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence)); - VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull)); - } - - const void* imagePtr = readImageBufferMemory->getHostPtr(); - const tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), - renderSize.x(), renderSize.y(), 1, imagePtr); - // Log image - { - const VkMappedMemoryRange range = - { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; - DE_NULL, // const void* pNext; - readImageBufferMemory->getMemory(), // VkDeviceMemory mem; - 0, // VkDeviceSize offset; - imageSizeBytes, // VkDeviceSize size; - }; - - VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range)); - context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer); - } - - const RGBA threshold(1, 1, 1, 1); - const RGBA upperLeft(pixelBuffer.getPixel(1, 1)); - if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold)) - return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper left corner mismatch")); - - const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1)); - if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold)) - return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper right corner mismatch")); - - const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1)); - if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold)) - return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower left corner mismatch")); - - const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1)); - if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold)) - return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower right corner mismatch")); - - return TestStatus::pass("Rendered output matches input"); -} - -void createTestsForAllStages (const std::string& name, - const RGBA (&inputColors)[4], - const RGBA (&outputColors)[4], - const map& testCodeFragments, - const vector& specConstants, - tcu::TestCaseGroup* tests, - const qpTestResult failResult = QP_TEST_RESULT_FAIL, - const string& failMessageTemplate = string()) -{ - const ShaderElement vertFragPipelineStages[] = - { - ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), - ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), - }; - - const ShaderElement tessPipelineStages[] = - { - ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), - ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), - ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), - ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), - }; - - const ShaderElement geomPipelineStages[] = - { - ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), - ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT), - ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), - }; - - StageToSpecConstantMap specConstantMap; - - specConstantMap[VK_SHADER_STAGE_VERTEX_BIT] = specConstants; - addFunctionCaseWithPrograms(tests, name + "_vert", "", addShaderCodeCustomVertex, runAndVerifyDefaultPipeline, - createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap, failResult, failMessageTemplate)); - - specConstantMap.clear(); - specConstantMap[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT] = specConstants; - addFunctionCaseWithPrograms(tests, name + "_tessc", "", addShaderCodeCustomTessControl, runAndVerifyDefaultPipeline, - createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap, failResult, failMessageTemplate)); - - specConstantMap.clear(); - specConstantMap[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = specConstants; - addFunctionCaseWithPrograms(tests, name + "_tesse", "", addShaderCodeCustomTessEval, runAndVerifyDefaultPipeline, - createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap, failResult, failMessageTemplate)); - - specConstantMap.clear(); - specConstantMap[VK_SHADER_STAGE_GEOMETRY_BIT] = specConstants; - addFunctionCaseWithPrograms(tests, name + "_geom", "", addShaderCodeCustomGeometry, runAndVerifyDefaultPipeline, - createInstanceContext(geomPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap, failResult, failMessageTemplate)); - - specConstantMap.clear(); - specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT] = specConstants; - addFunctionCaseWithPrograms(tests, name + "_frag", "", addShaderCodeCustomFragment, runAndVerifyDefaultPipeline, - createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap, failResult, failMessageTemplate)); -} - -inline void createTestsForAllStages (const string& name, - const RGBA (&inputColors)[4], - const RGBA (&outputColors)[4], - const map& testCodeFragments, - tcu::TestCaseGroup* tests, - const qpTestResult failResult = QP_TEST_RESULT_FAIL, - const string& failMessageTemplate = string()) -{ - vector noSpecConstants; - createTestsForAllStages(name, inputColors, outputColors, testCodeFragments, noSpecConstants, tests, failResult, failMessageTemplate); -} } // anonymous @@ -7960,26 +5703,6 @@ tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx) return testGroup.release(); } -// Adds a new test to group using custom fragments for the tessellation-control -// stage and passthrough fragments for all other stages. Uses default colors -// for input and expected output. -void addTessCtrlTest(tcu::TestCaseGroup* group, const char* name, const map& fragments) -{ - RGBA defaultColors[4]; - getDefaultColors(defaultColors); - const ShaderElement pipelineStages[] = - { - ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), - ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), - ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), - ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), - }; - - addFunctionCaseWithPrograms(group, name, "", addShaderCodeCustomTessControl, - runAndVerifyDefaultPipeline, createInstanceContext( - pipelineStages, defaultColors, defaultColors, fragments, StageToSpecConstantMap())); -} - // A collection of tests putting OpControlBarrier in places GLSL forbids but SPIR-V allows. tcu::TestCaseGroup* createBarrierTests(tcu::TestContext& testCtx) { @@ -8682,14 +6405,6 @@ deInt32 getInt(de::Random& rnd) return rnd.getInt(std::numeric_limits::min(), std::numeric_limits::max()); } -template -const string numberToString (T number) -{ - std::stringstream ss; - ss << number; - return ss.str(); -} - const string repeatString (const string& str, int times) { string filler;