• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2014 The Android Open Source Project
6  * Copyright (c) 2016 The Khronos Group Inc.
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 Tessellation Miscellaneous Draw Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktTessellationMiscDrawTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTessellationUtil.hpp"
28 
29 #include "tcuTestLog.hpp"
30 #include "tcuImageIO.hpp"
31 #include "tcuTexture.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuImageCompare.hpp"
34 
35 #include "vkDefs.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkImageUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkStrUtil.hpp"
42 #include "vkCmdUtil.hpp"
43 #include "vkObjUtil.hpp"
44 #include "vkBufferWithMemory.hpp"
45 #include "vkImageWithMemory.hpp"
46 
47 #include "deUniquePtr.hpp"
48 #include "deStringUtil.hpp"
49 
50 #include "rrRenderer.hpp"
51 
52 #include <string>
53 #include <vector>
54 #include <utility>
55 
56 namespace vkt
57 {
58 namespace tessellation
59 {
60 
61 using namespace vk;
62 
63 namespace
64 {
65 
66 typedef de::MovePtr<vk::Allocation> AllocationMp;
67 
68 struct CaseDefinition
69 {
70     TessPrimitiveType primitiveType;
71     SpacingMode spacingMode;
72     DrawType drawType;
73     std::string referenceImagePathPrefix; //!< without case suffix and extension (e.g. "_1.png")
74 };
75 
makeCaseDefinition(const TessPrimitiveType primitiveType,const SpacingMode spacingMode,const DrawType drawType,const std::string & referenceImagePathPrefix)76 inline CaseDefinition makeCaseDefinition(const TessPrimitiveType primitiveType, const SpacingMode spacingMode,
77                                          const DrawType drawType, const std::string &referenceImagePathPrefix)
78 {
79     CaseDefinition caseDef;
80     caseDef.primitiveType            = primitiveType;
81     caseDef.spacingMode              = spacingMode;
82     caseDef.drawType                 = drawType;
83     caseDef.referenceImagePathPrefix = referenceImagePathPrefix;
84     return caseDef;
85 }
86 
genTessLevelCases(const SpacingMode spacingMode)87 std::vector<TessLevels> genTessLevelCases(const SpacingMode spacingMode)
88 {
89     static const TessLevels tessLevelCases[] = {
90         {{9.0f, 9.0f}, {9.0f, 9.0f, 9.0f, 9.0f}},
91         {{8.0f, 11.0f}, {13.0f, 15.0f, 18.0f, 21.0f}},
92         {{17.0f, 14.0f}, {3.0f, 6.0f, 9.0f, 12.0f}},
93     };
94 
95     std::vector<TessLevels> resultTessLevels(DE_LENGTH_OF_ARRAY(tessLevelCases));
96 
97     for (int tessLevelCaseNdx = 0; tessLevelCaseNdx < DE_LENGTH_OF_ARRAY(tessLevelCases); ++tessLevelCaseNdx)
98     {
99         TessLevels &tessLevels = resultTessLevels[tessLevelCaseNdx];
100 
101         for (int i = 0; i < 2; ++i)
102             tessLevels.inner[i] =
103                 static_cast<float>(getClampedRoundedTessLevel(spacingMode, tessLevelCases[tessLevelCaseNdx].inner[i]));
104 
105         for (int i = 0; i < 4; ++i)
106             tessLevels.outer[i] =
107                 static_cast<float>(getClampedRoundedTessLevel(spacingMode, tessLevelCases[tessLevelCaseNdx].outer[i]));
108     }
109 
110     return resultTessLevels;
111 }
112 
genVertexPositions(const TessPrimitiveType primitiveType)113 std::vector<tcu::Vec2> genVertexPositions(const TessPrimitiveType primitiveType)
114 {
115     std::vector<tcu::Vec2> positions;
116     positions.reserve(4);
117 
118     if (primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
119     {
120         positions.push_back(tcu::Vec2(0.8f, 0.6f));
121         positions.push_back(tcu::Vec2(0.0f, -0.786f));
122         positions.push_back(tcu::Vec2(-0.8f, 0.6f));
123     }
124     else if (primitiveType == TESSPRIMITIVETYPE_QUADS || primitiveType == TESSPRIMITIVETYPE_ISOLINES)
125     {
126         positions.push_back(tcu::Vec2(-0.8f, -0.8f));
127         positions.push_back(tcu::Vec2(0.8f, -0.8f));
128         positions.push_back(tcu::Vec2(-0.8f, 0.8f));
129         positions.push_back(tcu::Vec2(0.8f, 0.8f));
130     }
131     else
132         DE_ASSERT(false);
133 
134     return positions;
135 }
136 
137 //! Common test function used by all test cases.
runTest(Context & context,const CaseDefinition caseDef)138 tcu::TestStatus runTest(Context &context, const CaseDefinition caseDef)
139 {
140     requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_TESSELLATION_SHADER);
141 
142     const DeviceInterface &vk       = context.getDeviceInterface();
143     const VkDevice device           = context.getDevice();
144     const VkQueue queue             = context.getUniversalQueue();
145     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
146     Allocator &allocator            = context.getDefaultAllocator();
147 
148     const std::vector<TessLevels> tessLevelCases = genTessLevelCases(caseDef.spacingMode);
149     const std::vector<tcu::Vec2> vertexData      = genVertexPositions(caseDef.primitiveType);
150     const uint32_t inPatchSize                   = (caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 3 : 4);
151 
152     // Vertex input: positions
153 
154     const VkFormat vertexFormat            = VK_FORMAT_R32G32_SFLOAT;
155     const uint32_t vertexStride            = tcu::getPixelSize(mapVkFormat(vertexFormat));
156     const VkDeviceSize vertexDataSizeBytes = sizeInBytes(vertexData);
157 
158     const BufferWithMemory vertexBuffer(vk, device, allocator,
159                                         makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
160                                         MemoryRequirement::HostVisible);
161 
162     DE_ASSERT(inPatchSize == vertexData.size());
163     DE_ASSERT(sizeof(vertexData[0]) == vertexStride);
164 
165     {
166         const Allocation &alloc = vertexBuffer.getAllocation();
167 
168         deMemcpy(alloc.getHostPtr(), &vertexData[0], static_cast<std::size_t>(vertexDataSizeBytes));
169         flushAlloc(vk, device, alloc);
170         // No barrier needed, flushed memory is automatically visible
171     }
172 
173     // Indirect buffer
174 
175     const VkDrawIndirectCommand drawIndirectArgs{
176         inPatchSize, // uint32_t vertexCount;
177         1u,          // uint32_t instanceCount;
178         0u,          // uint32_t firstVertex;
179         0u,          // uint32_t firstInstance;
180     };
181 
182     const BufferWithMemory indirectBuffer(
183         vk, device, allocator, makeBufferCreateInfo(sizeof(drawIndirectArgs), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
184         MemoryRequirement::HostVisible);
185 
186     {
187         const Allocation &alloc = indirectBuffer.getAllocation();
188 
189         deMemcpy(alloc.getHostPtr(), &drawIndirectArgs, sizeof(drawIndirectArgs));
190         flushAlloc(vk, device, alloc);
191         // No barrier needed, flushed memory is automatically visible
192     }
193 
194     // Color attachment
195 
196     const tcu::IVec2 renderSize = tcu::IVec2(256, 256);
197     const VkFormat colorFormat  = VK_FORMAT_R8G8B8A8_UNORM;
198     const VkImageSubresourceRange colorImageSubresourceRange =
199         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
200     const ImageWithMemory colorAttachmentImage(
201         vk, device, allocator,
202         makeImageCreateInfo(renderSize, colorFormat,
203                             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 1u),
204         MemoryRequirement::Any);
205 
206     // Color output buffer: image will be copied here for verification
207 
208     const VkDeviceSize colorBufferSizeBytes =
209         renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
210     const BufferWithMemory colorBuffer(vk, device, allocator,
211                                        makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT),
212                                        MemoryRequirement::HostVisible);
213 
214     // Input buffer: tessellation levels. Data is filled in later.
215 
216     const BufferWithMemory tessLevelsBuffer(
217         vk, device, allocator, makeBufferCreateInfo(sizeof(TessLevels), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
218         MemoryRequirement::HostVisible);
219 
220     // Descriptors
221 
222     const Unique<VkDescriptorSetLayout> descriptorSetLayout(
223         DescriptorSetLayoutBuilder()
224             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
225                               VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
226             .build(vk, device));
227 
228     const Unique<VkDescriptorPool> descriptorPool(
229         DescriptorPoolBuilder()
230             .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
231             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
232 
233     const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
234 
235     const VkDescriptorBufferInfo tessLevelsBufferInfo =
236         makeDescriptorBufferInfo(tessLevelsBuffer.get(), 0ull, sizeof(TessLevels));
237 
238     DescriptorSetUpdateBuilder()
239         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
240                      VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &tessLevelsBufferInfo)
241         .update(vk, device);
242 
243     // Pipeline
244 
245     const Unique<VkImageView> colorAttachmentView(makeImageView(
246         vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorImageSubresourceRange));
247     const Unique<VkRenderPass> renderPass(makeRenderPass(vk, device, colorFormat));
248     const Unique<VkFramebuffer> framebuffer(
249         makeFramebuffer(vk, device, *renderPass, *colorAttachmentView, renderSize.x(), renderSize.y()));
250     const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
251     const Unique<VkCommandPool> cmdPool(makeCommandPool(vk, device, queueFamilyIndex));
252     const Unique<VkCommandBuffer> cmdBuffer(
253         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
254 
255     const Unique<VkPipeline> pipeline(
256         GraphicsPipelineBuilder()
257             .setRenderSize(renderSize)
258             .setVertexInputSingleAttribute(vertexFormat, vertexStride)
259             .setPatchControlPoints(inPatchSize)
260             .setShader(vk, device, VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get("vert"), nullptr)
261             .setShader(vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, context.getBinaryCollection().get("tesc"),
262                        nullptr)
263             .setShader(vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
264                        context.getBinaryCollection().get("tese"), nullptr)
265             .setShader(vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get("frag"), nullptr)
266             .build(vk, device, *pipelineLayout, *renderPass));
267 
268     // Draw commands
269 
270     uint32_t numPassedCases = 0;
271 
272     for (uint32_t tessLevelCaseNdx = 0; tessLevelCaseNdx < tessLevelCases.size(); ++tessLevelCaseNdx)
273     {
274         context.getTestContext().getLog()
275             << tcu::TestLog::Message << "Tessellation levels: "
276             << getTessellationLevelsString(tessLevelCases[tessLevelCaseNdx], caseDef.primitiveType)
277             << tcu::TestLog::EndMessage;
278 
279         // Upload tessellation levels data to the input buffer
280         {
281             const Allocation &alloc            = tessLevelsBuffer.getAllocation();
282             TessLevels *const bufferTessLevels = static_cast<TessLevels *>(alloc.getHostPtr());
283 
284             *bufferTessLevels = tessLevelCases[tessLevelCaseNdx];
285             flushAlloc(vk, device, alloc);
286         }
287 
288         // Reset the command buffer and begin recording.
289         beginCommandBuffer(vk, *cmdBuffer);
290 
291         // Change color attachment image layout
292         {
293             // State is slightly different on the first iteration.
294             const VkImageLayout currentLayout =
295                 (tessLevelCaseNdx == 0 ? VK_IMAGE_LAYOUT_UNDEFINED : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
296             const VkAccessFlags srcFlags =
297                 (tessLevelCaseNdx == 0 ? (VkAccessFlags)0 : (VkAccessFlags)VK_ACCESS_TRANSFER_READ_BIT);
298 
299             const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
300                 srcFlags, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, currentLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
301                 *colorAttachmentImage, colorImageSubresourceRange);
302 
303             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
304                                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u,
305                                   &colorAttachmentLayoutBarrier);
306         }
307 
308         // Begin render pass
309         {
310             const VkRect2D renderArea = makeRect2D(renderSize);
311             const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
312 
313             beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
314         }
315 
316         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
317         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
318                                  &descriptorSet.get(), 0u, nullptr);
319         {
320             const VkDeviceSize vertexBufferOffset = 0ull;
321             vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
322         }
323 
324         // Process enough vertices to make a patch.
325         if (caseDef.drawType == DRAWTYPE_DRAW)
326             vk.cmdDraw(*cmdBuffer, inPatchSize, 1u, 0u, 0u);
327         else                                                                  // DRAWTYPE_DRAW_INDIRECT
328             vk.cmdDrawIndirect(*cmdBuffer, indirectBuffer.get(), 0u, 1u, 0u); // Stride is ignored
329         endRenderPass(vk, *cmdBuffer);
330 
331         // Copy render result to a host-visible buffer
332         copyImageToBuffer(vk, *cmdBuffer, *colorAttachmentImage, *colorBuffer, renderSize);
333 
334         endCommandBuffer(vk, *cmdBuffer);
335         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
336 
337         {
338             const Allocation &colorBufferAlloc = colorBuffer.getAllocation();
339 
340             invalidateAlloc(vk, device, colorBufferAlloc);
341 
342             // Verify case result
343             const tcu::ConstPixelBufferAccess resultImageAccess(mapVkFormat(colorFormat), renderSize.x(),
344                                                                 renderSize.y(), 1, colorBufferAlloc.getHostPtr());
345 
346             // Load reference image
347             const std::string referenceImagePath =
348                 caseDef.referenceImagePathPrefix + "_" + de::toString(tessLevelCaseNdx) + ".png";
349 
350             tcu::TextureLevel referenceImage;
351             tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), referenceImagePath.c_str());
352 
353             if (tcu::fuzzyCompare(context.getTestContext().getLog(), "ImageComparison", "Image Comparison",
354                                   referenceImage.getAccess(), resultImageAccess, 0.002f, tcu::COMPARE_LOG_RESULT))
355                 ++numPassedCases;
356         }
357     } // tessLevelCaseNdx
358 
359     return (numPassedCases == tessLevelCases.size() ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Failure"));
360 }
361 
getTessLevelsSSBODeclaration(void)362 inline const char *getTessLevelsSSBODeclaration(void)
363 {
364     return "layout(set = 0, binding = 0, std430) readonly restrict buffer TessLevels {\n"
365            "    float inner0;\n"
366            "    float inner1;\n"
367            "    float outer0;\n"
368            "    float outer1;\n"
369            "    float outer2;\n"
370            "    float outer3;\n"
371            "} sb_levels;\n";
372 }
373 
374 //! Add vertex, fragment, and tessellation control shaders.
initCommonPrograms(vk::SourceCollections & programCollection,const CaseDefinition caseDef)375 void initCommonPrograms(vk::SourceCollections &programCollection, const CaseDefinition caseDef)
376 {
377     DE_ASSERT(!programCollection.glslSources.contains("vert"));
378     DE_ASSERT(!programCollection.glslSources.contains("tesc"));
379     DE_ASSERT(!programCollection.glslSources.contains("frag"));
380 
381     // Vertex shader
382     {
383         std::ostringstream src;
384         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
385             << "\n"
386             << "layout(location = 0) in  highp vec2 in_v_position;\n"
387             << "layout(location = 0) out highp vec2 in_tc_position;\n"
388             << "\n"
389             << "void main (void)\n"
390             << "{\n"
391             << "    in_tc_position = in_v_position;\n"
392             << "}\n";
393 
394         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
395     }
396 
397     // Tessellation control shader
398     {
399         const int numVertices = (caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 3 : 4);
400 
401         std::ostringstream src;
402         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
403             << "#extension GL_EXT_tessellation_shader : require\n"
404             << "\n"
405             << "layout(vertices = " << numVertices << ") out;\n"
406             << "\n"
407             << getTessLevelsSSBODeclaration() << "\n"
408             << "layout(location = 0) in  highp vec2 in_tc_position[];\n"
409             << "layout(location = 0) out highp vec2 in_te_position[];\n"
410             << "\n"
411             << "void main (void)\n"
412             << "{\n"
413             << "    in_te_position[gl_InvocationID] = in_tc_position[gl_InvocationID];\n"
414             << "\n"
415             << "    gl_TessLevelInner[0] = sb_levels.inner0;\n"
416             << "    gl_TessLevelInner[1] = sb_levels.inner1;\n"
417             << "\n"
418             << "    gl_TessLevelOuter[0] = sb_levels.outer0;\n"
419             << "    gl_TessLevelOuter[1] = sb_levels.outer1;\n"
420             << "    gl_TessLevelOuter[2] = sb_levels.outer2;\n"
421             << "    gl_TessLevelOuter[3] = sb_levels.outer3;\n"
422             << "}\n";
423 
424         programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
425     }
426 
427     // Fragment shader
428     {
429         std::ostringstream src;
430         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
431             << "\n"
432             << "layout(location = 0) in  highp   vec4 in_f_color;\n"
433             << "layout(location = 0) out mediump vec4 o_color;\n"
434             << "\n"
435             << "void main (void)\n"
436             << "{\n"
437             << "    o_color = in_f_color;\n"
438             << "}\n";
439 
440         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
441     }
442 }
443 
initProgramsFillCoverCase(vk::SourceCollections & programCollection,const CaseDefinition caseDef)444 void initProgramsFillCoverCase(vk::SourceCollections &programCollection, const CaseDefinition caseDef)
445 {
446     DE_ASSERT(caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES || caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS);
447 
448     initCommonPrograms(programCollection, caseDef);
449 
450     // Tessellation evaluation shader
451     {
452         std::ostringstream src;
453         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
454             << "#extension GL_EXT_tessellation_shader : require\n"
455             << "\n"
456             << "layout(" << getTessPrimitiveTypeShaderName(caseDef.primitiveType) << ", "
457             << getSpacingModeShaderName(caseDef.spacingMode) << ") in;\n"
458             << "\n"
459             << "layout(location = 0) in  highp vec2 in_te_position[];\n"
460             << "layout(location = 0) out highp vec4 in_f_color;\n"
461             << "\n"
462             << "void main (void)\n"
463             << "{\n"
464             << (caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES ?
465                     "    highp float d = 3.0 * min(gl_TessCoord.x, min(gl_TessCoord.y, gl_TessCoord.z));\n"
466                     "    highp vec2 corner0 = in_te_position[0];\n"
467                     "    highp vec2 corner1 = in_te_position[1];\n"
468                     "    highp vec2 corner2 = in_te_position[2];\n"
469                     "    highp vec2 pos =  corner0*gl_TessCoord.x + corner1*gl_TessCoord.y + corner2*gl_TessCoord.z;\n"
470                     "    highp vec2 fromCenter = pos - (corner0 + corner1 + corner2) / 3.0;\n"
471                     "    highp float f = (1.0 - length(fromCenter)) * (1.5 - d);\n"
472                     "    pos += 0.75 * f * fromCenter / (length(fromCenter) + 0.3);\n"
473                     "    gl_Position = vec4(pos, 0.0, 1.0);\n" :
474                 caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS ?
475                     "    highp vec2 corner0 = in_te_position[0];\n"
476                     "    highp vec2 corner1 = in_te_position[1];\n"
477                     "    highp vec2 corner2 = in_te_position[2];\n"
478                     "    highp vec2 corner3 = in_te_position[3];\n"
479                     "    highp vec2 pos = (1.0-gl_TessCoord.x)*(1.0-gl_TessCoord.y)*corner0\n"
480                     "                   + (    gl_TessCoord.x)*(1.0-gl_TessCoord.y)*corner1\n"
481                     "                   + (1.0-gl_TessCoord.x)*(    gl_TessCoord.y)*corner2\n"
482                     "                   + (    gl_TessCoord.x)*(    gl_TessCoord.y)*corner3;\n"
483                     "    highp float d = 2.0 * min(abs(gl_TessCoord.x-0.5), abs(gl_TessCoord.y-0.5));\n"
484                     "    highp vec2 fromCenter = pos - (corner0 + corner1 + corner2 + corner3) / 4.0;\n"
485                     "    highp float f = (1.0 - length(fromCenter)) * sqrt(1.7 - d);\n"
486                     "    pos += 0.75 * f * fromCenter / (length(fromCenter) + 0.3);\n"
487                     "    gl_Position = vec4(pos, 0.0, 1.0);\n" :
488                     "")
489             << "    in_f_color = vec4(1.0);\n"
490             << "}\n";
491 
492         programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
493     }
494 }
495 
initProgramsFillNonOverlapCase(vk::SourceCollections & programCollection,const CaseDefinition caseDef)496 void initProgramsFillNonOverlapCase(vk::SourceCollections &programCollection, const CaseDefinition caseDef)
497 {
498     DE_ASSERT(caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES || caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS);
499 
500     initCommonPrograms(programCollection, caseDef);
501 
502     // Tessellation evaluation shader
503     {
504         std::ostringstream src;
505         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
506             << "#extension GL_EXT_tessellation_shader : require\n"
507             << "\n"
508             << "layout(" << getTessPrimitiveTypeShaderName(caseDef.primitiveType) << ", "
509             << getSpacingModeShaderName(caseDef.spacingMode) << ") in;\n"
510             << "\n"
511             << getTessLevelsSSBODeclaration() << "\n"
512             << "layout(location = 0) in  highp vec2 in_te_position[];\n"
513             << "layout(location = 0) out highp vec4 in_f_color;\n"
514             << "\n"
515             << "void main (void)\n"
516             << "{\n"
517             << (caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES ?
518                     "    highp vec2 corner0 = in_te_position[0];\n"
519                     "    highp vec2 corner1 = in_te_position[1];\n"
520                     "    highp vec2 corner2 = in_te_position[2];\n"
521                     "    highp vec2 pos =  corner0*gl_TessCoord.x + corner1*gl_TessCoord.y + corner2*gl_TessCoord.z;\n"
522                     "    gl_Position = vec4(pos, 0.0, 1.0);\n"
523                     "    highp int numConcentricTriangles = int(round(sb_levels.inner0)) / 2 + 1;\n"
524                     "    highp float d = 3.0 * min(gl_TessCoord.x, min(gl_TessCoord.y, gl_TessCoord.z));\n"
525                     "    highp int phase = int(d*float(numConcentricTriangles)) % 3;\n"
526                     "    in_f_color = phase == 0 ? vec4(1.0, 0.0, 0.0, 1.0)\n"
527                     "               : phase == 1 ? vec4(0.0, 1.0, 0.0, 1.0)\n"
528                     "               :              vec4(0.0, 0.0, 1.0, 1.0);\n" :
529                 caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS ?
530                     "    highp vec2 corner0 = in_te_position[0];\n"
531                     "    highp vec2 corner1 = in_te_position[1];\n"
532                     "    highp vec2 corner2 = in_te_position[2];\n"
533                     "    highp vec2 corner3 = in_te_position[3];\n"
534                     "    highp vec2 pos = (1.0-gl_TessCoord.x)*(1.0-gl_TessCoord.y)*corner0\n"
535                     "                   + (    gl_TessCoord.x)*(1.0-gl_TessCoord.y)*corner1\n"
536                     "                   + (1.0-gl_TessCoord.x)*(    gl_TessCoord.y)*corner2\n"
537                     "                   + (    gl_TessCoord.x)*(    gl_TessCoord.y)*corner3;\n"
538                     "    gl_Position = vec4(pos, 0.0, 1.0);\n"
539                     "    highp int phaseX = int(round((0.5 - abs(gl_TessCoord.x-0.5)) * sb_levels.inner0));\n"
540                     "    highp int phaseY = int(round((0.5 - abs(gl_TessCoord.y-0.5)) * sb_levels.inner1));\n"
541                     "    highp int phase = min(phaseX, phaseY) % 3;\n"
542                     "    in_f_color = phase == 0 ? vec4(1.0, 0.0, 0.0, 1.0)\n"
543                     "               : phase == 1 ? vec4(0.0, 1.0, 0.0, 1.0)\n"
544                     "               :              vec4(0.0, 0.0, 1.0, 1.0);\n" :
545                     "")
546             << "}\n";
547 
548         programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
549     }
550 }
551 
initProgramsIsolinesCase(vk::SourceCollections & programCollection,const CaseDefinition caseDef)552 void initProgramsIsolinesCase(vk::SourceCollections &programCollection, const CaseDefinition caseDef)
553 {
554     DE_ASSERT(caseDef.primitiveType == TESSPRIMITIVETYPE_ISOLINES);
555 
556     initCommonPrograms(programCollection, caseDef);
557 
558     // Tessellation evaluation shader
559     {
560         std::ostringstream src;
561         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
562             << "#extension GL_EXT_tessellation_shader : require\n"
563             << "\n"
564             << "layout(" << getTessPrimitiveTypeShaderName(caseDef.primitiveType) << ", "
565             << getSpacingModeShaderName(caseDef.spacingMode) << ") in;\n"
566             << "\n"
567             << getTessLevelsSSBODeclaration() << "\n"
568             << "layout(location = 0) in  highp vec2 in_te_position[];\n"
569             << "layout(location = 0) out highp vec4 in_f_color;\n"
570             << "\n"
571             << "void main (void)\n"
572             << "{\n"
573             << "    highp vec2 corner0 = in_te_position[0];\n"
574             << "    highp vec2 corner1 = in_te_position[1];\n"
575             << "    highp vec2 corner2 = in_te_position[2];\n"
576             << "    highp vec2 corner3 = in_te_position[3];\n"
577             << "    highp vec2 pos = (1.0-gl_TessCoord.x)*(1.0-gl_TessCoord.y)*corner0\n"
578             << "                   + (    gl_TessCoord.x)*(1.0-gl_TessCoord.y)*corner1\n"
579             << "                   + (1.0-gl_TessCoord.x)*(    gl_TessCoord.y)*corner2\n"
580             << "                   + (    gl_TessCoord.x)*(    gl_TessCoord.y)*corner3;\n"
581             << "    pos.y += 0.15*sin(gl_TessCoord.x*10.0);\n"
582             << "    gl_Position = vec4(pos, 0.0, 1.0);\n"
583             << "    highp int phaseX = int(round(gl_TessCoord.x*sb_levels.outer1));\n"
584             << "    highp int phaseY = int(round(gl_TessCoord.y*sb_levels.outer0));\n"
585             << "    highp int phase = (phaseX + phaseY) % 3;\n"
586             << "    in_f_color = phase == 0 ? vec4(1.0, 0.0, 0.0, 1.0)\n"
587             << "               : phase == 1 ? vec4(0.0, 1.0, 0.0, 1.0)\n"
588             << "               :              vec4(0.0, 0.0, 1.0, 1.0);\n"
589             << "}\n";
590 
591         programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
592     }
593 }
594 
getReferenceImagePathPrefix(const std::string & caseName)595 inline std::string getReferenceImagePathPrefix(const std::string &caseName)
596 {
597     return "vulkan/data/tessellation/" + caseName + "_ref";
598 }
599 
600 struct TessStateSwitchParams
601 {
602     const std::pair<TessPrimitiveType, TessPrimitiveType> patchTypes;
603     const std::pair<SpacingMode, SpacingMode> spacing;
604     const std::pair<VkTessellationDomainOrigin, VkTessellationDomainOrigin> domainOrigin;
605     const bool geometryShader;
606 
nonDefaultDomainOriginvkt::tessellation::__anonbc6b7a940111::TessStateSwitchParams607     bool nonDefaultDomainOrigin(void) const
608     {
609         return (domainOrigin.first != VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT ||
610                 domainOrigin.second != VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT);
611     }
612 };
613 
614 class TessStateSwitchInstance : public vkt::TestInstance
615 {
616 public:
TessStateSwitchInstance(Context & context,const TessStateSwitchParams & params)617     TessStateSwitchInstance(Context &context, const TessStateSwitchParams &params)
618         : vkt::TestInstance(context)
619         , m_params(params)
620     {
621     }
622 
~TessStateSwitchInstance(void)623     virtual ~TessStateSwitchInstance(void)
624     {
625     }
626 
627     tcu::TestStatus iterate(void);
628 
629 protected:
630     const TessStateSwitchParams m_params;
631 };
632 
633 class TessStateSwitchCase : public vkt::TestCase
634 {
635 public:
TessStateSwitchCase(tcu::TestContext & testCtx,const std::string & name,const TessStateSwitchParams & params)636     TessStateSwitchCase(tcu::TestContext &testCtx, const std::string &name, const TessStateSwitchParams &params)
637         : vkt::TestCase(testCtx, name)
638         , m_params(params)
639     {
640     }
641 
~TessStateSwitchCase(void)642     virtual ~TessStateSwitchCase(void)
643     {
644     }
645 
646     void checkSupport(Context &context) const;
647     void initPrograms(vk::SourceCollections &programCollection) const;
createInstance(Context & context) const648     TestInstance *createInstance(Context &context) const
649     {
650         return new TessStateSwitchInstance(context, m_params);
651     }
652 
653 protected:
654     const TessStateSwitchParams m_params;
655 };
656 
checkSupport(Context & context) const657 void TessStateSwitchCase::checkSupport(Context &context) const
658 {
659     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
660 
661     if (m_params.geometryShader)
662         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
663 
664     if (m_params.nonDefaultDomainOrigin())
665         context.requireDeviceFunctionality("VK_KHR_maintenance2");
666 }
667 
initPrograms(vk::SourceCollections & programCollection) const668 void TessStateSwitchCase::initPrograms(vk::SourceCollections &programCollection) const
669 {
670     std::ostringstream vert;
671     vert << "#version 460\n"
672          << "layout (location=0) in vec4 inPos;\n"
673          << "layout (push_constant, std430) uniform PushConstantBlock { vec2 offset; } pc;\n"
674          << "out gl_PerVertex\n"
675          << "{\n"
676          << "  vec4 gl_Position;\n"
677          << "};\n"
678          << "void main() {\n"
679          << "    gl_Position = inPos + vec4(pc.offset, 0.0, 0.0);\n"
680          << "}\n";
681     programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
682 
683     if (m_params.geometryShader)
684     {
685         std::ostringstream geom;
686         geom << "#version 460\n"
687              << "layout (triangles) in;\n"
688              << "layout (triangle_strip, max_vertices=3) out;\n"
689              << "in gl_PerVertex\n"
690              << "{\n"
691              << "    vec4 gl_Position;\n"
692              << "} gl_in[3];\n"
693              << "out gl_PerVertex\n"
694              << "{\n"
695              << "    vec4 gl_Position;\n"
696              << "};\n"
697              << "void main() {\n"
698              << "    gl_Position    = gl_in[0].gl_Position; EmitVertex();\n"
699              << "    gl_Position    = gl_in[1].gl_Position; EmitVertex();\n"
700              << "    gl_Position    = gl_in[2].gl_Position; EmitVertex();\n"
701              << "    gl_PrimitiveID = gl_PrimitiveIDIn;     EndPrimitive();\n"
702              << "}\n";
703         programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
704     }
705 
706     const auto even       = (m_params.spacing.second == SPACINGMODE_FRACTIONAL_EVEN);
707     const auto extraLevel = (even ? "1.0" : "0.0");
708 
709     std::ostringstream tesc;
710     tesc << "#version 460\n"
711          << "layout (vertices=4) out;\n"
712          << "in gl_PerVertex\n"
713          << "{\n"
714          << "  vec4 gl_Position;\n"
715          << "} gl_in[gl_MaxPatchVertices];\n"
716          << "out gl_PerVertex\n"
717          << "{\n"
718          << "  vec4 gl_Position;\n"
719          << "} gl_out[];\n"
720          << "void main() {\n"
721          << "    const float extraLevel = " << extraLevel << ";\n"
722          << "    gl_TessLevelInner[0] = 10.0 + extraLevel;\n"
723          << "    gl_TessLevelInner[1] = 10.0 + extraLevel;\n"
724          << "    gl_TessLevelOuter[0] = 50.0 + extraLevel;\n"
725          << "    gl_TessLevelOuter[1] = 40.0 + extraLevel;\n"
726          << "    gl_TessLevelOuter[2] = 30.0 + extraLevel;\n"
727          << "    gl_TessLevelOuter[3] = 20.0 + extraLevel;\n"
728          << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
729          << "}\n";
730     programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
731 
732     for (uint32_t i = 0u; i < 2u; ++i)
733     {
734         const auto &primType = ((i == 0u) ? m_params.patchTypes.first : m_params.patchTypes.second);
735         const auto &spacing  = ((i == 0u) ? m_params.spacing.first : m_params.spacing.second);
736 
737         std::ostringstream tese;
738         tese << "#version 460\n"
739              << "layout (" << getTessPrimitiveTypeShaderName(primType) << ", " << getSpacingModeShaderName(spacing)
740              << ", ccw) in;\n"
741              << "in gl_PerVertex\n"
742              << "{\n"
743              << "  vec4 gl_Position;\n"
744              << "} gl_in[gl_MaxPatchVertices];\n"
745              << "out gl_PerVertex\n"
746              << "{\n"
747              << "  vec4 gl_Position;\n"
748              << "};\n"
749              << "\n"
750              << "// This assumes 2D, calculates barycentrics for point p inside triangle (a, b, c)\n"
751              << "vec3 calcBaryCoords(vec2 p, vec2 a, vec2 b, vec2 c)\n"
752              << "{\n"
753              << "    const vec2 v0 = b - a;\n"
754              << "    const vec2 v1 = c - a;\n"
755              << "    const vec2 v2 = p - a;\n"
756              << "\n"
757              << "    const float den = v0.x * v1.y - v1.x * v0.y;\n"
758              << "    const float v   = (v2.x * v1.y - v1.x * v2.y) / den;\n"
759              << "    const float w   = (v0.x * v2.y - v2.x * v0.y) / den;\n"
760              << "    const float u   = 1.0 - v - w;\n"
761              << "\n"
762              << "    return vec3(u, v, w);\n"
763              << "}\n"
764              << "\n"
765              << "void main() {\n"
766              << ((primType == TESSPRIMITIVETYPE_QUADS)
767                      // For quads.
768                      ?
769                      "    const float u = gl_TessCoord.x;\n"
770                      "    const float v = gl_TessCoord.y;\n"
771                      "    gl_Position = (1 - u) * (1 - v) * gl_in[0].gl_Position + (1 - u) * v * gl_in[1].gl_Position "
772                      "+ u * (1 - v) * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position;\n"
773                      // For triangles.
774                      :
775                      "    // We have a patch with 4 corners (v0,v1,v2,v3), but triangle-based tessellation.\n"
776                      "    // Lets suppose the triangle covers half the patch (triangle v0,v2,v1).\n"
777                      "    // Expand the triangle by virtually grabbing it from the midpoint between v1 and v2 (which "
778                      "should fall in the middle of the patch) and stretching that point to the fourth corner (v3).\n"
779                      "    const vec4 origpoint = (gl_TessCoord.x * gl_in[0].gl_Position) +\n"
780                      "                           (gl_TessCoord.y * gl_in[2].gl_Position) +\n"
781                      "                           (gl_TessCoord.z * gl_in[1].gl_Position);\n"
782                      "    const vec4 midpoint = 0.5 * gl_in[1].gl_Position + 0.5 * gl_in[2].gl_Position;\n"
783                      "\n"
784                      "    // Find out if it falls on left or right side of the triangle.\n"
785                      "    vec4 halfTriangle[3];\n"
786                      "    vec4 stretchedHalf[3];\n"
787                      "\n"
788                      "    if (gl_TessCoord.z >= gl_TessCoord.y)\n"
789                      "    {\n"
790                      "        halfTriangle[0] = gl_in[0].gl_Position;\n"
791                      "        halfTriangle[1] = midpoint;\n"
792                      "        halfTriangle[2] = gl_in[1].gl_Position;\n"
793                      "\n"
794                      "        stretchedHalf[0] = gl_in[0].gl_Position;\n"
795                      "        stretchedHalf[1] = gl_in[3].gl_Position;\n"
796                      "        stretchedHalf[2] = gl_in[1].gl_Position;\n"
797                      "    }\n"
798                      "    else\n"
799                      "    {\n"
800                      "        halfTriangle[0] = gl_in[0].gl_Position;\n"
801                      "        halfTriangle[1] = gl_in[2].gl_Position;\n"
802                      "        halfTriangle[2] = midpoint;\n"
803                      "\n"
804                      "        stretchedHalf[0] = gl_in[0].gl_Position;\n"
805                      "        stretchedHalf[1] = gl_in[2].gl_Position;\n"
806                      "        stretchedHalf[2] = gl_in[3].gl_Position;\n"
807                      "    }\n"
808                      "\n"
809                      "    // Calculate the barycentric coordinates for the left or right sides.\n"
810                      "    vec3 sideBaryCoord = calcBaryCoords(origpoint.xy, halfTriangle[0].xy, halfTriangle[1].xy, "
811                      "halfTriangle[2].xy);\n"
812                      "\n"
813                      "    // Move the point by stretching the half triangle and dragging the midpoint vertex to v3.\n"
814                      "    gl_Position = sideBaryCoord.x * stretchedHalf[0] + sideBaryCoord.y * stretchedHalf[1] + "
815                      "sideBaryCoord.z * stretchedHalf[2];\n")
816              << "}\n";
817         programCollection.glslSources.add("tese" + std::to_string(i)) << glu::TessellationEvaluationSource(tese.str());
818     }
819 
820     std::ostringstream frag;
821     frag << "#version 460\n"
822          << "layout (location=0) out vec4 outColor;\n"
823          << "void main() {\n"
824          << "    outColor = vec4(0.5, 0.5, 0.5, 1.0);\n"
825          << "}\n";
826     programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
827 }
828 
iterate(void)829 tcu::TestStatus TessStateSwitchInstance::iterate(void)
830 {
831     const auto &ctx = m_context.getContextCommonData();
832     const tcu::IVec3 fbExtent(128, 128, 1);
833     const auto vkExtent    = makeExtent3D(fbExtent);
834     const auto colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
835     const auto tcuFormat   = mapVkFormat(colorFormat);
836     const auto colorUsage  = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
837     const auto imageType   = VK_IMAGE_TYPE_2D;
838     const auto colorSRR    = makeDefaultImageSubresourceRange();
839     const auto bindPoint   = VK_PIPELINE_BIND_POINT_GRAPHICS;
840 
841     ImageWithBuffer referenceBuffer(ctx.vkd, ctx.device, ctx.allocator, vkExtent, colorFormat, colorUsage, imageType,
842                                     colorSRR);
843     ImageWithBuffer resultBuffer(ctx.vkd, ctx.device, ctx.allocator, vkExtent, colorFormat, colorUsage, imageType,
844                                  colorSRR);
845 
846     // Vertex buffer containing a single full-screen patch.
847     const std::vector<tcu::Vec4> vertices{
848         tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
849         tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
850         tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f),
851         tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
852     };
853     const auto vertexCount        = de::sizeU32(vertices);
854     const auto patchControlPoints = vertexCount;
855 
856     const auto vertexBufferSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
857     const auto vertexBufferInfo = makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
858     BufferWithMemory vertexBuffer(ctx.vkd, ctx.device, ctx.allocator, vertexBufferInfo, MemoryRequirement::HostVisible);
859     auto &vertexBufferAlloc       = vertexBuffer.getAllocation();
860     void *vertexBufferData        = vertexBufferAlloc.getHostPtr();
861     const auto vertexBufferOffset = static_cast<VkDeviceSize>(0);
862 
863     deMemcpy(vertexBufferData, de::dataOrNull(vertices), de::dataSize(vertices));
864     flushAlloc(ctx.vkd, ctx.device, vertexBufferAlloc);
865 
866     const auto pcSize   = static_cast<uint32_t>(sizeof(tcu::Vec2));
867     const auto pcStages = static_cast<VkShaderStageFlags>(VK_SHADER_STAGE_VERTEX_BIT);
868     const auto pcRange  = makePushConstantRange(pcStages, 0u, pcSize);
869 
870     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, VK_NULL_HANDLE, &pcRange);
871 
872     const auto renderPass = makeRenderPass(ctx.vkd, ctx.device, colorFormat);
873 
874     // Framebuffers.
875     const auto framebuffer0 = makeFramebuffer(ctx.vkd, ctx.device, *renderPass, referenceBuffer.getImageView(),
876                                               vkExtent.width, vkExtent.height);
877     const auto framebuffer1 =
878         makeFramebuffer(ctx.vkd, ctx.device, *renderPass, resultBuffer.getImageView(), vkExtent.width, vkExtent.height);
879 
880     // Viewport and scissor.
881     const std::vector<VkViewport> viewports(1u, makeViewport(fbExtent));
882     const std::vector<VkRect2D> scissors(1u, makeRect2D(fbExtent));
883 
884     // Shaders.
885     const auto &binaries   = m_context.getBinaryCollection();
886     const auto vertModule  = createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
887     const auto tescModule  = createShaderModule(ctx.vkd, ctx.device, binaries.get("tesc"));
888     const auto teseModule0 = createShaderModule(ctx.vkd, ctx.device, binaries.get("tese0"));
889     const auto teseModule1 = createShaderModule(ctx.vkd, ctx.device, binaries.get("tese1"));
890     const auto geomModule  = (m_params.geometryShader ? createShaderModule(ctx.vkd, ctx.device, binaries.get("geom")) :
891                                                         Move<VkShaderModule>());
892     const auto fragModule  = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag"));
893 
894     const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
895         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
896         nullptr,                                                     // const void* pNext;
897         0u,                                                          // VkPipelineInputAssemblyStateCreateFlags flags;
898         VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,                            // VkPrimitiveTopology topology;
899         VK_FALSE,                                                    // VkBool32 primitiveRestartEnable;
900     };
901 
902     VkPipelineTessellationDomainOriginStateCreateInfo domainOriginStateCreateInfo = {
903         VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, // VkStructureType sType;
904         nullptr,                                                                 // const void* pNext;
905         m_params.domainOrigin.first, // VkTessellationDomainOrigin domainOrigin;
906     };
907 
908     const auto tessPNext = (m_params.nonDefaultDomainOrigin() ? &domainOriginStateCreateInfo : nullptr);
909     const VkPipelineTessellationStateCreateInfo tessellationStateCreateInfo = {
910         VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
911         tessPNext,                                                 // const void* pNext;
912         0u,                                                        // VkPipelineTessellationStateCreateFlags flags;
913         patchControlPoints,                                        // uint32_t patchControlPoints;
914     };
915 
916     const VkPipelineViewportStateCreateInfo viewportStateCreateInfo = {
917         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
918         nullptr,                                               // const void* pNext;
919         0u,                                                    // VkPipelineViewportStateCreateFlags flags;
920         de::sizeU32(viewports),                                // uint32_t viewportCount;
921         de::dataOrNull(viewports),                             // const VkViewport* pViewports;
922         de::sizeU32(scissors),                                 // uint32_t scissorCount;
923         de::dataOrNull(scissors),                              // const VkRect2D* pScissors;
924     };
925 
926     // In the rasterization parameters, use wireframe mode to see each triangle if possible.
927     // This makes the test harder to pass by mistake.
928     // We also cull back faces, which will help test domain origin.
929     // The front face changes with the domain origin.
930     const auto frontFace =
931         ((m_params.domainOrigin.second == VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT) ?
932              VK_FRONT_FACE_COUNTER_CLOCKWISE // With the default value it's as specified in the shader.
933              :
934              VK_FRONT_FACE_CLOCKWISE); // Otherwise the winding order changes.
935     const auto polygonMode =
936         ((m_context.getDeviceFeatures().fillModeNonSolid) ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL);
937     const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
938         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
939         nullptr,                                                    // const void* pNext;
940         0u,                                                         // VkPipelineRasterizationStateCreateFlags flags;
941         VK_FALSE,                                                   // VkBool32 depthClampEnable;
942         VK_FALSE,                                                   // VkBool32 rasterizerDiscardEnable;
943         polygonMode,                                                // VkPolygonMode polygonMode;
944         VK_CULL_MODE_BACK_BIT,                                      // VkCullModeFlags cullMode;
945         frontFace,                                                  // VkFrontFace frontFace;
946         VK_FALSE,                                                   // VkBool32 depthBiasEnable;
947         0.0f,                                                       // float depthBiasConstantFactor;
948         0.0f,                                                       // float depthBiasClamp;
949         0.0f,                                                       // float depthBiasSlopeFactor;
950         1.0f,                                                       // float lineWidth;
951     };
952 
953     // Create two pipelines varying the tessellation evaluation module.
954     const auto pipeline0 =
955         makeGraphicsPipeline(ctx.vkd, ctx.device, *pipelineLayout, *vertModule, *tescModule, *teseModule0, *geomModule,
956                              *fragModule, *renderPass, 0u, nullptr, &inputAssemblyStateCreateInfo,
957                              &tessellationStateCreateInfo, &viewportStateCreateInfo, &rasterizationStateCreateInfo);
958 
959     domainOriginStateCreateInfo.domainOrigin = m_params.domainOrigin.second;
960 
961     const auto pipeline1 =
962         makeGraphicsPipeline(ctx.vkd, ctx.device, *pipelineLayout, *vertModule, *tescModule, *teseModule1, *geomModule,
963                              *fragModule, *renderPass, 0u, nullptr, &inputAssemblyStateCreateInfo,
964                              &tessellationStateCreateInfo, &viewportStateCreateInfo, &rasterizationStateCreateInfo);
965 
966     const auto cmdPool      = makeCommandPool(ctx.vkd, ctx.device, ctx.qfIndex);
967     const auto cmdBufferRef = allocateCommandBuffer(ctx.vkd, ctx.device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
968     const auto cmdBufferRes = allocateCommandBuffer(ctx.vkd, ctx.device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
969 
970     const tcu::Vec2 noOffset(0.0f, 0.0f);
971     const tcu::Vec2 offscreenOffset(50.0f, 50.0f);
972     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
973 
974     // Reference image.
975     beginCommandBuffer(ctx.vkd, *cmdBufferRef);
976     beginRenderPass(ctx.vkd, *cmdBufferRef, *renderPass, *framebuffer0, scissors.at(0u), clearColor);
977     ctx.vkd.cmdBindVertexBuffers(*cmdBufferRef, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
978     ctx.vkd.cmdBindPipeline(*cmdBufferRef, bindPoint, *pipeline1);
979     ctx.vkd.cmdPushConstants(*cmdBufferRef, *pipelineLayout, pcStages, 0u, pcSize, &noOffset);
980     ctx.vkd.cmdDraw(*cmdBufferRef, vertexCount, 1u, 0u, 0u);
981     endRenderPass(ctx.vkd, *cmdBufferRef);
982     copyImageToBuffer(ctx.vkd, *cmdBufferRef, referenceBuffer.getImage(), referenceBuffer.getBuffer(),
983                       fbExtent.swizzle(0, 1), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
984                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1u, VK_IMAGE_ASPECT_COLOR_BIT,
985                       VK_IMAGE_ASPECT_COLOR_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
986     endCommandBuffer(ctx.vkd, *cmdBufferRef);
987     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, *cmdBufferRef);
988 
989     // Result image.
990     beginCommandBuffer(ctx.vkd, *cmdBufferRes);
991     beginRenderPass(ctx.vkd, *cmdBufferRes, *renderPass, *framebuffer1, scissors.at(0u), clearColor);
992     ctx.vkd.cmdBindVertexBuffers(*cmdBufferRes, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
993     // Draw offscreen first to force tessellation state emission.
994     ctx.vkd.cmdBindPipeline(*cmdBufferRes, bindPoint, *pipeline0);
995     ctx.vkd.cmdPushConstants(*cmdBufferRes, *pipelineLayout, pcStages, 0u, pcSize, &offscreenOffset);
996     ctx.vkd.cmdDraw(*cmdBufferRes, vertexCount, 1u, 0u, 0u);
997     // Draw on screen second changing some tessellation state.
998     ctx.vkd.cmdBindPipeline(*cmdBufferRes, bindPoint, *pipeline1);
999     ctx.vkd.cmdPushConstants(*cmdBufferRes, *pipelineLayout, pcStages, 0u, pcSize, &noOffset);
1000     ctx.vkd.cmdDraw(*cmdBufferRes, vertexCount, 1u, 0u, 0u);
1001     endRenderPass(ctx.vkd, *cmdBufferRes);
1002     copyImageToBuffer(ctx.vkd, *cmdBufferRes, resultBuffer.getImage(), resultBuffer.getBuffer(), fbExtent.swizzle(0, 1),
1003                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1u,
1004                       VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
1005                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
1006     endCommandBuffer(ctx.vkd, *cmdBufferRes);
1007     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, *cmdBufferRes);
1008 
1009     invalidateAlloc(ctx.vkd, ctx.device, referenceBuffer.getBufferAllocation());
1010     invalidateAlloc(ctx.vkd, ctx.device, resultBuffer.getBufferAllocation());
1011 
1012     tcu::ConstPixelBufferAccess referenceAccess(tcuFormat, fbExtent,
1013                                                 referenceBuffer.getBufferAllocation().getHostPtr());
1014     tcu::ConstPixelBufferAccess resultAccess(tcuFormat, fbExtent, resultBuffer.getBufferAllocation().getHostPtr());
1015 
1016     auto &log             = m_context.getTestContext().getLog();
1017     const float threshold = 0.005f; // 1/255 < 0.005 < 2/255
1018     const tcu::Vec4 thresholdVec(threshold, threshold, threshold, 0.0f);
1019 
1020     if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, thresholdVec,
1021                                     tcu::COMPARE_LOG_ON_ERROR))
1022         return tcu::TestStatus::fail("Color result does not match reference image -- check log for details");
1023 
1024     // Render pass and framebuffers.const DeviceCoreFeature requiredDeviceCoreFeature
1025     return tcu::TestStatus::pass("Pass");
1026 }
1027 
getDomainOriginName(VkTessellationDomainOrigin value)1028 std::string getDomainOriginName(VkTessellationDomainOrigin value)
1029 {
1030     static const size_t prefixLen = strlen("VK_TESSELLATION_DOMAIN_ORIGIN_");
1031     std::string nameStr           = getTessellationDomainOriginName(value);
1032 
1033     return de::toLower(nameStr.substr(prefixLen));
1034 }
1035 
1036 enum TessInstancedType
1037 {
1038     TESSINSTANCEDTYPE_NO_PATCHES = 0,
1039     TESSINSTANCEDTYPE_INSTANCED,
1040 
1041     TESSINSTANCEDTYPE_LAST,
1042 };
1043 
1044 struct TessInstancedDrawTestParams
1045 {
1046     TessInstancedType testType;
1047     TessPrimitiveType primitiveType;
1048 };
1049 
getInstancedDrawTestName(const TessInstancedType type)1050 static inline const char *getInstancedDrawTestName(const TessInstancedType type)
1051 {
1052     static std::string primitiveName[] = {
1053         "no_patches", // TESSINSTANCEDTYPE_NO_PATCHES
1054         "instances",  // TESSINSTANCEDTYPE_INSTANCED
1055     };
1056 
1057     if (type >= TESSINSTANCEDTYPE_LAST)
1058     {
1059         DE_FATAL("Unexpected test type.");
1060         return nullptr;
1061     }
1062 
1063     return primitiveName[type].c_str();
1064 }
1065 
1066 class TessInstancedDrawTestInstance : public vkt::TestInstance
1067 {
1068 public:
TessInstancedDrawTestInstance(Context & context,const TessInstancedDrawTestParams & testParams)1069     TessInstancedDrawTestInstance(Context &context, const TessInstancedDrawTestParams &testParams)
1070         : vkt::TestInstance(context)
1071         , m_params(testParams)
1072     {
1073     }
1074 
~TessInstancedDrawTestInstance()1075     ~TessInstancedDrawTestInstance()
1076     {
1077     }
1078 
1079     tcu::TestStatus iterate(void);
1080 
1081 protected:
1082     Move<VkBuffer> createBufferAndBindMemory(uint32_t bufferSize, VkBufferUsageFlags usageFlags,
1083                                              AllocationMp *outMemory);
1084     Move<VkImage> createImageAndBindMemory(tcu::IVec3 imgSize, VkFormat format, VkImageUsageFlags usageFlags,
1085                                            AllocationMp *outMemory);
1086     Move<VkImageView> createImageView(VkFormat format, VkImage image);
1087     Move<VkPipelineLayout> createPipelineLayout();
1088     Move<VkPipeline> createGraphicsPipeline(uint32_t patchCnt, VkPipelineLayout layout, VkRenderPass renderpass);
1089 
1090     std::vector<tcu::Vec4> genPerVertexVertexData();
1091     std::vector<tcu::Vec4> genPerInstanceVertexData();
1092     std::vector<uint16_t> genIndexData();
1093 
1094 protected:
1095     const TessInstancedDrawTestParams m_params;
1096 };
1097 
1098 class InstancedVertexShader : public rr::VertexShader
1099 {
1100 public:
InstancedVertexShader(void)1101     InstancedVertexShader(void) : rr::VertexShader(2, 0)
1102     {
1103         m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
1104         m_inputs[1].type = rr::GENERICVECTYPE_FLOAT;
1105     }
1106 
~InstancedVertexShader()1107     virtual ~InstancedVertexShader()
1108     {
1109     }
1110 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const1111     void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
1112     {
1113         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
1114         {
1115             const tcu::Vec4 position =
1116                 rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
1117             const tcu::Vec4 instancePosition =
1118                 rr::readVertexAttribFloat(inputs[1], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
1119 
1120             packets[packetNdx]->position = position + instancePosition;
1121         }
1122     }
1123 };
1124 
1125 class InstancedFragmentShader : public rr::FragmentShader
1126 {
1127 public:
InstancedFragmentShader(void)1128     InstancedFragmentShader(void) : rr::FragmentShader(0, 1)
1129     {
1130         m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
1131     }
1132 
~InstancedFragmentShader()1133     virtual ~InstancedFragmentShader()
1134     {
1135     }
1136 
shadeFragments(rr::FragmentPacket *,const int numPackets,const rr::FragmentShadingContext & context) const1137     void shadeFragments(rr::FragmentPacket *, const int numPackets, const rr::FragmentShadingContext &context) const
1138     {
1139         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
1140         {
1141             for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
1142             {
1143                 const tcu::Vec4 color(1.0f, 0.0f, 1.0f, 1.0f);
1144                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
1145             }
1146         }
1147     }
1148 };
1149 
1150 class TessInstancedDrawTestCase : public vkt::TestCase
1151 {
1152 public:
TessInstancedDrawTestCase(tcu::TestContext & testCtx,const std::string & name,const TessInstancedDrawTestParams & testParams)1153     TessInstancedDrawTestCase(tcu::TestContext &testCtx, const std::string &name,
1154                               const TessInstancedDrawTestParams &testParams)
1155         : vkt::TestCase(testCtx, name)
1156         , m_params(testParams)
1157     {
1158     }
1159 
~TessInstancedDrawTestCase()1160     ~TessInstancedDrawTestCase()
1161     {
1162     }
1163 
1164     void checkSupport(Context &context) const;
1165     void initPrograms(vk::SourceCollections &programCollection) const;
createInstance(Context & context) const1166     TestInstance *createInstance(Context &context) const
1167     {
1168         return new TessInstancedDrawTestInstance(context, m_params);
1169     }
1170 
1171 protected:
1172     const TessInstancedDrawTestParams m_params;
1173 };
1174 
checkSupport(Context & context) const1175 void TessInstancedDrawTestCase::checkSupport(Context &context) const
1176 {
1177     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1178 }
1179 
initPrograms(vk::SourceCollections & programCollection) const1180 void TessInstancedDrawTestCase::initPrograms(vk::SourceCollections &programCollection) const
1181 {
1182     std::ostringstream vert;
1183     vert << "#version 460\n"
1184          << "\n"
1185          << "layout (location = 0) in vec4 inPos;\n"
1186          << "layout (location = 1) in vec4 instancePos;\n"
1187          << "\n"
1188          << "void main()\n"
1189          << "{\n"
1190          << "    vec4 pos = inPos + instancePos;\n"
1191          << "\n"
1192          << "    gl_Position = pos;\n"
1193          << "}\n";
1194     programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
1195 
1196     std::ostringstream frag;
1197     frag << "#version 460\n"
1198          << "\n"
1199          << "layout (location = 0) out vec4 fragColor;\n"
1200          << "\n"
1201          << "void main()\n"
1202          << "{\n"
1203          << "    fragColor = vec4(1.0f, 0.0f, 1.0f, 1.0f);\n"
1204          << "}\n";
1205     programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1206 
1207     const int numVertices = m_params.primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 3 : 4;
1208 
1209     std::ostringstream tessCntrl;
1210     tessCntrl << "#version 460\n"
1211               << "\n"
1212               << "layout (vertices = " << numVertices << ") out;\n"
1213               << "\n"
1214               << "void main()\n"
1215               << "{\n"
1216               << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1217               << "    \n"
1218               << "    gl_TessLevelInner[0] = 1.0f;\n"
1219               << "    gl_TessLevelInner[1] = 1.0f;\n"
1220               << "    gl_TessLevelOuter[0] = 1.0f;\n"
1221               << "    gl_TessLevelOuter[1] = 1.0f;\n"
1222               << "    gl_TessLevelOuter[2] = 1.0f;\n"
1223               << "    gl_TessLevelOuter[3] = 1.0f;\n"
1224               << "    \n"
1225               << "}\n";
1226     programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(tessCntrl.str());
1227 
1228     std::ostringstream tessEvel;
1229     tessEvel << "#version 460\n"
1230              << "\n"
1231              << "layout ( " << getTessPrimitiveTypeShaderName(m_params.primitiveType) << " ) in;\n"
1232              << "\n"
1233              << "void main()\n"
1234              << "{\n"
1235              << "    const float u = gl_TessCoord.x;\n"
1236              << "    const float v = gl_TessCoord.y;\n";
1237     if (m_params.primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
1238     {
1239         tessEvel << "    gl_Position = (1 - u) * (1 - v) * gl_in[0].gl_Position + (1 - u) * v * gl_in[1].gl_Position "
1240                  << "+ u * (1 - v) * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position;\n";
1241     }
1242     else // m_params.primitiveType == TESSPRIMITIVETYPE_QUADS
1243     {
1244         tessEvel << "    gl_Position = (1 - u) * (1 - v) * gl_in[0].gl_Position + u * (1 - v) * gl_in[1].gl_Position "
1245                  << "+ u * v * gl_in[2].gl_Position + (1 - u) * v * gl_in[3].gl_Position;\n";
1246     }
1247     tessEvel << "}\n";
1248     programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(tessEvel.str());
1249 }
1250 
iterate(void)1251 tcu::TestStatus TessInstancedDrawTestInstance::iterate(void)
1252 {
1253     const DeviceInterface &devInterface = m_context.getDeviceInterface();
1254     VkDevice dev                        = m_context.getDevice();
1255     VkQueue queue                       = m_context.getUniversalQueue();
1256 
1257     // Command buffer
1258     Move<VkCommandPool> cmdPool(makeCommandPool(devInterface, dev, m_context.getUniversalQueueFamilyIndex()));
1259     Move<VkCommandBuffer> cmdBuffer(
1260         allocateCommandBuffer(devInterface, dev, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1261 
1262     // Per vertex vertex buffer
1263     const std::vector<tcu::Vec4> perVertexVertices = genPerVertexVertexData();
1264     const uint32_t perVertexVBSize = static_cast<uint32_t>(perVertexVertices.size() * sizeof(tcu::Vec4));
1265 
1266     AllocationMp perVertexVBMemory;
1267     Move<VkBuffer> perVertexVB(
1268         createBufferAndBindMemory(perVertexVBSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &perVertexVBMemory));
1269 
1270     {
1271         deMemcpy(perVertexVBMemory->getHostPtr(), perVertexVertices.data(), perVertexVBSize);
1272         flushAlloc(devInterface, dev, *perVertexVBMemory);
1273         // No barrier needed, flushed memory is automatically visible
1274     }
1275 
1276     const uint32_t patchCnt = static_cast<uint32_t>(perVertexVertices.size());
1277 
1278     // Per instance vertex buffer
1279     const std::vector<tcu::Vec4> perInstanceVertices = genPerInstanceVertexData();
1280     const uint32_t perInstanceVBSize = static_cast<uint32_t>(perInstanceVertices.size() * sizeof(tcu::Vec4));
1281 
1282     AllocationMp perInstanceVBMemory;
1283     Move<VkBuffer> perInstanceVB(
1284         createBufferAndBindMemory(perInstanceVBSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &perInstanceVBMemory));
1285 
1286     {
1287         deMemcpy(perInstanceVBMemory->getHostPtr(), perInstanceVertices.data(), perInstanceVBSize);
1288         flushAlloc(devInterface, dev, *perInstanceVBMemory);
1289         // No barrier needed, flushed memory is automatically visible
1290     }
1291 
1292     // Render target
1293     const tcu::IVec3 renderSize(256, 256, 1);
1294     const vk::VkFormat rtFormat = VK_FORMAT_R8G8B8A8_UNORM;
1295 
1296     AllocationMp rtMemory;
1297     Move<VkImage> renderTargetImage(createImageAndBindMemory(
1298         renderSize, rtFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, &rtMemory));
1299 
1300     // Render target view
1301     Move<VkImageView> rtView(createImageView(rtFormat, *renderTargetImage));
1302 
1303     // Pixel buffer
1304     const uint32_t pixelBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(rtFormat));
1305 
1306     AllocationMp pixelBufferMemory;
1307     Move<VkBuffer> pixelBuffer(
1308         createBufferAndBindMemory(pixelBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, &pixelBufferMemory));
1309 
1310     // Pipeline layout
1311     Move<VkPipelineLayout> pipelineLayout(createPipelineLayout());
1312 
1313     // Renderpass
1314     Move<VkRenderPass> renderPass(makeRenderPass(devInterface, dev, rtFormat));
1315 
1316     // Framebuffer
1317     Move<VkFramebuffer> framebuffer(
1318         makeFramebuffer(devInterface, dev, *renderPass, *rtView, renderSize.x(), renderSize.y()));
1319 
1320     // Pipeline
1321     Move<VkPipeline> pipeline(createGraphicsPipeline(patchCnt, *pipelineLayout, *renderPass));
1322 
1323     // Rendering
1324     beginCommandBuffer(devInterface, *cmdBuffer);
1325 
1326     const vk::VkBuffer vertexBuffers[]           = {*perVertexVB, *perInstanceVB};
1327     const vk::VkDeviceSize vertexBufferOffsets[] = {0, 0};
1328 
1329     devInterface.cmdBindVertexBuffers(*cmdBuffer, 0, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers,
1330                                       vertexBufferOffsets);
1331 
1332     devInterface.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1333 
1334     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1335     beginRenderPass(devInterface, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(renderSize), clearColor);
1336 
1337     if (m_params.testType == TESSINSTANCEDTYPE_INSTANCED)
1338         devInterface.cmdDraw(*cmdBuffer, patchCnt, static_cast<uint32_t>(perInstanceVertices.size()), 0u, 0u);
1339     else // m_params.testType == TESSINSTANCEDTYPE_NO_PATCHES
1340         devInterface.cmdDraw(*cmdBuffer, 2u, 1u, 0u, 0u);
1341 
1342     endRenderPass(devInterface, *cmdBuffer);
1343 
1344     copyImageToBuffer(devInterface, *cmdBuffer, *renderTargetImage, *pixelBuffer, {renderSize.x(), renderSize.y()});
1345 
1346     endCommandBuffer(devInterface, *cmdBuffer);
1347 
1348     submitCommandsAndWait(devInterface, dev, queue, cmdBuffer.get());
1349 
1350     // Reference rendering
1351     tcu::TextureFormat tcuFormat = mapVkFormat(rtFormat);
1352     tcu::TextureLevel refImage(tcuFormat, renderSize.x(), renderSize.y());
1353 
1354     tcu::clear(refImage.getAccess(), clearColor);
1355 
1356     if (m_params.testType == TESSINSTANCEDTYPE_INSTANCED)
1357     {
1358         const InstancedVertexShader vertShader;
1359         const InstancedFragmentShader fragShader;
1360         const rr::Program program(&vertShader, &fragShader);
1361         const rr::MultisamplePixelBufferAccess colorBuffer =
1362             rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refImage.getAccess());
1363         const rr::RenderTarget renderTarget(colorBuffer);
1364         const rr::RenderState renderState((rr::ViewportState(colorBuffer)),
1365                                           m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1366         const rr::Renderer renderer;
1367 
1368         const rr::VertexAttrib vertexAttribs[] = {
1369             rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0,
1370                              perVertexVertices.data()), // 0 means per vertex attribute
1371             rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 1,
1372                              perInstanceVertices.data()) // 1 means per instance attribute
1373         };
1374 
1375         if (m_params.primitiveType == TESSPRIMITIVETYPE_QUADS)
1376         {
1377             const std::vector<uint16_t> indices = genIndexData();
1378 
1379             const rr::DrawIndices drawIndices(indices.data());
1380             const rr::PrimitiveList primitives =
1381                 rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, static_cast<int>(indices.size()), drawIndices);
1382             const rr::DrawCommand command(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs),
1383                                           &vertexAttribs[0], primitives);
1384 
1385             renderer.drawInstanced(command, 4);
1386         }
1387         else
1388         {
1389             const rr::PrimitiveList primitives =
1390                 rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, static_cast<int>(perVertexVertices.size()), 0);
1391             const rr::DrawCommand command(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs),
1392                                           &vertexAttribs[0], primitives);
1393 
1394             renderer.drawInstanced(command, 4);
1395         }
1396     }
1397 
1398     // Compare result
1399     tcu::TestLog &log = m_context.getTestContext().getLog();
1400     qpTestResult res  = QP_TEST_RESULT_FAIL;
1401     const tcu::ConstPixelBufferAccess resultAccess(tcuFormat, renderSize, pixelBufferMemory->getHostPtr());
1402     const tcu::ConstPixelBufferAccess refAccess = refImage.getAccess();
1403 
1404     if (tcu::fuzzyCompare(log, "Result", "", refAccess, resultAccess, 0.05f, tcu::COMPARE_LOG_RESULT))
1405         res = QP_TEST_RESULT_PASS;
1406 
1407     return tcu::TestStatus(res, qpGetTestResultName(res));
1408 }
1409 
createBufferAndBindMemory(uint32_t bufferSize,VkBufferUsageFlags usageFlags,AllocationMp * outMemory)1410 Move<VkBuffer> TessInstancedDrawTestInstance::createBufferAndBindMemory(uint32_t bufferSize,
1411                                                                         VkBufferUsageFlags usageFlags,
1412                                                                         AllocationMp *outMemory)
1413 {
1414     const VkDevice &device      = m_context.getDevice();
1415     const DeviceInterface &vkdi = m_context.getDeviceInterface();
1416     Allocator &allocator        = m_context.getDefaultAllocator();
1417 
1418     const VkBufferCreateInfo bufferCreateInfo = {
1419         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType        sType
1420         nullptr,                              // const void*            pNext
1421         0,                                    // VkBufferCreateFlags    flags
1422         bufferSize,                           // VkDeviceSize           size
1423         usageFlags,                           // VkBufferUsageFlags     usage
1424         VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode          sharingMode
1425         0,                                    // uint32_t               queueFamilyIndexCount
1426         nullptr,                              // const uint32_t*        pQueueFamilyIndices
1427     };
1428 
1429     Move<VkBuffer> buffer(vk::createBuffer(vkdi, device, &bufferCreateInfo));
1430     const VkMemoryRequirements requirements = getBufferMemoryRequirements(vkdi, device, *buffer);
1431     AllocationMp bufferMemory               = allocator.allocate(requirements, MemoryRequirement::HostVisible);
1432 
1433     VK_CHECK(vkdi.bindBufferMemory(device, *buffer, bufferMemory->getMemory(), bufferMemory->getOffset()));
1434     *outMemory = bufferMemory;
1435 
1436     return buffer;
1437 }
1438 
createImageAndBindMemory(tcu::IVec3 imgSize,VkFormat format,VkImageUsageFlags usageFlags,AllocationMp * outMemory)1439 Move<VkImage> TessInstancedDrawTestInstance::createImageAndBindMemory(tcu::IVec3 imgSize, VkFormat format,
1440                                                                       VkImageUsageFlags usageFlags,
1441                                                                       AllocationMp *outMemory)
1442 {
1443     const VkDevice &device      = m_context.getDevice();
1444     const DeviceInterface &vkdi = m_context.getDeviceInterface();
1445     Allocator &allocator        = m_context.getDefaultAllocator();
1446 
1447     const VkImageCreateInfo imageCreateInfo = {
1448         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType          sType
1449         nullptr,                             // const void*              pNext
1450         0u,                                  // VkImageCreateFlags       flags
1451         VK_IMAGE_TYPE_2D,                    // VkImageType              imageType
1452         format,                              // VkFormat                 format
1453         makeExtent3D(imgSize),               // VkExtent3D               extent
1454         1u,                                  // uint32_t                 mipLevels
1455         1u,                                  // uint32_t                 arrayLayers
1456         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits    samples
1457         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling            tiling
1458         usageFlags,                          // VkImageUsageFlags        usage
1459         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode            sharingMode
1460         0u,                                  // uint32_t                 queueFamilyIndexCount
1461         nullptr,                             // const uint32_t*          pQueueFamilyIndices
1462         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout            initialLayout
1463     };
1464 
1465     Move<VkImage> image(vk::createImage(vkdi, device, &imageCreateInfo));
1466     const VkMemoryRequirements requirements = getImageMemoryRequirements(vkdi, device, *image);
1467     AllocationMp imageMemory                = allocator.allocate(requirements, MemoryRequirement::Any);
1468 
1469     VK_CHECK(vkdi.bindImageMemory(device, *image, imageMemory->getMemory(), imageMemory->getOffset()));
1470     *outMemory = imageMemory;
1471 
1472     return image;
1473 }
1474 
createImageView(VkFormat format,VkImage image)1475 Move<VkImageView> TessInstancedDrawTestInstance::createImageView(VkFormat format, VkImage image)
1476 {
1477     const VkDevice &device      = m_context.getDevice();
1478     const DeviceInterface &vkdi = m_context.getDeviceInterface();
1479 
1480     VkImageSubresourceRange range = {
1481         VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1482         0u,                        // uint32_t           baseMipLevel
1483         1u,                        // uint32_t           levelCount
1484         0u,                        // uint32_t           baseArrayLayer
1485         1u,                        // uint32_t           layerCount
1486     };
1487 
1488     return makeImageView(vkdi, device, image, VK_IMAGE_VIEW_TYPE_2D, format, range);
1489 }
1490 
createPipelineLayout()1491 Move<VkPipelineLayout> TessInstancedDrawTestInstance::createPipelineLayout()
1492 {
1493     const VkDevice &device      = m_context.getDevice();
1494     const DeviceInterface &vkdi = m_context.getDeviceInterface();
1495 
1496     const VkPipelineLayoutCreateInfo createInfo = {
1497         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType                 sType
1498         nullptr,                                       // const void*                     pNext
1499         (VkPipelineLayoutCreateFlags)0,                // VkPipelineLayoutCreateFlags     flags
1500         0u,                                            // uint32_t                        setLayoutCount
1501         nullptr,                                       // const VkDescriptorSetLayout*    pSetLayouts
1502         0u,                                            // uint32_t                        pushConstantRangeCount
1503         nullptr,                                       // const VkPushConstantRange*      pPushConstantRanges
1504     };
1505 
1506     return vk::createPipelineLayout(vkdi, device, &createInfo);
1507 }
1508 
createGraphicsPipeline(uint32_t patchCnt,VkPipelineLayout layout,VkRenderPass renderpass)1509 Move<VkPipeline> TessInstancedDrawTestInstance::createGraphicsPipeline(uint32_t patchCnt, VkPipelineLayout layout,
1510                                                                        VkRenderPass renderpass)
1511 {
1512     const VkDevice &device      = m_context.getDevice();
1513     const DeviceInterface &vkdi = m_context.getDeviceInterface();
1514 
1515     vk::BinaryCollection &binCollection = m_context.getBinaryCollection();
1516     Move<VkShaderModule> vertModule(createShaderModule(vkdi, device, binCollection.get("vert")));
1517     Move<VkShaderModule> tessCtrlModule(createShaderModule(vkdi, device, binCollection.get("tess_ctrl")));
1518     Move<VkShaderModule> tessEvalModule(createShaderModule(vkdi, device, binCollection.get("tess_eval")));
1519     Move<VkShaderModule> fragModule(createShaderModule(vkdi, device, binCollection.get("frag")));
1520 
1521     VkPipelineShaderStageCreateInfo stageInfos[4];
1522     uint32_t stageNdx = 0;
1523 
1524     {
1525         const VkPipelineShaderStageCreateInfo pipelineShaderStageParam = {
1526             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1527             nullptr,                                             // const void* pNext;
1528             0,                                                   // VkPipelineShaderStageCreateFlags flags;
1529             VK_SHADER_STAGE_VERTEX_BIT,                          // VkShaderStageFlagBits stage;
1530             *vertModule,                                         // VkShaderModule module;
1531             "main",                                              // const char* pName;
1532             nullptr,                                             // const VkSpecializationInfo* pSpecializationInfo;
1533         };
1534         stageInfos[stageNdx++] = pipelineShaderStageParam;
1535     }
1536 
1537     {
1538         const VkPipelineShaderStageCreateInfo pipelineShaderStageParam = {
1539             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1540             nullptr,                                             // const void* pNext;
1541             0,                                                   // VkPipelineShaderStageCreateFlags flags;
1542             VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,            // VkShaderStageFlagBits stage;
1543             *tessCtrlModule,                                     // VkShaderModule module;
1544             "main",                                              // const char* pName;
1545             nullptr,                                             // const VkSpecializationInfo* pSpecializationInfo;
1546         };
1547         stageInfos[stageNdx++] = pipelineShaderStageParam;
1548     }
1549 
1550     {
1551         const VkPipelineShaderStageCreateInfo pipelineShaderStageParam = {
1552             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1553             nullptr,                                             // const void* pNext;
1554             0,                                                   // VkPipelineShaderStageCreateFlags flags;
1555             VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,         // VkShaderStageFlagBits stage;
1556             *tessEvalModule,                                     // VkShaderModule module;
1557             "main",                                              // const char* pName;
1558             nullptr,                                             // const VkSpecializationInfo* pSpecializationInfo;
1559         };
1560         stageInfos[stageNdx++] = pipelineShaderStageParam;
1561     }
1562 
1563     {
1564         const VkPipelineShaderStageCreateInfo pipelineShaderStageParam = {
1565             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1566             nullptr,                                             // const void* pNext;
1567             0,                                                   // VkPipelineShaderStageCreateFlags flags;
1568             VK_SHADER_STAGE_FRAGMENT_BIT,                        // VkShaderStageFlagBits stage;
1569             *fragModule,                                         // VkShaderModule module;
1570             "main",                                              // const char* pName;
1571             nullptr,                                             // const VkSpecializationInfo* pSpecializationInfo;
1572         };
1573         stageInfos[stageNdx++] = pipelineShaderStageParam;
1574     }
1575 
1576     const VkVertexInputBindingDescription vertexInputBindingDescriptions[] = {
1577         {
1578             0u,                         // uint32_t             binding
1579             sizeof(tcu::Vec4),          // uint32_t             stride
1580             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate    inputRate
1581         },
1582         {
1583             1u,                           // uint32_t             binding
1584             sizeof(tcu::Vec4),            // uint32_t             stride
1585             VK_VERTEX_INPUT_RATE_INSTANCE // VkVertexInputRate    inputRate
1586         }};
1587 
1588     const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
1589         {
1590             0u,                            // uint32_t    location
1591             0u,                            // uint32_t    binding
1592             VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat    format
1593             0u                             // uint32_t    offset
1594         },
1595         {
1596             1u,                            // uint32_t    location
1597             1u,                            // uint32_t    binding
1598             VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat    format
1599             0u,                            // uint32_t    offset
1600         }};
1601 
1602     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfoDefault = {
1603         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                             sType
1604         nullptr,                                                   // const void*                                 pNext
1605         (VkPipelineVertexInputStateCreateFlags)0,                  // VkPipelineVertexInputStateCreateFlags       flags
1606         2u,                              // uint32_t                                    vertexBindingDescriptionCount
1607         vertexInputBindingDescriptions,  // const VkVertexInputBindingDescription*      pVertexBindingDescriptions
1608         2u,                              // uint32_t                                    vertexAttributeDescriptionCount
1609         vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
1610     };
1611 
1612     const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfoDefault = {
1613         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType                            sType
1614         nullptr,                                                     // const void*                                pNext
1615         0u,                                                          // VkPipelineInputAssemblyStateCreateFlags    flags
1616         VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, // VkPrimitiveTopology                        topology
1617         VK_FALSE                          // VkBool32                                   primitiveRestartEnable
1618     };
1619 
1620     const VkPipelineTessellationStateCreateInfo tessStateCreateInfo = {
1621         VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType                        sType
1622         nullptr,                                                   // const void*                            pNext
1623         0u,                                                        // VkPipelineTessellationStateCreateFlags flags
1624         patchCnt // uint32_t                               patchControlPoints
1625     };
1626 
1627     const VkViewport viewport = {
1628         0.0f,   // float x
1629         0.0f,   // float y
1630         256.0f, // float width
1631         256.0f, // float height
1632         0.0f,   // float minDepth
1633         1.0f    // float maxDepth
1634     };
1635 
1636     const VkRect2D scissor = {
1637         {0, 0},      // VkOffset2D    offset
1638         {256u, 256u} // VkExtent2D    extent
1639     };
1640 
1641     const VkPipelineViewportStateCreateInfo viewportStateCreateInfoDefault = {
1642         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType                             sType
1643         nullptr,                                               // const void*                                 pNext
1644         (VkPipelineViewportStateCreateFlags)0,                 // VkPipelineViewportStateCreateFlags          flags
1645         1u,        // uint32_t                                    viewportCount
1646         &viewport, // const VkViewport*                           pViewports
1647         1u,        // uint32_t                                    scissorCount
1648         &scissor   // const VkRect2D*                             pScissors
1649     };
1650 
1651     const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfoDefault = {
1652         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                            sType
1653         nullptr,                                                    // const void*                                pNext
1654         0u,                                                         // VkPipelineRasterizationStateCreateFlags    flags
1655         VK_FALSE,                        // VkBool32                                   depthClampEnable
1656         VK_FALSE,                        // VkBool32                                   rasterizerDiscardEnable
1657         VK_POLYGON_MODE_FILL,            // VkPolygonMode                              polygonMode
1658         VK_CULL_MODE_NONE,               // VkCullModeFlags                            cullMode
1659         VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace                                frontFace
1660         VK_FALSE,                        // VkBool32                                   depthBiasEnable
1661         0.0f,                            // float                                      depthBiasConstantFactor
1662         0.0f,                            // float                                      depthBiasClamp
1663         0.0f,                            // float                                      depthBiasSlopeFactor
1664         1.0f                             // float                                      lineWidth
1665     };
1666 
1667     const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfoDefault = {
1668         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType                          sType
1669         nullptr,                                                  // const void*                              pNext
1670         0u,                                                       // VkPipelineMultisampleStateCreateFlags    flags
1671         VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits                    rasterizationSamples
1672         VK_FALSE,              // VkBool32                                 sampleShadingEnable
1673         1.0f,                  // float                                    minSampleShading
1674         nullptr,               // const VkSampleMask*                      pSampleMask
1675         VK_FALSE,              // VkBool32                                 alphaToCoverageEnable
1676         VK_FALSE               // VkBool32                                 alphaToOneEnable
1677     };
1678 
1679     const VkStencilOpState stencilOpState = {
1680         VK_STENCIL_OP_KEEP,  // VkStencilOp    failOp
1681         VK_STENCIL_OP_KEEP,  // VkStencilOp    passOp
1682         VK_STENCIL_OP_KEEP,  // VkStencilOp    depthFailOp
1683         VK_COMPARE_OP_NEVER, // VkCompareOp    compareOp
1684         0,                   // uint32_t       compareMask
1685         0,                   // uint32_t       writeMask
1686         0                    // uint32_t       reference
1687     };
1688 
1689     const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfoDefault = {
1690         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                          sType
1691         nullptr,                                                    // const void*                              pNext
1692         0u,                                                         // VkPipelineDepthStencilStateCreateFlags   flags
1693         VK_FALSE,                    // VkBool32                                 depthTestEnable
1694         VK_FALSE,                    // VkBool32                                 depthWriteEnable
1695         VK_COMPARE_OP_LESS_OR_EQUAL, // VkCompareOp                              depthCompareOp
1696         VK_FALSE,                    // VkBool32                                 depthBoundsTestEnable
1697         VK_FALSE,                    // VkBool32                                 stencilTestEnable
1698         stencilOpState,              // VkStencilOpState                         front
1699         stencilOpState,              // VkStencilOpState                         back
1700         0.0f,                        // float                                    minDepthBounds
1701         1.0f,                        // float                                    maxDepthBounds
1702     };
1703 
1704     const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
1705         VK_FALSE,                // VkBool32                 blendEnable
1706         VK_BLEND_FACTOR_ZERO,    // VkBlendFactor            srcColorBlendFactor
1707         VK_BLEND_FACTOR_ZERO,    // VkBlendFactor            dstColorBlendFactor
1708         VK_BLEND_OP_ADD,         // VkBlendOp                colorBlendOp
1709         VK_BLEND_FACTOR_ZERO,    // VkBlendFactor            srcAlphaBlendFactor
1710         VK_BLEND_FACTOR_ZERO,    // VkBlendFactor            dstAlphaBlendFactor
1711         VK_BLEND_OP_ADD,         // VkBlendOp                alphaBlendOp
1712         VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags    colorWriteMask
1713             | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
1714 
1715     const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfoDefault = {
1716         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                               sType
1717         nullptr,                                                  // const void*                                   pNext
1718         0u,                                                       // VkPipelineColorBlendStateCreateFlags          flags
1719         VK_FALSE,                   // VkBool32                                      logicOpEnable
1720         VK_LOGIC_OP_CLEAR,          // VkLogicOp                                     logicOp
1721         1u,                         // uint32_t                                      attachmentCount
1722         &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState*    pAttachments
1723         {0.0f, 0.0f, 0.0f, 0.0f}    // float                                         blendConstants[4]
1724     };
1725 
1726     const VkGraphicsPipelineCreateInfo pipelineCreateInfo = {
1727         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType                                  sType
1728         nullptr,                                         // const void*                                      pNext
1729         0,                                               // VkPipelineCreateFlags                            flags
1730         stageNdx,                                        // uint32_t                                         stageCount
1731         stageInfos,                                      // const VkPipelineShaderStageCreateInfo*           pStages
1732         &vertexInputStateCreateInfoDefault,   // const VkPipelineVertexInputStateCreateInfo*      pVertexInputState
1733         &inputAssemblyStateCreateInfoDefault, // const VkPipelineInputAssemblyStateCreateInfo*    pInputAssemblyState
1734         &tessStateCreateInfo,                 // const VkPipelineTessellationStateCreateInfo*     pTessellationState
1735         &viewportStateCreateInfoDefault,      // const VkPipelineViewportStateCreateInfo*         pViewportState
1736         &rasterizationStateCreateInfoDefault, // const VkPipelineRasterizationStateCreateInfo*    pRasterizationState
1737         &multisampleStateCreateInfoDefault,   // const VkPipelineMultisampleStateCreateInfo*      pMultisampleState
1738         &depthStencilStateCreateInfoDefault,  // const VkPipelineDepthStencilStateCreateInfo*     pDepthStencilState
1739         &colorBlendStateCreateInfoDefault,    // const VkPipelineColorBlendStateCreateInfo*       pColorBlendState
1740         nullptr,                              // const VkPipelineDynamicStateCreateInfo*          pDynamicState
1741         layout,                               // VkPipelineLayout                                 layout
1742         renderpass,                           // VkRenderPass                                     renderPass
1743         0,                                    // uint32_t                                         subpass
1744         VK_NULL_HANDLE,                       // VkPipeline                                       basePipelineHandle
1745         0                                     // int32_t                                          basePipelineIndex;
1746     };
1747 
1748     return vk::createGraphicsPipeline(vkdi, device, VK_NULL_HANDLE, &pipelineCreateInfo);
1749 }
1750 
genPerVertexVertexData()1751 std::vector<tcu::Vec4> TessInstancedDrawTestInstance::genPerVertexVertexData()
1752 {
1753     std::vector<tcu::Vec4> vertices = {
1754         {-0.1f, -0.1f, 0.0f, 1.0f},
1755         {0.1f, -0.1f, 0.0f, 1.0f},
1756         {0.1f, 0.1f, 0.0f, 1.0f},
1757         {-0.1f, 0.1f, 0.0f, 1.0f},
1758     };
1759 
1760     return vertices;
1761 }
1762 
genPerInstanceVertexData()1763 std::vector<tcu::Vec4> TessInstancedDrawTestInstance::genPerInstanceVertexData()
1764 {
1765     std::vector<tcu::Vec4> vertices = {
1766         {-0.5f, -0.5f, 0.0f, 1.0f},
1767         {0.5f, -0.5f, 0.0f, 1.0f},
1768         {0.5f, 0.5f, 0.0f, 1.0f},
1769         {-0.5f, 0.5f, 0.0f, 1.0f},
1770     };
1771 
1772     return vertices;
1773 }
1774 
genIndexData()1775 std::vector<uint16_t> TessInstancedDrawTestInstance::genIndexData()
1776 {
1777     std::vector<uint16_t> indices = {0, 1, 2, 2, 3, 0};
1778 
1779     return indices;
1780 }
1781 
1782 } // namespace
1783 
1784 //! These tests correspond to dEQP-GLES31.functional.tessellation.misc_draw.*
createMiscDrawTests(tcu::TestContext & testCtx)1785 tcu::TestCaseGroup *createMiscDrawTests(tcu::TestContext &testCtx)
1786 {
1787     // Miscellaneous draw-result-verifying cases
1788     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "misc_draw"));
1789 
1790     static const TessPrimitiveType primitivesNoIsolines[] = {
1791         TESSPRIMITIVETYPE_TRIANGLES,
1792         TESSPRIMITIVETYPE_QUADS,
1793     };
1794 
1795     static const DrawType drawTypes[] = {
1796         DRAWTYPE_DRAW,
1797         DRAWTYPE_DRAW_INDIRECT,
1798     };
1799 
1800     // Triangle fill case
1801     for (int drawTypeNdx = 0; drawTypeNdx < DE_LENGTH_OF_ARRAY(drawTypes); ++drawTypeNdx)
1802         for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitivesNoIsolines); ++primitiveTypeNdx)
1803             for (int spacingModeNdx = 0; spacingModeNdx < SPACINGMODE_LAST; ++spacingModeNdx)
1804             {
1805                 const TessPrimitiveType primitiveType = primitivesNoIsolines[primitiveTypeNdx];
1806                 const SpacingMode spacingMode         = static_cast<SpacingMode>(spacingModeNdx);
1807                 const DrawType drawType               = static_cast<DrawType>(drawTypeNdx);
1808                 const std::string caseName            = std::string() + "fill_cover_" +
1809                                              getTessPrimitiveTypeShaderName(primitiveType) + "_" +
1810                                              getSpacingModeShaderName(spacingMode) + "_" + getDrawName(drawType);
1811                 const std::string refName = std::string() + "fill_cover_" +
1812                                             getTessPrimitiveTypeShaderName(primitiveType) + "_" +
1813                                             getSpacingModeShaderName(spacingMode);
1814 
1815                 // Check that there are no obvious gaps in the triangle-filled area of a tessellated shape
1816                 addFunctionCaseWithPrograms(
1817                     group.get(), caseName, initProgramsFillCoverCase, runTest,
1818                     makeCaseDefinition(primitiveType, spacingMode, drawType, getReferenceImagePathPrefix(refName)));
1819             }
1820 
1821     // Triangle non-overlap case
1822     for (int drawTypeNdx = 0; drawTypeNdx < DE_LENGTH_OF_ARRAY(drawTypes); ++drawTypeNdx)
1823         for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitivesNoIsolines); ++primitiveTypeNdx)
1824             for (int spacingModeNdx = 0; spacingModeNdx < SPACINGMODE_LAST; ++spacingModeNdx)
1825             {
1826                 const TessPrimitiveType primitiveType = primitivesNoIsolines[primitiveTypeNdx];
1827                 const SpacingMode spacingMode         = static_cast<SpacingMode>(spacingModeNdx);
1828                 const DrawType drawType               = static_cast<DrawType>(drawTypeNdx);
1829                 const std::string caseName            = std::string() + "fill_overlap_" +
1830                                              getTessPrimitiveTypeShaderName(primitiveType) + "_" +
1831                                              getSpacingModeShaderName(spacingMode) + "_" + getDrawName(drawType);
1832                 const std::string refName = std::string() + "fill_overlap_" +
1833                                             getTessPrimitiveTypeShaderName(primitiveType) + "_" +
1834                                             getSpacingModeShaderName(spacingMode);
1835 
1836                 // Check that there are no obvious triangle overlaps in the triangle-filled area of a tessellated shape
1837                 addFunctionCaseWithPrograms(
1838                     group.get(), caseName, initProgramsFillNonOverlapCase, runTest,
1839                     makeCaseDefinition(primitiveType, spacingMode, drawType, getReferenceImagePathPrefix(refName)));
1840             }
1841 
1842     // Isolines
1843     for (int drawTypeNdx = 0; drawTypeNdx < DE_LENGTH_OF_ARRAY(drawTypes); ++drawTypeNdx)
1844         for (int spacingModeNdx = 0; spacingModeNdx < SPACINGMODE_LAST; ++spacingModeNdx)
1845         {
1846             const SpacingMode spacingMode = static_cast<SpacingMode>(spacingModeNdx);
1847             const DrawType drawType       = static_cast<DrawType>(drawTypeNdx);
1848             const std::string caseName =
1849                 std::string() + "isolines_" + getSpacingModeShaderName(spacingMode) + "_" + getDrawName(drawType);
1850             const std::string refName = std::string() + "isolines_" + getSpacingModeShaderName(spacingMode);
1851 
1852             // Basic isolines render test
1853             addFunctionCaseWithPrograms(group.get(), caseName, checkSupportCase, initProgramsIsolinesCase, runTest,
1854                                         makeCaseDefinition(TESSPRIMITIVETYPE_ISOLINES, spacingMode, drawType,
1855                                                            getReferenceImagePathPrefix(refName)));
1856         }
1857 
1858     static const TessInstancedType tessInstancedTypes[] = {
1859         TESSINSTANCEDTYPE_NO_PATCHES,
1860         TESSINSTANCEDTYPE_INSTANCED,
1861     };
1862 
1863     // Instanced
1864     for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitivesNoIsolines); ++primitiveTypeNdx)
1865         for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(tessInstancedTypes); ++testTypeNdx)
1866         {
1867             const TessPrimitiveType primitiveType = primitivesNoIsolines[primitiveTypeNdx];
1868             const TessInstancedType testType      = tessInstancedTypes[testTypeNdx];
1869             const std::string caseName = std::string() + getTessPrimitiveTypeShaderName(primitiveType) + "_" +
1870                                          getInstancedDrawTestName(testType);
1871 
1872             const TessInstancedDrawTestParams testParams = {
1873                 testType,
1874                 primitiveType,
1875             };
1876 
1877             group->addChild(new TessInstancedDrawTestCase(testCtx, caseName.c_str(), testParams));
1878         }
1879 
1880     // Test switching tessellation parameters on the fly.
1881     for (const auto &geometryShader : {false, true})
1882     {
1883         const auto nameSuffix = (geometryShader ? "_with_geom_shader" : "");
1884 
1885         static const VkTessellationDomainOrigin domainOrigins[] = {
1886             VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT,
1887             VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT,
1888         };
1889 
1890         for (const auto &firstPrimitiveType : primitivesNoIsolines)
1891             for (const auto &secondPrimitiveType : primitivesNoIsolines)
1892             {
1893                 if (firstPrimitiveType == secondPrimitiveType)
1894                     continue;
1895 
1896                 const TessStateSwitchParams params{
1897                     std::make_pair(firstPrimitiveType, secondPrimitiveType),
1898                     std::make_pair(SPACINGMODE_EQUAL, SPACINGMODE_EQUAL),
1899                     std::make_pair(VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT),
1900                     geometryShader,
1901                 };
1902 
1903                 const auto testName = std::string("switch_primitive_") +
1904                                       getTessPrimitiveTypeShaderName(params.patchTypes.first) + "_to_" +
1905                                       getTessPrimitiveTypeShaderName(params.patchTypes.second) + nameSuffix;
1906                 group->addChild(new TessStateSwitchCase(testCtx, testName, params));
1907             }
1908 
1909         for (const auto &firstDomainOrigin : domainOrigins)
1910             for (const auto &secondDomainOrigin : domainOrigins)
1911             {
1912                 if (firstDomainOrigin == secondDomainOrigin)
1913                     continue;
1914 
1915                 const TessStateSwitchParams params{
1916                     std::make_pair(TESSPRIMITIVETYPE_QUADS, TESSPRIMITIVETYPE_QUADS),
1917                     std::make_pair(SPACINGMODE_EQUAL, SPACINGMODE_EQUAL),
1918                     std::make_pair(firstDomainOrigin, secondDomainOrigin),
1919                     geometryShader,
1920                 };
1921 
1922                 const auto testName = std::string("switch_domain_origin_") +
1923                                       getDomainOriginName(params.domainOrigin.first) + "_to_" +
1924                                       getDomainOriginName(params.domainOrigin.second) + nameSuffix;
1925                 group->addChild(new TessStateSwitchCase(testCtx, testName, params));
1926             }
1927 
1928         for (int firstSpacingModeNdx = 0; firstSpacingModeNdx < SPACINGMODE_LAST; ++firstSpacingModeNdx)
1929             for (int secondSpacingModeNdx = 0; secondSpacingModeNdx < SPACINGMODE_LAST; ++secondSpacingModeNdx)
1930             {
1931                 if (firstSpacingModeNdx == secondSpacingModeNdx)
1932                     continue;
1933 
1934                 const SpacingMode firstSpacingMode  = static_cast<SpacingMode>(firstSpacingModeNdx);
1935                 const SpacingMode secondSpacingMode = static_cast<SpacingMode>(secondSpacingModeNdx);
1936 
1937                 const TessStateSwitchParams params{
1938                     std::make_pair(TESSPRIMITIVETYPE_QUADS, TESSPRIMITIVETYPE_QUADS),
1939                     std::make_pair(firstSpacingMode, secondSpacingMode),
1940                     std::make_pair(VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT),
1941                     geometryShader,
1942                 };
1943 
1944                 const auto testName = std::string("switch_spacing_mode_") +
1945                                       getSpacingModeShaderName(params.spacing.first) + "_to_" +
1946                                       getSpacingModeShaderName(params.spacing.second) + nameSuffix;
1947                 group->addChild(new TessStateSwitchCase(testCtx, testName, params));
1948             }
1949     }
1950 
1951     return group.release();
1952 }
1953 
1954 } // namespace tessellation
1955 } // namespace vkt
1956