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