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_ViewportIndex in Vertex and Tessellation Shaders
23 * (part of VK_EXT_ShaderViewportIndexLayer)
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktDrawShaderViewportIndexTests.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 #include "vkBuilderUtil.hpp"
42 #include "vkBufferWithMemory.hpp"
43
44 #include "tcuTestLog.hpp"
45 #include "tcuVector.hpp"
46 #include "tcuImageCompare.hpp"
47 #include "tcuTextureUtil.hpp"
48
49 #include "deUniquePtr.hpp"
50 #include "deMath.h"
51
52 #include <vector>
53 #include <memory>
54
55 namespace vkt
56 {
57 namespace Draw
58 {
59 using namespace vk;
60 using de::UniquePtr;
61 using de::MovePtr;
62 using de::SharedPtr;
63 using tcu::Vec4;
64 using tcu::Vec2;
65 using tcu::UVec2;
66 using tcu::UVec4;
67
68 namespace
69 {
70
71 enum Constants
72 {
73 MIN_MAX_VIEWPORTS = 16, //!< Minimum number of viewports for an implementation supporting multiViewport.
74 };
75
76 struct TestParams
77 {
78 int numViewports;
79 bool writeFromVertex;
80 const SharedGroupParams groupParams;
81 bool useTessellationShader;
82 };
83
84 template<typename T>
sizeInBytes(const std::vector<T> & vec)85 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
86 {
87 return vec.size() * sizeof(vec[0]);
88 }
89
makeImageCreateInfo(const VkFormat format,const UVec2 & size,VkImageUsageFlags usage)90 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, VkImageUsageFlags usage)
91 {
92 const VkImageCreateInfo imageParams =
93 {
94 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
95 DE_NULL, // const void* pNext;
96 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
97 VK_IMAGE_TYPE_2D, // VkImageType imageType;
98 format, // VkFormat format;
99 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
100 1u, // deUint32 mipLevels;
101 1u, // deUint32 arrayLayers;
102 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
103 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
104 usage, // VkImageUsageFlags usage;
105 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
106 0u, // deUint32 queueFamilyIndexCount;
107 DE_NULL, // const deUint32* pQueueFamilyIndices;
108 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
109 };
110 return imageParams;
111 }
112
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,const int numViewports,const std::vector<UVec4> cells)113 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
114 const VkDevice device,
115 const VkPipelineLayout pipelineLayout,
116 const VkRenderPass renderPass,
117 const VkShaderModule vertexModule,
118 const VkShaderModule tessellationControlModule,
119 const VkShaderModule tessellationEvaluationModule,
120 const VkShaderModule fragmentModule,
121 const UVec2 renderSize,
122 const int numViewports,
123 const std::vector<UVec4> cells)
124 {
125 const VkVertexInputBindingDescription vertexInputBindingDescription =
126 {
127 0u, // uint32_t binding;
128 sizeof(PositionColorVertex), // uint32_t stride;
129 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
130 };
131
132 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
133 {
134 {
135 0u, // uint32_t location;
136 0u, // uint32_t binding;
137 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
138 0u, // uint32_t offset;
139 },
140 {
141 1u, // uint32_t location;
142 0u, // uint32_t binding;
143 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
144 sizeof(Vec4), // uint32_t offset;
145 },
146 };
147
148 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
149 {
150 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
151 DE_NULL, // const void* pNext;
152 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
153 1u, // uint32_t vertexBindingDescriptionCount;
154 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
155 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
156 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
157 };
158
159 const bool useTessellationShaders = (tessellationControlModule != DE_NULL) && (tessellationEvaluationModule != DE_NULL);
160
161 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
162 {
163 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
164 DE_NULL, // const void* pNext;
165 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
166 useTessellationShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
167 VK_FALSE, // VkBool32 primitiveRestartEnable;
168 };
169
170 DE_ASSERT(numViewports == static_cast<int>(cells.size()));
171
172 std::vector<VkViewport> viewports;
173 viewports.reserve(numViewports);
174
175 std::vector<VkRect2D> rectScissors;
176 rectScissors.reserve(numViewports);
177
178 for (std::vector<UVec4>::const_iterator it = cells.begin(); it != cells.end(); ++it) {
179 const VkViewport viewport = makeViewport(float(it->x()), float(it->y()), float(it->z()), float(it->w()), 0.0f, 1.0f);
180 viewports.push_back(viewport);
181 const VkRect2D rect = makeRect2D(renderSize);
182 rectScissors.push_back(rect);
183 }
184
185 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
186 {
187 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
188 DE_NULL, // const void* pNext;
189 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
190 static_cast<deUint32>(numViewports), // uint32_t viewportCount;
191 &viewports[0], // const VkViewport* pViewports;
192 static_cast<deUint32>(numViewports), // uint32_t scissorCount;
193 &rectScissors[0], // const VkRect2D* pScissors;
194 };
195
196 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
197 {
198 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
199 DE_NULL, // const void* pNext;
200 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
201 VK_FALSE, // VkBool32 depthClampEnable;
202 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
203 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
204 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
205 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
206 VK_FALSE, // VkBool32 depthBiasEnable;
207 0.0f, // float depthBiasConstantFactor;
208 0.0f, // float depthBiasClamp;
209 0.0f, // float depthBiasSlopeFactor;
210 1.0f, // float lineWidth;
211 };
212
213 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
214 {
215 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
216 DE_NULL, // const void* pNext;
217 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
218 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
219 VK_FALSE, // VkBool32 sampleShadingEnable;
220 0.0f, // float minSampleShading;
221 DE_NULL, // const VkSampleMask* pSampleMask;
222 VK_FALSE, // VkBool32 alphaToCoverageEnable;
223 VK_FALSE // VkBool32 alphaToOneEnable;
224 };
225
226 const VkStencilOpState stencilOpState = makeStencilOpState(
227 VK_STENCIL_OP_KEEP, // stencil fail
228 VK_STENCIL_OP_KEEP, // depth & stencil pass
229 VK_STENCIL_OP_KEEP, // depth only fail
230 VK_COMPARE_OP_ALWAYS, // compare op
231 0u, // compare mask
232 0u, // write mask
233 0u); // reference
234
235 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
236 {
237 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
238 DE_NULL, // const void* pNext;
239 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
240 VK_FALSE, // VkBool32 depthTestEnable;
241 VK_FALSE, // VkBool32 depthWriteEnable;
242 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
243 VK_FALSE, // VkBool32 depthBoundsTestEnable;
244 VK_FALSE, // VkBool32 stencilTestEnable;
245 stencilOpState, // VkStencilOpState front;
246 stencilOpState, // VkStencilOpState back;
247 0.0f, // float minDepthBounds;
248 1.0f, // float maxDepthBounds;
249 };
250
251 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
252 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
253 {
254 VK_FALSE, // VkBool32 blendEnable;
255 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
256 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
257 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
258 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
259 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
260 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
261 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
262 };
263
264 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
265 {
266 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
267 DE_NULL, // const void* pNext;
268 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
269 VK_FALSE, // VkBool32 logicOpEnable;
270 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
271 1u, // deUint32 attachmentCount;
272 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
273 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
274 };
275
276 const VkPipelineShaderStageCreateInfo pShaderStages[] =
277 {
278 {
279 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
280 DE_NULL, // const void* pNext;
281 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
282 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
283 vertexModule, // VkShaderModule module;
284 "main", // const char* pName;
285 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
286 },
287 {
288 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
289 DE_NULL, // const void* pNext;
290 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
291 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
292 fragmentModule, // VkShaderModule module;
293 "main", // const char* pName;
294 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
295 },
296 {
297 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
298 DE_NULL, // const void* pNext;
299 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
300 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlagBits stage;
301 tessellationControlModule, // VkShaderModule module;
302 "main", // const char* pName;
303 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
304 },
305 {
306 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
307 DE_NULL, // const void* pNext;
308 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
309 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, // VkShaderStageFlagBits stage;
310 tessellationEvaluationModule, // VkShaderModule module;
311 "main", // const char* pName;
312 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
313 },
314 };
315
316 const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
317 {
318 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
319 DE_NULL, // const void* pNext;
320 (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags;
321 3, // uint32_t patchControlPoints;
322 };
323
324 VkGraphicsPipelineCreateInfo graphicsPipelineInfo
325 {
326 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
327 DE_NULL, // const void* pNext;
328 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
329 useTessellationShaders ? deUint32(4) : deUint32(2), // deUint32 stageCount;
330 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
331 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
332 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
333 useTessellationShaders ? &pipelineTessellationStateInfo : DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
334 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
335 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
336 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
337 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
338 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
339 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
340 pipelineLayout, // VkPipelineLayout layout;
341 renderPass, // VkRenderPass renderPass;
342 0u, // deUint32 subpass;
343 DE_NULL, // VkPipeline basePipelineHandle;
344 0, // deInt32 basePipelineIndex;
345 };
346
347 #ifndef CTS_USES_VULKANSC
348 VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
349 VkPipelineRenderingCreateInfoKHR renderingCreateInfo
350 {
351 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
352 DE_NULL,
353 0u,
354 1u,
355 &colorAttachmentFormat,
356 VK_FORMAT_UNDEFINED,
357 VK_FORMAT_UNDEFINED
358 };
359
360 // when pipeline is created without render pass we are using dynamic rendering
361 if (renderPass == DE_NULL)
362 graphicsPipelineInfo.pNext = &renderingCreateInfo;
363 #endif // CTS_USES_VULKANSC
364
365 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
366 }
367
generateGrid(const int numCells,const UVec2 & renderSize)368 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
369 {
370 const int numCols = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
371 const int numRows = deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
372 const int rectWidth = renderSize.x() / numCols;
373 const int rectHeight = renderSize.y() / numRows;
374
375 std::vector<UVec4> cells;
376 cells.reserve(numCells);
377
378 int x = 0;
379 int y = 0;
380
381 for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
382 {
383 const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
384 if (nextRow)
385 {
386 x = 0;
387 y += rectHeight;
388 }
389
390 cells.push_back(UVec4(x, y, rectWidth, rectHeight));
391
392 x += rectWidth;
393 }
394
395 return cells;
396 }
397
generateColors(const int numColors)398 std::vector<Vec4> generateColors (const int numColors)
399 {
400 const Vec4 colors[] =
401 {
402 Vec4(0.18f, 0.42f, 0.17f, 1.0f),
403 Vec4(0.29f, 0.62f, 0.28f, 1.0f),
404 Vec4(0.59f, 0.84f, 0.44f, 1.0f),
405 Vec4(0.96f, 0.95f, 0.72f, 1.0f),
406 Vec4(0.94f, 0.55f, 0.39f, 1.0f),
407 Vec4(0.82f, 0.19f, 0.12f, 1.0f),
408 Vec4(0.46f, 0.15f, 0.26f, 1.0f),
409 Vec4(0.24f, 0.14f, 0.24f, 1.0f),
410 Vec4(0.49f, 0.31f, 0.26f, 1.0f),
411 Vec4(0.78f, 0.52f, 0.33f, 1.0f),
412 Vec4(0.94f, 0.82f, 0.31f, 1.0f),
413 Vec4(0.98f, 0.65f, 0.30f, 1.0f),
414 Vec4(0.22f, 0.65f, 0.53f, 1.0f),
415 Vec4(0.67f, 0.81f, 0.91f, 1.0f),
416 Vec4(0.43f, 0.44f, 0.75f, 1.0f),
417 Vec4(0.26f, 0.24f, 0.48f, 1.0f),
418 };
419
420 DE_ASSERT(numColors <= DE_LENGTH_OF_ARRAY(colors));
421
422 return std::vector<Vec4>(colors, colors + numColors);
423 }
424
425 //! Renders a colorful grid of rectangles.
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const Vec4 & clearColor,const std::vector<UVec4> & cells,const std::vector<Vec4> & cellColors)426 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format,
427 const UVec2& renderSize,
428 const Vec4& clearColor,
429 const std::vector<UVec4>& cells,
430 const std::vector<Vec4>& cellColors)
431 {
432 DE_ASSERT(cells.size() == cellColors.size());
433
434 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
435 tcu::clear(image.getAccess(), clearColor);
436
437 for (std::size_t i = 0; i < cells.size(); ++i)
438 {
439 const UVec4& cell = cells[i];
440 tcu::clear(
441 tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()),
442 cellColors[i]);
443 }
444
445 return image;
446 }
447
initVertexTestPrograms(SourceCollections & programCollection,const TestParams)448 void initVertexTestPrograms (SourceCollections& programCollection, const TestParams)
449 {
450 // Vertex shader
451 {
452 std::ostringstream src;
453 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
454 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
455 << "\n"
456 << "layout(location = 0) in vec4 in_position;\n"
457 << "layout(location = 1) in vec4 in_color;\n"
458 << "layout(location = 0) out vec4 out_color;\n"
459 << "\n"
460 << "void main(void)\n"
461 << "{\n"
462 << " gl_ViewportIndex = gl_VertexIndex / 6;\n"
463 << " gl_Position = in_position;\n"
464 << " out_color = in_color;\n"
465 << "}\n";
466
467 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
468 }
469
470 // Fragment shader
471 {
472 std::ostringstream src;
473 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
474 << "\n"
475 << "layout(location = 0) in vec4 in_color;\n"
476 << "layout(location = 0) out vec4 out_color;\n"
477 << "\n"
478 << "void main(void)\n"
479 << "{\n"
480 << " out_color = in_color;\n"
481 << "}\n";
482
483 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
484 }
485 }
486
initFragmentTestPrograms(SourceCollections & programCollection,const TestParams testParams)487 void initFragmentTestPrograms (SourceCollections& programCollection, const TestParams testParams)
488 {
489 // Vertex shader.
490 {
491 std::ostringstream src;
492 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
493 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
494 << "\n"
495 << "layout(location = 0) in vec4 in_position;\n"
496 << "layout(location = 1) in vec4 in_color;\n"
497 << "layout(location = 0) out vec4 out_color;\n"
498 << "\n"
499 << "void main(void)\n"
500 << "{\n"
501 << (testParams.writeFromVertex ? " gl_ViewportIndex = gl_VertexIndex / 6;\n" : "")
502 << " gl_Position = in_position;\n"
503 << " out_color = in_color;\n"
504 << "}\n";
505
506 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
507 }
508
509 // Fragment shader
510 {
511 // Ignore input color and choose one using the viewport index.
512 std::ostringstream src;
513 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
514 << "\n"
515 << "layout(location = 0) in vec4 in_color;\n"
516 << "layout(location = 0) out vec4 out_color;\n"
517 << "layout(set=0, binding=0) uniform Colors {\n"
518 << " vec4 color[" << testParams.numViewports << "];\n"
519 << "};\n"
520 << "\n"
521 << "void main(void)\n"
522 << "{\n"
523 << " out_color = color[gl_ViewportIndex];\n"
524 << "}\n";
525
526 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
527 }
528 }
529
initTessellationTestPrograms(SourceCollections & programCollection,const TestParams)530 void initTessellationTestPrograms (SourceCollections& programCollection, const TestParams)
531 {
532 // Vertex shader
533 {
534 std::ostringstream src;
535 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
536 << "\n"
537 << "layout(location = 0) in vec4 in_position;\n"
538 << "layout(location = 1) in vec4 in_color;\n"
539 << "layout(location = 0) out vec4 out_color;\n"
540 << "\n"
541 << "void main(void)\n"
542 << "{\n"
543 << " gl_Position = in_position;\n"
544 << " out_color = in_color;\n"
545 << "}\n";
546
547 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
548 }
549
550 // Tessellation control shader
551 {
552 std::ostringstream src;
553 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
554 << "\n"
555 << "layout(vertices = 3) out;\n"
556 << "\n"
557 << "layout(location = 0) in vec4 in_color[];\n"
558 << "layout(location = 0) out vec4 out_color[];\n"
559 << "\n"
560 << "void main(void)\n"
561 << "{\n"
562 << " if (gl_InvocationID == 0) {\n"
563 << " gl_TessLevelInner[0] = 1.0;\n"
564 << " gl_TessLevelInner[1] = 1.0;\n"
565 << " gl_TessLevelOuter[0] = 1.0;\n"
566 << " gl_TessLevelOuter[1] = 1.0;\n"
567 << " gl_TessLevelOuter[2] = 1.0;\n"
568 << " gl_TessLevelOuter[3] = 1.0;\n"
569 << " }\n"
570 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
571 << " out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
572 << "}\n";
573
574 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
575 }
576
577 // Tessellation evaluation shader
578 {
579 std::ostringstream src;
580 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
581 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
582 << "\n"
583 << "layout(triangles, equal_spacing, cw) in;\n"
584 << "\n"
585 << "layout(location = 0) in vec4 in_color[];\n"
586 << "layout(location = 0) out vec4 out_color;\n"
587 << "\n"
588 << "void main(void)\n"
589 << "{\n"
590 << " gl_ViewportIndex = gl_PrimitiveID / 2;\n"
591 << " gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
592 << " gl_in[1].gl_Position * gl_TessCoord.y +\n"
593 << " gl_in[2].gl_Position * gl_TessCoord.z;\n"
594 << "\n"
595 << " out_color = in_color[0] * gl_TessCoord.x +\n"
596 << " in_color[1] * gl_TessCoord.y +\n"
597 << " in_color[2] * gl_TessCoord.z;\n"
598 << "}\n";
599
600 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
601 }
602
603 // Fragment shader
604 {
605 std::ostringstream src;
606 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
607 << "\n"
608 << "layout(location = 0) in vec4 in_color;\n"
609 << "layout(location = 0) out vec4 out_color;\n"
610 << "\n"
611 << "void main(void)\n"
612 << "{\n"
613 << " out_color = in_color;\n"
614 << "}\n";
615
616 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
617 }
618 }
619
generateVertices(const std::vector<Vec4> & colors)620 std::vector<PositionColorVertex> generateVertices (const std::vector<Vec4>& colors)
621 {
622 // Two triangles for each color (viewport).
623 std::size_t total = colors.size() * 6;
624
625 std::vector<PositionColorVertex> result;
626 result.reserve(total);
627
628 for (std::size_t i = 0; i < total; ++i)
629 {
630 Vec4 pos;
631 pos.z() = 0.0;
632 pos.w() = 1.0;
633
634 switch (i % 6) {
635 case 0: pos.xy() = Vec2(-1.0, 1.0); break;
636 case 1: pos.xy() = Vec2( 1.0, 1.0); break;
637 case 2: pos.xy() = Vec2(-1.0, -1.0); break;
638 case 3: pos.xy() = Vec2( 1.0, -1.0); break;
639 case 4: pos.xy() = Vec2( 1.0, 1.0); break;
640 case 5: pos.xy() = Vec2(-1.0, -1.0); break;
641 }
642
643 result.push_back(PositionColorVertex(pos, colors[i/6]));
644 }
645
646 return result;
647 }
648
649 // Renderer generates two triangles per viewport, each pair using a different color. The
650 // numViewports are positioned to form a grid.
651 class Renderer
652 {
653 public:
654 enum Shader {
655 VERTEX,
656 TESSELLATION,
657 FRAGMENT,
658 };
659
Renderer(Context & context,const UVec2 & renderSize,const TestParams & testParams,const std::vector<UVec4> & cells,const VkFormat colorFormat,const Vec4 & clearColor,const std::vector<Vec4> & colors,const Shader shader)660 Renderer (Context& context,
661 const UVec2& renderSize,
662 const TestParams& testParams,
663 const std::vector<UVec4>& cells,
664 const VkFormat colorFormat,
665 const Vec4& clearColor,
666 const std::vector<Vec4>& colors,
667 const Shader shader)
668 : m_groupParams (testParams.groupParams)
669 , m_renderSize (renderSize)
670 , m_colorFormat (colorFormat)
671 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
672 , m_clearValue (makeClearValueColor(clearColor))
673 , m_numViewports (testParams.numViewports)
674 , m_colors (colors)
675 , m_vertices (generateVertices(colors))
676 , m_shader (shader)
677 {
678 const DeviceInterface& vk = context.getDeviceInterface();
679 const VkDevice device = context.getDevice();
680 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
681 Allocator& allocator = context.getDefaultAllocator();
682 const VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices);
683
684 m_colorImage = makeImage (vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
685 m_colorImageAlloc = bindImage (vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
686 m_colorAttachment = makeImageView (vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
687
688 m_vertexBuffer = Buffer::createAndAlloc (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
689
690 {
691 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
692 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
693 }
694
695 if (shader == TESSELLATION)
696 {
697 m_tessellationControlModule = createShaderModule (vk, device, context.getBinaryCollection().get("tesc"), 0u);
698 m_tessellationEvaluationModule = createShaderModule (vk, device, context.getBinaryCollection().get("tese"), 0u);
699 }
700
701 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u);
702 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u);
703
704 if (!m_groupParams->useDynamicRendering)
705 {
706 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
707
708 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, m_colorAttachment.get(),
709 static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y()));
710 }
711
712 if (shader == FRAGMENT)
713 {
714 vk::DescriptorSetLayoutBuilder builder;
715 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
716 m_descriptorSetLayout = builder.build(vk, device);
717 }
718
719 m_pipelineLayout = makePipelineLayout (vk, device, (shader == FRAGMENT ? m_descriptorSetLayout.get() : DE_NULL));
720 m_pipeline = makeGraphicsPipeline (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
721 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize, m_numViewports, cells);
722 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
723 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
724 m_secCmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
725 }
726
draw(Context & context,const VkBuffer colorBuffer)727 void draw (Context& context, const VkBuffer colorBuffer)
728 {
729 const DeviceInterface& vk = context.getDeviceInterface();
730 const VkDevice device = context.getDevice();
731 const VkQueue queue = context.getUniversalQueue();
732 const VkRect2D renderArea
733 {
734 makeOffset2D(0, 0),
735 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
736 };
737
738 #ifndef CTS_USES_VULKANSC
739 if (m_groupParams->useSecondaryCmdBuffer)
740 {
741 // record secondary command buffer
742 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
743 {
744 beginSecondaryCmdBuffer(context, *m_secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
745 beginRendering(vk, *m_secCmdBuffer, *m_colorAttachment, renderArea, m_clearValue,
746 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
747 }
748 else
749 beginSecondaryCmdBuffer(context, *m_secCmdBuffer);
750
751 drawCommands(context, *m_secCmdBuffer);
752
753 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
754 endRendering(vk, *m_secCmdBuffer);
755
756 endCommandBuffer(vk, *m_secCmdBuffer);
757
758 // record primary command buffer
759 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
760
761 preRenderCommands(context, *m_cmdBuffer);
762
763 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
764 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, m_clearValue,
765 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR);
766
767 vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
768
769 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
770 endRendering(vk, *m_cmdBuffer);
771
772 postRenderCommands(context, colorBuffer);
773 endCommandBuffer(vk, *m_cmdBuffer);
774 }
775 else if (m_groupParams->useDynamicRendering)
776 {
777 beginCommandBuffer(vk, *m_cmdBuffer);
778
779 preRenderCommands(context, *m_cmdBuffer);
780 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, m_clearValue,
781 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
782 drawCommands(context, *m_cmdBuffer);
783 endRendering(vk, *m_cmdBuffer);
784 postRenderCommands(context, colorBuffer);
785
786 endCommandBuffer(vk, *m_cmdBuffer);
787 }
788 #endif // CTS_USES_VULKANSC
789
790 if (!m_groupParams->useDynamicRendering)
791 {
792 beginCommandBuffer(vk, *m_cmdBuffer);
793
794 preRenderCommands(context, *m_cmdBuffer);
795 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, m_clearValue);
796 drawCommands(context, *m_cmdBuffer);
797 endRenderPass(vk, *m_cmdBuffer);
798 postRenderCommands(context, colorBuffer);
799
800 endCommandBuffer(vk, *m_cmdBuffer);
801 }
802
803 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
804 }
805
806 protected:
807
808 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(Context & context,VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags=0u) const809 void beginSecondaryCmdBuffer(Context& context, VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const
810 {
811 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
812 {
813 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
814 DE_NULL, // const void* pNext;
815 renderingFlags, // VkRenderingFlagsKHR flags;
816 0u, // uint32_t viewMask;
817 1u, // uint32_t colorAttachmentCount;
818 &m_colorFormat, // const VkFormat* pColorAttachmentFormats;
819 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
820 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
821 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
822 };
823 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
824
825 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
826 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
827 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
828
829 const VkCommandBufferBeginInfo commandBufBeginParams
830 {
831 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
832 DE_NULL, // const void* pNext;
833 usageFlags, // VkCommandBufferUsageFlags flags;
834 &bufferInheritanceInfo
835 };
836
837 const DeviceInterface& vk = context.getDeviceInterface();
838 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
839 }
840 #endif // CTS_USES_VULKANSC
841
preRenderCommands(Context & context,VkCommandBuffer cmdBuffer) const842 void preRenderCommands(Context& context, VkCommandBuffer cmdBuffer) const
843 {
844 if (m_groupParams->useDynamicRendering)
845 {
846 const DeviceInterface& vk = context.getDeviceInterface();
847 initialTransitionColor2DImage(vk, cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
848 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
849 }
850 }
851
postRenderCommands(Context & context,VkBuffer colorBuffer) const852 void postRenderCommands(Context& context, VkBuffer colorBuffer) const
853 {
854 const DeviceInterface& vk = context.getDeviceInterface();
855 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()));
856 }
857
drawCommands(Context & context,VkCommandBuffer cmdBuffer)858 void drawCommands(Context& context, VkCommandBuffer cmdBuffer)
859 {
860 const DeviceInterface& vk = context.getDeviceInterface();
861 const VkDevice device = context.getDevice();
862 Allocator& allocator = context.getDefaultAllocator();
863 const VkBuffer vertexBuffer = m_vertexBuffer->object();
864 const VkDeviceSize vertexBufferOffset = 0ull;
865
866 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
867 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
868
869 // Prepare colors buffer if needed.
870 if (m_shader == FRAGMENT)
871 {
872 // Create buffer.
873 const auto colorsBufferSize = m_colors.size() * sizeof(decltype(m_colors)::value_type);
874 const auto colorsBufferCreateInfo = vk::makeBufferCreateInfo(static_cast<VkDeviceSize>(colorsBufferSize), vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
875 m_colorsBuffer = SharedPtr<BufferWithMemory>(new vk::BufferWithMemory{ vk, device, allocator, colorsBufferCreateInfo, MemoryRequirement::HostVisible });
876
877 // Copy colors and flush allocation.
878 auto& colorsBufferAlloc = m_colorsBuffer->getAllocation();
879 deMemcpy(colorsBufferAlloc.getHostPtr(), m_colors.data(), colorsBufferSize);
880 vk::flushAlloc(vk, device, colorsBufferAlloc);
881
882 // Descriptor pool.
883 DescriptorPoolBuilder poolBuilder;
884 poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u);
885 m_descriptorPool = poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
886
887 // Descriptor set.
888 m_descriptorSet = vk::makeDescriptorSet(vk, device, m_descriptorPool.get(), m_descriptorSetLayout.get());
889
890 // Update and bind descriptor set.
891 const auto colorsBufferDescriptorInfo = vk::makeDescriptorBufferInfo(m_colorsBuffer->get(), 0ull, VK_WHOLE_SIZE);
892 vk::DescriptorSetUpdateBuilder updateBuilder;
893 updateBuilder.writeSingle(m_descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &colorsBufferDescriptorInfo);
894 updateBuilder.update(vk, device);
895
896 vk.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u, nullptr);
897 }
898
899 vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numViewports * 6), 1u, 0u, 0u); // two triangles per viewport
900 }
901
902 private:
903 const SharedGroupParams m_groupParams;
904 const UVec2 m_renderSize;
905 const VkFormat m_colorFormat;
906 const VkImageSubresourceRange m_colorSubresourceRange;
907 const VkClearValue m_clearValue;
908 const int m_numViewports;
909 const std::vector<Vec4> m_colors;
910 const std::vector<PositionColorVertex> m_vertices;
911 const Shader m_shader;
912
913 Move<VkImage> m_colorImage;
914 MovePtr<Allocation> m_colorImageAlloc;
915 Move<VkImageView> m_colorAttachment;
916 SharedPtr<BufferWithMemory> m_colorsBuffer;
917 SharedPtr<Buffer> m_vertexBuffer;
918 Move<VkShaderModule> m_vertexModule;
919 Move<VkShaderModule> m_tessellationControlModule;
920 Move<VkShaderModule> m_tessellationEvaluationModule;
921 Move<VkShaderModule> m_fragmentModule;
922 Move<VkRenderPass> m_renderPass;
923 Move<VkFramebuffer> m_framebuffer;
924 Move<VkDescriptorPool> m_descriptorPool;
925 Move<VkDescriptorSet> m_descriptorSet;
926 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
927 Move<VkPipelineLayout> m_pipelineLayout;
928 Move<VkPipeline> m_pipeline;
929 Move<VkCommandPool> m_cmdPool;
930 Move<VkCommandBuffer> m_cmdBuffer;
931 Move<VkCommandBuffer> m_secCmdBuffer;
932
933 // "deleted"
934 Renderer (const Renderer&);
935 Renderer& operator= (const Renderer&);
936 };
937
testVertexFragmentShader(Context & context,const TestParams & testParams,Renderer::Shader shader)938 tcu::TestStatus testVertexFragmentShader (Context& context, const TestParams& testParams, Renderer::Shader shader)
939 {
940 const DeviceInterface& vk = context.getDeviceInterface();
941 const VkDevice device = context.getDevice();
942 Allocator& allocator = context.getDefaultAllocator();
943
944 const UVec2 renderSize (128, 128);
945 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
946 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
947 const std::vector<Vec4> colors = generateColors(testParams.numViewports);
948 const std::vector<UVec4> cells = generateGrid(testParams.numViewports, renderSize);
949
950 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
951
952 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
953
954 // Zero buffer.
955 {
956 const Allocation alloc = colorBuffer->getBoundMemory();
957 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
958 flushAlloc(vk, device, alloc);
959 }
960
961 {
962 context.getTestContext().getLog()
963 << tcu::TestLog::Message << "Rendering a colorful grid of " << testParams.numViewports << " rectangle(s)." << tcu::TestLog::EndMessage
964 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
965 }
966
967 // Draw
968 {
969 Renderer renderer (context, renderSize, testParams, cells, colorFormat, clearColor, colors, shader);
970 renderer.draw(context, colorBuffer->object());
971 }
972
973 // Log image
974 {
975 const Allocation alloc = colorBuffer->getBoundMemory();
976 invalidateAlloc(vk, device, alloc);
977
978 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr());
979 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors);
980
981 // Images should now match.
982 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
983 TCU_FAIL("Rendered image is not correct");
984 }
985
986 return tcu::TestStatus::pass("OK");
987 }
988
testVertexShader(Context & context,const TestParams testParams)989 tcu::TestStatus testVertexShader (Context& context, const TestParams testParams)
990 {
991 return testVertexFragmentShader(context, testParams, Renderer::VERTEX);
992 }
993
testFragmentShader(Context & context,const TestParams testParams)994 tcu::TestStatus testFragmentShader (Context& context, const TestParams testParams)
995 {
996 return testVertexFragmentShader(context, testParams, Renderer::FRAGMENT);
997 }
998
testTessellationShader(Context & context,const TestParams testParams)999 tcu::TestStatus testTessellationShader (Context& context, const TestParams testParams)
1000 {
1001 const DeviceInterface& vk = context.getDeviceInterface();
1002 const VkDevice device = context.getDevice();
1003 Allocator& allocator = context.getDefaultAllocator();
1004
1005 const UVec2 renderSize (128, 128);
1006 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1007 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
1008 const std::vector<Vec4> colors = generateColors(testParams.numViewports);
1009 const std::vector<UVec4> cells = generateGrid(testParams.numViewports, renderSize);
1010
1011 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
1012
1013 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
1014
1015 // Zero buffer.
1016 {
1017 const Allocation alloc = colorBuffer->getBoundMemory();
1018 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1019 flushAlloc(vk, device, alloc);
1020 }
1021
1022 {
1023 context.getTestContext().getLog()
1024 << tcu::TestLog::Message << "Rendering a colorful grid of " << testParams.numViewports << " rectangle(s)." << tcu::TestLog::EndMessage
1025 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
1026 }
1027
1028 // Draw
1029 {
1030 Renderer renderer (context, renderSize, testParams, cells, colorFormat, clearColor, colors, Renderer::TESSELLATION);
1031 renderer.draw(context, colorBuffer->object());
1032 }
1033
1034 // Log image
1035 {
1036 const Allocation alloc = colorBuffer->getBoundMemory();
1037 invalidateAlloc(vk, device, alloc);
1038
1039 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr());
1040 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors);
1041
1042 // Images should now match.
1043 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
1044 TCU_FAIL("Rendered image is not correct");
1045 }
1046
1047 return tcu::TestStatus::pass("OK");
1048 }
1049
checkSupport(Context & context,TestParams params)1050 void checkSupport (Context& context, TestParams params)
1051 {
1052 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
1053 context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
1054
1055 if (context.getDeviceProperties().limits.maxViewports < MIN_MAX_VIEWPORTS)
1056 TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
1057
1058 if (params.useTessellationShader)
1059 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1060
1061 if (params.groupParams->useDynamicRendering)
1062 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1063 }
1064
1065 } // anonymous
1066
createShaderViewportIndexTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1067 tcu::TestCaseGroup* createShaderViewportIndexTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
1068 {
1069 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_viewport_index", ""));
1070
1071 TestParams testParams
1072 {
1073 1, // int numViewports;
1074 false, // bool writeFromVertex;
1075 groupParams, // SharedGroupParams groupParams;
1076 false // bool useTessellationShader;
1077 };
1078
1079 for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
1080 addFunctionCaseWithPrograms(group.get(), "vertex_shader_" + de::toString(testParams.numViewports), "", checkSupport, initVertexTestPrograms, testVertexShader, testParams);
1081
1082 testParams.numViewports = 1;
1083 addFunctionCaseWithPrograms(group.get(), "fragment_shader_implicit", "", checkSupport, initFragmentTestPrograms, testFragmentShader, testParams);
1084 testParams.writeFromVertex = true;
1085 for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
1086 addFunctionCaseWithPrograms(group.get(), "fragment_shader_" + de::toString(testParams.numViewports), "", checkSupport, initFragmentTestPrograms, testFragmentShader, testParams);
1087 testParams.writeFromVertex = false;
1088
1089 testParams.useTessellationShader = true;
1090 for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
1091 addFunctionCaseWithPrograms(group.get(), "tessellation_shader_" + de::toString(testParams.numViewports), "", checkSupport, initTessellationTestPrograms, testTessellationShader, testParams);
1092
1093 return group.release();
1094 }
1095
1096 } // Draw
1097 } // vkt
1098