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::UniquePtr;
58 using de::MovePtr;
59 using de::SharedPtr;
60 using tcu::Vec4;
61 using tcu::Vec2;
62 using tcu::UVec2;
63 using tcu::UVec4;
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 deUint32 numLayers,VkImageUsageFlags usage)86 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, const deUint32 numLayers, VkImageUsageFlags usage)
87 {
88 const VkImageCreateInfo imageParams =
89 {
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;
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,
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)
118 {
119 const VkVertexInputBindingDescription vertexInputBindingDescription =
120 {
121 0u, // uint32_t binding;
122 sizeof(PositionColorVertex), // uint32_t stride;
123 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
124 };
125
126 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
127 {
128 {
129 0u, // uint32_t location;
130 0u, // uint32_t binding;
131 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
132 0u, // uint32_t offset;
133 },
134 {
135 1u, // uint32_t location;
136 0u, // uint32_t binding;
137 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
138 sizeof(Vec4), // uint32_t offset;
139 },
140 };
141
142 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
143 {
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;
151 };
152
153 const bool useTessellationShaders = (tessellationControlModule != DE_NULL) && (tessellationEvaluationModule != DE_NULL);
154
155 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
156 {
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;
162 };
163
164
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() } };
167
168 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
169 {
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;
177 };
178
179 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
180 {
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;
194 };
195
196 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
197 {
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;
207 };
208
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
214 0u, // compare mask
215 0u, // write mask
216 0u); // reference
217
218 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
219 {
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;
232 };
233
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 =
236 {
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;
245 };
246
247 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
248 {
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];
257 };
258
259 const VkPipelineShaderStageCreateInfo pShaderStages[] =
260 {
261 {
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;
269 },
270 {
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;
278 },
279 {
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;
287 },
288 {
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;
296 },
297 };
298
299 const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
300 {
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;
305 };
306
307 VkGraphicsPipelineCreateInfo graphicsPipelineInfo
308 {
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;
328 };
329
330 #ifndef CTS_USES_VULKANSC
331 VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
332 VkPipelineRenderingCreateInfoKHR renderingCreateInfo
333 {
334 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
335 DE_NULL,
336 0u,
337 1u,
338 &colorAttachmentFormat,
339 VK_FORMAT_UNDEFINED,
340 VK_FORMAT_UNDEFINED
341 };
342
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
347
348 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
349 }
350
351 //! Renders a colorful grid of rectangles.
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const Vec4 & clearColor,const UVec4 & cell,const Vec4 & cellColor)352 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format,
353 const UVec2& renderSize,
354 const Vec4& clearColor,
355 const UVec4& cell,
356 const Vec4& cellColor)
357 {
358 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
359 tcu::clear(image.getAccess(), clearColor);
360
361 tcu::clear(tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()),
362 cellColor);
363
364 return image;
365 }
366
initVertexTestPrograms(SourceCollections & programCollection,const TestParams params)367 void initVertexTestPrograms (SourceCollections& programCollection, const TestParams params)
368 {
369 DE_UNREF(params.numLayers);
370
371 // Vertex shader
372 {
373 std::ostringstream src;
374 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
375 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
376 << "\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"
380 << "\n"
381 << "void main(void)\n"
382 << "{\n"
383 << " gl_Layer = gl_VertexIndex / 6;\n"
384 << " gl_Position = in_position;\n"
385 << " out_color = in_color;\n"
386 << "}\n";
387
388 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
389 programCollection.glslSources.add("vert_1_2") << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
390
391 }
392
393 // Fragment shader
394 {
395 std::ostringstream src;
396 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
397 << "\n"
398 << "layout(location = 0) in vec4 in_color;\n"
399 << "layout(location = 0) out vec4 out_color;\n"
400 << "\n"
401 << "void main(void)\n"
402 << "{\n"
403 << " out_color = in_color;\n"
404 << "}\n";
405
406 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
407 }
408 }
409
initTessellationTestPrograms(SourceCollections & programCollection,const TestParams params)410 void initTessellationTestPrograms (SourceCollections& programCollection, const TestParams params)
411 {
412 DE_UNREF(params.numLayers);
413
414 // Vertex shader
415 {
416 std::ostringstream src;
417 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
418 << "\n"
419 << "layout(location = 0) in vec4 in_position;\n"
420 << "layout(location = 1) in vec4 in_color;\n"
421 << "layout(location = 0) out vec4 out_color;\n"
422 << "\n"
423 << "void main(void)\n"
424 << "{\n"
425 << " gl_Position = in_position;\n"
426 << " out_color = in_color;\n"
427 << "}\n";
428
429 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
430 programCollection.glslSources.add("vert_1_2") << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
431 }
432
433 // Tessellation control shader
434 {
435 std::ostringstream src;
436 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
437 << "\n"
438 << "layout(vertices = 3) out;\n"
439 << "\n"
440 << "layout(location = 0) in vec4 in_color[];\n"
441 << "layout(location = 0) out vec4 out_color[];\n"
442 << "\n"
443 << "void main(void)\n"
444 << "{\n"
445 << " if (gl_InvocationID == 0) {\n"
446 << " gl_TessLevelInner[0] = 1.0;\n"
447 << " gl_TessLevelInner[1] = 1.0;\n"
448 << " gl_TessLevelOuter[0] = 1.0;\n"
449 << " gl_TessLevelOuter[1] = 1.0;\n"
450 << " gl_TessLevelOuter[2] = 1.0;\n"
451 << " gl_TessLevelOuter[3] = 1.0;\n"
452 << " }\n"
453 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
454 << " out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
455 << "}\n";
456
457 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
458 }
459
460 // Tessellation evaluation shader
461 {
462 std::ostringstream src;
463 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
464 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
465 << "\n"
466 << "layout(triangles, equal_spacing, cw) in;\n"
467 << "\n"
468 << "layout(location = 0) in vec4 in_color[];\n"
469 << "layout(location = 0) out vec4 out_color;\n"
470 << "\n"
471 << "void main(void)\n"
472 << "{\n"
473 << " gl_Layer = gl_PrimitiveID / 2;\n"
474 << " gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
475 << " gl_in[1].gl_Position * gl_TessCoord.y +\n"
476 << " gl_in[2].gl_Position * gl_TessCoord.z;\n"
477 << "\n"
478 << " out_color = in_color[0] * gl_TessCoord.x +\n"
479 << " in_color[1] * gl_TessCoord.y +\n"
480 << " in_color[2] * gl_TessCoord.z;\n"
481 << "}\n";
482
483 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
484 programCollection.glslSources.add("tese_1_2") << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
485 }
486
487 // Fragment shader
488 {
489 std::ostringstream src;
490 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
491 << "\n"
492 << "layout(location = 0) in vec4 in_color;\n"
493 << "layout(location = 0) out vec4 out_color;\n"
494 << "\n"
495 << "void main(void)\n"
496 << "{\n"
497 << " out_color = in_color;\n"
498 << "}\n";
499
500 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
501 }
502 }
503
generateGrid(const int numCells,const UVec2 & renderSize)504 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
505 {
506 const int numCols = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
507 const int numRows = deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
508 const int rectWidth = renderSize.x() / numCols;
509 const int rectHeight = renderSize.y() / numRows;
510
511 std::vector<UVec4> cells;
512 cells.reserve(numCells);
513
514 int x = 0;
515 int y = 0;
516
517 for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
518 {
519 const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
520 if (nextRow)
521 {
522 x = 0;
523 y += rectHeight;
524 }
525
526 cells.push_back(UVec4(x, y, rectWidth, rectHeight));
527
528 x += rectWidth;
529 }
530
531 return cells;
532 }
533
generateColors(int numColors)534 std::vector<Vec4> generateColors (int numColors)
535 {
536 const Vec4 colors[] =
537 {
538 Vec4(0.18f, 0.42f, 0.17f, 1.0f),
539 Vec4(0.29f, 0.62f, 0.28f, 1.0f),
540 Vec4(0.59f, 0.84f, 0.44f, 1.0f),
541 Vec4(0.96f, 0.95f, 0.72f, 1.0f),
542 Vec4(0.94f, 0.55f, 0.39f, 1.0f),
543 Vec4(0.82f, 0.19f, 0.12f, 1.0f),
544 Vec4(0.46f, 0.15f, 0.26f, 1.0f),
545 Vec4(0.24f, 0.14f, 0.24f, 1.0f),
546 Vec4(0.49f, 0.31f, 0.26f, 1.0f),
547 Vec4(0.78f, 0.52f, 0.33f, 1.0f),
548 Vec4(0.94f, 0.82f, 0.31f, 1.0f),
549 Vec4(0.98f, 0.65f, 0.30f, 1.0f),
550 Vec4(0.22f, 0.65f, 0.53f, 1.0f),
551 Vec4(0.67f, 0.81f, 0.91f, 1.0f),
552 Vec4(0.43f, 0.44f, 0.75f, 1.0f),
553 Vec4(0.26f, 0.24f, 0.48f, 1.0f),
554 };
555
556 std::vector<Vec4> result;
557 result.reserve(numColors);
558
559 for (int i = 0; i < numColors; ++i)
560 {
561 result.push_back(colors[i % DE_LENGTH_OF_ARRAY(colors)]);
562 }
563
564 return result;
565 }
566
generateVertices(const std::vector<UVec4> & grid,const std::vector<Vec4> & colors,const UVec2 & renderSize)567 std::vector<PositionColorVertex> generateVertices (const std::vector<UVec4>& grid, const std::vector<Vec4>& colors, const UVec2& renderSize)
568 {
569 DE_ASSERT(colors.size() == grid.size());
570
571 // Two triangles for each cell. Each cell correspond to a layer.
572 std::size_t total = grid.size() * 6;
573
574 std::vector<PositionColorVertex> result;
575 result.reserve(total);
576
577 for (std::size_t i = 0; i < total; ++i)
578 {
579 Vec4 pos;
580 pos.z() = 0.0;
581 pos.w() = 1.0;
582
583 Vec4 cell = grid[i/6].asFloat() * 2.0f;
584 float x = cell.x() / float(renderSize.x()) - 1.0f;
585 float y = cell.y() / float(renderSize.y()) - 1.0f;
586 float width = cell.z() / float(renderSize.x());
587 float height = cell.w() / float(renderSize.y());
588
589 switch (i % 6)
590 {
591 case 0: pos.xy() = Vec2(x, y + height); break;
592 case 1: pos.xy() = Vec2(x + width, y + height); break;
593 case 2: pos.xy() = Vec2(x, y); break;
594 case 3: pos.xy() = Vec2(x + width, y); break;
595 case 4: pos.xy() = Vec2(x + width, y + height); break;
596 case 5: pos.xy() = Vec2(x, y); break;
597 }
598
599 result.push_back(PositionColorVertex(pos, colors[i/6]));
600 }
601
602 return result;
603 }
604
605 // Renderer generates two triangles per layer, each pair using a different
606 // color and a different position.
607 class Renderer
608 {
609 public:
610 enum Shader
611 {
612 VERTEX,
613 TESSELLATION,
614 };
615
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)616 Renderer (Context& context,
617 const SharedGroupParams groupParams,
618 const UVec2& renderSize,
619 const int numLayers,
620 const VkFormat colorFormat,
621 const Vec4& clearColor,
622 const std::vector<PositionColorVertex>& vertices,
623 const Shader shader)
624 : m_groupParams (groupParams)
625 , m_renderSize (renderSize)
626 , m_colorFormat (colorFormat)
627 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers))
628 , m_clearColor (clearColor)
629 , m_numLayers (numLayers)
630 , m_vertices (vertices)
631 {
632 const DeviceInterface& vk = context.getDeviceInterface();
633 const VkDevice device = context.getDevice();
634 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
635 Allocator& allocator = context.getDefaultAllocator();
636 const VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices);
637
638 m_colorImage = makeImage (vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, m_numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
639 m_colorImageAlloc = bindImage (vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
640 m_colorAttachment = makeImageView (vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_colorFormat, m_colorSubresourceRange);
641
642 m_vertexBuffer = Buffer::createAndAlloc (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
643
644 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
645 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
646
647 if (shader == TESSELLATION)
648 {
649 m_tessellationControlModule = createShaderModule (vk, device, context.getBinaryCollection().get("tesc"), 0u);
650 if (context.contextSupports(VK_API_VERSION_1_2))
651 m_tessellationEvaluationModule = createShaderModule (vk, device, context.getBinaryCollection().get("tese_1_2"), 0u);
652 else
653 m_tessellationEvaluationModule = createShaderModule(vk, device, context.getBinaryCollection().get("tese"), 0u);
654 }
655
656 if (context.contextSupports(VK_API_VERSION_1_2))
657 m_vertexModule = createShaderModule(vk, device, context.getBinaryCollection().get("vert_1_2"), 0u);
658 else
659 m_vertexModule = createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u);
660
661 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u);
662
663 if (!m_groupParams->useDynamicRendering)
664 {
665 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
666
667 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, m_colorAttachment.get(),
668 static_cast<deUint32>(m_renderSize.x()),
669 static_cast<deUint32>(m_renderSize.y()),
670 numLayers);
671 }
672
673 m_pipelineLayout = makePipelineLayout (vk, device);
674 m_pipeline = makeGraphicsPipeline (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
675 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize);
676 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
677 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
678 m_secCmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
679 }
680
draw(Context & context,const VkBuffer colorBuffer) const681 void draw (Context& context, const VkBuffer colorBuffer) const
682 {
683 const DeviceInterface& vk = context.getDeviceInterface();
684 const VkDevice device = context.getDevice();
685 const VkQueue queue = context.getUniversalQueue();
686 const VkClearValue clearValue = makeClearValueColor(m_clearColor);
687 const VkRect2D renderArea
688 {
689 makeOffset2D(0, 0),
690 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
691 };
692
693 #ifndef CTS_USES_VULKANSC
694 if (m_groupParams->useSecondaryCmdBuffer)
695 {
696 // record secondary command buffer
697 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
698 {
699 beginSecondaryCmdBuffer(context, *m_secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
700 beginRendering(vk, *m_secCmdBuffer, *m_colorAttachment, renderArea, clearValue,
701 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, 0u, m_numLayers);
702 }
703 else
704 beginSecondaryCmdBuffer(context, *m_secCmdBuffer);
705
706 drawCommands(context, *m_secCmdBuffer);
707
708 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
709 endRendering(vk, *m_secCmdBuffer);
710
711 endCommandBuffer(vk, *m_secCmdBuffer);
712
713 // record primary command buffer
714 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
715
716 preRenderCommands(context, *m_cmdBuffer);
717
718 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
719 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
720 VK_ATTACHMENT_LOAD_OP_CLEAR, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, m_numLayers);
721
722 vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
723
724 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
725 endRendering(vk, *m_cmdBuffer);
726
727 postRenderCommands(context, colorBuffer);
728 endCommandBuffer(vk, *m_cmdBuffer);
729 }
730 else if (m_groupParams->useDynamicRendering)
731 {
732 beginCommandBuffer(vk, *m_cmdBuffer);
733
734 preRenderCommands(context, *m_cmdBuffer);
735 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue,
736 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, 0u, m_numLayers);
737 drawCommands(context, *m_cmdBuffer);
738 endRendering(vk, *m_cmdBuffer);
739 postRenderCommands(context, colorBuffer);
740
741 endCommandBuffer(vk, *m_cmdBuffer);
742 }
743 #endif // CTS_USES_VULKANSC
744
745 if (!m_groupParams->useDynamicRendering)
746 {
747 beginCommandBuffer(vk, *m_cmdBuffer);
748
749 preRenderCommands(context, *m_cmdBuffer);
750 beginRenderPass(context, *m_cmdBuffer, renderArea, clearValue);
751 drawCommands(context, *m_cmdBuffer);
752 vk.cmdEndRenderPass(*m_cmdBuffer);
753 postRenderCommands(context, colorBuffer);
754
755 endCommandBuffer(vk, *m_cmdBuffer);
756 }
757
758 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
759 }
760
761 protected:
762
preRenderCommands(Context & context,VkCommandBuffer cmdBuffer) const763 void preRenderCommands(Context& context, VkCommandBuffer cmdBuffer) const
764 {
765 if (m_groupParams->useDynamicRendering)
766 {
767 const DeviceInterface& vk = context.getDeviceInterface();
768 initialTransitionColor2DImage(vk, cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
769 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, m_colorSubresourceRange.layerCount);
770 }
771 }
772
postRenderCommands(Context & context,VkBuffer colorBuffer) const773 void postRenderCommands(Context& context, VkBuffer colorBuffer) const
774 {
775 const DeviceInterface& vk = context.getDeviceInterface();
776 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);
777 }
778
beginRenderPass(Context & context,VkCommandBuffer cmdBuffer,const VkRect2D & renderArea,const VkClearValue & clearValue) const779 void beginRenderPass(Context& context, VkCommandBuffer cmdBuffer, const VkRect2D& renderArea, const VkClearValue& clearValue) const
780 {
781 const DeviceInterface& vk = context.getDeviceInterface();
782 const VkRenderPassBeginInfo renderPassBeginInfo
783 {
784 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
785 DE_NULL, // const void* pNext;
786 *m_renderPass, // VkRenderPass renderPass;
787 *m_framebuffer, // VkFramebuffer framebuffer;
788 renderArea, // VkRect2D renderArea;
789 1u, // uint32_t clearValueCount;
790 &clearValue, // const VkClearValue* pClearValues;
791 };
792 vk.cmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
793 }
794
drawCommands(Context & context,VkCommandBuffer cmdBuffer) const795 void drawCommands (Context& context, VkCommandBuffer cmdBuffer) const
796 {
797 const DeviceInterface& vk = context.getDeviceInterface();
798 const VkBuffer vertexBuffer = m_vertexBuffer->object();
799 const VkDeviceSize vertexBufferOffset = 0ull;
800
801 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
802 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
803 vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numLayers * 6), 1u, 0u, 0u); // two triangles per layer
804 }
805
806 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(Context & context,VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags=0u) const807 void beginSecondaryCmdBuffer(Context& context, VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const
808 {
809 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
810 {
811 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
812 DE_NULL, // const void* pNext;
813 renderingFlags, // VkRenderingFlagsKHR flags;
814 0u, // uint32_t viewMask;
815 1u, // uint32_t colorAttachmentCount;
816 &m_colorFormat, // const VkFormat* pColorAttachmentFormats;
817 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
818 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
819 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
820 };
821 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
822
823 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
824 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
825 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
826
827 const VkCommandBufferBeginInfo commandBufBeginParams
828 {
829 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
830 DE_NULL, // const void* pNext;
831 usageFlags, // VkCommandBufferUsageFlags flags;
832 &bufferInheritanceInfo
833 };
834
835 const DeviceInterface& vk = context.getDeviceInterface();
836 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
837 }
838 #endif // CTS_USES_VULKANSC
839
840 private:
841 const SharedGroupParams m_groupParams;
842 const UVec2 m_renderSize;
843 const VkFormat m_colorFormat;
844 const VkImageSubresourceRange m_colorSubresourceRange;
845 const Vec4 m_clearColor;
846 const int m_numLayers;
847 const std::vector<PositionColorVertex> m_vertices;
848
849 Move<VkImage> m_colorImage;
850 MovePtr<Allocation> m_colorImageAlloc;
851 Move<VkImageView> m_colorAttachment;
852 SharedPtr<Buffer> m_vertexBuffer;
853 Move<VkShaderModule> m_vertexModule;
854 Move<VkShaderModule> m_tessellationControlModule;
855 Move<VkShaderModule> m_tessellationEvaluationModule;
856 Move<VkShaderModule> m_fragmentModule;
857 Move<VkRenderPass> m_renderPass;
858 Move<VkFramebuffer> m_framebuffer;
859 Move<VkPipelineLayout> m_pipelineLayout;
860 Move<VkPipeline> m_pipeline;
861 Move<VkCommandPool> m_cmdPool;
862 Move<VkCommandBuffer> m_cmdBuffer;
863 Move<VkCommandBuffer> m_secCmdBuffer;
864
865 // "deleted"
866 Renderer (const Renderer&);
867 Renderer& operator= (const Renderer&);
868 };
869
checkRequirements(Context & context,const TestParams params)870 void checkRequirements (Context& context, const TestParams params)
871 {
872 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
873 context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
874
875 if (params.groupParams->useDynamicRendering)
876 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
877
878 const VkPhysicalDeviceLimits limits = context.getDeviceProperties().limits;
879
880 if (limits.maxFramebufferLayers < MIN_MAX_FRAMEBUFFER_LAYERS)
881 TCU_FAIL("maxFramebuffersLayers is less than the minimum required");
882
883 if (limits.maxViewports < MIN_MAX_VIEWPORTS)
884 TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
885 }
886
testVertexShader(Context & context,const TestParams params)887 tcu::TestStatus testVertexShader (Context& context, const TestParams params)
888 {
889 const DeviceInterface& vk = context.getDeviceInterface();
890 const VkDevice device = context.getDevice();
891 Allocator& allocator = context.getDefaultAllocator();
892
893 const UVec2 renderSize (256, 256);
894 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
895 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
896 const std::vector<UVec4> grid = generateGrid(params.numLayers, renderSize);
897 const std::vector<Vec4> colors = generateColors(params.numLayers);
898 const std::vector<PositionColorVertex> vertices = generateVertices(grid, colors, renderSize);
899
900 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * params.numLayers;
901
902 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
903
904 // Zero buffer.
905 {
906 const Allocation alloc = colorBuffer->getBoundMemory();
907 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
908 flushAlloc(vk, device, alloc);
909 }
910
911 {
912 context.getTestContext().getLog()
913 << tcu::TestLog::Message << "Rendering a rectangle in each of the " << params.numLayers << " layer(s)." << tcu::TestLog::EndMessage
914 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
915 }
916
917 // Draw.
918 {
919 const Renderer renderer (context, params.groupParams, renderSize, params.numLayers, colorFormat, clearColor, vertices, Renderer::VERTEX);
920 renderer.draw(context, colorBuffer->object());
921 }
922
923 // Verify layers.
924 {
925 const Allocation alloc = colorBuffer->getBoundMemory();
926 invalidateAlloc(vk, device, alloc);
927
928 deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
929 for (int i = 0; i < params.numLayers; i++)
930 {
931 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / params.numLayers) * i));
932 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
933 std::string imageSetName = "layer_" + de::toString(i);
934 std::string imageSetDesc = "Image compare for layer " + de::toString(i);
935 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
936 TCU_FAIL("Rendered image is not correct");
937 }
938 }
939
940 return tcu::TestStatus::pass("OK");
941 }
942
testTessellationShader(Context & context,const TestParams params)943 tcu::TestStatus testTessellationShader (Context& context, const TestParams params)
944 {
945 const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures();
946 if (!features.tessellationShader)
947 TCU_THROW(NotSupportedError, "Required feature is not supported: tessellationShader");
948
949 const DeviceInterface& vk = context.getDeviceInterface();
950 const VkDevice device = context.getDevice();
951 Allocator& allocator = context.getDefaultAllocator();
952
953 const UVec2 renderSize (256, 256);
954 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
955 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
956 const std::vector<UVec4> grid = generateGrid(params.numLayers, renderSize);
957 const std::vector<Vec4> colors = generateColors(params.numLayers);
958 const std::vector<PositionColorVertex> vertices = generateVertices(grid, colors, renderSize);
959
960 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * params.numLayers;
961
962 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
963
964 // Zero buffer.
965 {
966 const Allocation alloc = colorBuffer->getBoundMemory();
967 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
968 flushAlloc(vk, device, alloc);
969 }
970
971 {
972 context.getTestContext().getLog()
973 << tcu::TestLog::Message << "Rendering a rectangle in each of the " << params.numLayers << " layer(s)." << tcu::TestLog::EndMessage
974 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
975 }
976
977 // Draw.
978 {
979 const Renderer renderer (context, params.groupParams, renderSize, params.numLayers, colorFormat, clearColor, vertices, Renderer::TESSELLATION);
980 renderer.draw(context, colorBuffer->object());
981 }
982
983 // Verify layers.
984 {
985 const Allocation alloc = colorBuffer->getBoundMemory();
986 invalidateAlloc(vk, device, alloc);
987
988 deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
989 for (int i = 0; i < params.numLayers; i++) {
990 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / params.numLayers) * i));
991 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
992 std::string imageSetName = "layer_" + de::toString(i);
993 std::string imageSetDesc = "Image compare for layer " + de::toString(i);
994 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
995 TCU_FAIL("Rendered image is not correct");
996 }
997 }
998
999 return tcu::TestStatus::pass("OK");
1000 }
1001
1002 } // anonymous
1003
createShaderLayerTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1004 tcu::TestCaseGroup* createShaderLayerTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
1005 {
1006 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_layer", ""));
1007
1008 int numLayersToTest[] =
1009 {
1010 1,
1011 2,
1012 3,
1013 4,
1014 5,
1015 6,
1016 7,
1017 8,
1018 MIN_MAX_FRAMEBUFFER_LAYERS,
1019 };
1020
1021 TestParams parmas
1022 {
1023 1,
1024 groupParams
1025 };
1026
1027 for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1028 {
1029 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1030 if (groupParams->useSecondaryCmdBuffer && (i % 2))
1031 continue;
1032
1033 parmas.numLayers = numLayersToTest[i];
1034 addFunctionCaseWithPrograms<TestParams>(group.get(), "vertex_shader_" + de::toString(parmas.numLayers), "", checkRequirements, initVertexTestPrograms, testVertexShader, parmas);
1035 }
1036
1037 for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1038 {
1039 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1040 if (groupParams->useSecondaryCmdBuffer && (i % 2))
1041 continue;
1042
1043 parmas.numLayers = numLayersToTest[i];
1044 addFunctionCaseWithPrograms<TestParams>(group.get(), "tessellation_shader_" + de::toString(parmas.numLayers), "", checkRequirements, initTessellationTestPrograms, testTessellationShader, parmas);
1045 }
1046
1047 return group.release();
1048 }
1049
1050 } // Draw
1051 } // vkt
1052