Merge vk-gl-cts/opengl-cts-4.6.0 into vk-gl-cts/master
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / dynamic_state / vktDynamicStateVPTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Intel Corporation
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 Dynamic State Viewport Tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktDynamicStateVPTests.hpp"
26
27 #include "vktDynamicStateBaseClass.hpp"
28 #include "vktDynamicStateTestCaseUtil.hpp"
29
30 #include "vkImageUtil.hpp"
31
32 #include "tcuTextureUtil.hpp"
33 #include "tcuImageCompare.hpp"
34 #include "tcuRGBA.hpp"
35
36 namespace vkt
37 {
38 namespace DynamicState
39 {
40
41 using namespace Draw;
42
43 namespace
44 {
45
46 class ViewportStateBaseCase : public DynamicStateBaseClass
47 {
48 public:
49         ViewportStateBaseCase (Context& context, const char* vertexShaderName, const char* fragmentShaderName)
50                 : DynamicStateBaseClass (context, vertexShaderName, fragmentShaderName)
51         {}
52
53         void initialize(void)
54         {
55                 m_topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
56
57                 m_data.push_back(PositionColorVertex(tcu::Vec4(-0.5f, 0.5f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
58                 m_data.push_back(PositionColorVertex(tcu::Vec4(0.5f, 0.5f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
59                 m_data.push_back(PositionColorVertex(tcu::Vec4(-0.5f, -0.5f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
60                 m_data.push_back(PositionColorVertex(tcu::Vec4(0.5f, -0.5f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
61
62                 DynamicStateBaseClass::initialize();
63         }
64
65         virtual tcu::Texture2D buildReferenceFrame (void)
66         {
67                 DE_ASSERT(false);
68                 return tcu::Texture2D(tcu::TextureFormat(), 0, 0);
69         }
70
71         virtual void setDynamicStates (void)
72         {
73                 DE_ASSERT(false);
74         }
75
76         virtual tcu::TestStatus iterate (void)
77         {
78                 tcu::TestLog &log                       = m_context.getTestContext().getLog();
79                 const vk::VkQueue queue         = m_context.getUniversalQueue();
80
81                 beginRenderPass();
82
83                 // set states here
84                 setDynamicStates();
85
86                 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
87
88                 const vk::VkDeviceSize vertexBufferOffset = 0;
89                 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
90                 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
91
92                 m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
93
94                 m_vk.cmdEndRenderPass(*m_cmdBuffer);
95                 m_vk.endCommandBuffer(*m_cmdBuffer);
96
97                 vk::VkSubmitInfo submitInfo =
98                 {
99                         vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
100                         DE_NULL,                                                        // const void*                          pNext;
101                         0,                                                                      // deUint32                                     waitSemaphoreCount;
102                         DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
103                         (const vk::VkPipelineStageFlags*)DE_NULL,
104                         1,                                                                      // deUint32                                     commandBufferCount;
105                         &m_cmdBuffer.get(),                                     // const VkCommandBuffer*       pCommandBuffers;
106                         0,                                                                      // deUint32                                     signalSemaphoreCount;
107                         DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
108                 };
109                 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
110
111                 // validation
112                 {
113                         VK_CHECK(m_vk.queueWaitIdle(queue));
114
115                         tcu::Texture2D referenceFrame = buildReferenceFrame();
116
117                         const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
118                         const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
119                                 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
120
121                         if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
122                                 referenceFrame.getLevel(0), renderedFrame, 0.05f,
123                                 tcu::COMPARE_LOG_RESULT))
124                         {
125                                 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
126                         }
127
128                         return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
129                 }
130         }
131 };
132
133 class ViewportParamTestInstane : public ViewportStateBaseCase
134 {
135 public:
136         ViewportParamTestInstane (Context& context, ShaderMap shaders)
137                 : ViewportStateBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
138         {
139                 ViewportStateBaseCase::initialize();
140         }
141
142         virtual void setDynamicStates(void)
143         {
144                 const vk::VkViewport viewport   = { 0.0f, 0.0f, (float)WIDTH * 2, (float)HEIGHT * 2, 0.0f, 0.0f };
145                 const vk::VkRect2D scissor              = { { 0, 0 }, { WIDTH, HEIGHT } };
146
147                 setDynamicViewportState(1, &viewport, &scissor);
148                 setDynamicRasterizationState();
149                 setDynamicBlendState();
150                 setDynamicDepthStencilState();
151         }
152
153         virtual tcu::Texture2D buildReferenceFrame (void)
154         {
155                 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
156                 referenceFrame.allocLevel(0);
157
158                 const deInt32 frameWidth        = referenceFrame.getWidth();
159                 const deInt32 frameHeight       = referenceFrame.getHeight();
160
161                 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
162
163                 for (int y = 0; y < frameHeight; y++)
164                 {
165                         const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
166
167                         for (int x = 0; x < frameWidth; x++)
168                         {
169                                 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
170
171                                 if (xCoord >= 0.0f && xCoord <= 1.0f && yCoord >= 0.0f && yCoord <= 1.0f)
172                                         referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
173                         }
174                 }
175
176                 return referenceFrame;
177         }
178 };
179
180 class ScissorParamTestInstance : public ViewportStateBaseCase
181 {
182 public:
183         ScissorParamTestInstance (Context& context, ShaderMap shaders)
184                 : ViewportStateBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
185         {
186                 ViewportStateBaseCase::initialize();
187         }
188
189         virtual void setDynamicStates (void)
190         {
191                 const vk::VkViewport viewport   = { 0.0f, 0.0f, (float)WIDTH, (float)HEIGHT, 0.0f, 0.0f };
192                 const vk::VkRect2D scissor              = { { 0, 0 }, { WIDTH / 2, HEIGHT / 2 } };
193
194                 setDynamicViewportState(1, &viewport, &scissor);
195                 setDynamicRasterizationState();
196                 setDynamicBlendState();
197                 setDynamicDepthStencilState();
198         }
199
200         virtual tcu::Texture2D buildReferenceFrame (void)
201         {
202                 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
203                 referenceFrame.allocLevel(0);
204
205                 const deInt32 frameWidth        = referenceFrame.getWidth();
206                 const deInt32 frameHeight       = referenceFrame.getHeight();
207
208                 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
209
210                 for (int y = 0; y < frameHeight; y++)
211                 {
212                         const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
213
214                         for (int x = 0; x < frameWidth; x++)
215                         {
216                                 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
217
218                                 if (xCoord >= -0.5f && xCoord <= 0.0f && yCoord >= -0.5f && yCoord <= 0.0f)
219                                         referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
220                         }
221                 }
222
223                 return referenceFrame;
224         }
225 };
226
227 class ViewportArrayTestInstance : public DynamicStateBaseClass
228 {
229 protected:
230         std::string m_geometryShaderName;
231
232 public:
233
234         ViewportArrayTestInstance (Context& context, ShaderMap shaders)
235                 : DynamicStateBaseClass (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
236                 , m_geometryShaderName  (shaders[glu::SHADERTYPE_GEOMETRY])
237         {
238                 // Check geometry shader support
239                 {
240                         const vk::VkPhysicalDeviceFeatures& deviceFeatures = m_context.getDeviceFeatures();
241
242                         if (!deviceFeatures.multiViewport)
243                                 throw tcu::NotSupportedError("Multi-viewport is not supported");
244
245                         if (!deviceFeatures.geometryShader)
246                                 throw tcu::NotSupportedError("Geometry shaders are not supported");
247                 }
248
249                 for (int i = 0; i < 4; i++)
250                 {
251                         m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 1.0f, (float)i / 3.0f, 1.0f), tcu::RGBA::green().toVec()));
252                         m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, (float)i / 3.0f, 1.0f), tcu::RGBA::green().toVec()));
253                         m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, (float)i / 3.0f, 1.0f), tcu::RGBA::green().toVec()));
254                         m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, -1.0f, (float)i / 3.0f, 1.0f), tcu::RGBA::green().toVec()));
255                 }
256
257                 DynamicStateBaseClass::initialize();
258         }
259
260         virtual void initPipeline (const vk::VkDevice device)
261         {
262                 const vk::Unique<vk::VkShaderModule> vs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get(m_vertexShaderName), 0));
263                 const vk::Unique<vk::VkShaderModule> gs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get(m_geometryShaderName), 0));
264                 const vk::Unique<vk::VkShaderModule> fs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get(m_fragmentShaderName), 0));
265
266                 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
267
268                 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
269                 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
270                 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*gs, "main", vk::VK_SHADER_STAGE_GEOMETRY_BIT));
271                 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
272                 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
273                 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_topology));
274                 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
275                 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(4));
276                 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
277                 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
278                 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
279                 pipelineCreateInfo.addState(PipelineCreateInfo::DynamicState());
280
281                 m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
282         }
283
284         virtual tcu::TestStatus iterate (void)
285         {
286                 tcu::TestLog &log = m_context.getTestContext().getLog();
287                 const vk::VkQueue queue = m_context.getUniversalQueue();
288
289                 beginRenderPass();
290
291                 // set states here
292                 const float halfWidth           = (float)WIDTH / 2;
293                 const float halfHeight          = (float)HEIGHT / 2;
294                 const deInt32 quarterWidth      = WIDTH / 4;
295                 const deInt32 quarterHeight = HEIGHT / 4;
296
297                 const vk::VkViewport viewports[4] =
298                 {
299                         { 0.0f, 0.0f, (float)halfWidth, (float)halfHeight, 0.0f, 0.0f },
300                         { halfWidth, 0.0f, (float)halfWidth, (float)halfHeight, 0.0f, 0.0f },
301                         { halfWidth, halfHeight, (float)halfWidth, (float)halfHeight, 0.0f, 0.0f },
302                         { 0.0f, halfHeight, (float)halfWidth, (float)halfHeight, 0.0f, 0.0f }
303                 };
304
305                 const vk::VkRect2D scissors[4] =
306                 {
307                         { { quarterWidth, quarterHeight }, { quarterWidth, quarterHeight } },
308                         { { (deInt32)halfWidth, quarterHeight }, { quarterWidth, quarterHeight } },
309                         { { (deInt32)halfWidth, (deInt32)halfHeight }, { quarterWidth, quarterHeight } },
310                         { { quarterWidth, (deInt32)halfHeight }, { quarterWidth, quarterHeight } },
311                 };
312
313                 setDynamicViewportState(4, viewports, scissors);
314                 setDynamicRasterizationState();
315                 setDynamicBlendState();
316                 setDynamicDepthStencilState();
317
318                 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
319
320                 const vk::VkDeviceSize vertexBufferOffset = 0;
321                 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
322                 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
323
324                 m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
325
326                 m_vk.cmdEndRenderPass(*m_cmdBuffer);
327                 m_vk.endCommandBuffer(*m_cmdBuffer);
328
329                 vk::VkSubmitInfo submitInfo =
330                 {
331                         vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
332                         DE_NULL,                                                        // const void*                          pNext;
333                         0,                                                                      // deUint32                                     waitSemaphoreCount;
334                         DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
335                         (const vk::VkPipelineStageFlags*)DE_NULL,
336                         1,                                                                      // deUint32                                     commandBufferCount;
337                         &m_cmdBuffer.get(),                                     // const VkCommandBuffer*       pCommandBuffers;
338                         0,                                                                      // deUint32                                     signalSemaphoreCount;
339                         DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
340                 };
341                 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
342
343                 // validation
344                 {
345                         VK_CHECK(m_vk.queueWaitIdle(queue));
346
347                         tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
348                         referenceFrame.allocLevel(0);
349
350                         const deInt32 frameWidth = referenceFrame.getWidth();
351                         const deInt32 frameHeight = referenceFrame.getHeight();
352
353                         tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
354
355                         for (int y = 0; y < frameHeight; y++)
356                         {
357                                 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
358
359                                 for (int x = 0; x < frameWidth; x++)
360                                 {
361                                         const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
362
363                                         if (xCoord >= -0.5f && xCoord <= 0.5f && yCoord >= -0.5f && yCoord <= 0.5f)
364                                                 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
365                                 }
366                         }
367
368                         const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
369                         const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
370                                 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
371
372                         if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
373                                 referenceFrame.getLevel(0), renderedFrame, 0.05f,
374                                 tcu::COMPARE_LOG_RESULT))
375                         {
376                                 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
377                         }
378
379                         return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
380                 }
381         }
382 };
383
384 } //anonymous
385
386 DynamicStateVPTests::DynamicStateVPTests (tcu::TestContext& testCtx)
387         : TestCaseGroup (testCtx, "vp_state", "Tests for viewport state")
388 {
389         /* Left blank on purpose */
390 }
391
392 DynamicStateVPTests::~DynamicStateVPTests ()
393 {
394 }
395
396 void DynamicStateVPTests::init (void)
397 {
398         ShaderMap shaderPaths;
399         shaderPaths[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
400         shaderPaths[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
401
402         addChild(new InstanceFactory<ViewportParamTestInstane>(m_testCtx, "viewport", "Set viewport which is twice bigger than screen size", shaderPaths));
403         addChild(new InstanceFactory<ScissorParamTestInstance>(m_testCtx, "scissor", "Perform a scissor test on 1/4 bottom-left part of the surface", shaderPaths));
404
405         shaderPaths[glu::SHADERTYPE_GEOMETRY] = "vulkan/dynamic_state/ViewportArray.geom";
406         addChild(new InstanceFactory<ViewportArrayTestInstance>(m_testCtx, "viewport_array", "Multiple viewports and scissors", shaderPaths));
407 }
408
409 } // DynamicState
410 } // vkt