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 bool useDynamicRendering;
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 VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
331 VkPipelineRenderingCreateInfoKHR renderingCreateInfo
332 {
333 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
334 DE_NULL,
335 0u,
336 1u,
337 &colorAttachmentFormat,
338 VK_FORMAT_UNDEFINED,
339 VK_FORMAT_UNDEFINED
340 };
341
342 // when pipeline is created without render pass we are using dynamic rendering
343 if (renderPass == DE_NULL)
344 graphicsPipelineInfo.pNext = &renderingCreateInfo;
345
346 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
347 }
348
349 //! Renders a colorful grid of rectangles.
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const Vec4 & clearColor,const UVec4 & cell,const Vec4 & cellColor)350 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format,
351 const UVec2& renderSize,
352 const Vec4& clearColor,
353 const UVec4& cell,
354 const Vec4& cellColor)
355 {
356 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
357 tcu::clear(image.getAccess(), clearColor);
358
359 tcu::clear(tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()),
360 cellColor);
361
362 return image;
363 }
364
initVertexTestPrograms(SourceCollections & programCollection,const TestParams params)365 void initVertexTestPrograms (SourceCollections& programCollection, const TestParams params)
366 {
367 DE_UNREF(params.numLayers);
368
369 // Vertex shader
370 {
371 std::ostringstream src;
372 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
373 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
374 << "\n"
375 << "layout(location = 0) in vec4 in_position;\n"
376 << "layout(location = 1) in vec4 in_color;\n"
377 << "layout(location = 0) out vec4 out_color;\n"
378 << "\n"
379 << "void main(void)\n"
380 << "{\n"
381 << " gl_Layer = gl_VertexIndex / 6;\n"
382 << " gl_Position = in_position;\n"
383 << " out_color = in_color;\n"
384 << "}\n";
385
386 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
387 }
388
389 // Fragment shader
390 {
391 std::ostringstream src;
392 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
393 << "\n"
394 << "layout(location = 0) in vec4 in_color;\n"
395 << "layout(location = 0) out vec4 out_color;\n"
396 << "\n"
397 << "void main(void)\n"
398 << "{\n"
399 << " out_color = in_color;\n"
400 << "}\n";
401
402 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
403 }
404 }
405
initTessellationTestPrograms(SourceCollections & programCollection,const TestParams params)406 void initTessellationTestPrograms (SourceCollections& programCollection, const TestParams params)
407 {
408 DE_UNREF(params.numLayers);
409
410 // Vertex shader
411 {
412 std::ostringstream src;
413 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
414 << "\n"
415 << "layout(location = 0) in vec4 in_position;\n"
416 << "layout(location = 1) in vec4 in_color;\n"
417 << "layout(location = 0) out vec4 out_color;\n"
418 << "\n"
419 << "void main(void)\n"
420 << "{\n"
421 << " gl_Position = in_position;\n"
422 << " out_color = in_color;\n"
423 << "}\n";
424
425 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
426 }
427
428 // Tessellation control shader
429 {
430 std::ostringstream src;
431 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
432 << "\n"
433 << "layout(vertices = 3) out;\n"
434 << "\n"
435 << "layout(location = 0) in vec4 in_color[];\n"
436 << "layout(location = 0) out vec4 out_color[];\n"
437 << "\n"
438 << "void main(void)\n"
439 << "{\n"
440 << " if (gl_InvocationID == 0) {\n"
441 << " gl_TessLevelInner[0] = 1.0;\n"
442 << " gl_TessLevelInner[1] = 1.0;\n"
443 << " gl_TessLevelOuter[0] = 1.0;\n"
444 << " gl_TessLevelOuter[1] = 1.0;\n"
445 << " gl_TessLevelOuter[2] = 1.0;\n"
446 << " gl_TessLevelOuter[3] = 1.0;\n"
447 << " }\n"
448 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
449 << " out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
450 << "}\n";
451
452 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
453 }
454
455 // Tessellation evaluation shader
456 {
457 std::ostringstream src;
458 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
459 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
460 << "\n"
461 << "layout(triangles, equal_spacing, cw) in;\n"
462 << "\n"
463 << "layout(location = 0) in vec4 in_color[];\n"
464 << "layout(location = 0) out vec4 out_color;\n"
465 << "\n"
466 << "void main(void)\n"
467 << "{\n"
468 << " gl_Layer = gl_PrimitiveID / 2;\n"
469 << " gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
470 << " gl_in[1].gl_Position * gl_TessCoord.y +\n"
471 << " gl_in[2].gl_Position * gl_TessCoord.z;\n"
472 << "\n"
473 << " out_color = in_color[0] * gl_TessCoord.x +\n"
474 << " in_color[1] * gl_TessCoord.y +\n"
475 << " in_color[2] * gl_TessCoord.z;\n"
476 << "}\n";
477
478 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
479 }
480
481 // Fragment shader
482 {
483 std::ostringstream src;
484 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
485 << "\n"
486 << "layout(location = 0) in vec4 in_color;\n"
487 << "layout(location = 0) out vec4 out_color;\n"
488 << "\n"
489 << "void main(void)\n"
490 << "{\n"
491 << " out_color = in_color;\n"
492 << "}\n";
493
494 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
495 }
496 }
497
generateGrid(const int numCells,const UVec2 & renderSize)498 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
499 {
500 const int numCols = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
501 const int numRows = deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
502 const int rectWidth = renderSize.x() / numCols;
503 const int rectHeight = renderSize.y() / numRows;
504
505 std::vector<UVec4> cells;
506 cells.reserve(numCells);
507
508 int x = 0;
509 int y = 0;
510
511 for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
512 {
513 const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
514 if (nextRow)
515 {
516 x = 0;
517 y += rectHeight;
518 }
519
520 cells.push_back(UVec4(x, y, rectWidth, rectHeight));
521
522 x += rectWidth;
523 }
524
525 return cells;
526 }
527
generateColors(int numColors)528 std::vector<Vec4> generateColors (int numColors)
529 {
530 const Vec4 colors[] =
531 {
532 Vec4(0.18f, 0.42f, 0.17f, 1.0f),
533 Vec4(0.29f, 0.62f, 0.28f, 1.0f),
534 Vec4(0.59f, 0.84f, 0.44f, 1.0f),
535 Vec4(0.96f, 0.95f, 0.72f, 1.0f),
536 Vec4(0.94f, 0.55f, 0.39f, 1.0f),
537 Vec4(0.82f, 0.19f, 0.12f, 1.0f),
538 Vec4(0.46f, 0.15f, 0.26f, 1.0f),
539 Vec4(0.24f, 0.14f, 0.24f, 1.0f),
540 Vec4(0.49f, 0.31f, 0.26f, 1.0f),
541 Vec4(0.78f, 0.52f, 0.33f, 1.0f),
542 Vec4(0.94f, 0.82f, 0.31f, 1.0f),
543 Vec4(0.98f, 0.65f, 0.30f, 1.0f),
544 Vec4(0.22f, 0.65f, 0.53f, 1.0f),
545 Vec4(0.67f, 0.81f, 0.91f, 1.0f),
546 Vec4(0.43f, 0.44f, 0.75f, 1.0f),
547 Vec4(0.26f, 0.24f, 0.48f, 1.0f),
548 };
549
550 std::vector<Vec4> result;
551 result.reserve(numColors);
552
553 for (int i = 0; i < numColors; ++i)
554 {
555 result.push_back(colors[i % DE_LENGTH_OF_ARRAY(colors)]);
556 }
557
558 return result;
559 }
560
generateVertices(const std::vector<UVec4> & grid,const std::vector<Vec4> & colors,const UVec2 & renderSize)561 std::vector<PositionColorVertex> generateVertices (const std::vector<UVec4>& grid, const std::vector<Vec4>& colors, const UVec2& renderSize)
562 {
563 DE_ASSERT(colors.size() == grid.size());
564
565 // Two triangles for each cell. Each cell correspond to a layer.
566 std::size_t total = grid.size() * 6;
567
568 std::vector<PositionColorVertex> result;
569 result.reserve(total);
570
571 for (std::size_t i = 0; i < total; ++i)
572 {
573 Vec4 pos;
574 pos.z() = 0.0;
575 pos.w() = 1.0;
576
577 Vec4 cell = grid[i/6].asFloat() * 2.0f;
578 float x = cell.x() / float(renderSize.x()) - 1.0f;
579 float y = cell.y() / float(renderSize.y()) - 1.0f;
580 float width = cell.z() / float(renderSize.x());
581 float height = cell.w() / float(renderSize.y());
582
583 switch (i % 6)
584 {
585 case 0: pos.xy() = Vec2(x, y + height); break;
586 case 1: pos.xy() = Vec2(x + width, y + height); break;
587 case 2: pos.xy() = Vec2(x, y); break;
588 case 3: pos.xy() = Vec2(x + width, y); break;
589 case 4: pos.xy() = Vec2(x + width, y + height); break;
590 case 5: pos.xy() = Vec2(x, y); break;
591 }
592
593 result.push_back(PositionColorVertex(pos, colors[i/6]));
594 }
595
596 return result;
597 }
598
599 // Renderer generates two triangles per layer, each pair using a different
600 // color and a different position.
601 class Renderer
602 {
603 public:
604 enum Shader
605 {
606 VERTEX,
607 TESSELLATION,
608 };
609
Renderer(Context & context,const bool useDynamicRendering,const UVec2 & renderSize,const int numLayers,const VkFormat colorFormat,const Vec4 & clearColor,const std::vector<PositionColorVertex> & vertices,const Shader shader)610 Renderer (Context& context,
611 const bool useDynamicRendering,
612 const UVec2& renderSize,
613 const int numLayers,
614 const VkFormat colorFormat,
615 const Vec4& clearColor,
616 const std::vector<PositionColorVertex>& vertices,
617 const Shader shader)
618 : m_useDynamicRendering (useDynamicRendering)
619 , m_renderSize (renderSize)
620 , m_colorFormat (colorFormat)
621 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers))
622 , m_clearColor (clearColor)
623 , m_numLayers (numLayers)
624 , m_vertices (vertices)
625 {
626 const DeviceInterface& vk = context.getDeviceInterface();
627 const VkDevice device = context.getDevice();
628 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
629 Allocator& allocator = context.getDefaultAllocator();
630 const VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices);
631
632 m_colorImage = makeImage (vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, m_numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
633 m_colorImageAlloc = bindImage (vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
634 m_colorAttachment = makeImageView (vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_colorFormat, m_colorSubresourceRange);
635
636 m_vertexBuffer = Buffer::createAndAlloc (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
637
638 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
639 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
640
641 if (shader == TESSELLATION)
642 {
643 m_tessellationControlModule = createShaderModule (vk, device, context.getBinaryCollection().get("tesc"), 0u);
644 m_tessellationEvaluationModule = createShaderModule (vk, device, context.getBinaryCollection().get("tese"), 0u);
645 }
646
647 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u);
648 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u);
649
650 if (!m_useDynamicRendering)
651 {
652 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
653
654 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, m_colorAttachment.get(),
655 static_cast<deUint32>(m_renderSize.x()),
656 static_cast<deUint32>(m_renderSize.y()),
657 numLayers);
658 }
659
660 m_pipelineLayout = makePipelineLayout (vk, device);
661 m_pipeline = makeGraphicsPipeline (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
662 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize);
663 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
664 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
665 }
666
draw(Context & context,const VkBuffer colorBuffer) const667 void draw (Context& context, const VkBuffer colorBuffer) const
668 {
669 const DeviceInterface& vk = context.getDeviceInterface();
670 const VkDevice device = context.getDevice();
671 const VkQueue queue = context.getUniversalQueue();
672
673 beginCommandBuffer(vk, *m_cmdBuffer);
674
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 if (m_useDynamicRendering)
683 {
684 initialTransitionColor2DImage(vk, *m_cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
685 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
686 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, 0, m_numLayers);
687 }
688 else
689 {
690 const VkRenderPassBeginInfo renderPassBeginInfo =
691 {
692 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
693 DE_NULL, // const void* pNext;
694 *m_renderPass, // VkRenderPass renderPass;
695 *m_framebuffer, // VkFramebuffer framebuffer;
696 renderArea, // VkRect2D renderArea;
697 1u, // uint32_t clearValueCount;
698 &clearValue, // const VkClearValue* pClearValues;
699 };
700 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
701 }
702
703 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
704 {
705 const VkBuffer vertexBuffer = m_vertexBuffer->object();
706 const VkDeviceSize vertexBufferOffset = 0ull;
707 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
708 }
709 vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_numLayers * 6), 1u, 0u, 0u); // two triangles per layer
710
711 if (m_useDynamicRendering)
712 endRendering(vk, *m_cmdBuffer);
713 else
714 vk.cmdEndRenderPass(*m_cmdBuffer);
715
716 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);
717
718 endCommandBuffer(vk, *m_cmdBuffer);
719 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
720 }
721
722 private:
723 const bool m_useDynamicRendering;
724 const UVec2 m_renderSize;
725 const VkFormat m_colorFormat;
726 const VkImageSubresourceRange m_colorSubresourceRange;
727 const Vec4 m_clearColor;
728 const int m_numLayers;
729 const std::vector<PositionColorVertex> m_vertices;
730
731 Move<VkImage> m_colorImage;
732 MovePtr<Allocation> m_colorImageAlloc;
733 Move<VkImageView> m_colorAttachment;
734 SharedPtr<Buffer> m_vertexBuffer;
735 Move<VkShaderModule> m_vertexModule;
736 Move<VkShaderModule> m_tessellationControlModule;
737 Move<VkShaderModule> m_tessellationEvaluationModule;
738 Move<VkShaderModule> m_fragmentModule;
739 Move<VkRenderPass> m_renderPass;
740 Move<VkFramebuffer> m_framebuffer;
741 Move<VkPipelineLayout> m_pipelineLayout;
742 Move<VkPipeline> m_pipeline;
743 Move<VkCommandPool> m_cmdPool;
744 Move<VkCommandBuffer> m_cmdBuffer;
745
746 // "deleted"
747 Renderer (const Renderer&);
748 Renderer& operator= (const Renderer&);
749 };
750
checkRequirements(Context & context,const TestParams params)751 void checkRequirements (Context& context, const TestParams params)
752 {
753 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
754 context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
755
756 if (params.useDynamicRendering)
757 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
758
759 const VkPhysicalDeviceLimits limits = context.getDeviceProperties().limits;
760
761 if (limits.maxFramebufferLayers < MIN_MAX_FRAMEBUFFER_LAYERS)
762 TCU_FAIL("maxFramebuffersLayers is less than the minimum required");
763
764 if (limits.maxViewports < MIN_MAX_VIEWPORTS)
765 TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
766 }
767
testVertexShader(Context & context,const TestParams params)768 tcu::TestStatus testVertexShader (Context& context, const TestParams params)
769 {
770 const DeviceInterface& vk = context.getDeviceInterface();
771 const VkDevice device = context.getDevice();
772 Allocator& allocator = context.getDefaultAllocator();
773
774 const UVec2 renderSize (256, 256);
775 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
776 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
777 const std::vector<UVec4> grid = generateGrid(params.numLayers, renderSize);
778 const std::vector<Vec4> colors = generateColors(params.numLayers);
779 const std::vector<PositionColorVertex> vertices = generateVertices(grid, colors, renderSize);
780
781 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * params.numLayers;
782
783 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
784
785 // Zero buffer.
786 {
787 const Allocation alloc = colorBuffer->getBoundMemory();
788 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
789 flushAlloc(vk, device, alloc);
790 }
791
792 {
793 context.getTestContext().getLog()
794 << tcu::TestLog::Message << "Rendering a rectangle in each of the " << params.numLayers << " layer(s)." << tcu::TestLog::EndMessage
795 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
796 }
797
798 // Draw.
799 {
800 const Renderer renderer (context, params.useDynamicRendering, renderSize, params.numLayers, colorFormat, clearColor, vertices, Renderer::VERTEX);
801 renderer.draw(context, colorBuffer->object());
802 }
803
804 // Verify layers.
805 {
806 const Allocation alloc = colorBuffer->getBoundMemory();
807 invalidateAlloc(vk, device, alloc);
808
809 deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
810 for (int i = 0; i < params.numLayers; i++)
811 {
812 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / params.numLayers) * i));
813 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
814 std::string imageSetName = "layer_" + de::toString(i);
815 std::string imageSetDesc = "Image compare for layer " + de::toString(i);
816 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
817 TCU_FAIL("Rendered image is not correct");
818 }
819 }
820
821 return tcu::TestStatus::pass("OK");
822 }
823
testTessellationShader(Context & context,const TestParams params)824 tcu::TestStatus testTessellationShader (Context& context, const TestParams params)
825 {
826 const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures();
827 if (!features.tessellationShader)
828 TCU_THROW(NotSupportedError, "Required feature is not supported: tessellationShader");
829
830 const DeviceInterface& vk = context.getDeviceInterface();
831 const VkDevice device = context.getDevice();
832 Allocator& allocator = context.getDefaultAllocator();
833
834 const UVec2 renderSize (256, 256);
835 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
836 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
837 const std::vector<UVec4> grid = generateGrid(params.numLayers, renderSize);
838 const std::vector<Vec4> colors = generateColors(params.numLayers);
839 const std::vector<PositionColorVertex> vertices = generateVertices(grid, colors, renderSize);
840
841 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)) * params.numLayers;
842
843 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
844
845 // Zero buffer.
846 {
847 const Allocation alloc = colorBuffer->getBoundMemory();
848 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
849 flushAlloc(vk, device, alloc);
850 }
851
852 {
853 context.getTestContext().getLog()
854 << tcu::TestLog::Message << "Rendering a rectangle in each of the " << params.numLayers << " layer(s)." << tcu::TestLog::EndMessage
855 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
856 }
857
858 // Draw.
859 {
860 const Renderer renderer (context, params.useDynamicRendering, renderSize, params.numLayers, colorFormat, clearColor, vertices, Renderer::TESSELLATION);
861 renderer.draw(context, colorBuffer->object());
862 }
863
864 // Verify layers.
865 {
866 const Allocation alloc = colorBuffer->getBoundMemory();
867 invalidateAlloc(vk, device, alloc);
868
869 deUint8* resultMem = reinterpret_cast<deUint8*>(alloc.getHostPtr());
870 for (int i = 0; i < params.numLayers; i++) {
871 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, resultMem + ((colorBufferSize / params.numLayers) * i));
872 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, grid[i], colors[i]);
873 std::string imageSetName = "layer_" + de::toString(i);
874 std::string imageSetDesc = "Image compare for layer " + de::toString(i);
875 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), imageSetName.c_str(), imageSetDesc.c_str(), referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
876 TCU_FAIL("Rendered image is not correct");
877 }
878 }
879
880 return tcu::TestStatus::pass("OK");
881 }
882
883 } // anonymous
884
createShaderLayerTests(tcu::TestContext & testCtx,bool useDynamicRendering)885 tcu::TestCaseGroup* createShaderLayerTests (tcu::TestContext& testCtx, bool useDynamicRendering)
886 {
887 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_layer", ""));
888
889 int numLayersToTest[] =
890 {
891 1,
892 2,
893 3,
894 4,
895 5,
896 6,
897 7,
898 8,
899 MIN_MAX_FRAMEBUFFER_LAYERS,
900 };
901
902 TestParams parmas
903 {
904 1,
905 useDynamicRendering
906 };
907
908 for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
909 {
910 parmas.numLayers = numLayersToTest[i];
911 addFunctionCaseWithPrograms<TestParams>(group.get(), "vertex_shader_" + de::toString(parmas.numLayers), "", checkRequirements, initVertexTestPrograms, testVertexShader, parmas);
912 }
913
914 for (int i = 0; i < DE_LENGTH_OF_ARRAY(numLayersToTest); ++i)
915 {
916 parmas.numLayers = numLayersToTest[i];
917 addFunctionCaseWithPrograms<TestParams>(group.get(), "tessellation_shader_" + de::toString(parmas.numLayers), "", checkRequirements, initTessellationTestPrograms, testTessellationShader, parmas);
918 }
919
920 return group.release();
921 }
922
923 } // Draw
924 } // vkt
925