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