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 template<typename T>
sizeInBytes(const std::vector<T> & vec)75 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
76 {
77 return vec.size() * sizeof(vec[0]);
78 }
79
makeImageCreateInfo(const VkFormat format,const UVec2 & size,const deUint32 numLayers,VkImageUsageFlags usage)80 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, const deUint32 numLayers, VkImageUsageFlags usage)
81 {
82 const VkImageCreateInfo imageParams =
83 {
84 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
85 DE_NULL, // const void* pNext;
86 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
87 VK_IMAGE_TYPE_2D, // VkImageType imageType;
88 format, // VkFormat format;
89 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
90 1u, // deUint32 mipLevels;
91 numLayers, // deUint32 arrayLayers;
92 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
93 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
94 usage, // VkImageUsageFlags usage;
95 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
96 0u, // deUint32 queueFamilyIndexCount;
97 DE_NULL, // const deUint32* pQueueFamilyIndices;
98 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
99 };
100 return imageParams;
101 }
102
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)103 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
104 const VkDevice device,
105 const VkPipelineLayout pipelineLayout,
106 const VkRenderPass renderPass,
107 const VkShaderModule vertexModule,
108 const VkShaderModule tessellationControlModule,
109 const VkShaderModule tessellationEvaluationModule,
110 const VkShaderModule fragmentModule,
111 const UVec2 renderSize)
112 {
113 const VkVertexInputBindingDescription vertexInputBindingDescription =
114 {
115 0u, // uint32_t binding;
116 sizeof(PositionColorVertex), // uint32_t stride;
117 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
118 };
119
120 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
121 {
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 {
138 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
139 DE_NULL, // const void* pNext;
140 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
141 1u, // uint32_t vertexBindingDescriptionCount;
142 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
143 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
144 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
145 };
146
147 const bool useTessellationShaders = (tessellationControlModule != DE_NULL) && (tessellationEvaluationModule != DE_NULL);
148
149 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
150 {
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 ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
155 VK_FALSE, // VkBool32 primitiveRestartEnable;
156 };
157
158
159 VkViewport viewport = makeViewport(0.0f, 0.0f, static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 0.0f, 1.0f);
160 VkRect2D rectScissor = { { 0, 0 }, { renderSize.x(), renderSize.y() } };
161
162 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
163 {
164 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
165 DE_NULL, // const void* pNext;
166 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
167 1u, // uint32_t viewportCount;
168 &viewport, // const VkViewport* pViewports;
169 1u, // uint32_t scissorCount;
170 &rectScissor, // const VkRect2D* pScissors;
171 };
172
173 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
174 {
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 {
192 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
193 DE_NULL, // const void* pNext;
194 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
195 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
196 VK_FALSE, // VkBool32 sampleShadingEnable;
197 0.0f, // float minSampleShading;
198 DE_NULL, // const VkSampleMask* pSampleMask;
199 VK_FALSE, // VkBool32 alphaToCoverageEnable;
200 VK_FALSE // VkBool32 alphaToOneEnable;
201 };
202
203 const VkStencilOpState stencilOpState = makeStencilOpState(
204 VK_STENCIL_OP_KEEP, // stencil fail
205 VK_STENCIL_OP_KEEP, // depth & stencil pass
206 VK_STENCIL_OP_KEEP, // depth only fail
207 VK_COMPARE_OP_ALWAYS, // compare op
208 0u, // compare mask
209 0u, // write mask
210 0u); // reference
211
212 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
213 {
214 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
215 DE_NULL, // const void* pNext;
216 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
217 VK_FALSE, // VkBool32 depthTestEnable;
218 VK_FALSE, // VkBool32 depthWriteEnable;
219 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
220 VK_FALSE, // VkBool32 depthBoundsTestEnable;
221 VK_FALSE, // VkBool32 stencilTestEnable;
222 stencilOpState, // VkStencilOpState front;
223 stencilOpState, // VkStencilOpState back;
224 0.0f, // float minDepthBounds;
225 1.0f, // float maxDepthBounds;
226 };
227
228 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
229 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
230 {
231 VK_FALSE, // VkBool32 blendEnable;
232 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
233 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
234 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
235 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
236 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
237 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
238 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
239 };
240
241 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
242 {
243 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
244 DE_NULL, // const void* pNext;
245 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
246 VK_FALSE, // VkBool32 logicOpEnable;
247 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
248 1u, // deUint32 attachmentCount;
249 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
250 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
251 };
252
253 const VkPipelineShaderStageCreateInfo pShaderStages[] =
254 {
255 {
256 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
257 DE_NULL, // const void* pNext;
258 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
259 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
260 vertexModule, // VkShaderModule module;
261 "main", // const char* pName;
262 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
263 },
264 {
265 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
266 DE_NULL, // const void* pNext;
267 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
268 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
269 fragmentModule, // VkShaderModule module;
270 "main", // const char* pName;
271 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
272 },
273 {
274 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
275 DE_NULL, // const void* pNext;
276 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
277 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlagBits stage;
278 tessellationControlModule, // VkShaderModule module;
279 "main", // const char* pName;
280 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
281 },
282 {
283 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
284 DE_NULL, // const void* pNext;
285 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
286 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, // VkShaderStageFlagBits stage;
287 tessellationEvaluationModule, // VkShaderModule module;
288 "main", // const char* pName;
289 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
290 },
291 };
292
293 const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
294 {
295 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
296 DE_NULL, // const void* pNext;
297 (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags;
298 3, // uint32_t patchControlPoints;
299 };
300
301 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
302 {
303 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
304 DE_NULL, // const void* pNext;
305 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
306 useTessellationShaders ? deUint32(4) : deUint32(2), // deUint32 stageCount;
307 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
308 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
309 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
310 useTessellationShaders ? &pipelineTessellationStateInfo : DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
311 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
312 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
313 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
314 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
315 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
316 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
317 pipelineLayout, // VkPipelineLayout layout;
318 renderPass, // VkRenderPass renderPass;
319 0u, // deUint32 subpass;
320 DE_NULL, // VkPipeline basePipelineHandle;
321 0, // deInt32 basePipelineIndex;
322 };
323
324 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
325 }
326
327 //! Renders a colorful grid of rectangles.
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const Vec4 & clearColor,const UVec4 & cell,const Vec4 & cellColor)328 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format,
329 const UVec2& renderSize,
330 const Vec4& clearColor,
331 const UVec4& cell,
332 const Vec4& cellColor)
333 {
334 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
335 tcu::clear(image.getAccess(), clearColor);
336
337 tcu::clear(tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()),
338 cellColor);
339
340 return image;
341 }
342
initVertexTestPrograms(SourceCollections & programCollection,const int numViewports)343 void initVertexTestPrograms (SourceCollections& programCollection, const int numViewports)
344 {
345 DE_UNREF(numViewports);
346
347 // Vertex shader
348 {
349 std::ostringstream src;
350 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
351 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
352 << "\n"
353 << "layout(location = 0) in vec4 in_position;\n"
354 << "layout(location = 1) in vec4 in_color;\n"
355 << "layout(location = 0) out vec4 out_color;\n"
356 << "\n"
357 << "void main(void)\n"
358 << "{\n"
359 << " gl_Layer = gl_VertexIndex / 6;\n"
360 << " gl_Position = in_position;\n"
361 << " out_color = in_color;\n"
362 << "}\n";
363
364 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
365 }
366
367 // Fragment shader
368 {
369 std::ostringstream src;
370 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
371 << "\n"
372 << "layout(location = 0) in vec4 in_color;\n"
373 << "layout(location = 0) out vec4 out_color;\n"
374 << "\n"
375 << "void main(void)\n"
376 << "{\n"
377 << " out_color = in_color;\n"
378 << "}\n";
379
380 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
381 }
382 }
383
initTessellationTestPrograms(SourceCollections & programCollection,const int numViewports)384 void initTessellationTestPrograms (SourceCollections& programCollection, const int numViewports)
385 {
386 DE_UNREF(numViewports);
387
388 // Vertex shader
389 {
390 std::ostringstream src;
391 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
392 << "\n"
393 << "layout(location = 0) in vec4 in_position;\n"
394 << "layout(location = 1) in vec4 in_color;\n"
395 << "layout(location = 0) out vec4 out_color;\n"
396 << "\n"
397 << "void main(void)\n"
398 << "{\n"
399 << " gl_Position = in_position;\n"
400 << " out_color = in_color;\n"
401 << "}\n";
402
403 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
404 }
405
406 // Tessellation control shader
407 {
408 std::ostringstream src;
409 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
410 << "\n"
411 << "layout(vertices = 3) out;\n"
412 << "\n"
413 << "layout(location = 0) in vec4 in_color[];\n"
414 << "layout(location = 0) out vec4 out_color[];\n"
415 << "\n"
416 << "void main(void)\n"
417 << "{\n"
418 << " if (gl_InvocationID == 0) {\n"
419 << " gl_TessLevelInner[0] = 1.0;\n"
420 << " gl_TessLevelInner[1] = 1.0;\n"
421 << " gl_TessLevelOuter[0] = 1.0;\n"
422 << " gl_TessLevelOuter[1] = 1.0;\n"
423 << " gl_TessLevelOuter[2] = 1.0;\n"
424 << " gl_TessLevelOuter[3] = 1.0;\n"
425 << " }\n"
426 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
427 << " out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
428 << "}\n";
429
430 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
431 }
432
433 // Tessellation evaluation shader
434 {
435 std::ostringstream src;
436 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
437 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
438 << "\n"
439 << "layout(triangles, equal_spacing, cw) in;\n"
440 << "\n"
441 << "layout(location = 0) in vec4 in_color[];\n"
442 << "layout(location = 0) out vec4 out_color;\n"
443 << "\n"
444 << "void main(void)\n"
445 << "{\n"
446 << " gl_Layer = gl_PrimitiveID / 2;\n"
447 << " gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
448 << " gl_in[1].gl_Position * gl_TessCoord.y +\n"
449 << " gl_in[2].gl_Position * gl_TessCoord.z;\n"
450 << "\n"
451 << " out_color = in_color[0] * gl_TessCoord.x +\n"
452 << " in_color[1] * gl_TessCoord.y +\n"
453 << " in_color[2] * gl_TessCoord.z;\n"
454 << "}\n";
455
456 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
457 }
458
459 // Fragment shader
460 {
461 std::ostringstream src;
462 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
463 << "\n"
464 << "layout(location = 0) in vec4 in_color;\n"
465 << "layout(location = 0) out vec4 out_color;\n"
466 << "\n"
467 << "void main(void)\n"
468 << "{\n"
469 << " out_color = in_color;\n"
470 << "}\n";
471
472 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
473 }
474 }
475
generateGrid(const int numCells,const UVec2 & renderSize)476 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
477 {
478 const int numCols = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
479 const int numRows = deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
480 const int rectWidth = renderSize.x() / numCols;
481 const int rectHeight = renderSize.y() / numRows;
482
483 std::vector<UVec4> cells;
484 cells.reserve(numCells);
485
486 int x = 0;
487 int y = 0;
488
489 for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
490 {
491 const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
492 if (nextRow)
493 {
494 x = 0;
495 y += rectHeight;
496 }
497
498 cells.push_back(UVec4(x, y, rectWidth, rectHeight));
499
500 x += rectWidth;
501 }
502
503 return cells;
504 }
505
generateColors(int numColors)506 std::vector<Vec4> generateColors (int numColors)
507 {
508 const Vec4 colors[] =
509 {
510 Vec4(0.18f, 0.42f, 0.17f, 1.0f),
511 Vec4(0.29f, 0.62f, 0.28f, 1.0f),
512 Vec4(0.59f, 0.84f, 0.44f, 1.0f),
513 Vec4(0.96f, 0.95f, 0.72f, 1.0f),
514 Vec4(0.94f, 0.55f, 0.39f, 1.0f),
515 Vec4(0.82f, 0.19f, 0.12f, 1.0f),
516 Vec4(0.46f, 0.15f, 0.26f, 1.0f),
517 Vec4(0.24f, 0.14f, 0.24f, 1.0f),
518 Vec4(0.49f, 0.31f, 0.26f, 1.0f),
519 Vec4(0.78f, 0.52f, 0.33f, 1.0f),
520 Vec4(0.94f, 0.82f, 0.31f, 1.0f),
521 Vec4(0.98f, 0.65f, 0.30f, 1.0f),
522 Vec4(0.22f, 0.65f, 0.53f, 1.0f),
523 Vec4(0.67f, 0.81f, 0.91f, 1.0f),
524 Vec4(0.43f, 0.44f, 0.75f, 1.0f),
525 Vec4(0.26f, 0.24f, 0.48f, 1.0f),
526 };
527
528 std::vector<Vec4> result;
529 result.reserve(numColors);
530
531 for (int i = 0; i < numColors; ++i)
532 {
533 result.push_back(colors[i % DE_LENGTH_OF_ARRAY(colors)]);
534 }
535
536 return result;
537 }
538
generateVertices(const std::vector<UVec4> & grid,const std::vector<Vec4> & colors,const UVec2 & renderSize)539 std::vector<PositionColorVertex> generateVertices (const std::vector<UVec4>& grid, const std::vector<Vec4>& colors, const UVec2& renderSize)
540 {
541 DE_ASSERT(colors.size() == grid.size());
542
543 // Two triangles for each cell. Each cell correspond to a layer.
544 std::size_t total = grid.size() * 6;
545
546 std::vector<PositionColorVertex> result;
547 result.reserve(total);
548
549 for (std::size_t i = 0; i < total; ++i)
550 {
551 Vec4 pos;
552 pos.z() = 0.0;
553 pos.w() = 1.0;
554
555 Vec4 cell = grid[i/6].asFloat() * 2.0f;
556 float x = cell.x() / float(renderSize.x()) - 1.0f;
557 float y = cell.y() / float(renderSize.y()) - 1.0f;
558 float width = cell.z() / float(renderSize.x());
559 float height = cell.w() / float(renderSize.y());
560
561 switch (i % 6)
562 {
563 case 0: pos.xy() = Vec2(x, y + height); break;
564 case 1: pos.xy() = Vec2(x + width, y + height); break;
565 case 2: pos.xy() = Vec2(x, y); break;
566 case 3: pos.xy() = Vec2(x + width, y); break;
567 case 4: pos.xy() = Vec2(x + width, y + height); break;
568 case 5: pos.xy() = Vec2(x, y); break;
569 }
570
571 result.push_back(PositionColorVertex(pos, colors[i/6]));
572 }
573
574 return result;
575 }
576
577 // Renderer generates two triangles per layer, each pair using a different
578 // color and a different position.
579 class Renderer
580 {
581 public:
582 enum Shader
583 {
584 VERTEX,
585 TESSELLATION,
586 };
587
Renderer(Context & context,const UVec2 & renderSize,const int numLayers,const VkFormat colorFormat,const Vec4 & clearColor,const std::vector<PositionColorVertex> & vertices,const Shader shader)588 Renderer (Context& context,
589 const UVec2& renderSize,
590 const int numLayers,
591 const VkFormat colorFormat,
592 const Vec4& clearColor,
593 const std::vector<PositionColorVertex>& vertices,
594 const Shader shader)
595 : m_renderSize (renderSize)
596 , m_colorFormat (colorFormat)
597 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers))
598 , m_clearColor (clearColor)
599 , m_numLayers (numLayers)
600 , m_vertices (vertices)
601 {
602 const DeviceInterface& vk = context.getDeviceInterface();
603 const VkDevice device = context.getDevice();
604 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
605 Allocator& allocator = context.getDefaultAllocator();
606 const VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices);
607
608 m_colorImage = makeImage (vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, m_numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
609 m_colorImageAlloc = bindImage (vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
610 m_colorAttachment = makeImageView (vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_colorFormat, m_colorSubresourceRange);
611
612 m_vertexBuffer = Buffer::createAndAlloc (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
613
614 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
615 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
616
617 if (shader == TESSELLATION)
618 {
619 m_tessellationControlModule = createShaderModule (vk, device, context.getBinaryCollection().get("tesc"), 0u);
620 m_tessellationEvaluationModule = createShaderModule (vk, device, context.getBinaryCollection().get("tese"), 0u);
621 }
622
623 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u);
624 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u);
625 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
626 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, m_colorAttachment.get(),
627 static_cast<deUint32>(m_renderSize.x()),
628 static_cast<deUint32>(m_renderSize.y()),
629 numLayers);
630 m_pipelineLayout = makePipelineLayout (vk, device);
631 m_pipeline = makeGraphicsPipeline (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
632 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize);
633 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
634 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
635 }
636
draw(Context & context,const VkBuffer colorBuffer) const637 void draw (Context& context, const VkBuffer colorBuffer) const
638 {
639 const DeviceInterface& vk = context.getDeviceInterface();
640 const VkDevice device = context.getDevice();
641 const VkQueue queue = context.getUniversalQueue();
642
643 beginCommandBuffer(vk, *m_cmdBuffer);
644
645 const VkClearValue clearValue = makeClearValueColor(m_clearColor);
646 const VkRect2D renderArea =
647 {
648 makeOffset2D(0, 0),
649 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
650 };
651 const VkRenderPassBeginInfo renderPassBeginInfo =
652 {
653 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
654 DE_NULL, // const void* pNext;
655 *m_renderPass, // VkRenderPass renderPass;
656 *m_framebuffer, // VkFramebuffer framebuffer;
657 renderArea, // VkRect2D renderArea;
658 1u, // uint32_t clearValueCount;
659 &clearValue, // const VkClearValue* pClearValues;
660 };
661 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
662
663 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
664 {
665 const VkBuffer vertexBuffer = m_vertexBuffer->object();
666 const VkDeviceSize vertexBufferOffset = 0ull;
667 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
668 }
669 vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_numLayers * 6), 1u, 0u, 0u); // two triangles per layer
670 vk.cmdEndRenderPass(*m_cmdBuffer);
671
672 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);
673
674 endCommandBuffer(vk, *m_cmdBuffer);
675 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
676 }
677
678 private:
679 const UVec2 m_renderSize;
680 const VkFormat m_colorFormat;
681 const VkImageSubresourceRange m_colorSubresourceRange;
682 const Vec4 m_clearColor;
683 const int m_numLayers;
684 const std::vector<PositionColorVertex> m_vertices;
685
686 Move<VkImage> m_colorImage;
687 MovePtr<Allocation> m_colorImageAlloc;
688 Move<VkImageView> m_colorAttachment;
689 SharedPtr<Buffer> m_vertexBuffer;
690 Move<VkShaderModule> m_vertexModule;
691 Move<VkShaderModule> m_tessellationControlModule;
692 Move<VkShaderModule> m_tessellationEvaluationModule;
693 Move<VkShaderModule> m_fragmentModule;
694 Move<VkRenderPass> m_renderPass;
695 Move<VkFramebuffer> m_framebuffer;
696 Move<VkPipelineLayout> m_pipelineLayout;
697 Move<VkPipeline> m_pipeline;
698 Move<VkCommandPool> m_cmdPool;
699 Move<VkCommandBuffer> m_cmdBuffer;
700
701 // "deleted"
702 Renderer (const Renderer&);
703 Renderer& operator= (const Renderer&);
704 };
705
checkRequirements(Context & context,const int)706 void checkRequirements (Context& context, const int)
707 {
708 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
709 context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
710
711 const VkPhysicalDeviceLimits limits = context.getDeviceProperties().limits;
712
713 if (limits.maxFramebufferLayers < MIN_MAX_FRAMEBUFFER_LAYERS)
714 TCU_FAIL("maxFramebuffersLayers is less than the minimum required");
715
716 if (limits.maxViewports < MIN_MAX_VIEWPORTS)
717 TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
718 }
719
testVertexShader(Context & context,const int numLayers)720 tcu::TestStatus testVertexShader (Context& context, const int numLayers)
721 {
722 const DeviceInterface& vk = context.getDeviceInterface();
723 const VkDevice device = context.getDevice();
724 Allocator& allocator = context.getDefaultAllocator();
725
726 const UVec2 renderSize (256, 256);
727 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
728 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
729 const std::vector<UVec4> grid = generateGrid(numLayers, renderSize);
730 const std::vector<Vec4> colors = generateColors(numLayers);
731 const std::vector<PositionColorVertex> vertices = generateVertices(grid, colors, renderSize);
732
733 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * numLayers;
734
735 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
736
737 // Zero buffer.
738 {
739 const Allocation alloc = colorBuffer->getBoundMemory();
740 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
741 flushAlloc(vk, device, alloc);
742 }
743
744 {
745 context.getTestContext().getLog()
746 << tcu::TestLog::Message << "Rendering a rectangle in each of the " << numLayers << " layer(s)." << tcu::TestLog::EndMessage
747 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
748 }
749
750 // Draw.
751 {
752 const Renderer renderer (context, renderSize, numLayers, colorFormat, clearColor, vertices, Renderer::VERTEX);
753 renderer.draw(context, colorBuffer->object());
754 }
755
756 // Verify layers.
757 {
758 const Allocation alloc = colorBuffer->getBoundMemory();
759 invalidateAlloc(vk, device, alloc);
760
761 deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
762 for (int i = 0; i < numLayers; i++)
763 {
764 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / numLayers) * i));
765 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
766 std::string imageSetName = "layer_" + de::toString(i);
767 std::string imageSetDesc = "Image compare for layer " + de::toString(i);
768 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
769 TCU_FAIL("Rendered image is not correct");
770 }
771 }
772
773 return tcu::TestStatus::pass("OK");
774 }
775
testTessellationShader(Context & context,const int numLayers)776 tcu::TestStatus testTessellationShader (Context& context, const int numLayers)
777 {
778 const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures();
779 if (!features.tessellationShader)
780 TCU_THROW(NotSupportedError, "Required feature is not supported: tessellationShader");
781
782 const DeviceInterface& vk = context.getDeviceInterface();
783 const VkDevice device = context.getDevice();
784 Allocator& allocator = context.getDefaultAllocator();
785
786 const UVec2 renderSize (256, 256);
787 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
788 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
789 const std::vector<UVec4> grid = generateGrid(numLayers, renderSize);
790 const std::vector<Vec4> colors = generateColors(numLayers);
791 const std::vector<PositionColorVertex> vertices = generateVertices(grid, colors, renderSize);
792
793 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * numLayers;
794
795 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
796
797 // Zero buffer.
798 {
799 const Allocation alloc = colorBuffer->getBoundMemory();
800 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
801 flushAlloc(vk, device, alloc);
802 }
803
804 {
805 context.getTestContext().getLog()
806 << tcu::TestLog::Message << "Rendering a rectangle in each of the " << numLayers << " layer(s)." << tcu::TestLog::EndMessage
807 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
808 }
809
810 // Draw.
811 {
812 const Renderer renderer (context, renderSize, numLayers, colorFormat, clearColor, vertices, Renderer::TESSELLATION);
813 renderer.draw(context, colorBuffer->object());
814 }
815
816 // Verify layers.
817 {
818 const Allocation alloc = colorBuffer->getBoundMemory();
819 invalidateAlloc(vk, device, alloc);
820
821 deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
822 for (int i = 0; i < numLayers; i++) {
823 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / numLayers) * i));
824 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
825 std::string imageSetName = "layer_" + de::toString(i);
826 std::string imageSetDesc = "Image compare for layer " + de::toString(i);
827 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
828 TCU_FAIL("Rendered image is not correct");
829 }
830 }
831
832 return tcu::TestStatus::pass("OK");
833 }
834
835 } // anonymous
836
createShaderLayerTests(tcu::TestContext & testCtx)837 tcu::TestCaseGroup* createShaderLayerTests (tcu::TestContext& testCtx)
838 {
839 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_layer", ""));
840
841 int numLayersToTest[] =
842 {
843 1,
844 2,
845 3,
846 4,
847 5,
848 6,
849 7,
850 8,
851 MIN_MAX_FRAMEBUFFER_LAYERS,
852 };
853
854 for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
855 {
856 int numLayers = numLayersToTest[i];
857 addFunctionCaseWithPrograms(group.get(), "vertex_shader_" + de::toString(numLayers), "", checkRequirements, initVertexTestPrograms, testVertexShader, numLayers);
858 }
859
860 for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
861 {
862 int numLayers = numLayersToTest[i];
863 addFunctionCaseWithPrograms(group.get(), "tessellation_shader_" + de::toString(numLayers), "", checkRequirements, initTessellationTestPrograms, testTessellationShader, numLayers);
864 }
865
866 return group.release();
867 }
868
869 } // Draw
870 } // vkt
871