Merge vk-gl-cts/vulkan-cts-1.0.2 into vk-gl-cts/master
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / draw / vktDrawNegativeViewportHeightTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Negative viewport height (part of VK_KHR_maintenance1)
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktDrawNegativeViewportHeightTests.hpp"
25 #include "vktDrawCreateInfoUtil.hpp"
26 #include "vktDrawImageObjectUtil.hpp"
27 #include "vktDrawBufferObjectUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29 #include "vktTestCaseUtil.hpp"
30
31 #include "vkPrograms.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkImageUtil.hpp"
34
35 #include "tcuVector.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuImageCompare.hpp"
38 #include "tcuTestLog.hpp"
39
40 #include "deSharedPtr.hpp"
41
42 namespace vkt
43 {
44 namespace Draw
45 {
46 namespace
47 {
48 using namespace vk;
49 using tcu::Vec4;
50 using de::SharedPtr;
51 using de::MovePtr;
52
53 enum Constants
54 {
55         WIDTH   = 256,
56         HEIGHT  = WIDTH/2,
57 };
58
59 struct TestParams
60 {
61         VkFrontFace                             frontFace;
62         VkCullModeFlagBits              cullMode;
63 };
64
65 class NegativeViewportHeightTestInstance : public TestInstance
66 {
67 public:
68                                                                         NegativeViewportHeightTestInstance      (Context& context, const TestParams& params);
69         tcu::TestStatus                                 iterate                                                         (void);
70         tcu::ConstPixelBufferAccess             draw                                                            (const VkViewport viewport);
71         MovePtr<tcu::TextureLevel>              generateReferenceImage                          (void) const;
72         bool                                                    isCulled                                                        (const VkFrontFace triangleFace) const;
73
74 private:
75         const TestParams                                m_params;
76         const VkFormat                                  m_colorAttachmentFormat;
77         SharedPtr<Image>                                m_colorTargetImage;
78         Move<VkImageView>                               m_colorTargetView;
79         SharedPtr<Buffer>                               m_vertexBuffer;
80         Move<VkRenderPass>                              m_renderPass;
81         Move<VkFramebuffer>                             m_framebuffer;
82         Move<VkPipelineLayout>                  m_pipelineLayout;
83         Move<VkPipeline>                                m_pipeline;
84 };
85
86 NegativeViewportHeightTestInstance::NegativeViewportHeightTestInstance (Context& context, const TestParams& params)
87         : TestInstance                          (context)
88         , m_params                                      (params)
89         , m_colorAttachmentFormat       (VK_FORMAT_R8G8B8A8_UNORM)
90 {
91         const DeviceInterface&  vk              = m_context.getDeviceInterface();
92         const VkDevice                  device  = m_context.getDevice();
93
94         // Vertex data
95         {
96                 std::vector<Vec4> vertexData;
97
98                 // CCW triangle
99                 vertexData.push_back(Vec4(-0.8f, -0.6f, 0.0f, 1.0f));   //  0-----2
100                 vertexData.push_back(Vec4(-0.8f,  0.6f, 0.0f, 1.0f));   //   |  /
101                 vertexData.push_back(Vec4(-0.2f, -0.6f, 0.0f, 1.0f));   //  1|/
102
103                 // CW triangle
104                 vertexData.push_back(Vec4( 0.2f, -0.6f, 0.0f, 1.0f));   //  0-----1
105                 vertexData.push_back(Vec4( 0.8f, -0.6f, 0.0f, 1.0f));   //    \  |
106                 vertexData.push_back(Vec4( 0.8f,  0.6f, 0.0f, 1.0f));   //      \|2
107
108                 const VkDeviceSize dataSize = vertexData.size() * sizeof(Vec4);
109                 m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
110                                                                                                 m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
111
112                 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &vertexData[0], static_cast<std::size_t>(dataSize));
113                 flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
114         }
115
116         // Render pass
117         {
118                 const VkExtent3D                targetImageExtent               = { WIDTH, HEIGHT, 1 };
119                 const VkImageUsageFlags targetImageUsageFlags   = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
120
121                 const ImageCreateInfo   targetImageCreateInfo(
122                         VK_IMAGE_TYPE_2D,                                               // imageType,
123                         m_colorAttachmentFormat,                                // format,
124                         targetImageExtent,                                              // extent,
125                         1u,                                                                             // mipLevels,
126                         1u,                                                                             // arrayLayers,
127                         VK_SAMPLE_COUNT_1_BIT,                                  // samples,
128                         VK_IMAGE_TILING_OPTIMAL,                                // tiling,
129                         targetImageUsageFlags);                                 // usage,
130
131                 m_colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
132
133                 RenderPassCreateInfo    renderPassCreateInfo;
134                 renderPassCreateInfo.addAttachment(AttachmentDescription(
135                         m_colorAttachmentFormat,                                // format
136                         VK_SAMPLE_COUNT_1_BIT,                                  // samples
137                         VK_ATTACHMENT_LOAD_OP_LOAD,                             // loadOp
138                         VK_ATTACHMENT_STORE_OP_STORE,                   // storeOp
139                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,                // stencilLoadOp
140                         VK_ATTACHMENT_STORE_OP_DONT_CARE,               // stencilStoreOp
141                         VK_IMAGE_LAYOUT_GENERAL,                                // initialLayout
142                         VK_IMAGE_LAYOUT_GENERAL));                              // finalLayout
143
144                 const VkAttachmentReference colorAttachmentReference =
145                 {
146                         0u,
147                         VK_IMAGE_LAYOUT_GENERAL
148                 };
149
150                 renderPassCreateInfo.addSubpass(SubpassDescription(
151                         VK_PIPELINE_BIND_POINT_GRAPHICS,                // pipelineBindPoint
152                         (VkSubpassDescriptionFlags)0,                   // flags
153                         0u,                                                                             // inputAttachmentCount
154                         DE_NULL,                                                                // inputAttachments
155                         1u,                                                                             // colorAttachmentCount
156                         &colorAttachmentReference,                              // colorAttachments
157                         DE_NULL,                                                                // resolveAttachments
158                         AttachmentReference(),                                  // depthStencilAttachment
159                         0u,                                                                             // preserveAttachmentCount
160                         DE_NULL));                                                              // preserveAttachments
161
162                 m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
163         }
164
165         // Framebuffer
166         {
167                 const ImageViewCreateInfo colorTargetViewInfo (m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
168                 m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
169
170                 std::vector<VkImageView> colorAttachments(1);
171                 colorAttachments[0] = *m_colorTargetView;
172
173                 const FramebufferCreateInfo     framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
174                 m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
175         }
176
177         // Vertex input
178
179         const VkVertexInputBindingDescription           vertexInputBindingDescription =
180         {
181                 0u,                                                                             // uint32_t             binding;
182                 sizeof(Vec4),                                                   // uint32_t             stride;
183                 VK_VERTEX_INPUT_RATE_VERTEX,                    // VkVertexInputRate    inputRate;
184         };
185
186         const VkVertexInputAttributeDescription         vertexInputAttributeDescription =
187         {
188                 0u,                                                                             // uint32_t    location;
189                 0u,                                                                             // uint32_t    binding;
190                 VK_FORMAT_R32G32B32A32_SFLOAT,                  // VkFormat    format;
191                 0u                                                                              // uint32_t    offset;
192         };
193
194         const PipelineCreateInfo::VertexInputState      vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription,
195                                                                                                                                                                                                                 1, &vertexInputAttributeDescription);
196
197         // Graphics pipeline
198
199         const VkRect2D scissor =
200         {
201                 { 0,            0               },              // x, y
202                 { WIDTH,        HEIGHT  },              // width, height
203         };
204
205         std::vector<VkDynamicState>             dynamicStates;
206         dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
207
208         const Unique<VkShaderModule>    vertexModule    (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
209         const Unique<VkShaderModule>    fragmentModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
210
211         const PipelineLayoutCreateInfo  pipelineLayoutCreateInfo;
212         m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
213
214         const PipelineCreateInfo::ColorBlendState::Attachment colorBlendAttachmentState;
215
216         PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
217         pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vertexModule,   "main", VK_SHADER_STAGE_VERTEX_BIT));
218         pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
219         pipelineCreateInfo.addState (PipelineCreateInfo::VertexInputState       (vertexInputState));
220         pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
221         pipelineCreateInfo.addState (PipelineCreateInfo::ColorBlendState        (1, &colorBlendAttachmentState));
222         pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState          (1, std::vector<VkViewport>(), std::vector<VkRect2D>(1, scissor)));
223         pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState      ());
224         pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState        (
225                 VK_FALSE,                                       // depthClampEnable
226                 VK_FALSE,                                       // rasterizerDiscardEnable
227                 VK_POLYGON_MODE_FILL,           // polygonMode
228                 m_params.cullMode,                      // cullMode
229                 m_params.frontFace,                     // frontFace
230                 VK_FALSE,                                       // depthBiasEnable
231                 0.0f,                                           // depthBiasConstantFactor
232                 0.0f,                                           // depthBiasClamp
233                 0.0f,                                           // depthBiasSlopeFactor
234                 1.0f));                                         // lineWidth
235         pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState       ());
236         pipelineCreateInfo.addState (PipelineCreateInfo::DynamicState           (dynamicStates));
237
238         m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
239 }
240
241 tcu::ConstPixelBufferAccess NegativeViewportHeightTestInstance::draw (const VkViewport viewport)
242 {
243         const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
244         const VkDevice                  device                          = m_context.getDevice();
245         const VkQueue                   queue                           = m_context.getUniversalQueue();
246         const deUint32                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
247
248         // Command buffer
249
250         const CmdPoolCreateInfo                 cmdPoolCreateInfo       (queueFamilyIndex);
251         const Unique<VkCommandPool>             cmdPool                         (createCommandPool(vk, device, &cmdPoolCreateInfo));
252         const Unique<VkCommandBuffer>   cmdBuffer                       (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
253
254         // Draw
255
256         {
257                 const CmdBufferBeginInfo beginInfo;
258                 vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
259         }
260
261         vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport);
262
263         {
264                 const VkClearColorValue         clearColor                      = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f).color;
265                 const ImageSubresourceRange subresourceRange    (VK_IMAGE_ASPECT_COLOR_BIT);
266
267                 initialTransitionColor2DImage(vk, *cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL,
268                                                                           VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
269                 vk.cmdClearColorImage(*cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
270         }
271         {
272                 const VkMemoryBarrier memBarrier =
273                 {
274                         VK_STRUCTURE_TYPE_MEMORY_BARRIER,                                                                                               // VkStructureType    sType;
275                         DE_NULL,                                                                                                                                                // const void*        pNext;
276                         VK_ACCESS_TRANSFER_WRITE_BIT,                                                                                                   // VkAccessFlags      srcAccessMask;
277                         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT              // VkAccessFlags      dstAccessMask;
278                 };
279
280                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
281         }
282         {
283                 const VkRect2D                          renderArea              = { { 0, 0 }, { WIDTH, HEIGHT } };
284                 const RenderPassBeginInfo       renderPassBegin (*m_renderPass, *m_framebuffer, renderArea);
285
286                 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, VK_SUBPASS_CONTENTS_INLINE);
287         }
288         {
289                 const VkDeviceSize      offset  = 0;
290                 const VkBuffer          buffer  = m_vertexBuffer->object();
291
292                 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &offset);
293         }
294
295         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
296         vk.cmdDraw(*cmdBuffer, 6, 1, 0, 0);
297         vk.cmdEndRenderPass(*cmdBuffer);
298         vk.endCommandBuffer(*cmdBuffer);
299
300         // Submit
301         {
302                 const Unique<VkFence>   fence           (createFence(vk, device));
303                 const VkSubmitInfo              submitInfo      =
304                 {
305                         VK_STRUCTURE_TYPE_SUBMIT_INFO,                          // VkStructureType                sType;
306                         DE_NULL,                                                                        // const void*                    pNext;
307                         0,                                                                                      // uint32_t                       waitSemaphoreCount;
308                         DE_NULL,                                                                        // const VkSemaphore*             pWaitSemaphores;
309                         (const VkPipelineStageFlags*)DE_NULL,           // const VkPipelineStageFlags*    pWaitDstStageMask;
310                         1,                                                                                      // uint32_t                       commandBufferCount;
311                         &cmdBuffer.get(),                                                       // const VkCommandBuffer*         pCommandBuffers;
312                         0,                                                                                      // uint32_t                       signalSemaphoreCount;
313                         DE_NULL                                                                         // const VkSemaphore*             pSignalSemaphores;
314                 };
315
316                 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
317                 VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), VK_TRUE, ~0ull));
318         }
319
320         // Get result
321         {
322                 const VkOffset3D zeroOffset = { 0, 0, 0 };
323                 return m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT);
324         }
325 }
326
327 //! Determine if a triangle with triangleFace orientation will be culled or not
328 bool NegativeViewportHeightTestInstance::isCulled (const VkFrontFace triangleFace) const
329 {
330         const bool isFrontFacing = (triangleFace == m_params.frontFace);
331
332         if (m_params.cullMode == VK_CULL_MODE_FRONT_BIT && isFrontFacing)
333                 return true;
334         if (m_params.cullMode == VK_CULL_MODE_BACK_BIT  && !isFrontFacing)
335                 return true;
336
337         return m_params.cullMode == VK_CULL_MODE_FRONT_AND_BACK;
338 }
339
340 MovePtr<tcu::TextureLevel> NegativeViewportHeightTestInstance::generateReferenceImage (void) const
341 {
342         DE_ASSERT(HEIGHT == WIDTH/2);
343
344         MovePtr<tcu::TextureLevel>              image   (new tcu::TextureLevel(mapVkFormat(m_colorAttachmentFormat), WIDTH, HEIGHT));
345         const tcu::PixelBufferAccess    access  (image->getAccess());
346         const Vec4                                              black   (0.0f, 0.0f, 0.0f, 1.0f);
347         const Vec4                                              white   (1.0f);
348         const Vec4                                              gray    (0.5f, 0.5f, 0.5f, 1.0f);
349
350         tcu::clear(access, black);
351
352         const int p1 =      static_cast<int>(static_cast<float>(HEIGHT) * (1.0f - 0.6f) / 2.0f);
353         const int p2 = p1 + static_cast<int>(static_cast<float>(HEIGHT) * (2.0f * 0.6f) / 2.0f);
354
355         // left triangle (CCW -> CW after y-flip)
356         if (!isCulled(VK_FRONT_FACE_CLOCKWISE))
357         {
358                 const Vec4& color = (m_params.frontFace == VK_FRONT_FACE_CLOCKWISE ? white : gray);
359
360                 for (int y = p1; y <= p2; ++y)
361                 for (int x = p1; x <  y;  ++x)
362                         access.setPixel(color, x, y);
363         }
364
365         // right triangle (CW -> CCW after y-flip)
366         if (!isCulled(VK_FRONT_FACE_COUNTER_CLOCKWISE))
367         {
368                 const Vec4& color = (m_params.frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE ? white : gray);
369
370                 for (int y = p1;        y <= p2;          ++y)
371                 for (int x = WIDTH - y; x <  p2 + HEIGHT; ++x)
372                         access.setPixel(color, x, y);
373         }
374
375         return image;
376 }
377
378 std::string getCullModeStr (const VkCullModeFlagBits cullMode)
379 {
380         // Cull mode flags are a bit special, because there's a meaning to 0 and or'ed flags.
381         // The function getCullModeFlagsStr() doesn't work too well in this case.
382
383         switch (cullMode)
384         {
385                 case VK_CULL_MODE_NONE:                         return "VK_CULL_MODE_NONE";
386                 case VK_CULL_MODE_FRONT_BIT:            return "VK_CULL_MODE_FRONT_BIT";
387                 case VK_CULL_MODE_BACK_BIT:                     return "VK_CULL_MODE_BACK_BIT";
388                 case VK_CULL_MODE_FRONT_AND_BACK:       return "VK_CULL_MODE_FRONT_AND_BACK";
389
390                 default:
391                         DE_ASSERT(0);
392                         return std::string();
393         }
394 }
395
396 tcu::TestStatus NegativeViewportHeightTestInstance::iterate (void)
397 {
398         // Check requirements
399
400         if (!de::contains(m_context.getDeviceExtensions().begin(), m_context.getDeviceExtensions().end(), std::string("VK_KHR_maintenance1")))
401                 TCU_THROW(NotSupportedError, "Missing extension: VK_KHR_maintenance1");
402
403         // Set up the viewport and draw
404
405         const VkViewport viewport =
406         {
407                 0.0f,                                                   // float    x;
408                 static_cast<float>(HEIGHT),             // float    y;
409                 static_cast<float>(WIDTH),              // float    width;
410                 -static_cast<float>(HEIGHT),    // float    height;
411                 0.0f,                                                   // float    minDepth;
412                 1.0f,                                                   // float    maxDepth;
413         };
414
415         const tcu::ConstPixelBufferAccess       resultImage     = draw(viewport);
416
417         // Verify the results
418
419         tcu::TestLog&                           log                             = m_context.getTestContext().getLog();
420         MovePtr<tcu::TextureLevel>      referenceImage  = generateReferenceImage();
421
422         log << tcu::TestLog::Message
423                 << "Drawing two triangles with negative viewport height, which will cause a y-flip. This changes the sign of the triangle's area."
424                 << tcu::TestLog::EndMessage;
425         log << tcu::TestLog::Message
426                 << "After the flip, the triangle on the left is CW and the triangle on the right is CCW. Right angles of the both triangles should be at the bottom of the image."
427                 << " Front face is white, back face is gray."
428                 << tcu::TestLog::EndMessage;
429         log << tcu::TestLog::Message
430                 << "Front face: " << getFrontFaceName(m_params.frontFace) << "\n"
431                 << "Cull mode: "  << getCullModeStr  (m_params.cullMode)  << "\n"
432                 << tcu::TestLog::EndMessage;
433
434         if (!tcu::fuzzyCompare(log, "Image compare", "Image compare", referenceImage->getAccess(), resultImage, 0.02f, tcu::COMPARE_LOG_RESULT))
435                 return tcu::TestStatus::fail("Rendered image is incorrect");
436         else
437                 return tcu::TestStatus::pass("Pass");
438 }
439
440 class NegativeViewportHeightTest : public TestCase
441 {
442 public:
443         NegativeViewportHeightTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
444                 : TestCase      (testCtx, name, description)
445                 , m_params      (params)
446         {
447         }
448
449         void initPrograms (SourceCollections& programCollection) const
450         {
451                 // Vertex shader
452                 {
453                         std::ostringstream src;
454                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
455                                 << "\n"
456                                 << "layout(location = 0) in vec4 in_position;\n"
457                                 << "\n"
458                                 << "out gl_PerVertex {\n"
459                                 << "    vec4  gl_Position;\n"
460                                 << "};\n"
461                                 << "\n"
462                                 << "void main(void)\n"
463                                 << "{\n"
464                                 << "    gl_Position = in_position;\n"
465                                 << "}\n";
466
467                         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
468                 }
469
470                 // Fragment shader
471                 {
472                         std::ostringstream src;
473                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
474                                 << "\n"
475                                 << "layout(location = 0) out vec4 out_color;\n"
476                                 << "\n"
477                                 << "void main(void)\n"
478                                 << "{\n"
479                                 << "    if (gl_FrontFacing)\n"
480                                 << "        out_color = vec4(1.0);\n"
481                                 << "    else\n"
482                                 << "        out_color = vec4(vec3(0.5), 1.0);\n"
483                                 << "}\n";
484
485                         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
486                 }
487         }
488
489         virtual TestInstance* createInstance (Context& context) const
490         {
491                 return new NegativeViewportHeightTestInstance(context, m_params);
492         }
493
494 private:
495         const TestParams        m_params;
496 };
497
498 void populateTestGroup (tcu::TestCaseGroup* testGroup)
499 {
500         const struct
501         {
502                 const char* const       name;
503                 VkFrontFace                     frontFace;
504         } frontFace[] =
505         {
506                 { "front_ccw",  VK_FRONT_FACE_COUNTER_CLOCKWISE },
507                 { "front_cw",   VK_FRONT_FACE_CLOCKWISE                 },
508         };
509
510         const struct
511         {
512                 const char* const       name;
513                 VkCullModeFlagBits      cullMode;
514         } cullMode[] =
515         {
516                 { "cull_none",  VK_CULL_MODE_NONE                       },
517                 { "cull_front", VK_CULL_MODE_FRONT_BIT          },
518                 { "cull_back",  VK_CULL_MODE_BACK_BIT           },
519                 { "cull_both",  VK_CULL_MODE_FRONT_AND_BACK     },
520         };
521
522         for (int ndxFrontFace = 0; ndxFrontFace < DE_LENGTH_OF_ARRAY(frontFace); ++ndxFrontFace)
523         for (int ndxCullMode  = 0; ndxCullMode  < DE_LENGTH_OF_ARRAY(cullMode);  ++ndxCullMode)
524         {
525                 const TestParams params =
526                 {
527                         frontFace[ndxFrontFace].frontFace,
528                         cullMode[ndxCullMode].cullMode,
529                 };
530                 std::ostringstream      name;
531                 name << frontFace[ndxFrontFace].name << "_" << cullMode[ndxCullMode].name;
532
533                 testGroup->addChild(new NegativeViewportHeightTest(testGroup->getTestContext(), name.str(), "", params));
534         }
535 }
536
537 }       // anonymous
538
539 tcu::TestCaseGroup*     createNegativeViewportHeightTests (tcu::TestContext& testCtx)
540 {
541         return createTestGroup(testCtx, "negative_viewport_height", "Negative viewport height (VK_KHR_maintenance1)", populateTestGroup);
542 }
543
544 }       // Draw
545 }       // vkt