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