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 programCollection.glslSources.add("vert_1_2") << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
469 }
470
471 // Fragment shader
472 {
473 std::ostringstream src;
474 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
475 << "\n"
476 << "layout(location = 0) in vec4 in_color;\n"
477 << "layout(location = 0) out vec4 out_color;\n"
478 << "\n"
479 << "void main(void)\n"
480 << "{\n"
481 << " out_color = in_color;\n"
482 << "}\n";
483
484 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
485 }
486 }
487
initFragmentTestPrograms(SourceCollections & programCollection,const TestParams testParams)488 void initFragmentTestPrograms (SourceCollections& programCollection, const TestParams testParams)
489 {
490 // Vertex shader.
491 {
492 std::ostringstream src;
493 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
494 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
495 << "\n"
496 << "layout(location = 0) in vec4 in_position;\n"
497 << "layout(location = 1) in vec4 in_color;\n"
498 << "layout(location = 0) out vec4 out_color;\n"
499 << "\n"
500 << "void main(void)\n"
501 << "{\n"
502 << (testParams.writeFromVertex ? " gl_ViewportIndex = gl_VertexIndex / 6;\n" : "")
503 << " gl_Position = in_position;\n"
504 << " out_color = in_color;\n"
505 << "}\n";
506
507 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
508 programCollection.glslSources.add("vert_1_2") << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
509 }
510
511 // Fragment shader
512 {
513 // Ignore input color and choose one using the viewport index.
514 std::ostringstream src;
515 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
516 << "\n"
517 << "layout(location = 0) in vec4 in_color;\n"
518 << "layout(location = 0) out vec4 out_color;\n"
519 << "layout(set=0, binding=0) uniform Colors {\n"
520 << " vec4 color[" << testParams.numViewports << "];\n"
521 << "};\n"
522 << "\n"
523 << "void main(void)\n"
524 << "{\n"
525 << " out_color = color[gl_ViewportIndex];\n"
526 << "}\n";
527
528 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
529 }
530 }
531
initTessellationTestPrograms(SourceCollections & programCollection,const TestParams)532 void initTessellationTestPrograms (SourceCollections& programCollection, const TestParams)
533 {
534 // Vertex shader
535 {
536 std::ostringstream src;
537 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
538 << "\n"
539 << "layout(location = 0) in vec4 in_position;\n"
540 << "layout(location = 1) in vec4 in_color;\n"
541 << "layout(location = 0) out vec4 out_color;\n"
542 << "\n"
543 << "void main(void)\n"
544 << "{\n"
545 << " gl_Position = in_position;\n"
546 << " out_color = in_color;\n"
547 << "}\n";
548
549 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
550 programCollection.glslSources.add("vert_1_2") << glu::VertexSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
551 }
552
553 // Tessellation control shader
554 {
555 std::ostringstream src;
556 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
557 << "\n"
558 << "layout(vertices = 3) out;\n"
559 << "\n"
560 << "layout(location = 0) in vec4 in_color[];\n"
561 << "layout(location = 0) out vec4 out_color[];\n"
562 << "\n"
563 << "void main(void)\n"
564 << "{\n"
565 << " if (gl_InvocationID == 0) {\n"
566 << " gl_TessLevelInner[0] = 1.0;\n"
567 << " gl_TessLevelInner[1] = 1.0;\n"
568 << " gl_TessLevelOuter[0] = 1.0;\n"
569 << " gl_TessLevelOuter[1] = 1.0;\n"
570 << " gl_TessLevelOuter[2] = 1.0;\n"
571 << " gl_TessLevelOuter[3] = 1.0;\n"
572 << " }\n"
573 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
574 << " out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
575 << "}\n";
576
577 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
578 }
579
580 // Tessellation evaluation shader
581 {
582 std::ostringstream src;
583 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
584 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
585 << "\n"
586 << "layout(triangles, equal_spacing, cw) in;\n"
587 << "\n"
588 << "layout(location = 0) in vec4 in_color[];\n"
589 << "layout(location = 0) out vec4 out_color;\n"
590 << "\n"
591 << "void main(void)\n"
592 << "{\n"
593 << " gl_ViewportIndex = gl_PrimitiveID / 2;\n"
594 << " gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
595 << " gl_in[1].gl_Position * gl_TessCoord.y +\n"
596 << " gl_in[2].gl_Position * gl_TessCoord.z;\n"
597 << "\n"
598 << " out_color = in_color[0] * gl_TessCoord.x +\n"
599 << " in_color[1] * gl_TessCoord.y +\n"
600 << " in_color[2] * gl_TessCoord.z;\n"
601 << "}\n";
602
603 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
604 programCollection.glslSources.add("tese_1_2") << glu::TessellationEvaluationSource(src.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
605 }
606
607 // Fragment shader
608 {
609 std::ostringstream src;
610 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
611 << "\n"
612 << "layout(location = 0) in vec4 in_color;\n"
613 << "layout(location = 0) out vec4 out_color;\n"
614 << "\n"
615 << "void main(void)\n"
616 << "{\n"
617 << " out_color = in_color;\n"
618 << "}\n";
619
620 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
621 }
622 }
623
generateVertices(const std::vector<Vec4> & colors)624 std::vector<PositionColorVertex> generateVertices (const std::vector<Vec4>& colors)
625 {
626 // Two triangles for each color (viewport).
627 std::size_t total = colors.size() * 6;
628
629 std::vector<PositionColorVertex> result;
630 result.reserve(total);
631
632 for (std::size_t i = 0; i < total; ++i)
633 {
634 Vec4 pos;
635 pos.z() = 0.0;
636 pos.w() = 1.0;
637
638 switch (i % 6) {
639 case 0: pos.xy() = Vec2(-1.0, 1.0); break;
640 case 1: pos.xy() = Vec2( 1.0, 1.0); break;
641 case 2: pos.xy() = Vec2(-1.0, -1.0); break;
642 case 3: pos.xy() = Vec2( 1.0, -1.0); break;
643 case 4: pos.xy() = Vec2( 1.0, 1.0); break;
644 case 5: pos.xy() = Vec2(-1.0, -1.0); break;
645 }
646
647 result.push_back(PositionColorVertex(pos, colors[i/6]));
648 }
649
650 return result;
651 }
652
653 // Renderer generates two triangles per viewport, each pair using a different color. The
654 // numViewports are positioned to form a grid.
655 class Renderer
656 {
657 public:
658 enum Shader {
659 VERTEX,
660 TESSELLATION,
661 FRAGMENT,
662 };
663
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)664 Renderer (Context& context,
665 const UVec2& renderSize,
666 const TestParams& testParams,
667 const std::vector<UVec4>& cells,
668 const VkFormat colorFormat,
669 const Vec4& clearColor,
670 const std::vector<Vec4>& colors,
671 const Shader shader)
672 : m_groupParams (testParams.groupParams)
673 , m_renderSize (renderSize)
674 , m_colorFormat (colorFormat)
675 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
676 , m_clearValue (makeClearValueColor(clearColor))
677 , m_numViewports (testParams.numViewports)
678 , m_colors (colors)
679 , m_vertices (generateVertices(colors))
680 , m_shader (shader)
681 {
682 const DeviceInterface& vk = context.getDeviceInterface();
683 const VkDevice device = context.getDevice();
684 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
685 Allocator& allocator = context.getDefaultAllocator();
686 const VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices);
687
688 m_colorImage = makeImage (vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
689 m_colorImageAlloc = bindImage (vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
690 m_colorAttachment = makeImageView (vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
691
692 m_vertexBuffer = Buffer::createAndAlloc (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
693
694 {
695 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &m_vertices[0], static_cast<std::size_t>(vertexBufferSize));
696 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
697 }
698
699 if (shader == TESSELLATION)
700 {
701 m_tessellationControlModule = createShaderModule (vk, device, context.getBinaryCollection().get("tesc"), 0u);
702 m_tessellationEvaluationModule = createShaderModule (vk, device, context.getBinaryCollection().get(context.contextSupports(VK_API_VERSION_1_2) ? "tese_1_2" : "tese"), 0u);
703 }
704
705 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get(context.contextSupports(VK_API_VERSION_1_2) ? "vert_1_2" : "vert"), 0u);
706 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u);
707
708 if (!m_groupParams->useDynamicRendering)
709 {
710 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
711
712 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, m_colorAttachment.get(),
713 static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y()));
714 }
715
716 if (shader == FRAGMENT)
717 {
718 vk::DescriptorSetLayoutBuilder builder;
719 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
720 m_descriptorSetLayout = builder.build(vk, device);
721 }
722
723 m_pipelineLayout = makePipelineLayout (vk, device, (shader == FRAGMENT ? m_descriptorSetLayout.get() : DE_NULL));
724 m_pipeline = makeGraphicsPipeline (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_tessellationControlModule,
725 *m_tessellationEvaluationModule, *m_fragmentModule, m_renderSize, m_numViewports, cells);
726 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
727 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
728 m_secCmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
729 }
730
draw(Context & context,const VkBuffer colorBuffer)731 void draw (Context& context, const VkBuffer colorBuffer)
732 {
733 const DeviceInterface& vk = context.getDeviceInterface();
734 const VkDevice device = context.getDevice();
735 const VkQueue queue = context.getUniversalQueue();
736 const VkRect2D renderArea
737 {
738 makeOffset2D(0, 0),
739 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
740 };
741
742 #ifndef CTS_USES_VULKANSC
743 if (m_groupParams->useSecondaryCmdBuffer)
744 {
745 // record secondary command buffer
746 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
747 {
748 beginSecondaryCmdBuffer(context, *m_secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
749 beginRendering(vk, *m_secCmdBuffer, *m_colorAttachment, renderArea, m_clearValue,
750 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
751 }
752 else
753 beginSecondaryCmdBuffer(context, *m_secCmdBuffer);
754
755 drawCommands(context, *m_secCmdBuffer);
756
757 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
758 endRendering(vk, *m_secCmdBuffer);
759
760 endCommandBuffer(vk, *m_secCmdBuffer);
761
762 // record primary command buffer
763 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
764
765 preRenderCommands(context, *m_cmdBuffer);
766
767 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
768 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, m_clearValue,
769 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR);
770
771 vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
772
773 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
774 endRendering(vk, *m_cmdBuffer);
775
776 postRenderCommands(context, colorBuffer);
777 endCommandBuffer(vk, *m_cmdBuffer);
778 }
779 else if (m_groupParams->useDynamicRendering)
780 {
781 beginCommandBuffer(vk, *m_cmdBuffer);
782
783 preRenderCommands(context, *m_cmdBuffer);
784 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, m_clearValue,
785 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
786 drawCommands(context, *m_cmdBuffer);
787 endRendering(vk, *m_cmdBuffer);
788 postRenderCommands(context, colorBuffer);
789
790 endCommandBuffer(vk, *m_cmdBuffer);
791 }
792 #endif // CTS_USES_VULKANSC
793
794 if (!m_groupParams->useDynamicRendering)
795 {
796 beginCommandBuffer(vk, *m_cmdBuffer);
797
798 preRenderCommands(context, *m_cmdBuffer);
799 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, m_clearValue);
800 drawCommands(context, *m_cmdBuffer);
801 endRenderPass(vk, *m_cmdBuffer);
802 postRenderCommands(context, colorBuffer);
803
804 endCommandBuffer(vk, *m_cmdBuffer);
805 }
806
807 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
808 }
809
810 protected:
811
812 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(Context & context,VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags=0u) const813 void beginSecondaryCmdBuffer(Context& context, VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const
814 {
815 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
816 {
817 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
818 DE_NULL, // const void* pNext;
819 renderingFlags, // VkRenderingFlagsKHR flags;
820 0u, // uint32_t viewMask;
821 1u, // uint32_t colorAttachmentCount;
822 &m_colorFormat, // const VkFormat* pColorAttachmentFormats;
823 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
824 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
825 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
826 };
827 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
828
829 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
830 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
831 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
832
833 const VkCommandBufferBeginInfo commandBufBeginParams
834 {
835 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
836 DE_NULL, // const void* pNext;
837 usageFlags, // VkCommandBufferUsageFlags flags;
838 &bufferInheritanceInfo
839 };
840
841 const DeviceInterface& vk = context.getDeviceInterface();
842 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
843 }
844 #endif // CTS_USES_VULKANSC
845
preRenderCommands(Context & context,VkCommandBuffer cmdBuffer) const846 void preRenderCommands(Context& context, VkCommandBuffer cmdBuffer) const
847 {
848 if (m_groupParams->useDynamicRendering)
849 {
850 const DeviceInterface& vk = context.getDeviceInterface();
851 initialTransitionColor2DImage(vk, cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
852 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
853 }
854 }
855
postRenderCommands(Context & context,VkBuffer colorBuffer) const856 void postRenderCommands(Context& context, VkBuffer colorBuffer) const
857 {
858 const DeviceInterface& vk = context.getDeviceInterface();
859 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()));
860 }
861
drawCommands(Context & context,VkCommandBuffer cmdBuffer)862 void drawCommands(Context& context, VkCommandBuffer cmdBuffer)
863 {
864 const DeviceInterface& vk = context.getDeviceInterface();
865 const VkDevice device = context.getDevice();
866 Allocator& allocator = context.getDefaultAllocator();
867 const VkBuffer vertexBuffer = m_vertexBuffer->object();
868 const VkDeviceSize vertexBufferOffset = 0ull;
869
870 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
871 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
872
873 // Prepare colors buffer if needed.
874 if (m_shader == FRAGMENT)
875 {
876 // Create buffer.
877 const auto colorsBufferSize = m_colors.size() * sizeof(decltype(m_colors)::value_type);
878 const auto colorsBufferCreateInfo = vk::makeBufferCreateInfo(static_cast<VkDeviceSize>(colorsBufferSize), vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
879 m_colorsBuffer = SharedPtr<BufferWithMemory>(new vk::BufferWithMemory{ vk, device, allocator, colorsBufferCreateInfo, MemoryRequirement::HostVisible });
880
881 // Copy colors and flush allocation.
882 auto& colorsBufferAlloc = m_colorsBuffer->getAllocation();
883 deMemcpy(colorsBufferAlloc.getHostPtr(), m_colors.data(), colorsBufferSize);
884 vk::flushAlloc(vk, device, colorsBufferAlloc);
885
886 // Descriptor pool.
887 DescriptorPoolBuilder poolBuilder;
888 poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u);
889 m_descriptorPool = poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
890
891 // Descriptor set.
892 m_descriptorSet = vk::makeDescriptorSet(vk, device, m_descriptorPool.get(), m_descriptorSetLayout.get());
893
894 // Update and bind descriptor set.
895 const auto colorsBufferDescriptorInfo = vk::makeDescriptorBufferInfo(m_colorsBuffer->get(), 0ull, VK_WHOLE_SIZE);
896 vk::DescriptorSetUpdateBuilder updateBuilder;
897 updateBuilder.writeSingle(m_descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &colorsBufferDescriptorInfo);
898 updateBuilder.update(vk, device);
899
900 vk.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u, nullptr);
901 }
902
903 vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numViewports * 6), 1u, 0u, 0u); // two triangles per viewport
904 }
905
906 private:
907 const SharedGroupParams m_groupParams;
908 const UVec2 m_renderSize;
909 const VkFormat m_colorFormat;
910 const VkImageSubresourceRange m_colorSubresourceRange;
911 const VkClearValue m_clearValue;
912 const int m_numViewports;
913 const std::vector<Vec4> m_colors;
914 const std::vector<PositionColorVertex> m_vertices;
915 const Shader m_shader;
916
917 Move<VkImage> m_colorImage;
918 MovePtr<Allocation> m_colorImageAlloc;
919 Move<VkImageView> m_colorAttachment;
920 SharedPtr<BufferWithMemory> m_colorsBuffer;
921 SharedPtr<Buffer> m_vertexBuffer;
922 Move<VkShaderModule> m_vertexModule;
923 Move<VkShaderModule> m_tessellationControlModule;
924 Move<VkShaderModule> m_tessellationEvaluationModule;
925 Move<VkShaderModule> m_fragmentModule;
926 Move<VkRenderPass> m_renderPass;
927 Move<VkFramebuffer> m_framebuffer;
928 Move<VkDescriptorPool> m_descriptorPool;
929 Move<VkDescriptorSet> m_descriptorSet;
930 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
931 Move<VkPipelineLayout> m_pipelineLayout;
932 Move<VkPipeline> m_pipeline;
933 Move<VkCommandPool> m_cmdPool;
934 Move<VkCommandBuffer> m_cmdBuffer;
935 Move<VkCommandBuffer> m_secCmdBuffer;
936
937 // "deleted"
938 Renderer (const Renderer&);
939 Renderer& operator= (const Renderer&);
940 };
941
testVertexFragmentShader(Context & context,const TestParams & testParams,Renderer::Shader shader)942 tcu::TestStatus testVertexFragmentShader (Context& context, const TestParams& testParams, Renderer::Shader shader)
943 {
944 const DeviceInterface& vk = context.getDeviceInterface();
945 const VkDevice device = context.getDevice();
946 Allocator& allocator = context.getDefaultAllocator();
947
948 const UVec2 renderSize (128, 128);
949 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
950 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
951 const std::vector<Vec4> colors = generateColors(testParams.numViewports);
952 const std::vector<UVec4> cells = generateGrid(testParams.numViewports, renderSize);
953
954 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
955
956 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
957
958 // Zero buffer.
959 {
960 const Allocation alloc = colorBuffer->getBoundMemory();
961 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
962 flushAlloc(vk, device, alloc);
963 }
964
965 {
966 context.getTestContext().getLog()
967 << tcu::TestLog::Message << "Rendering a colorful grid of " << testParams.numViewports << " rectangle(s)." << tcu::TestLog::EndMessage
968 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
969 }
970
971 // Draw
972 {
973 Renderer renderer (context, renderSize, testParams, cells, colorFormat, clearColor, colors, shader);
974 renderer.draw(context, colorBuffer->object());
975 }
976
977 // Log image
978 {
979 const Allocation alloc = colorBuffer->getBoundMemory();
980 invalidateAlloc(vk, device, alloc);
981
982 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr());
983 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors);
984
985 // Images should now match.
986 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
987 TCU_FAIL("Rendered image is not correct");
988 }
989
990 return tcu::TestStatus::pass("OK");
991 }
992
testVertexShader(Context & context,const TestParams testParams)993 tcu::TestStatus testVertexShader (Context& context, const TestParams testParams)
994 {
995 return testVertexFragmentShader(context, testParams, Renderer::VERTEX);
996 }
997
testFragmentShader(Context & context,const TestParams testParams)998 tcu::TestStatus testFragmentShader (Context& context, const TestParams testParams)
999 {
1000 return testVertexFragmentShader(context, testParams, Renderer::FRAGMENT);
1001 }
1002
testTessellationShader(Context & context,const TestParams testParams)1003 tcu::TestStatus testTessellationShader (Context& context, const TestParams testParams)
1004 {
1005 const DeviceInterface& vk = context.getDeviceInterface();
1006 const VkDevice device = context.getDevice();
1007 Allocator& allocator = context.getDefaultAllocator();
1008
1009 const UVec2 renderSize (128, 128);
1010 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1011 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
1012 const std::vector<Vec4> colors = generateColors(testParams.numViewports);
1013 const std::vector<UVec4> cells = generateGrid(testParams.numViewports, renderSize);
1014
1015 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
1016
1017 const SharedPtr<Buffer> colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
1018
1019 // Zero buffer.
1020 {
1021 const Allocation alloc = colorBuffer->getBoundMemory();
1022 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1023 flushAlloc(vk, device, alloc);
1024 }
1025
1026 {
1027 context.getTestContext().getLog()
1028 << tcu::TestLog::Message << "Rendering a colorful grid of " << testParams.numViewports << " rectangle(s)." << tcu::TestLog::EndMessage
1029 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
1030 }
1031
1032 // Draw
1033 {
1034 Renderer renderer (context, renderSize, testParams, cells, colorFormat, clearColor, colors, Renderer::TESSELLATION);
1035 renderer.draw(context, colorBuffer->object());
1036 }
1037
1038 // Log image
1039 {
1040 const Allocation alloc = colorBuffer->getBoundMemory();
1041 invalidateAlloc(vk, device, alloc);
1042
1043 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, alloc.getHostPtr());
1044 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, cells, colors);
1045
1046 // Images should now match.
1047 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
1048 TCU_FAIL("Rendered image is not correct");
1049 }
1050
1051 return tcu::TestStatus::pass("OK");
1052 }
1053
checkSupport(Context & context,TestParams params)1054 void checkSupport (Context& context, TestParams params)
1055 {
1056 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
1057 context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
1058
1059 if (context.getDeviceProperties().limits.maxViewports < MIN_MAX_VIEWPORTS)
1060 TCU_FAIL("multiViewport supported but maxViewports is less than the minimum required");
1061
1062 if (params.useTessellationShader)
1063 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1064
1065 if (params.groupParams->useDynamicRendering)
1066 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1067 }
1068
1069 } // anonymous
1070
createShaderViewportIndexTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1071 tcu::TestCaseGroup* createShaderViewportIndexTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
1072 {
1073 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_viewport_index"));
1074
1075 TestParams testParams
1076 {
1077 1, // int numViewports;
1078 false, // bool writeFromVertex;
1079 groupParams, // SharedGroupParams groupParams;
1080 false // bool useTessellationShader;
1081 };
1082
1083 for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
1084 addFunctionCaseWithPrograms(group.get(), "vertex_shader_" + de::toString(testParams.numViewports), checkSupport, initVertexTestPrograms, testVertexShader, testParams);
1085
1086 testParams.numViewports = 1;
1087 addFunctionCaseWithPrograms(group.get(), "fragment_shader_implicit", checkSupport, initFragmentTestPrograms, testFragmentShader, testParams);
1088 testParams.writeFromVertex = true;
1089 for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
1090 addFunctionCaseWithPrograms(group.get(), "fragment_shader_" + de::toString(testParams.numViewports), checkSupport, initFragmentTestPrograms, testFragmentShader, testParams);
1091 testParams.writeFromVertex = false;
1092
1093 testParams.useTessellationShader = true;
1094 for (testParams.numViewports = 1; testParams.numViewports <= MIN_MAX_VIEWPORTS; ++testParams.numViewports)
1095 addFunctionCaseWithPrograms(group.get(), "tessellation_shader_" + de::toString(testParams.numViewports), checkSupport, initTessellationTestPrograms, testTessellationShader, testParams);
1096
1097 return group.release();
1098 }
1099
1100 } // Draw
1101 } // vkt
1102