xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/draw/vktDrawShaderLayerTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
6  * Copyright (c) 2018 The Android Open Source Project
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Use of gl_Layer in Vertex and Tessellation Shaders
23  *        (part of VK_EXT_ShaderViewportIndexLayer)
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktDrawShaderLayerTests.hpp"
27 
28 #include "vktDrawBaseClass.hpp"
29 #include "vktTestCaseUtil.hpp"
30 
31 #include "vkDefs.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 
42 #include "tcuTestLog.hpp"
43 #include "tcuVector.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuTextureUtil.hpp"
46 
47 #include "deUniquePtr.hpp"
48 #include "deMath.h"
49 
50 #include <vector>
51 
52 namespace vkt
53 {
54 namespace Draw
55 {
56 using namespace vk;
57 using de::MovePtr;
58 using de::SharedPtr;
59 using de::UniquePtr;
60 using tcu::UVec2;
61 using tcu::UVec4;
62 using tcu::Vec2;
63 using tcu::Vec4;
64 
65 namespace
66 {
67 
68 enum Constants
69 {
70     MIN_MAX_FRAMEBUFFER_LAYERS = 256, //!< Minimum number of framebuffer layers.
71     MIN_MAX_VIEWPORTS          = 16,  //!< Minimum number of viewports for an implementation supporting multiViewport.
72 };
73 
74 struct TestParams
75 {
76     int numLayers;
77     const SharedGroupParams groupParams;
78 };
79 
80 template <typename T>
sizeInBytes(const std::vector<T> & vec)81 inline VkDeviceSize sizeInBytes(const std::vector<T> &vec)
82 {
83     return vec.size() * sizeof(vec[0]);
84 }
85 
makeImageCreateInfo(const VkFormat format,const UVec2 & size,const uint32_t numLayers,VkImageUsageFlags usage)86 VkImageCreateInfo makeImageCreateInfo(const VkFormat format, const UVec2 &size, const uint32_t numLayers,
87                                       VkImageUsageFlags usage)
88 {
89     const VkImageCreateInfo imageParams = {
90         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
91         DE_NULL,                             // const void* pNext;
92         (VkImageCreateFlags)0,               // VkImageCreateFlags flags;
93         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
94         format,                              // VkFormat format;
95         makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
96         1u,                                  // uint32_t mipLevels;
97         numLayers,                           // uint32_t arrayLayers;
98         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
99         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
100         usage,                               // VkImageUsageFlags usage;
101         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
102         0u,                                  // uint32_t queueFamilyIndexCount;
103         DE_NULL,                             // const uint32_t* pQueueFamilyIndices;
104         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
105     };
106     return imageParams;
107 }
108 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule tessellationControlModule,const VkShaderModule tessellationEvaluationModule,const VkShaderModule fragmentModule,const UVec2 renderSize)109 Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, const VkDevice device,
110                                       const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass,
111                                       const VkShaderModule vertexModule, const VkShaderModule tessellationControlModule,
112                                       const VkShaderModule tessellationEvaluationModule,
113                                       const VkShaderModule fragmentModule, const UVec2 renderSize)
114 {
115     const VkVertexInputBindingDescription vertexInputBindingDescription = {
116         0u,                          // uint32_t binding;
117         sizeof(PositionColorVertex), // uint32_t stride;
118         VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
119     };
120 
121     const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
122         {
123             0u,                            // uint32_t location;
124             0u,                            // uint32_t binding;
125             VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
126             0u,                            // uint32_t offset;
127         },
128         {
129             1u,                            // uint32_t location;
130             0u,                            // uint32_t binding;
131             VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
132             sizeof(Vec4),                  // uint32_t offset;
133         },
134     };
135 
136     const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = {
137         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                             sType;
138         DE_NULL,                                                   // const void*                                 pNext;
139         (VkPipelineVertexInputStateCreateFlags)0,                  // VkPipelineVertexInputStateCreateFlags       flags;
140         1u,                             // uint32_t                                    vertexBindingDescriptionCount;
141         &vertexInputBindingDescription, // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
142         DE_LENGTH_OF_ARRAY(
143             vertexInputAttributeDescriptions), // uint32_t                                    vertexAttributeDescriptionCount;
144         vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
145     };
146 
147     const bool useTessellationShaders =
148         (tessellationControlModule != DE_NULL) && (tessellationEvaluationModule != DE_NULL);
149 
150     const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = {
151         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType                             sType;
152         DE_NULL,                                    // const void*                                 pNext;
153         (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags     flags;
154         useTessellationShaders ?
155             VK_PRIMITIVE_TOPOLOGY_PATCH_LIST :
156             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology                         topology;
157         VK_FALSE,                                // VkBool32                                    primitiveRestartEnable;
158     };
159 
160     VkViewport viewport =
161         makeViewport(0.0f, 0.0f, static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 0.0f, 1.0f);
162     VkRect2D rectScissor = {{0, 0}, {renderSize.x(), renderSize.y()}};
163 
164     const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = {
165         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType                             sType;
166         DE_NULL,                                               // const void*                                 pNext;
167         (VkPipelineViewportStateCreateFlags)0,                 // VkPipelineViewportStateCreateFlags          flags;
168         1u,           // uint32_t                                    viewportCount;
169         &viewport,    // const VkViewport*                           pViewports;
170         1u,           // uint32_t                                    scissorCount;
171         &rectScissor, // const VkRect2D*                             pScissors;
172     };
173 
174     const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = {
175         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                          sType;
176         DE_NULL,                                                    // const void*                              pNext;
177         (VkPipelineRasterizationStateCreateFlags)0,                 // VkPipelineRasterizationStateCreateFlags  flags;
178         VK_FALSE,                        // VkBool32                                 depthClampEnable;
179         VK_FALSE,                        // VkBool32                                 rasterizerDiscardEnable;
180         VK_POLYGON_MODE_FILL,            // VkPolygonMode polygonMode;
181         VK_CULL_MODE_NONE,               // VkCullModeFlags cullMode;
182         VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
183         VK_FALSE,                        // VkBool32 depthBiasEnable;
184         0.0f,                            // float depthBiasConstantFactor;
185         0.0f,                            // float depthBiasClamp;
186         0.0f,                            // float depthBiasSlopeFactor;
187         1.0f,                            // float lineWidth;
188     };
189 
190     const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = {
191         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
192         DE_NULL,                                                  // const void* pNext;
193         (VkPipelineMultisampleStateCreateFlags)0,                 // VkPipelineMultisampleStateCreateFlags flags;
194         VK_SAMPLE_COUNT_1_BIT,                                    // VkSampleCountFlagBits rasterizationSamples;
195         VK_FALSE,                                                 // VkBool32 sampleShadingEnable;
196         0.0f,                                                     // float minSampleShading;
197         DE_NULL,                                                  // const VkSampleMask* pSampleMask;
198         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
199         VK_FALSE                                                  // VkBool32 alphaToOneEnable;
200     };
201 
202     const VkStencilOpState stencilOpState = makeStencilOpState(VK_STENCIL_OP_KEEP,   // stencil fail
203                                                                VK_STENCIL_OP_KEEP,   // depth & stencil pass
204                                                                VK_STENCIL_OP_KEEP,   // depth only fail
205                                                                VK_COMPARE_OP_ALWAYS, // compare op
206                                                                0u,                   // compare mask
207                                                                0u,                   // write mask
208                                                                0u);                  // reference
209 
210     VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = {
211         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
212         DE_NULL,                                                    // const void* pNext;
213         (VkPipelineDepthStencilStateCreateFlags)0,                  // VkPipelineDepthStencilStateCreateFlags flags;
214         VK_FALSE,                                                   // VkBool32 depthTestEnable;
215         VK_FALSE,                                                   // VkBool32 depthWriteEnable;
216         VK_COMPARE_OP_LESS,                                         // VkCompareOp depthCompareOp;
217         VK_FALSE,                                                   // VkBool32 depthBoundsTestEnable;
218         VK_FALSE,                                                   // VkBool32 stencilTestEnable;
219         stencilOpState,                                             // VkStencilOpState front;
220         stencilOpState,                                             // VkStencilOpState back;
221         0.0f,                                                       // float minDepthBounds;
222         1.0f,                                                       // float maxDepthBounds;
223     };
224 
225     const VkColorComponentFlags colorComponentsAll =
226         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
227     const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {
228         VK_FALSE,             // VkBool32 blendEnable;
229         VK_BLEND_FACTOR_ONE,  // VkBlendFactor srcColorBlendFactor;
230         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
231         VK_BLEND_OP_ADD,      // VkBlendOp colorBlendOp;
232         VK_BLEND_FACTOR_ONE,  // VkBlendFactor srcAlphaBlendFactor;
233         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
234         VK_BLEND_OP_ADD,      // VkBlendOp alphaBlendOp;
235         colorComponentsAll,   // VkColorComponentFlags colorWriteMask;
236     };
237 
238     const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = {
239         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
240         DE_NULL,                                                  // const void* pNext;
241         (VkPipelineColorBlendStateCreateFlags)0,                  // VkPipelineColorBlendStateCreateFlags flags;
242         VK_FALSE,                                                 // VkBool32 logicOpEnable;
243         VK_LOGIC_OP_COPY,                                         // VkLogicOp logicOp;
244         1u,                                                       // uint32_t attachmentCount;
245         &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
246         {0.0f, 0.0f, 0.0f, 0.0f},           // float blendConstants[4];
247     };
248 
249     const VkPipelineShaderStageCreateInfo pShaderStages[] = {
250         {
251             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
252             DE_NULL,                                             // const void* pNext;
253             (VkPipelineShaderStageCreateFlags)0,                 // VkPipelineShaderStageCreateFlags flags;
254             VK_SHADER_STAGE_VERTEX_BIT,                          // VkShaderStageFlagBits stage;
255             vertexModule,                                        // VkShaderModule module;
256             "main",                                              // const char* pName;
257             DE_NULL,                                             // const VkSpecializationInfo* pSpecializationInfo;
258         },
259         {
260             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
261             DE_NULL,                                             // const void* pNext;
262             (VkPipelineShaderStageCreateFlags)0,                 // VkPipelineShaderStageCreateFlags flags;
263             VK_SHADER_STAGE_FRAGMENT_BIT,                        // VkShaderStageFlagBits stage;
264             fragmentModule,                                      // VkShaderModule module;
265             "main",                                              // const char* pName;
266             DE_NULL,                                             // const VkSpecializationInfo* pSpecializationInfo;
267         },
268         {
269             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
270             DE_NULL,                                             // const void* pNext;
271             (VkPipelineShaderStageCreateFlags)0,                 // VkPipelineShaderStageCreateFlags flags;
272             VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,            // VkShaderStageFlagBits stage;
273             tessellationControlModule,                           // VkShaderModule module;
274             "main",                                              // const char* pName;
275             DE_NULL,                                             // const VkSpecializationInfo* pSpecializationInfo;
276         },
277         {
278             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
279             DE_NULL,                                             // const void* pNext;
280             (VkPipelineShaderStageCreateFlags)0,                 // VkPipelineShaderStageCreateFlags flags;
281             VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,         // VkShaderStageFlagBits stage;
282             tessellationEvaluationModule,                        // VkShaderModule module;
283             "main",                                              // const char* pName;
284             DE_NULL,                                             // const VkSpecializationInfo* pSpecializationInfo;
285         },
286     };
287 
288     const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo = {
289         VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
290         DE_NULL,                                                   // const void* pNext;
291         (VkPipelineTessellationStateCreateFlags)0,                 // VkPipelineTessellationStateCreateFlags flags;
292         3,                                                         // uint32_t patchControlPoints;
293     };
294 
295     VkGraphicsPipelineCreateInfo graphicsPipelineInfo{
296         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,    // VkStructureType sType;
297         DE_NULL,                                            // const void* pNext;
298         (VkPipelineCreateFlags)0,                           // VkPipelineCreateFlags flags;
299         useTessellationShaders ? uint32_t(4) : uint32_t(2), // uint32_t stageCount;
300         pShaderStages,                                      // const VkPipelineShaderStageCreateInfo* pStages;
301         &vertexInputStateInfo,           // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
302         &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
303         useTessellationShaders ? &pipelineTessellationStateInfo :
304                                  DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
305         &pipelineViewportStateInfo,       // const VkPipelineViewportStateCreateInfo* pViewportState;
306         &pipelineRasterizationStateInfo,  // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
307         &pipelineMultisampleStateInfo,    // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
308         &pipelineDepthStencilStateInfo,   // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
309         &pipelineColorBlendStateInfo,     // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
310         DE_NULL,                          // const VkPipelineDynamicStateCreateInfo* pDynamicState;
311         pipelineLayout,                   // VkPipelineLayout layout;
312         renderPass,                       // VkRenderPass renderPass;
313         0u,                               // uint32_t subpass;
314         DE_NULL,                          // VkPipeline basePipelineHandle;
315         0,                                // int32_t basePipelineIndex;
316     };
317 
318 #ifndef CTS_USES_VULKANSC
319     VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
320     VkPipelineRenderingCreateInfoKHR renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
321                                                          DE_NULL,
322                                                          0u,
323                                                          1u,
324                                                          &colorAttachmentFormat,
325                                                          VK_FORMAT_UNDEFINED,
326                                                          VK_FORMAT_UNDEFINED};
327 
328     // when pipeline is created without render pass we are using dynamic rendering
329     if (renderPass == DE_NULL)
330         graphicsPipelineInfo.pNext = &renderingCreateInfo;
331 #endif // CTS_USES_VULKANSC
332 
333     return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
334 }
335 
336 //! Renders a colorful grid of rectangles.
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const Vec4 & clearColor,const UVec4 & cell,const Vec4 & cellColor)337 tcu::TextureLevel generateReferenceImage(const tcu::TextureFormat format, const UVec2 &renderSize,
338                                          const Vec4 &clearColor, const UVec4 &cell, const Vec4 &cellColor)
339 {
340     tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
341     tcu::clear(image.getAccess(), clearColor);
342 
343     tcu::clear(tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()), cellColor);
344 
345     return image;
346 }
347 
initVertexTestPrograms(SourceCollections & programCollection,const TestParams params)348 void initVertexTestPrograms(SourceCollections &programCollection, const TestParams params)
349 {
350     DE_UNREF(params.numLayers);
351 
352     // Vertex shader
353     {
354         std::ostringstream src;
355         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
356             << "#extension GL_ARB_shader_viewport_layer_array : require\n"
357             << "\n"
358             << "layout(location = 0) in  vec4 in_position;\n"
359             << "layout(location = 1) in  vec4 in_color;\n"
360             << "layout(location = 0) out vec4 out_color;\n"
361             << "\n"
362             << "void main(void)\n"
363             << "{\n"
364             << "    gl_Layer = gl_VertexIndex / 6;\n"
365             << "    gl_Position = in_position;\n"
366             << "    out_color = in_color;\n"
367             << "}\n";
368 
369         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
370         programCollection.glslSources.add("vert_1_2")
371             << glu::VertexSource(src.str())
372             << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
373     }
374 
375     // Fragment shader
376     {
377         std::ostringstream src;
378         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
379             << "\n"
380             << "layout(location = 0) in  vec4 in_color;\n"
381             << "layout(location = 0) out vec4 out_color;\n"
382             << "\n"
383             << "void main(void)\n"
384             << "{\n"
385             << "    out_color = in_color;\n"
386             << "}\n";
387 
388         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
389     }
390 }
391 
initTessellationTestPrograms(SourceCollections & programCollection,const TestParams params)392 void initTessellationTestPrograms(SourceCollections &programCollection, const TestParams params)
393 {
394     DE_UNREF(params.numLayers);
395 
396     // Vertex shader
397     {
398         std::ostringstream src;
399         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
400             << "\n"
401             << "layout(location = 0) in  vec4 in_position;\n"
402             << "layout(location = 1) in  vec4 in_color;\n"
403             << "layout(location = 0) out vec4 out_color;\n"
404             << "\n"
405             << "void main(void)\n"
406             << "{\n"
407             << "    gl_Position = in_position;\n"
408             << "    out_color = in_color;\n"
409             << "}\n";
410 
411         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
412         programCollection.glslSources.add("vert_1_2")
413             << glu::VertexSource(src.str())
414             << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
415     }
416 
417     // Tessellation control shader
418     {
419         std::ostringstream src;
420         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
421             << "\n"
422             << "layout(vertices = 3) out;\n"
423             << "\n"
424             << "layout(location = 0) in  vec4 in_color[];\n"
425             << "layout(location = 0) out vec4 out_color[];\n"
426             << "\n"
427             << "void main(void)\n"
428             << "{\n"
429             << "    if (gl_InvocationID == 0) {\n"
430             << "        gl_TessLevelInner[0] = 1.0;\n"
431             << "        gl_TessLevelInner[1] = 1.0;\n"
432             << "        gl_TessLevelOuter[0] = 1.0;\n"
433             << "        gl_TessLevelOuter[1] = 1.0;\n"
434             << "        gl_TessLevelOuter[2] = 1.0;\n"
435             << "        gl_TessLevelOuter[3] = 1.0;\n"
436             << "    }\n"
437             << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
438             << "    out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
439             << "}\n";
440 
441         programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
442     }
443 
444     // Tessellation evaluation shader
445     {
446         std::ostringstream src;
447         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
448             << "#extension GL_ARB_shader_viewport_layer_array : require\n"
449             << "\n"
450             << "layout(triangles, equal_spacing, cw) in;\n"
451             << "\n"
452             << "layout(location = 0) in  vec4 in_color[];\n"
453             << "layout(location = 0) out vec4 out_color;\n"
454             << "\n"
455             << "void main(void)\n"
456             << "{\n"
457             << "    gl_Layer = gl_PrimitiveID / 2;\n"
458             << "    gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
459             << "                  gl_in[1].gl_Position * gl_TessCoord.y +\n"
460             << "                  gl_in[2].gl_Position * gl_TessCoord.z;\n"
461             << "\n"
462             << "    out_color = in_color[0] * gl_TessCoord.x +\n"
463             << "                in_color[1] * gl_TessCoord.y +\n"
464             << "                in_color[2] * gl_TessCoord.z;\n"
465             << "}\n";
466 
467         programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
468         programCollection.glslSources.add("tese_1_2")
469             << glu::TessellationEvaluationSource(src.str())
470             << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
471     }
472 
473     // Fragment shader
474     {
475         std::ostringstream src;
476         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
477             << "\n"
478             << "layout(location = 0) in  vec4 in_color;\n"
479             << "layout(location = 0) out vec4 out_color;\n"
480             << "\n"
481             << "void main(void)\n"
482             << "{\n"
483             << "    out_color = in_color;\n"
484             << "}\n";
485 
486         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
487     }
488 }
489 
generateGrid(const int numCells,const UVec2 & renderSize)490 std::vector<UVec4> generateGrid(const int numCells, const UVec2 &renderSize)
491 {
492     const int numCols    = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
493     const int numRows    = deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
494     const int rectWidth  = renderSize.x() / numCols;
495     const int rectHeight = renderSize.y() / numRows;
496 
497     std::vector<UVec4> cells;
498     cells.reserve(numCells);
499 
500     int x = 0;
501     int y = 0;
502 
503     for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
504     {
505         const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
506         if (nextRow)
507         {
508             x = 0;
509             y += rectHeight;
510         }
511 
512         cells.push_back(UVec4(x, y, rectWidth, rectHeight));
513 
514         x += rectWidth;
515     }
516 
517     return cells;
518 }
519 
generateColors(int numColors)520 std::vector<Vec4> generateColors(int numColors)
521 {
522     const Vec4 colors[] = {
523         Vec4(0.18f, 0.42f, 0.17f, 1.0f), Vec4(0.29f, 0.62f, 0.28f, 1.0f), Vec4(0.59f, 0.84f, 0.44f, 1.0f),
524         Vec4(0.96f, 0.95f, 0.72f, 1.0f), Vec4(0.94f, 0.55f, 0.39f, 1.0f), Vec4(0.82f, 0.19f, 0.12f, 1.0f),
525         Vec4(0.46f, 0.15f, 0.26f, 1.0f), Vec4(0.24f, 0.14f, 0.24f, 1.0f), Vec4(0.49f, 0.31f, 0.26f, 1.0f),
526         Vec4(0.78f, 0.52f, 0.33f, 1.0f), Vec4(0.94f, 0.82f, 0.31f, 1.0f), Vec4(0.98f, 0.65f, 0.30f, 1.0f),
527         Vec4(0.22f, 0.65f, 0.53f, 1.0f), Vec4(0.67f, 0.81f, 0.91f, 1.0f), Vec4(0.43f, 0.44f, 0.75f, 1.0f),
528         Vec4(0.26f, 0.24f, 0.48f, 1.0f),
529     };
530 
531     std::vector<Vec4> result;
532     result.reserve(numColors);
533 
534     for (int i = 0; i < numColors; ++i)
535     {
536         result.push_back(colors[i % DE_LENGTH_OF_ARRAY(colors)]);
537     }
538 
539     return result;
540 }
541 
generateVertices(const std::vector<UVec4> & grid,const std::vector<Vec4> & colors,const UVec2 & renderSize)542 std::vector<PositionColorVertex> generateVertices(const std::vector<UVec4> &grid, const std::vector<Vec4> &colors,
543                                                   const UVec2 &renderSize)
544 {
545     DE_ASSERT(colors.size() == grid.size());
546 
547     // Two triangles for each cell. Each cell correspond to a layer.
548     std::size_t total = grid.size() * 6;
549 
550     std::vector<PositionColorVertex> result;
551     result.reserve(total);
552 
553     for (std::size_t i = 0; i < total; ++i)
554     {
555         Vec4 pos;
556         pos.z() = 0.0;
557         pos.w() = 1.0;
558 
559         Vec4 cell    = grid[i / 6].asFloat() * 2.0f;
560         float x      = cell.x() / float(renderSize.x()) - 1.0f;
561         float y      = cell.y() / float(renderSize.y()) - 1.0f;
562         float width  = cell.z() / float(renderSize.x());
563         float height = cell.w() / float(renderSize.y());
564 
565         switch (i % 6)
566         {
567         case 0:
568             pos.xy() = Vec2(x, y + height);
569             break;
570         case 1:
571             pos.xy() = Vec2(x + width, y + height);
572             break;
573         case 2:
574             pos.xy() = Vec2(x, y);
575             break;
576         case 3:
577             pos.xy() = Vec2(x + width, y);
578             break;
579         case 4:
580             pos.xy() = Vec2(x + width, y + height);
581             break;
582         case 5:
583             pos.xy() = Vec2(x, y);
584             break;
585         }
586 
587         result.push_back(PositionColorVertex(pos, colors[i / 6]));
588     }
589 
590     return result;
591 }
592 
593 // Renderer generates two triangles per layer, each pair using a different
594 // color and a different position.
595 class Renderer
596 {
597 public:
598     enum Shader
599     {
600         VERTEX,
601         TESSELLATION,
602     };
603 
Renderer(Context & context,const SharedGroupParams groupParams,const UVec2 & renderSize,const int numLayers,const VkFormat colorFormat,const Vec4 & clearColor,const std::vector<PositionColorVertex> & vertices,const Shader shader)604     Renderer(Context &context, const SharedGroupParams groupParams, const UVec2 &renderSize, const int numLayers,
605              const VkFormat colorFormat, const Vec4 &clearColor, const std::vector<PositionColorVertex> &vertices,
606              const Shader shader)
607         : m_groupParams(groupParams)
608         , m_renderSize(renderSize)
609         , m_colorFormat(colorFormat)
610         , m_colorSubresourceRange(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers))
611         , m_clearColor(clearColor)
612         , m_numLayers(numLayers)
613         , m_vertices(vertices)
614     {
615         const DeviceInterface &vk           = context.getDeviceInterface();
616         const VkDevice device               = context.getDevice();
617         const uint32_t queueFamilyIndex     = context.getUniversalQueueFamilyIndex();
618         Allocator &allocator                = context.getDefaultAllocator();
619         const VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices);
620 
621         m_colorImage =
622             makeImage(vk, device,
623                       makeImageCreateInfo(m_colorFormat, m_renderSize, m_numLayers,
624                                           VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
625         m_colorImageAlloc = bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
626         m_colorAttachment = makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_colorFormat,
627                                           m_colorSubresourceRange);
628 
629         m_vertexBuffer = Buffer::createAndAlloc(
630             vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator,
631             MemoryRequirement::HostVisible);
632 
633         deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0],
634                  static_cast<std::size_t>(vertexBufferSize));
635         flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
636 
637         if (shader == TESSELLATION)
638         {
639             m_tessellationControlModule = createShaderModule(vk, device, context.getBinaryCollection().get("tesc"), 0u);
640             if (context.contextSupports(VK_API_VERSION_1_2))
641                 m_tessellationEvaluationModule =
642                     createShaderModule(vk, device, context.getBinaryCollection().get("tese_1_2"), 0u);
643             else
644                 m_tessellationEvaluationModule =
645                     createShaderModule(vk, device, context.getBinaryCollection().get("tese"), 0u);
646         }
647 
648         if (context.contextSupports(VK_API_VERSION_1_2))
649             m_vertexModule = createShaderModule(vk, device, context.getBinaryCollection().get("vert_1_2"), 0u);
650         else
651             m_vertexModule = createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u);
652 
653         m_fragmentModule = createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u);
654 
655         if (!m_groupParams->useDynamicRendering)
656         {
657             m_renderPass = makeRenderPass(vk, device, m_colorFormat);
658 
659             m_framebuffer = makeFramebuffer(vk, device, *m_renderPass, m_colorAttachment.get(),
660                                             static_cast<uint32_t>(m_renderSize.x()),
661                                             static_cast<uint32_t>(m_renderSize.y()), numLayers);
662         }
663 
664         m_pipelineLayout = makePipelineLayout(vk, device);
665         m_pipeline       = makeGraphicsPipeline(vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule,
666                                                 *m_tessellationControlModule, *m_tessellationEvaluationModule,
667                                                 *m_fragmentModule, m_renderSize);
668         m_cmdPool   = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
669         m_cmdBuffer = allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
670         m_secCmdBuffer = allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
671     }
672 
draw(Context & context,const VkBuffer colorBuffer) const673     void draw(Context &context, const VkBuffer colorBuffer) const
674     {
675         const DeviceInterface &vk     = context.getDeviceInterface();
676         const VkDevice device         = context.getDevice();
677         const VkQueue queue           = context.getUniversalQueue();
678         const VkClearValue clearValue = makeClearValueColor(m_clearColor);
679         const VkRect2D renderArea{
680             makeOffset2D(0, 0),
681             makeExtent2D(m_renderSize.x(), m_renderSize.y()),
682         };
683 
684 #ifndef CTS_USES_VULKANSC
685         if (m_groupParams->useSecondaryCmdBuffer)
686         {
687             // record secondary command buffer
688             if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
689             {
690                 beginSecondaryCmdBuffer(context, *m_secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
691                 beginRendering(vk, *m_secCmdBuffer, *m_colorAttachment, renderArea, clearValue,
692                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, 0u, m_numLayers);
693             }
694             else
695                 beginSecondaryCmdBuffer(context, *m_secCmdBuffer);
696 
697             drawCommands(context, *m_secCmdBuffer);
698 
699             if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
700                 endRendering(vk, *m_secCmdBuffer);
701 
702             endCommandBuffer(vk, *m_secCmdBuffer);
703 
704             // record primary command buffer
705             beginCommandBuffer(vk, *m_cmdBuffer, 0u);
706 
707             preRenderCommands(context, *m_cmdBuffer);
708 
709             if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
710                 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue,
711                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR,
712                                VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, m_numLayers);
713 
714             vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
715 
716             if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
717                 endRendering(vk, *m_cmdBuffer);
718 
719             postRenderCommands(context, colorBuffer);
720             endCommandBuffer(vk, *m_cmdBuffer);
721         }
722         else if (m_groupParams->useDynamicRendering)
723         {
724             beginCommandBuffer(vk, *m_cmdBuffer);
725 
726             preRenderCommands(context, *m_cmdBuffer);
727             beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue,
728                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, 0u, m_numLayers);
729             drawCommands(context, *m_cmdBuffer);
730             endRendering(vk, *m_cmdBuffer);
731             postRenderCommands(context, colorBuffer);
732 
733             endCommandBuffer(vk, *m_cmdBuffer);
734         }
735 #endif // CTS_USES_VULKANSC
736 
737         if (!m_groupParams->useDynamicRendering)
738         {
739             beginCommandBuffer(vk, *m_cmdBuffer);
740 
741             preRenderCommands(context, *m_cmdBuffer);
742             beginRenderPass(context, *m_cmdBuffer, renderArea, clearValue);
743             drawCommands(context, *m_cmdBuffer);
744             vk.cmdEndRenderPass(*m_cmdBuffer);
745             postRenderCommands(context, colorBuffer);
746 
747             endCommandBuffer(vk, *m_cmdBuffer);
748         }
749 
750         submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
751     }
752 
753 protected:
preRenderCommands(Context & context,VkCommandBuffer cmdBuffer) const754     void preRenderCommands(Context &context, VkCommandBuffer cmdBuffer) const
755     {
756         if (m_groupParams->useDynamicRendering)
757         {
758             const DeviceInterface &vk = context.getDeviceInterface();
759             initialTransitionColor2DImage(vk, cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
760                                           VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
761                                           m_colorSubresourceRange.layerCount);
762         }
763     }
764 
postRenderCommands(Context & context,VkBuffer colorBuffer) const765     void postRenderCommands(Context &context, VkBuffer colorBuffer) const
766     {
767         const DeviceInterface &vk = context.getDeviceInterface();
768         copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()),
769                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
770                           m_colorSubresourceRange.layerCount);
771     }
772 
beginRenderPass(Context & context,VkCommandBuffer cmdBuffer,const VkRect2D & renderArea,const VkClearValue & clearValue) const773     void beginRenderPass(Context &context, VkCommandBuffer cmdBuffer, const VkRect2D &renderArea,
774                          const VkClearValue &clearValue) const
775     {
776         const DeviceInterface &vk = context.getDeviceInterface();
777         const VkRenderPassBeginInfo renderPassBeginInfo{
778             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
779             DE_NULL,                                  // const void* pNext;
780             *m_renderPass,                            // VkRenderPass renderPass;
781             *m_framebuffer,                           // VkFramebuffer framebuffer;
782             renderArea,                               // VkRect2D renderArea;
783             1u,                                       // uint32_t clearValueCount;
784             &clearValue,                              // const VkClearValue* pClearValues;
785         };
786         vk.cmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
787     }
788 
drawCommands(Context & context,VkCommandBuffer cmdBuffer) const789     void drawCommands(Context &context, VkCommandBuffer cmdBuffer) const
790     {
791         const DeviceInterface &vk             = context.getDeviceInterface();
792         const VkBuffer vertexBuffer           = m_vertexBuffer->object();
793         const VkDeviceSize vertexBufferOffset = 0ull;
794 
795         vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
796         vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
797         vk.cmdDraw(cmdBuffer, static_cast<uint32_t>(m_numLayers * 6), 1u, 0u, 0u); // two triangles per layer
798     }
799 
800 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(Context & context,VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags=0u) const801     void beginSecondaryCmdBuffer(Context &context, VkCommandBuffer cmdBuffer,
802                                  VkRenderingFlagsKHR renderingFlags = 0u) const
803     {
804         VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
805             VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
806             DE_NULL,                                                         // const void* pNext;
807             renderingFlags,                                                  // VkRenderingFlagsKHR flags;
808             0u,                                                              // uint32_t viewMask;
809             1u,                                                              // uint32_t colorAttachmentCount;
810             &m_colorFormat,                                                  // const VkFormat* pColorAttachmentFormats;
811             VK_FORMAT_UNDEFINED,                                             // VkFormat depthAttachmentFormat;
812             VK_FORMAT_UNDEFINED,                                             // VkFormat stencilAttachmentFormat;
813             VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
814         };
815         const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
816 
817         VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
818         if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
819             usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
820 
821         const VkCommandBufferBeginInfo commandBufBeginParams{
822             VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
823             DE_NULL,                                     // const void* pNext;
824             usageFlags,                                  // VkCommandBufferUsageFlags flags;
825             &bufferInheritanceInfo};
826 
827         const DeviceInterface &vk = context.getDeviceInterface();
828         VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
829     }
830 #endif // CTS_USES_VULKANSC
831 
832 private:
833     const SharedGroupParams m_groupParams;
834     const UVec2 m_renderSize;
835     const VkFormat m_colorFormat;
836     const VkImageSubresourceRange m_colorSubresourceRange;
837     const Vec4 m_clearColor;
838     const int m_numLayers;
839     const std::vector<PositionColorVertex> m_vertices;
840 
841     Move<VkImage> m_colorImage;
842     MovePtr<Allocation> m_colorImageAlloc;
843     Move<VkImageView> m_colorAttachment;
844     SharedPtr<Buffer> m_vertexBuffer;
845     Move<VkShaderModule> m_vertexModule;
846     Move<VkShaderModule> m_tessellationControlModule;
847     Move<VkShaderModule> m_tessellationEvaluationModule;
848     Move<VkShaderModule> m_fragmentModule;
849     Move<VkRenderPass> m_renderPass;
850     Move<VkFramebuffer> m_framebuffer;
851     Move<VkPipelineLayout> m_pipelineLayout;
852     Move<VkPipeline> m_pipeline;
853     Move<VkCommandPool> m_cmdPool;
854     Move<VkCommandBuffer> m_cmdBuffer;
855     Move<VkCommandBuffer> m_secCmdBuffer;
856 
857     // "deleted"
858     Renderer(const Renderer &);
859     Renderer &operator=(const Renderer &);
860 };
861 
checkRequirements(Context & context,const TestParams params)862 void checkRequirements(Context &context, const TestParams params)
863 {
864     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
865     context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
866 
867     if (params.groupParams->useDynamicRendering)
868         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
869 
870     const VkPhysicalDeviceLimits limits = context.getDeviceProperties().limits;
871 
872     if (limits.maxFramebufferLayers < MIN_MAX_FRAMEBUFFER_LAYERS)
873         TCU_FAIL("maxFramebuffersLayers is less than the minimum required");
874 
875     if (limits.maxViewports < MIN_MAX_VIEWPORTS)
876         TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
877 }
878 
testVertexShader(Context & context,const TestParams params)879 tcu::TestStatus testVertexShader(Context &context, const TestParams params)
880 {
881     const DeviceInterface &vk = context.getDeviceInterface();
882     const VkDevice device     = context.getDevice();
883     Allocator &allocator      = context.getDefaultAllocator();
884 
885     const UVec2 renderSize(256, 256);
886     const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
887     const Vec4 clearColor(0.5f, 0.5f, 0.5f, 1.0f);
888     const std::vector<UVec4> grid                   = generateGrid(params.numLayers, renderSize);
889     const std::vector<Vec4> colors                  = generateColors(params.numLayers);
890     const std::vector<PositionColorVertex> vertices = generateVertices(grid, colors, renderSize);
891 
892     const VkDeviceSize colorBufferSize =
893         renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * params.numLayers;
894 
895     const SharedPtr<Buffer> colorBuffer =
896         Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT),
897                                allocator, MemoryRequirement::HostVisible);
898 
899     // Zero buffer.
900     {
901         const Allocation alloc = colorBuffer->getBoundMemory();
902         deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
903         flushAlloc(vk, device, alloc);
904     }
905 
906     {
907         context.getTestContext().getLog()
908             << tcu::TestLog::Message << "Rendering a rectangle in each of the " << params.numLayers << " layer(s)."
909             << tcu::TestLog::EndMessage << tcu::TestLog::Message << "Not covered area will be filled with a gray color."
910             << tcu::TestLog::EndMessage;
911     }
912 
913     // Draw.
914     {
915         const Renderer renderer(context, params.groupParams, renderSize, params.numLayers, colorFormat, clearColor,
916                                 vertices, Renderer::VERTEX);
917         renderer.draw(context, colorBuffer->object());
918     }
919 
920     // Verify layers.
921     {
922         const Allocation alloc = colorBuffer->getBoundMemory();
923         invalidateAlloc(vk, device, alloc);
924 
925         uint8_t *resultMem = reinterpret_cast<uint8_t *>(alloc.getHostPtr());
926         for (int i = 0; i < params.numLayers; i++)
927         {
928             const tcu::ConstPixelBufferAccess resultImage(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u,
929                                                           resultMem + ((colorBufferSize / params.numLayers) * i));
930             const tcu::TextureLevel referenceImage =
931                 generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
932             std::string imageSetName = "layer_" + de::toString(i);
933             std::string imageSetDesc = "Image compare for layer " + de::toString(i);
934             if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(),
935                                             imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f),
936                                             tcu::COMPARE_LOG_RESULT))
937                 TCU_FAIL("Rendered image is not correct");
938         }
939     }
940 
941     return tcu::TestStatus::pass("OK");
942 }
943 
testTessellationShader(Context & context,const TestParams params)944 tcu::TestStatus testTessellationShader(Context &context, const TestParams params)
945 {
946     const VkPhysicalDeviceFeatures &features = context.getDeviceFeatures();
947     if (!features.tessellationShader)
948         TCU_THROW(NotSupportedError, "Required feature is not supported: tessellationShader");
949 
950     const DeviceInterface &vk = context.getDeviceInterface();
951     const VkDevice device     = context.getDevice();
952     Allocator &allocator      = context.getDefaultAllocator();
953 
954     const UVec2 renderSize(256, 256);
955     const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
956     const Vec4 clearColor(0.5f, 0.5f, 0.5f, 1.0f);
957     const std::vector<UVec4> grid                   = generateGrid(params.numLayers, renderSize);
958     const std::vector<Vec4> colors                  = generateColors(params.numLayers);
959     const std::vector<PositionColorVertex> vertices = generateVertices(grid, colors, renderSize);
960 
961     const VkDeviceSize colorBufferSize =
962         renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * params.numLayers;
963 
964     const SharedPtr<Buffer> colorBuffer =
965         Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT),
966                                allocator, MemoryRequirement::HostVisible);
967 
968     // Zero buffer.
969     {
970         const Allocation alloc = colorBuffer->getBoundMemory();
971         deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
972         flushAlloc(vk, device, alloc);
973     }
974 
975     {
976         context.getTestContext().getLog()
977             << tcu::TestLog::Message << "Rendering a rectangle in each of the " << params.numLayers << " layer(s)."
978             << tcu::TestLog::EndMessage << tcu::TestLog::Message << "Not covered area will be filled with a gray color."
979             << tcu::TestLog::EndMessage;
980     }
981 
982     // Draw.
983     {
984         const Renderer renderer(context, params.groupParams, renderSize, params.numLayers, colorFormat, clearColor,
985                                 vertices, Renderer::TESSELLATION);
986         renderer.draw(context, colorBuffer->object());
987     }
988 
989     // Verify layers.
990     {
991         const Allocation alloc = colorBuffer->getBoundMemory();
992         invalidateAlloc(vk, device, alloc);
993 
994         uint8_t *resultMem = reinterpret_cast<uint8_t *>(alloc.getHostPtr());
995         for (int i = 0; i < params.numLayers; i++)
996         {
997             const tcu::ConstPixelBufferAccess resultImage(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u,
998                                                           resultMem + ((colorBufferSize / params.numLayers) * i));
999             const tcu::TextureLevel referenceImage =
1000                 generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
1001             std::string imageSetName = "layer_" + de::toString(i);
1002             std::string imageSetDesc = "Image compare for layer " + de::toString(i);
1003             if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(),
1004                                             imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f),
1005                                             tcu::COMPARE_LOG_RESULT))
1006                 TCU_FAIL("Rendered image is not correct");
1007         }
1008     }
1009 
1010     return tcu::TestStatus::pass("OK");
1011 }
1012 
1013 } // namespace
1014 
createShaderLayerTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1015 tcu::TestCaseGroup *createShaderLayerTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
1016 {
1017     MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_layer"));
1018 
1019     int numLayersToTest[] = {
1020         1, 2, 3, 4, 5, 6, 7, 8, MIN_MAX_FRAMEBUFFER_LAYERS,
1021     };
1022 
1023     TestParams parmas{1, groupParams};
1024 
1025     for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1026     {
1027         // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1028         if (groupParams->useSecondaryCmdBuffer && (i % 2))
1029             continue;
1030 
1031         parmas.numLayers = numLayersToTest[i];
1032         addFunctionCaseWithPrograms<TestParams>(group.get(), "vertex_shader_" + de::toString(parmas.numLayers),
1033                                                 checkRequirements, initVertexTestPrograms, testVertexShader, parmas);
1034     }
1035 
1036     for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1037     {
1038         // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1039         if (groupParams->useSecondaryCmdBuffer && (i % 2))
1040             continue;
1041 
1042         parmas.numLayers = numLayersToTest[i];
1043         addFunctionCaseWithPrograms<TestParams>(group.get(), "tessellation_shader_" + de::toString(parmas.numLayers),
1044                                                 checkRequirements, initTessellationTestPrograms, testTessellationShader,
1045                                                 parmas);
1046     }
1047 
1048     return group.release();
1049 }
1050 
1051 } // namespace Draw
1052 } // namespace vkt
1053