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 }
390
391 // Fragment shader
392 {
393 std::ostringstream src;
394 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
395 << "\n"
396 << "layout(location = 0) in vec4 in_color;\n"
397 << "layout(location = 0) out vec4 out_color;\n"
398 << "\n"
399 << "void main(void)\n"
400 << "{\n"
401 << " out_color = in_color;\n"
402 << "}\n";
403
404 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
405 }
406 }
407
initTessellationTestPrograms(SourceCollections & programCollection,const TestParams params)408 void initTessellationTestPrograms (SourceCollections& programCollection, const TestParams params)
409 {
410 DE_UNREF(params.numLayers);
411
412 // Vertex shader
413 {
414 std::ostringstream src;
415 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
416 << "\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"
420 << "\n"
421 << "void main(void)\n"
422 << "{\n"
423 << " gl_Position = in_position;\n"
424 << " out_color = in_color;\n"
425 << "}\n";
426
427 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
428 }
429
430 // Tessellation control shader
431 {
432 std::ostringstream src;
433 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
434 << "\n"
435 << "layout(vertices = 3) out;\n"
436 << "\n"
437 << "layout(location = 0) in vec4 in_color[];\n"
438 << "layout(location = 0) out vec4 out_color[];\n"
439 << "\n"
440 << "void main(void)\n"
441 << "{\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"
449 << " }\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"
452 << "}\n";
453
454 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
455 }
456
457 // Tessellation evaluation shader
458 {
459 std::ostringstream src;
460 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
461 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
462 << "\n"
463 << "layout(triangles, equal_spacing, cw) in;\n"
464 << "\n"
465 << "layout(location = 0) in vec4 in_color[];\n"
466 << "layout(location = 0) out vec4 out_color;\n"
467 << "\n"
468 << "void main(void)\n"
469 << "{\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"
474 << "\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"
478 << "}\n";
479
480 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
481 }
482
483 // Fragment shader
484 {
485 std::ostringstream src;
486 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
487 << "\n"
488 << "layout(location = 0) in vec4 in_color;\n"
489 << "layout(location = 0) out vec4 out_color;\n"
490 << "\n"
491 << "void main(void)\n"
492 << "{\n"
493 << " out_color = in_color;\n"
494 << "}\n";
495
496 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
497 }
498 }
499
generateGrid(const int numCells,const UVec2 & renderSize)500 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
501 {
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;
506
507 std::vector<UVec4> cells;
508 cells.reserve(numCells);
509
510 int x = 0;
511 int y = 0;
512
513 for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
514 {
515 const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
516 if (nextRow)
517 {
518 x = 0;
519 y += rectHeight;
520 }
521
522 cells.push_back(UVec4(x, y, rectWidth, rectHeight));
523
524 x += rectWidth;
525 }
526
527 return cells;
528 }
529
generateColors(int numColors)530 std::vector<Vec4> generateColors (int numColors)
531 {
532 const Vec4 colors[] =
533 {
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),
550 };
551
552 std::vector<Vec4> result;
553 result.reserve(numColors);
554
555 for (int i = 0; i < numColors; ++i)
556 {
557 result.push_back(colors[i % DE_LENGTH_OF_ARRAY(colors)]);
558 }
559
560 return result;
561 }
562
generateVertices(const std::vector<UVec4> & grid,const std::vector<Vec4> & colors,const UVec2 & renderSize)563 std::vector<PositionColorVertex> generateVertices (const std::vector<UVec4>& grid, const std::vector<Vec4>& colors, const UVec2& renderSize)
564 {
565 DE_ASSERT(colors.size() == grid.size());
566
567 // Two triangles for each cell. Each cell correspond to a layer.
568 std::size_t total = grid.size() * 6;
569
570 std::vector<PositionColorVertex> result;
571 result.reserve(total);
572
573 for (std::size_t i = 0; i < total; ++i)
574 {
575 Vec4 pos;
576 pos.z() = 0.0;
577 pos.w() = 1.0;
578
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());
584
585 switch (i % 6)
586 {
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;
593 }
594
595 result.push_back(PositionColorVertex(pos, colors[i/6]));
596 }
597
598 return result;
599 }
600
601 // Renderer generates two triangles per layer, each pair using a different
602 // color and a different position.
603 class Renderer
604 {
605 public:
606 enum Shader
607 {
608 VERTEX,
609 TESSELLATION,
610 };
611
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)612 Renderer (Context& context,
613 const SharedGroupParams groupParams,
614 const UVec2& renderSize,
615 const int numLayers,
616 const VkFormat colorFormat,
617 const Vec4& clearColor,
618 const std::vector<PositionColorVertex>& vertices,
619 const Shader shader)
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)
627 {
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);
633
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);
637
638 m_vertexBuffer = Buffer::createAndAlloc (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
639
640 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
641 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
642
643 if (shader == TESSELLATION)
644 {
645 m_tessellationControlModule = createShaderModule (vk, device, context.getBinaryCollection().get("tesc"), 0u);
646 m_tessellationEvaluationModule = createShaderModule (vk, device, context.getBinaryCollection().get("tese"), 0u);
647 }
648
649 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u);
650 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u);
651
652 if (!m_groupParams->useDynamicRendering)
653 {
654 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
655
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()),
659 numLayers);
660 }
661
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);
668 }
669
draw(Context & context,const VkBuffer colorBuffer) const670 void draw (Context& context, const VkBuffer colorBuffer) const
671 {
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
677 {
678 makeOffset2D(0, 0),
679 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
680 };
681
682 #ifndef CTS_USES_VULKANSC
683 if (m_groupParams->useSecondaryCmdBuffer)
684 {
685 // record secondary command buffer
686 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
687 {
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);
691 }
692 else
693 beginSecondaryCmdBuffer(context, *m_secCmdBuffer);
694
695 drawCommands(context, *m_secCmdBuffer);
696
697 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
698 endRendering(vk, *m_secCmdBuffer);
699
700 endCommandBuffer(vk, *m_secCmdBuffer);
701
702 // record primary command buffer
703 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
704
705 preRenderCommands(context, *m_cmdBuffer);
706
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);
710
711 vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
712
713 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
714 endRendering(vk, *m_cmdBuffer);
715
716 postRenderCommands(context, colorBuffer);
717 endCommandBuffer(vk, *m_cmdBuffer);
718 }
719 else if (m_groupParams->useDynamicRendering)
720 {
721 beginCommandBuffer(vk, *m_cmdBuffer);
722
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);
729
730 endCommandBuffer(vk, *m_cmdBuffer);
731 }
732 #endif // CTS_USES_VULKANSC
733
734 if (!m_groupParams->useDynamicRendering)
735 {
736 beginCommandBuffer(vk, *m_cmdBuffer);
737
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);
743
744 endCommandBuffer(vk, *m_cmdBuffer);
745 }
746
747 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
748 }
749
750 protected:
751
preRenderCommands(Context & context,VkCommandBuffer cmdBuffer) const752 void preRenderCommands(Context& context, VkCommandBuffer cmdBuffer) const
753 {
754 if (m_groupParams->useDynamicRendering)
755 {
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);
759 }
760 }
761
postRenderCommands(Context & context,VkBuffer colorBuffer) const762 void postRenderCommands(Context& context, VkBuffer colorBuffer) const
763 {
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);
766 }
767
beginRenderPass(Context & context,VkCommandBuffer cmdBuffer,const VkRect2D & renderArea,const VkClearValue & clearValue) const768 void beginRenderPass(Context& context, VkCommandBuffer cmdBuffer, const VkRect2D& renderArea, const VkClearValue& clearValue) const
769 {
770 const DeviceInterface& vk = context.getDeviceInterface();
771 const VkRenderPassBeginInfo renderPassBeginInfo
772 {
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;
780 };
781 vk.cmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
782 }
783
drawCommands(Context & context,VkCommandBuffer cmdBuffer) const784 void drawCommands (Context& context, VkCommandBuffer cmdBuffer) const
785 {
786 const DeviceInterface& vk = context.getDeviceInterface();
787 const VkBuffer vertexBuffer = m_vertexBuffer->object();
788 const VkDeviceSize vertexBufferOffset = 0ull;
789
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
793 }
794
795 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(Context & context,VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags=0u) const796 void beginSecondaryCmdBuffer(Context& context, VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const
797 {
798 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
799 {
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;
809 };
810 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
811
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;
815
816 const VkCommandBufferBeginInfo commandBufBeginParams
817 {
818 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
819 DE_NULL, // const void* pNext;
820 usageFlags, // VkCommandBufferUsageFlags flags;
821 &bufferInheritanceInfo
822 };
823
824 const DeviceInterface& vk = context.getDeviceInterface();
825 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
826 }
827 #endif // CTS_USES_VULKANSC
828
829 private:
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;
837
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;
853
854 // "deleted"
855 Renderer (const Renderer&);
856 Renderer& operator= (const Renderer&);
857 };
858
checkRequirements(Context & context,const TestParams params)859 void checkRequirements (Context& context, const TestParams params)
860 {
861 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
862 context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
863
864 if (params.groupParams->useDynamicRendering)
865 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
866
867 const VkPhysicalDeviceLimits limits = context.getDeviceProperties().limits;
868
869 if (limits.maxFramebufferLayers < MIN_MAX_FRAMEBUFFER_LAYERS)
870 TCU_FAIL("maxFramebuffersLayers is less than the minimum required");
871
872 if (limits.maxViewports < MIN_MAX_VIEWPORTS)
873 TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
874 }
875
testVertexShader(Context & context,const TestParams params)876 tcu::TestStatus testVertexShader (Context& context, const TestParams params)
877 {
878 const DeviceInterface& vk = context.getDeviceInterface();
879 const VkDevice device = context.getDevice();
880 Allocator& allocator = context.getDefaultAllocator();
881
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);
888
889 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * params.numLayers;
890
891 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
892
893 // Zero buffer.
894 {
895 const Allocation alloc = colorBuffer->getBoundMemory();
896 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
897 flushAlloc(vk, device, alloc);
898 }
899
900 {
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;
904 }
905
906 // Draw.
907 {
908 const Renderer renderer (context, params.groupParams, renderSize, params.numLayers, colorFormat, clearColor, vertices, Renderer::VERTEX);
909 renderer.draw(context, colorBuffer->object());
910 }
911
912 // Verify layers.
913 {
914 const Allocation alloc = colorBuffer->getBoundMemory();
915 invalidateAlloc(vk, device, alloc);
916
917 deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
918 for (int i = 0; i < params.numLayers; i++)
919 {
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");
926 }
927 }
928
929 return tcu::TestStatus::pass("OK");
930 }
931
testTessellationShader(Context & context,const TestParams params)932 tcu::TestStatus testTessellationShader (Context& context, const TestParams params)
933 {
934 const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures();
935 if (!features.tessellationShader)
936 TCU_THROW(NotSupportedError, "Required feature is not supported: tessellationShader");
937
938 const DeviceInterface& vk = context.getDeviceInterface();
939 const VkDevice device = context.getDevice();
940 Allocator& allocator = context.getDefaultAllocator();
941
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);
948
949 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * params.numLayers;
950
951 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
952
953 // Zero buffer.
954 {
955 const Allocation alloc = colorBuffer->getBoundMemory();
956 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
957 flushAlloc(vk, device, alloc);
958 }
959
960 {
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;
964 }
965
966 // Draw.
967 {
968 const Renderer renderer (context, params.groupParams, renderSize, params.numLayers, colorFormat, clearColor, vertices, Renderer::TESSELLATION);
969 renderer.draw(context, colorBuffer->object());
970 }
971
972 // Verify layers.
973 {
974 const Allocation alloc = colorBuffer->getBoundMemory();
975 invalidateAlloc(vk, device, alloc);
976
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");
985 }
986 }
987
988 return tcu::TestStatus::pass("OK");
989 }
990
991 } // anonymous
992
createShaderLayerTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)993 tcu::TestCaseGroup* createShaderLayerTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
994 {
995 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_layer", ""));
996
997 int numLayersToTest[] =
998 {
999 1,
1000 2,
1001 3,
1002 4,
1003 5,
1004 6,
1005 7,
1006 8,
1007 MIN_MAX_FRAMEBUFFER_LAYERS,
1008 };
1009
1010 TestParams parmas
1011 {
1012 1,
1013 groupParams
1014 };
1015
1016 for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1017 {
1018 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1019 if (groupParams->useSecondaryCmdBuffer && (i % 2))
1020 continue;
1021
1022 parmas.numLayers = numLayersToTest[i];
1023 addFunctionCaseWithPrograms<TestParams>(group.get(), "vertex_shader_" + de::toString(parmas.numLayers), "", checkRequirements, initVertexTestPrograms, testVertexShader, parmas);
1024 }
1025
1026 for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
1027 {
1028 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1029 if (groupParams->useSecondaryCmdBuffer && (i % 2))
1030 continue;
1031
1032 parmas.numLayers = numLayersToTest[i];
1033 addFunctionCaseWithPrograms<TestParams>(group.get(), "tessellation_shader_" + de::toString(parmas.numLayers), "", checkRequirements, initTessellationTestPrograms, testTessellationShader, parmas);
1034 }
1035
1036 return group.release();
1037 }
1038
1039 } // Draw
1040 } // vkt
1041