1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2018 The Khronos Group Inc.
6 * Copyright (c) 2018 The Android Open Source Project
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Use of gl_Layer in Vertex and Tessellation Shaders
23 * (part of VK_EXT_ShaderViewportIndexLayer)
24 *//*--------------------------------------------------------------------*/
26 #include "vktDrawShaderLayerTests.hpp"
28 #include "vktDrawBaseClass.hpp"
29 #include "vktTestCaseUtil.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"
42 #include "tcuTestLog.hpp"
43 #include "tcuVector.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuTextureUtil.hpp"
47 #include "deUniquePtr.hpp"
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.
77 const SharedGroupParams groupParams;
81 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
83 return vec.size() * sizeof(vec[0]);
86 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, const deUint32 numLayers, VkImageUsageFlags usage)
88 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, // deUint32 mipLevels;
97 numLayers, // deUint32 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, // deUint32 queueFamilyIndexCount;
103 DE_NULL, // const deUint32* pQueueFamilyIndices;
104 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
109 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
110 const VkDevice device,
111 const VkPipelineLayout pipelineLayout,
112 const VkRenderPass renderPass,
113 const VkShaderModule vertexModule,
114 const VkShaderModule tessellationControlModule,
115 const VkShaderModule tessellationEvaluationModule,
116 const VkShaderModule fragmentModule,
117 const UVec2 renderSize)
119 const VkVertexInputBindingDescription vertexInputBindingDescription =
121 0u, // uint32_t binding;
122 sizeof(PositionColorVertex), // uint32_t stride;
123 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
126 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
129 0u, // uint32_t location;
130 0u, // uint32_t binding;
131 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
132 0u, // uint32_t offset;
135 1u, // uint32_t location;
136 0u, // uint32_t binding;
137 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
138 sizeof(Vec4), // uint32_t offset;
142 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
144 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
145 DE_NULL, // const void* pNext;
146 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
147 1u, // uint32_t vertexBindingDescriptionCount;
148 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
149 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
150 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
153 const bool useTessellationShaders = (tessellationControlModule != DE_NULL) && (tessellationEvaluationModule != DE_NULL);
155 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
157 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
158 DE_NULL, // const void* pNext;
159 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
160 useTessellationShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
161 VK_FALSE, // VkBool32 primitiveRestartEnable;
165 VkViewport viewport = makeViewport(0.0f, 0.0f, static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 0.0f, 1.0f);
166 VkRect2D rectScissor = { { 0, 0 }, { renderSize.x(), renderSize.y() } };
168 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
170 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
171 DE_NULL, // const void* pNext;
172 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
173 1u, // uint32_t viewportCount;
174 &viewport, // const VkViewport* pViewports;
175 1u, // uint32_t scissorCount;
176 &rectScissor, // const VkRect2D* pScissors;
179 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
181 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
182 DE_NULL, // const void* pNext;
183 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
184 VK_FALSE, // VkBool32 depthClampEnable;
185 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
186 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
187 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
188 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
189 VK_FALSE, // VkBool32 depthBiasEnable;
190 0.0f, // float depthBiasConstantFactor;
191 0.0f, // float depthBiasClamp;
192 0.0f, // float depthBiasSlopeFactor;
193 1.0f, // float lineWidth;
196 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
198 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
199 DE_NULL, // const void* pNext;
200 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
201 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
202 VK_FALSE, // VkBool32 sampleShadingEnable;
203 0.0f, // float minSampleShading;
204 DE_NULL, // const VkSampleMask* pSampleMask;
205 VK_FALSE, // VkBool32 alphaToCoverageEnable;
206 VK_FALSE // VkBool32 alphaToOneEnable;
209 const VkStencilOpState stencilOpState = makeStencilOpState(
210 VK_STENCIL_OP_KEEP, // stencil fail
211 VK_STENCIL_OP_KEEP, // depth & stencil pass
212 VK_STENCIL_OP_KEEP, // depth only fail
213 VK_COMPARE_OP_ALWAYS, // compare op
218 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
220 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
221 DE_NULL, // const void* pNext;
222 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
223 VK_FALSE, // VkBool32 depthTestEnable;
224 VK_FALSE, // VkBool32 depthWriteEnable;
225 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
226 VK_FALSE, // VkBool32 depthBoundsTestEnable;
227 VK_FALSE, // VkBool32 stencilTestEnable;
228 stencilOpState, // VkStencilOpState front;
229 stencilOpState, // VkStencilOpState back;
230 0.0f, // float minDepthBounds;
231 1.0f, // float maxDepthBounds;
234 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
235 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
237 VK_FALSE, // VkBool32 blendEnable;
238 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
239 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
240 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
241 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
242 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
243 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
244 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
247 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
249 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
250 DE_NULL, // const void* pNext;
251 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
252 VK_FALSE, // VkBool32 logicOpEnable;
253 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
254 1u, // deUint32 attachmentCount;
255 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
256 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
259 const VkPipelineShaderStageCreateInfo pShaderStages[] =
262 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
263 DE_NULL, // const void* pNext;
264 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
265 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
266 vertexModule, // VkShaderModule module;
267 "main", // const char* pName;
268 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
271 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
272 DE_NULL, // const void* pNext;
273 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
274 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
275 fragmentModule, // VkShaderModule module;
276 "main", // const char* pName;
277 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
280 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
281 DE_NULL, // const void* pNext;
282 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
283 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlagBits stage;
284 tessellationControlModule, // VkShaderModule module;
285 "main", // const char* pName;
286 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
289 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
290 DE_NULL, // const void* pNext;
291 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
292 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, // VkShaderStageFlagBits stage;
293 tessellationEvaluationModule, // VkShaderModule module;
294 "main", // const char* pName;
295 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
299 const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
301 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
302 DE_NULL, // const void* pNext;
303 (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags;
304 3, // uint32_t patchControlPoints;
307 VkGraphicsPipelineCreateInfo graphicsPipelineInfo
309 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
310 DE_NULL, // const void* pNext;
311 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
312 useTessellationShaders ? deUint32(4) : deUint32(2), // deUint32 stageCount;
313 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
314 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
315 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
316 useTessellationShaders ? &pipelineTessellationStateInfo : DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
317 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
318 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
319 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
320 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
321 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
322 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
323 pipelineLayout, // VkPipelineLayout layout;
324 renderPass, // VkRenderPass renderPass;
325 0u, // deUint32 subpass;
326 DE_NULL, // VkPipeline basePipelineHandle;
327 0, // deInt32 basePipelineIndex;
330 #ifndef CTS_USES_VULKANSC
331 VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
332 VkPipelineRenderingCreateInfoKHR renderingCreateInfo
334 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
338 &colorAttachmentFormat,
343 // when pipeline is created without render pass we are using dynamic rendering
344 if (renderPass == DE_NULL)
345 graphicsPipelineInfo.pNext = &renderingCreateInfo;
346 #endif // CTS_USES_VULKANSC
348 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
351 //! Renders a colorful grid of rectangles.
352 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format,
353 const UVec2& renderSize,
354 const Vec4& clearColor,
356 const Vec4& cellColor)
358 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
359 tcu::clear(image.getAccess(), clearColor);
361 tcu::clear(tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()),
367 void initVertexTestPrograms (SourceCollections& programCollection, const TestParams params)
369 DE_UNREF(params.numLayers);
373 std::ostringstream src;
374 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
375 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
377 << "layout(location = 0) in vec4 in_position;\n"
378 << "layout(location = 1) in vec4 in_color;\n"
379 << "layout(location = 0) out vec4 out_color;\n"
381 << "void main(void)\n"
383 << " gl_Layer = gl_VertexIndex / 6;\n"
384 << " gl_Position = in_position;\n"
385 << " out_color = in_color;\n"
388 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
393 std::ostringstream src;
394 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
396 << "layout(location = 0) in vec4 in_color;\n"
397 << "layout(location = 0) out vec4 out_color;\n"
399 << "void main(void)\n"
401 << " out_color = in_color;\n"
404 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
408 void initTessellationTestPrograms (SourceCollections& programCollection, const TestParams params)
410 DE_UNREF(params.numLayers);
414 std::ostringstream src;
415 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
417 << "layout(location = 0) in vec4 in_position;\n"
418 << "layout(location = 1) in vec4 in_color;\n"
419 << "layout(location = 0) out vec4 out_color;\n"
421 << "void main(void)\n"
423 << " gl_Position = in_position;\n"
424 << " out_color = in_color;\n"
427 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
430 // Tessellation control shader
432 std::ostringstream src;
433 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
435 << "layout(vertices = 3) out;\n"
437 << "layout(location = 0) in vec4 in_color[];\n"
438 << "layout(location = 0) out vec4 out_color[];\n"
440 << "void main(void)\n"
442 << " if (gl_InvocationID == 0) {\n"
443 << " gl_TessLevelInner[0] = 1.0;\n"
444 << " gl_TessLevelInner[1] = 1.0;\n"
445 << " gl_TessLevelOuter[0] = 1.0;\n"
446 << " gl_TessLevelOuter[1] = 1.0;\n"
447 << " gl_TessLevelOuter[2] = 1.0;\n"
448 << " gl_TessLevelOuter[3] = 1.0;\n"
450 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
451 << " out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
454 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
457 // Tessellation evaluation shader
459 std::ostringstream src;
460 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
461 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
463 << "layout(triangles, equal_spacing, cw) in;\n"
465 << "layout(location = 0) in vec4 in_color[];\n"
466 << "layout(location = 0) out vec4 out_color;\n"
468 << "void main(void)\n"
470 << " gl_Layer = gl_PrimitiveID / 2;\n"
471 << " gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
472 << " gl_in[1].gl_Position * gl_TessCoord.y +\n"
473 << " gl_in[2].gl_Position * gl_TessCoord.z;\n"
475 << " out_color = in_color[0] * gl_TessCoord.x +\n"
476 << " in_color[1] * gl_TessCoord.y +\n"
477 << " in_color[2] * gl_TessCoord.z;\n"
480 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
485 std::ostringstream src;
486 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
488 << "layout(location = 0) in vec4 in_color;\n"
489 << "layout(location = 0) out vec4 out_color;\n"
491 << "void main(void)\n"
493 << " out_color = in_color;\n"
496 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
500 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
502 const int numCols = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
503 const int numRows = deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
504 const int rectWidth = renderSize.x() / numCols;
505 const int rectHeight = renderSize.y() / numRows;
507 std::vector<UVec4> cells;
508 cells.reserve(numCells);
513 for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
515 const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
522 cells.push_back(UVec4(x, y, rectWidth, rectHeight));
530 std::vector<Vec4> generateColors (int numColors)
532 const Vec4 colors[] =
534 Vec4(0.18f, 0.42f, 0.17f, 1.0f),
535 Vec4(0.29f, 0.62f, 0.28f, 1.0f),
536 Vec4(0.59f, 0.84f, 0.44f, 1.0f),
537 Vec4(0.96f, 0.95f, 0.72f, 1.0f),
538 Vec4(0.94f, 0.55f, 0.39f, 1.0f),
539 Vec4(0.82f, 0.19f, 0.12f, 1.0f),
540 Vec4(0.46f, 0.15f, 0.26f, 1.0f),
541 Vec4(0.24f, 0.14f, 0.24f, 1.0f),
542 Vec4(0.49f, 0.31f, 0.26f, 1.0f),
543 Vec4(0.78f, 0.52f, 0.33f, 1.0f),
544 Vec4(0.94f, 0.82f, 0.31f, 1.0f),
545 Vec4(0.98f, 0.65f, 0.30f, 1.0f),
546 Vec4(0.22f, 0.65f, 0.53f, 1.0f),
547 Vec4(0.67f, 0.81f, 0.91f, 1.0f),
548 Vec4(0.43f, 0.44f, 0.75f, 1.0f),
549 Vec4(0.26f, 0.24f, 0.48f, 1.0f),
552 std::vector<Vec4> result;
553 result.reserve(numColors);
555 for (int i = 0; i < numColors; ++i)
557 result.push_back(colors[i % DE_LENGTH_OF_ARRAY(colors)]);
563 std::vector<PositionColorVertex> generateVertices (const std::vector<UVec4>& grid, const std::vector<Vec4>& colors, const UVec2& renderSize)
565 DE_ASSERT(colors.size() == grid.size());
567 // Two triangles for each cell. Each cell correspond to a layer.
568 std::size_t total = grid.size() * 6;
570 std::vector<PositionColorVertex> result;
571 result.reserve(total);
573 for (std::size_t i = 0; i < total; ++i)
579 Vec4 cell = grid[i/6].asFloat() * 2.0f;
580 float x = cell.x() / float(renderSize.x()) - 1.0f;
581 float y = cell.y() / float(renderSize.y()) - 1.0f;
582 float width = cell.z() / float(renderSize.x());
583 float height = cell.w() / float(renderSize.y());
587 case 0: pos.xy() = Vec2(x, y + height); break;
588 case 1: pos.xy() = Vec2(x + width, y + height); break;
589 case 2: pos.xy() = Vec2(x, y); break;
590 case 3: pos.xy() = Vec2(x + width, y); break;
591 case 4: pos.xy() = Vec2(x + width, y + height); break;
592 case 5: pos.xy() = Vec2(x, y); break;
595 result.push_back(PositionColorVertex(pos, colors[i/6]));
601 // Renderer generates two triangles per layer, each pair using a different
602 // color and a different position.
612 Renderer (Context& context,
613 const SharedGroupParams groupParams,
614 const UVec2& renderSize,
616 const VkFormat colorFormat,
617 const Vec4& clearColor,
618 const std::vector<PositionColorVertex>& vertices,
620 : m_groupParams (groupParams)
621 , m_renderSize (renderSize)
622 , m_colorFormat (colorFormat)
623 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers))
624 , m_clearColor (clearColor)
625 , m_numLayers (numLayers)
626 , m_vertices (vertices)
628 const DeviceInterface& vk = context.getDeviceInterface();
629 const VkDevice device = context.getDevice();
630 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
631 Allocator& allocator = context.getDefaultAllocator();
632 const VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices);
634 m_colorImage = makeImage (vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, m_numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
635 m_colorImageAlloc = bindImage (vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
636 m_colorAttachment = makeImageView (vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_colorFormat, m_colorSubresourceRange);
638 m_vertexBuffer = Buffer::createAndAlloc (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
640 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
641 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
643 if (shader == TESSELLATION)
645 m_tessellationControlModule = createShaderModule (vk, device, context.getBinaryCollection().get("tesc"), 0u);
646 m_tessellationEvaluationModule = createShaderModule (vk, device, context.getBinaryCollection().get("tese"), 0u);
649 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u);
650 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u);
652 if (!m_groupParams->useDynamicRendering)
654 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
656 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, m_colorAttachment.get(),
657 static_cast<deUint32>(m_renderSize.x()),
658 static_cast<deUint32>(m_renderSize.y()),
662 m_pipelineLayout = makePipelineLayout (vk, device);
663 m_pipeline = makeGraphicsPipeline (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
664 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize);
665 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
666 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
667 m_secCmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
670 void draw (Context& context, const VkBuffer colorBuffer) const
672 const DeviceInterface& vk = context.getDeviceInterface();
673 const VkDevice device = context.getDevice();
674 const VkQueue queue = context.getUniversalQueue();
675 const VkClearValue clearValue = makeClearValueColor(m_clearColor);
676 const VkRect2D renderArea
679 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
682 #ifndef CTS_USES_VULKANSC
683 if (m_groupParams->useSecondaryCmdBuffer)
685 // record secondary command buffer
686 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
688 beginSecondaryCmdBuffer(context, *m_secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
689 beginRendering(vk, *m_secCmdBuffer, *m_colorAttachment, renderArea, clearValue,
690 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, 0u, m_numLayers);
693 beginSecondaryCmdBuffer(context, *m_secCmdBuffer);
695 drawCommands(context, *m_secCmdBuffer);
697 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
698 endRendering(vk, *m_secCmdBuffer);
700 endCommandBuffer(vk, *m_secCmdBuffer);
702 // record primary command buffer
703 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
705 preRenderCommands(context, *m_cmdBuffer);
707 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
708 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
709 VK_ATTACHMENT_LOAD_OP_CLEAR, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, m_numLayers);
711 vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
713 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
714 endRendering(vk, *m_cmdBuffer);
716 postRenderCommands(context, colorBuffer);
717 endCommandBuffer(vk, *m_cmdBuffer);
719 else if (m_groupParams->useDynamicRendering)
721 beginCommandBuffer(vk, *m_cmdBuffer);
723 preRenderCommands(context, *m_cmdBuffer);
724 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue,
725 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, 0u, m_numLayers);
726 drawCommands(context, *m_cmdBuffer);
727 endRendering(vk, *m_cmdBuffer);
728 postRenderCommands(context, colorBuffer);
730 endCommandBuffer(vk, *m_cmdBuffer);
732 #endif // CTS_USES_VULKANSC
734 if (!m_groupParams->useDynamicRendering)
736 beginCommandBuffer(vk, *m_cmdBuffer);
738 preRenderCommands(context, *m_cmdBuffer);
739 beginRenderPass(context, *m_cmdBuffer, renderArea, clearValue);
740 drawCommands(context, *m_cmdBuffer);
741 vk.cmdEndRenderPass(*m_cmdBuffer);
742 postRenderCommands(context, colorBuffer);
744 endCommandBuffer(vk, *m_cmdBuffer);
747 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
752 void preRenderCommands(Context& context, VkCommandBuffer cmdBuffer) const
754 if (m_groupParams->useDynamicRendering)
756 const DeviceInterface& vk = context.getDeviceInterface();
757 initialTransitionColor2DImage(vk, cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
758 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, m_colorSubresourceRange.layerCount);
762 void postRenderCommands(Context& context, VkBuffer colorBuffer) const
764 const DeviceInterface& vk = context.getDeviceInterface();
765 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, m_colorSubresourceRange.layerCount);
768 void beginRenderPass(Context& context, VkCommandBuffer cmdBuffer, const VkRect2D& renderArea, const VkClearValue& clearValue) const
770 const DeviceInterface& vk = context.getDeviceInterface();
771 const VkRenderPassBeginInfo renderPassBeginInfo
773 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
774 DE_NULL, // const void* pNext;
775 *m_renderPass, // VkRenderPass renderPass;
776 *m_framebuffer, // VkFramebuffer framebuffer;
777 renderArea, // VkRect2D renderArea;
778 1u, // uint32_t clearValueCount;
779 &clearValue, // const VkClearValue* pClearValues;
781 vk.cmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
784 void drawCommands (Context& context, VkCommandBuffer cmdBuffer) const
786 const DeviceInterface& vk = context.getDeviceInterface();
787 const VkBuffer vertexBuffer = m_vertexBuffer->object();
788 const VkDeviceSize vertexBufferOffset = 0ull;
790 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
791 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
792 vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numLayers * 6), 1u, 0u, 0u); // two triangles per layer
795 #ifndef CTS_USES_VULKANSC
796 void beginSecondaryCmdBuffer(Context& context, VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const
798 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
800 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
801 DE_NULL, // const void* pNext;
802 renderingFlags, // VkRenderingFlagsKHR flags;
803 0u, // uint32_t viewMask;
804 1u, // uint32_t colorAttachmentCount;
805 &m_colorFormat, // const VkFormat* pColorAttachmentFormats;
806 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
807 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
808 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
810 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
812 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
813 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
814 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
816 const VkCommandBufferBeginInfo commandBufBeginParams
818 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
819 DE_NULL, // const void* pNext;
820 usageFlags, // VkCommandBufferUsageFlags flags;
821 &bufferInheritanceInfo
824 const DeviceInterface& vk = context.getDeviceInterface();
825 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
827 #endif // CTS_USES_VULKANSC
830 const SharedGroupParams m_groupParams;
831 const UVec2 m_renderSize;
832 const VkFormat m_colorFormat;
833 const VkImageSubresourceRange m_colorSubresourceRange;
834 const Vec4 m_clearColor;
835 const int m_numLayers;
836 const std::vector<PositionColorVertex> m_vertices;
838 Move<VkImage> m_colorImage;
839 MovePtr<Allocation> m_colorImageAlloc;
840 Move<VkImageView> m_colorAttachment;
841 SharedPtr<Buffer> m_vertexBuffer;
842 Move<VkShaderModule> m_vertexModule;
843 Move<VkShaderModule> m_tessellationControlModule;
844 Move<VkShaderModule> m_tessellationEvaluationModule;
845 Move<VkShaderModule> m_fragmentModule;
846 Move<VkRenderPass> m_renderPass;
847 Move<VkFramebuffer> m_framebuffer;
848 Move<VkPipelineLayout> m_pipelineLayout;
849 Move<VkPipeline> m_pipeline;
850 Move<VkCommandPool> m_cmdPool;
851 Move<VkCommandBuffer> m_cmdBuffer;
852 Move<VkCommandBuffer> m_secCmdBuffer;
855 Renderer (const Renderer&);
856 Renderer& operator= (const Renderer&);
859 void checkRequirements (Context& context, const TestParams params)
861 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
862 context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
864 if (params.groupParams->useDynamicRendering)
865 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
867 const VkPhysicalDeviceLimits limits = context.getDeviceProperties().limits;
869 if (limits.maxFramebufferLayers < MIN_MAX_FRAMEBUFFER_LAYERS)
870 TCU_FAIL("maxFramebuffersLayers is less than the minimum required");
872 if (limits.maxViewports < MIN_MAX_VIEWPORTS)
873 TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
876 tcu::TestStatus testVertexShader (Context& context, const TestParams params)
878 const DeviceInterface& vk = context.getDeviceInterface();
879 const VkDevice device = context.getDevice();
880 Allocator& allocator = context.getDefaultAllocator();
882 const UVec2 renderSize (256, 256);
883 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
884 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
885 const std::vector<UVec4> grid = generateGrid(params.numLayers, renderSize);
886 const std::vector<Vec4> colors = generateColors(params.numLayers);
887 const std::vector<PositionColorVertex> vertices = generateVertices(grid, colors, renderSize);
889 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * params.numLayers;
891 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
895 const Allocation alloc = colorBuffer->getBoundMemory();
896 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
897 flushAlloc(vk, device, alloc);
901 context.getTestContext().getLog()
902 << tcu::TestLog::Message << "Rendering a rectangle in each of the " << params.numLayers << " layer(s)." << tcu::TestLog::EndMessage
903 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
908 const Renderer renderer (context, params.groupParams, renderSize, params.numLayers, colorFormat, clearColor, vertices, Renderer::VERTEX);
909 renderer.draw(context, colorBuffer->object());
914 const Allocation alloc = colorBuffer->getBoundMemory();
915 invalidateAlloc(vk, device, alloc);
917 deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
918 for (int i = 0; i < params.numLayers; i++)
920 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / params.numLayers) * i));
921 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
922 std::string imageSetName = "layer_" + de::toString(i);
923 std::string imageSetDesc = "Image compare for layer " + de::toString(i);
924 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
925 TCU_FAIL("Rendered image is not correct");
929 return tcu::TestStatus::pass("OK");
932 tcu::TestStatus testTessellationShader (Context& context, const TestParams params)
934 const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures();
935 if (!features.tessellationShader)
936 TCU_THROW(NotSupportedError, "Required feature is not supported: tessellationShader");
938 const DeviceInterface& vk = context.getDeviceInterface();
939 const VkDevice device = context.getDevice();
940 Allocator& allocator = context.getDefaultAllocator();
942 const UVec2 renderSize (256, 256);
943 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
944 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
945 const std::vector<UVec4> grid = generateGrid(params.numLayers, renderSize);
946 const std::vector<Vec4> colors = generateColors(params.numLayers);
947 const std::vector<PositionColorVertex> vertices = generateVertices(grid, colors, renderSize);
949 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * params.numLayers;
951 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
955 const Allocation alloc = colorBuffer->getBoundMemory();
956 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
957 flushAlloc(vk, device, alloc);
961 context.getTestContext().getLog()
962 << tcu::TestLog::Message << "Rendering a rectangle in each of the " << params.numLayers << " layer(s)." << tcu::TestLog::EndMessage
963 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
968 const Renderer renderer (context, params.groupParams, renderSize, params.numLayers, colorFormat, clearColor, vertices, Renderer::TESSELLATION);
969 renderer.draw(context, colorBuffer->object());
974 const Allocation alloc = colorBuffer->getBoundMemory();
975 invalidateAlloc(vk, device, alloc);
977 deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
978 for (int i = 0; i < params.numLayers; i++) {
979 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / params.numLayers) * i));
980 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
981 std::string imageSetName = "layer_" + de::toString(i);
982 std::string imageSetDesc = "Image compare for layer " + de::toString(i);
983 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
984 TCU_FAIL("Rendered image is not correct");
988 return tcu::TestStatus::pass("OK");
993 tcu::TestCaseGroup* createShaderLayerTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
995 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_layer", ""));
997 int numLayersToTest[] =
1007 MIN_MAX_FRAMEBUFFER_LAYERS,
1016 for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1018 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1019 if (groupParams->useSecondaryCmdBuffer && (i % 2))
1022 parmas.numLayers = numLayersToTest[i];
1023 addFunctionCaseWithPrograms<TestParams>(group.get(), "vertex_shader_" + de::toString(parmas.numLayers), "", checkRequirements, initVertexTestPrograms, testVertexShader, parmas);
1026 for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1028 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1029 if (groupParams->useSecondaryCmdBuffer && (i % 2))
1032 parmas.numLayers = numLayersToTest[i];
1033 addFunctionCaseWithPrograms<TestParams>(group.get(), "tessellation_shader_" + de::toString(parmas.numLayers), "", checkRequirements, initTessellationTestPrograms, testTessellationShader, parmas);
1036 return group.release();