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 bool useDynamicRendering;
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 VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
348 VkPipelineRenderingCreateInfoKHR renderingCreateInfo
349 {
350 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
351 DE_NULL,
352 0u,
353 1u,
354 &colorAttachmentFormat,
355 VK_FORMAT_UNDEFINED,
356 VK_FORMAT_UNDEFINED
357 };
358
359 // when pipeline is created without render pass we are using dynamic rendering
360 if (renderPass == DE_NULL)
361 graphicsPipelineInfo.pNext = &renderingCreateInfo;
362
363 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
364 }
365
generateGrid(const int numCells,const UVec2 & renderSize)366 std::vector<UVec4> generateGrid (const int numCells, const UVec2& renderSize)
367 {
368 const int numCols = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numCells)));
369 const int numRows = deCeilFloatToInt32(static_cast<float>(numCells) / static_cast<float>(numCols));
370 const int rectWidth = renderSize.x() / numCols;
371 const int rectHeight = renderSize.y() / numRows;
372
373 std::vector<UVec4> cells;
374 cells.reserve(numCells);
375
376 int x = 0;
377 int y = 0;
378
379 for (int cellNdx = 0; cellNdx < numCells; ++cellNdx)
380 {
381 const bool nextRow = (cellNdx != 0) && (cellNdx % numCols == 0);
382 if (nextRow)
383 {
384 x = 0;
385 y += rectHeight;
386 }
387
388 cells.push_back(UVec4(x, y, rectWidth, rectHeight));
389
390 x += rectWidth;
391 }
392
393 return cells;
394 }
395
generateColors(const int numColors)396 std::vector<Vec4> generateColors (const int numColors)
397 {
398 const Vec4 colors[] =
399 {
400 Vec4(0.18f, 0.42f, 0.17f, 1.0f),
401 Vec4(0.29f, 0.62f, 0.28f, 1.0f),
402 Vec4(0.59f, 0.84f, 0.44f, 1.0f),
403 Vec4(0.96f, 0.95f, 0.72f, 1.0f),
404 Vec4(0.94f, 0.55f, 0.39f, 1.0f),
405 Vec4(0.82f, 0.19f, 0.12f, 1.0f),
406 Vec4(0.46f, 0.15f, 0.26f, 1.0f),
407 Vec4(0.24f, 0.14f, 0.24f, 1.0f),
408 Vec4(0.49f, 0.31f, 0.26f, 1.0f),
409 Vec4(0.78f, 0.52f, 0.33f, 1.0f),
410 Vec4(0.94f, 0.82f, 0.31f, 1.0f),
411 Vec4(0.98f, 0.65f, 0.30f, 1.0f),
412 Vec4(0.22f, 0.65f, 0.53f, 1.0f),
413 Vec4(0.67f, 0.81f, 0.91f, 1.0f),
414 Vec4(0.43f, 0.44f, 0.75f, 1.0f),
415 Vec4(0.26f, 0.24f, 0.48f, 1.0f),
416 };
417
418 DE_ASSERT(numColors <= DE_LENGTH_OF_ARRAY(colors));
419
420 return std::vector<Vec4>(colors, colors + numColors);
421 }
422
423 //! 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)424 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format,
425 const UVec2& renderSize,
426 const Vec4& clearColor,
427 const std::vector<UVec4>& cells,
428 const std::vector<Vec4>& cellColors)
429 {
430 DE_ASSERT(cells.size() == cellColors.size());
431
432 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
433 tcu::clear(image.getAccess(), clearColor);
434
435 for (std::size_t i = 0; i < cells.size(); ++i)
436 {
437 const UVec4& cell = cells[i];
438 tcu::clear(
439 tcu::getSubregion(image.getAccess(), cell.x(), cell.y(), cell.z(), cell.w()),
440 cellColors[i]);
441 }
442
443 return image;
444 }
445
initVertexTestPrograms(SourceCollections & programCollection,const TestParams)446 void initVertexTestPrograms (SourceCollections& programCollection, const TestParams)
447 {
448 // Vertex shader
449 {
450 std::ostringstream src;
451 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
452 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
453 << "\n"
454 << "layout(location = 0) in vec4 in_position;\n"
455 << "layout(location = 1) in vec4 in_color;\n"
456 << "layout(location = 0) out vec4 out_color;\n"
457 << "\n"
458 << "void main(void)\n"
459 << "{\n"
460 << " gl_ViewportIndex = gl_VertexIndex / 6;\n"
461 << " gl_Position = in_position;\n"
462 << " out_color = in_color;\n"
463 << "}\n";
464
465 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
466 }
467
468 // Fragment shader
469 {
470 std::ostringstream src;
471 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
472 << "\n"
473 << "layout(location = 0) in vec4 in_color;\n"
474 << "layout(location = 0) out vec4 out_color;\n"
475 << "\n"
476 << "void main(void)\n"
477 << "{\n"
478 << " out_color = in_color;\n"
479 << "}\n";
480
481 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
482 }
483 }
484
initFragmentTestPrograms(SourceCollections & programCollection,const TestParams testParams)485 void initFragmentTestPrograms (SourceCollections& programCollection, const TestParams testParams)
486 {
487 // Vertex shader.
488 {
489 std::ostringstream src;
490 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
491 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
492 << "\n"
493 << "layout(location = 0) in vec4 in_position;\n"
494 << "layout(location = 1) in vec4 in_color;\n"
495 << "layout(location = 0) out vec4 out_color;\n"
496 << "\n"
497 << "void main(void)\n"
498 << "{\n"
499 << (testParams.writeFromVertex ? " gl_ViewportIndex = gl_VertexIndex / 6;\n" : "")
500 << " gl_Position = in_position;\n"
501 << " out_color = in_color;\n"
502 << "}\n";
503
504 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
505 }
506
507 // Fragment shader
508 {
509 // Ignore input color and choose one using the viewport index.
510 std::ostringstream src;
511 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
512 << "\n"
513 << "layout(location = 0) in vec4 in_color;\n"
514 << "layout(location = 0) out vec4 out_color;\n"
515 << "layout(set=0, binding=0) uniform Colors {\n"
516 << " vec4 color[" << testParams.numViewports << "];\n"
517 << "};\n"
518 << "\n"
519 << "void main(void)\n"
520 << "{\n"
521 << " out_color = color[gl_ViewportIndex];\n"
522 << "}\n";
523
524 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
525 }
526 }
527
initTessellationTestPrograms(SourceCollections & programCollection,const TestParams)528 void initTessellationTestPrograms (SourceCollections& programCollection, const TestParams)
529 {
530 // Vertex shader
531 {
532 std::ostringstream src;
533 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
534 << "\n"
535 << "layout(location = 0) in vec4 in_position;\n"
536 << "layout(location = 1) in vec4 in_color;\n"
537 << "layout(location = 0) out vec4 out_color;\n"
538 << "\n"
539 << "void main(void)\n"
540 << "{\n"
541 << " gl_Position = in_position;\n"
542 << " out_color = in_color;\n"
543 << "}\n";
544
545 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
546 }
547
548 // Tessellation control shader
549 {
550 std::ostringstream src;
551 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
552 << "\n"
553 << "layout(vertices = 3) out;\n"
554 << "\n"
555 << "layout(location = 0) in vec4 in_color[];\n"
556 << "layout(location = 0) out vec4 out_color[];\n"
557 << "\n"
558 << "void main(void)\n"
559 << "{\n"
560 << " if (gl_InvocationID == 0) {\n"
561 << " gl_TessLevelInner[0] = 1.0;\n"
562 << " gl_TessLevelInner[1] = 1.0;\n"
563 << " gl_TessLevelOuter[0] = 1.0;\n"
564 << " gl_TessLevelOuter[1] = 1.0;\n"
565 << " gl_TessLevelOuter[2] = 1.0;\n"
566 << " gl_TessLevelOuter[3] = 1.0;\n"
567 << " }\n"
568 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
569 << " out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
570 << "}\n";
571
572 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
573 }
574
575 // Tessellation evaluation shader
576 {
577 std::ostringstream src;
578 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
579 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
580 << "\n"
581 << "layout(triangles, equal_spacing, cw) in;\n"
582 << "\n"
583 << "layout(location = 0) in vec4 in_color[];\n"
584 << "layout(location = 0) out vec4 out_color;\n"
585 << "\n"
586 << "void main(void)\n"
587 << "{\n"
588 << " gl_ViewportIndex = gl_PrimitiveID / 2;\n"
589 << " gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
590 << " gl_in[1].gl_Position * gl_TessCoord.y +\n"
591 << " gl_in[2].gl_Position * gl_TessCoord.z;\n"
592 << "\n"
593 << " out_color = in_color[0] * gl_TessCoord.x +\n"
594 << " in_color[1] * gl_TessCoord.y +\n"
595 << " in_color[2] * gl_TessCoord.z;\n"
596 << "}\n";
597
598 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
599 }
600
601 // Fragment shader
602 {
603 std::ostringstream src;
604 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
605 << "\n"
606 << "layout(location = 0) in vec4 in_color;\n"
607 << "layout(location = 0) out vec4 out_color;\n"
608 << "\n"
609 << "void main(void)\n"
610 << "{\n"
611 << " out_color = in_color;\n"
612 << "}\n";
613
614 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
615 }
616 }
617
generateVertices(const std::vector<Vec4> & colors)618 std::vector<PositionColorVertex> generateVertices (const std::vector<Vec4>& colors)
619 {
620 // Two triangles for each color (viewport).
621 std::size_t total = colors.size() * 6;
622
623 std::vector<PositionColorVertex> result;
624 result.reserve(total);
625
626 for (std::size_t i = 0; i < total; ++i)
627 {
628 Vec4 pos;
629 pos.z() = 0.0;
630 pos.w() = 1.0;
631
632 switch (i % 6) {
633 case 0: pos.xy() = Vec2(-1.0, 1.0); break;
634 case 1: pos.xy() = Vec2( 1.0, 1.0); break;
635 case 2: pos.xy() = Vec2(-1.0, -1.0); break;
636 case 3: pos.xy() = Vec2( 1.0, -1.0); break;
637 case 4: pos.xy() = Vec2( 1.0, 1.0); break;
638 case 5: pos.xy() = Vec2(-1.0, -1.0); break;
639 }
640
641 result.push_back(PositionColorVertex(pos, colors[i/6]));
642 }
643
644 return result;
645 }
646
647 // Renderer generates two triangles per viewport, each pair using a different color. The
648 // numViewports are positioned to form a grid.
649 class Renderer
650 {
651 public:
652 enum Shader {
653 VERTEX,
654 TESSELLATION,
655 FRAGMENT,
656 };
657
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)658 Renderer (Context& context,
659 const UVec2& renderSize,
660 const TestParams& testParams,
661 const std::vector<UVec4>& cells,
662 const VkFormat colorFormat,
663 const Vec4& clearColor,
664 const std::vector<Vec4>& colors,
665 const Shader shader)
666 : m_useDynamicRendering (testParams.useDynamicRendering)
667 , m_renderSize (renderSize)
668 , m_colorFormat (colorFormat)
669 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
670 , m_clearValue (makeClearValueColor(clearColor))
671 , m_numViewports (testParams.numViewports)
672 , m_colors (colors)
673 , m_vertices (generateVertices(colors))
674 , m_shader (shader)
675 {
676 const DeviceInterface& vk = context.getDeviceInterface();
677 const VkDevice device = context.getDevice();
678 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
679 Allocator& allocator = context.getDefaultAllocator();
680 const VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices);
681
682 m_colorImage = makeImage (vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
683 m_colorImageAlloc = bindImage (vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
684 m_colorAttachment = makeImageView (vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
685
686 m_vertexBuffer = Buffer::createAndAlloc (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
687
688 {
689 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
690 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
691 }
692
693 if (shader == TESSELLATION)
694 {
695 m_tessellationControlModule = createShaderModule (vk, device, context.getBinaryCollection().get("tesc"), 0u);
696 m_tessellationEvaluationModule = createShaderModule (vk, device, context.getBinaryCollection().get("tese"), 0u);
697 }
698
699 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u);
700 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u);
701
702 if (!m_useDynamicRendering)
703 {
704 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
705
706 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, m_colorAttachment.get(),
707 static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y()));
708 }
709
710 if (shader == FRAGMENT)
711 {
712 vk::DescriptorSetLayoutBuilder builder;
713 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
714 m_descriptorSetLayout = builder.build(vk, device);
715 }
716
717 m_pipelineLayout = makePipelineLayout (vk, device, (shader == FRAGMENT ? m_descriptorSetLayout.get() : DE_NULL));
718 m_pipeline = makeGraphicsPipeline (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
719 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize, m_numViewports, cells);
720 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
721 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
722 }
723
draw(Context & context,const VkBuffer colorBuffer) const724 void draw (Context& context, const VkBuffer colorBuffer) const
725 {
726 const DeviceInterface& vk = context.getDeviceInterface();
727 const VkDevice device = context.getDevice();
728 const VkQueue queue = context.getUniversalQueue();
729 Allocator& allocator = context.getDefaultAllocator();
730
731 beginCommandBuffer(vk, *m_cmdBuffer);
732
733 const VkRect2D renderArea = makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y());
734 if (m_useDynamicRendering)
735 {
736 initialTransitionColor2DImage(vk, *m_cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
737 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
738 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, m_clearValue, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
739 }
740 else
741 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, m_clearValue);
742
743 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
744 {
745 const VkBuffer vertexBuffer = m_vertexBuffer->object();
746 const VkDeviceSize vertexBufferOffset = 0ull;
747 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
748 }
749
750 // Prepare colors buffer if needed.
751 std::unique_ptr<vk::BufferWithMemory> colorsBuffer;
752 vk::Move<vk::VkDescriptorPool> descriptorPool;
753 vk::Move<vk::VkDescriptorSet> descriptorSet;
754
755 if (m_shader == FRAGMENT)
756 {
757 // Create buffer.
758 const auto colorsBufferSize = m_colors.size() * sizeof(decltype(m_colors)::value_type);
759 const auto colorsBufferCreateInfo = vk::makeBufferCreateInfo(static_cast<VkDeviceSize>(colorsBufferSize), vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
760 colorsBuffer.reset(new vk::BufferWithMemory{vk, device, allocator, colorsBufferCreateInfo, MemoryRequirement::HostVisible});
761
762 // Copy colors and flush allocation.
763 auto& colorsBufferAlloc = colorsBuffer->getAllocation();
764 deMemcpy(colorsBufferAlloc.getHostPtr(), m_colors.data(), colorsBufferSize);
765 vk::flushAlloc(vk, device, colorsBufferAlloc);
766
767 // Descriptor pool.
768 vk::DescriptorPoolBuilder poolBuilder;
769 poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u);
770 descriptorPool = poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
771
772 // Descriptor set.
773 descriptorSet = vk::makeDescriptorSet(vk, device, descriptorPool.get(), m_descriptorSetLayout.get());
774
775 // Update and bind descriptor set.
776 const auto colorsBufferDescriptorInfo = vk::makeDescriptorBufferInfo(colorsBuffer->get(), 0ull, VK_WHOLE_SIZE);
777 vk::DescriptorSetUpdateBuilder updateBuilder;
778 updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &colorsBufferDescriptorInfo);
779 updateBuilder.update(vk, device);
780
781 vk.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
782 }
783
784 vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_numViewports * 6), 1u, 0u, 0u); // two triangles per viewport
785
786 if (m_useDynamicRendering)
787 endRendering(vk, *m_cmdBuffer);
788 else
789 endRenderPass(vk, *m_cmdBuffer);
790
791 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()));
792
793 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
794 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
795 }
796
797 private:
798 const bool m_useDynamicRendering;
799 const UVec2 m_renderSize;
800 const VkFormat m_colorFormat;
801 const VkImageSubresourceRange m_colorSubresourceRange;
802 const VkClearValue m_clearValue;
803 const int m_numViewports;
804 const std::vector<Vec4> m_colors;
805 const std::vector<PositionColorVertex> m_vertices;
806 const Shader m_shader;
807
808 Move<VkImage> m_colorImage;
809 MovePtr<Allocation> m_colorImageAlloc;
810 Move<VkImageView> m_colorAttachment;
811 SharedPtr<Buffer> m_vertexBuffer;
812 Move<VkShaderModule> m_vertexModule;
813 Move<VkShaderModule> m_tessellationControlModule;
814 Move<VkShaderModule> m_tessellationEvaluationModule;
815 Move<VkShaderModule> m_fragmentModule;
816 Move<VkRenderPass> m_renderPass;
817 Move<VkFramebuffer> m_framebuffer;
818 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
819 Move<VkPipelineLayout> m_pipelineLayout;
820 Move<VkPipeline> m_pipeline;
821 Move<VkCommandPool> m_cmdPool;
822 Move<VkCommandBuffer> m_cmdBuffer;
823
824 // "deleted"
825 Renderer (const Renderer&);
826 Renderer& operator= (const Renderer&);
827 };
828
testVertexFragmentShader(Context & context,const TestParams & testParams,Renderer::Shader shader)829 tcu::TestStatus testVertexFragmentShader (Context& context, const TestParams& testParams, Renderer::Shader shader)
830 {
831 const DeviceInterface& vk = context.getDeviceInterface();
832 const VkDevice device = context.getDevice();
833 Allocator& allocator = context.getDefaultAllocator();
834
835 const UVec2 renderSize (128, 128);
836 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
837 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
838 const std::vector<Vec4> colors = generateColors(testParams.numViewports);
839 const std::vector<UVec4> cells = generateGrid(testParams.numViewports, renderSize);
840
841 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
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 colorful grid of " << testParams.numViewports << " rectangle(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, renderSize, testParams, cells, colorFormat, clearColor, colors, shader);
861 renderer.draw(context, colorBuffer->object());
862 }
863
864 // Log image
865 {
866 const Allocation alloc = colorBuffer->getBoundMemory();
867 invalidateAlloc(vk, device, alloc);
868
869 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr());
870 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors);
871
872 // Images should now match.
873 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
874 TCU_FAIL("Rendered image is not correct");
875 }
876
877 return tcu::TestStatus::pass("OK");
878 }
879
testVertexShader(Context & context,const TestParams testParams)880 tcu::TestStatus testVertexShader (Context& context, const TestParams testParams)
881 {
882 return testVertexFragmentShader(context, testParams, Renderer::VERTEX);
883 }
884
testFragmentShader(Context & context,const TestParams testParams)885 tcu::TestStatus testFragmentShader (Context& context, const TestParams testParams)
886 {
887 return testVertexFragmentShader(context, testParams, Renderer::FRAGMENT);
888 }
889
testTessellationShader(Context & context,const TestParams testParams)890 tcu::TestStatus testTessellationShader (Context& context, const TestParams testParams)
891 {
892 const DeviceInterface& vk = context.getDeviceInterface();
893 const VkDevice device = context.getDevice();
894 Allocator& allocator = context.getDefaultAllocator();
895
896 const UVec2 renderSize (128, 128);
897 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
898 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
899 const std::vector<Vec4> colors = generateColors(testParams.numViewports);
900 const std::vector<UVec4> cells = generateGrid(testParams.numViewports, renderSize);
901
902 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
903
904 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
905
906 // Zero buffer.
907 {
908 const Allocation alloc = colorBuffer->getBoundMemory();
909 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
910 flushAlloc(vk, device, alloc);
911 }
912
913 {
914 context.getTestContext().getLog()
915 << tcu::TestLog::Message << "Rendering a colorful grid of " << testParams.numViewports << " rectangle(s)." << tcu::TestLog::EndMessage
916 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
917 }
918
919 // Draw
920 {
921 const Renderer renderer (context, renderSize, testParams, cells, colorFormat, clearColor, colors, Renderer::TESSELLATION);
922 renderer.draw(context, colorBuffer->object());
923 }
924
925 // Log image
926 {
927 const Allocation alloc = colorBuffer->getBoundMemory();
928 invalidateAlloc(vk, device, alloc);
929
930 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr());
931 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors);
932
933 // Images should now match.
934 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
935 TCU_FAIL("Rendered image is not correct");
936 }
937
938 return tcu::TestStatus::pass("OK");
939 }
940
checkSupport(Context & context,TestParams params)941 void checkSupport (Context& context, TestParams params)
942 {
943 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
944 context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
945
946 if (context.getDeviceProperties().limits.maxViewports < MIN_MAX_VIEWPORTS)
947 TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
948
949 if (params.useTessellationShader)
950 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
951
952 if (params.useDynamicRendering)
953 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
954 }
955
956 } // anonymous
957
createShaderViewportIndexTests(tcu::TestContext & testCtx,bool useDynamicRendering)958 tcu::TestCaseGroup* createShaderViewportIndexTests (tcu::TestContext& testCtx, bool useDynamicRendering)
959 {
960 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_viewport_index", ""));
961
962 TestParams testParams
963 {
964 1, // int numViewports;
965 false, // bool writeFromVertex;
966 useDynamicRendering, // bool useDynamicRendering;
967 false // bool useTessellationShader;
968 };
969
970 for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
971 addFunctionCaseWithPrograms(group.get(), "vertex_shader_" + de::toString(testParams.numViewports), "", checkSupport, initVertexTestPrograms, testVertexShader, testParams);
972
973 testParams.numViewports = 1;
974 addFunctionCaseWithPrograms(group.get(), "fragment_shader_implicit", "", checkSupport, initFragmentTestPrograms, testFragmentShader, testParams);
975 testParams.writeFromVertex = true;
976 for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
977 addFunctionCaseWithPrograms(group.get(), "fragment_shader_" + de::toString(testParams.numViewports), "", checkSupport, initFragmentTestPrograms, testFragmentShader, testParams);
978 testParams.writeFromVertex = false;
979
980 testParams.useTessellationShader = true;
981 for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
982 addFunctionCaseWithPrograms(group.get(), "tessellation_shader_" + de::toString(testParams.numViewports), "", checkSupport, initTessellationTestPrograms, testTessellationShader, testParams);
983
984 return group.release();
985 }
986
987 } // Draw
988 } // vkt
989