1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel Corporation
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:
16 * The above copyright notice(s) and this permission notice shall be included
17 * in all copies or substantial portions of the Materials.
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.
29 * \brief Dynamic State Viewport Tests
30 *//*--------------------------------------------------------------------*/
32 #include "vktDynamicStateVPTests.hpp"
34 #include "vktDynamicStateBaseClass.hpp"
35 #include "vktDynamicStateTestCaseUtil.hpp"
37 #include "vkImageUtil.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuRGBA.hpp"
45 namespace DynamicState
50 class ViewportStateBaseCase : public DynamicStateBaseClass
53 ViewportStateBaseCase (Context& context, const char* vertexShaderName, const char* fragmentShaderName)
54 : DynamicStateBaseClass (context, vertexShaderName, fragmentShaderName)
59 m_topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
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()));
66 DynamicStateBaseClass::initialize();
69 virtual tcu::Texture2D buildReferenceFrame (void)
72 return tcu::Texture2D(tcu::TextureFormat(), 0, 0);
75 virtual void setDynamicStates (void)
80 virtual tcu::TestStatus iterate (void)
82 tcu::TestLog &log = m_context.getTestContext().getLog();
83 const vk::VkQueue queue = m_context.getUniversalQueue();
90 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
92 const vk::VkDeviceSize vertexBufferOffset = 0;
93 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
94 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
96 m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
98 m_vk.cmdEndRenderPass(*m_cmdBuffer);
99 m_vk.endCommandBuffer(*m_cmdBuffer);
101 vk::VkSubmitInfo submitInfo =
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;
113 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
117 VK_CHECK(m_vk.queueWaitIdle(queue));
119 tcu::Texture2D referenceFrame = buildReferenceFrame();
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);
125 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
126 referenceFrame.getLevel(0), renderedFrame, 0.05f,
127 tcu::COMPARE_LOG_RESULT))
129 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
132 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
137 class ViewportParamTestInstane : public ViewportStateBaseCase
140 ViewportParamTestInstane (Context& context, ShaderMap shaders)
141 : ViewportStateBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
143 ViewportStateBaseCase::initialize();
146 virtual void setDynamicStates(void)
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 } };
151 setDynamicViewportState(1, &viewport, &scissor);
152 setDynamicRasterizationState();
153 setDynamicBlendState();
154 setDynamicDepthStencilState();
157 virtual tcu::Texture2D buildReferenceFrame (void)
159 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
160 referenceFrame.allocLevel(0);
162 const deInt32 frameWidth = referenceFrame.getWidth();
163 const deInt32 frameHeight = referenceFrame.getHeight();
165 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
167 for (int y = 0; y < frameHeight; y++)
169 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
171 for (int x = 0; x < frameWidth; x++)
173 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
180 return referenceFrame;
184 class ScissorParamTestInstance : public ViewportStateBaseCase
187 ScissorParamTestInstance (Context& context, ShaderMap shaders)
188 : ViewportStateBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
190 ViewportStateBaseCase::initialize();
193 virtual void setDynamicStates (void)
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 } };
198 setDynamicViewportState(1, &viewport, &scissor);
199 setDynamicRasterizationState();
200 setDynamicBlendState();
201 setDynamicDepthStencilState();
204 virtual tcu::Texture2D buildReferenceFrame (void)
206 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
207 referenceFrame.allocLevel(0);
209 const deInt32 frameWidth = referenceFrame.getWidth();
210 const deInt32 frameHeight = referenceFrame.getHeight();
212 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
214 for (int y = 0; y < frameHeight; y++)
216 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
218 for (int x = 0; x < frameWidth; x++)
220 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
227 return referenceFrame;
231 class ViewportArrayTestInstance : public DynamicStateBaseClass
234 std::string m_geometryShaderName;
238 ViewportArrayTestInstance (Context& context, ShaderMap shaders)
239 : DynamicStateBaseClass (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
240 , m_geometryShaderName (shaders[glu::SHADERTYPE_GEOMETRY])
242 // Check geometry shader support
244 const vk::VkPhysicalDeviceFeatures& deviceFeatures = m_context.getDeviceFeatures();
246 if (!deviceFeatures.multiViewport)
247 throw tcu::NotSupportedError("Multi-viewport is not supported");
249 if (!deviceFeatures.geometryShader)
250 throw tcu::NotSupportedError("Geometry shaders are not supported");
253 for (int i = 0; i < 4; i++)
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()));
261 DynamicStateBaseClass::initialize();
264 virtual void initPipeline (const vk::VkDevice device)
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));
270 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
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());
285 m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
288 virtual tcu::TestStatus iterate (void)
290 tcu::TestLog &log = m_context.getTestContext().getLog();
291 const vk::VkQueue queue = m_context.getUniversalQueue();
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;
301 const vk::VkViewport viewports[4] =
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 }
309 const vk::VkRect2D scissors[4] =
311 { { quarterWidth, quarterHeight }, { quarterWidth, quarterHeight } },
312 { { (deInt32)halfWidth, quarterHeight }, { quarterWidth, quarterHeight } },
313 { { (deInt32)halfWidth, (deInt32)halfHeight }, { quarterWidth, quarterHeight } },
314 { { quarterWidth, (deInt32)halfHeight }, { quarterWidth, quarterHeight } },
317 setDynamicViewportState(4, viewports, scissors);
318 setDynamicRasterizationState();
319 setDynamicBlendState();
320 setDynamicDepthStencilState();
322 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
324 const vk::VkDeviceSize vertexBufferOffset = 0;
325 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
326 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
328 m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
330 m_vk.cmdEndRenderPass(*m_cmdBuffer);
331 m_vk.endCommandBuffer(*m_cmdBuffer);
333 vk::VkSubmitInfo submitInfo =
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;
345 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
349 VK_CHECK(m_vk.queueWaitIdle(queue));
351 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
352 referenceFrame.allocLevel(0);
354 const deInt32 frameWidth = referenceFrame.getWidth();
355 const deInt32 frameHeight = referenceFrame.getHeight();
357 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
359 for (int y = 0; y < frameHeight; y++)
361 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
363 for (int x = 0; x < frameWidth; x++)
365 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
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);
376 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
377 referenceFrame.getLevel(0), renderedFrame, 0.05f,
378 tcu::COMPARE_LOG_RESULT))
380 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
383 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
390 DynamicStateVPTests::DynamicStateVPTests (tcu::TestContext& testCtx)
391 : TestCaseGroup (testCtx, "vp_state", "Tests for viewport state")
393 /* Left blank on purpose */
396 DynamicStateVPTests::~DynamicStateVPTests ()
400 void DynamicStateVPTests::init (void)
402 ShaderMap shaderPaths;
403 shaderPaths[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
404 shaderPaths[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
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));
409 shaderPaths[glu::SHADERTYPE_GEOMETRY] = "vulkan/dynamic_state/ViewportArray.geom";
410 addChild(new InstanceFactory<ViewportArrayTestInstance>(m_testCtx, "viewport_array", "Multiple viewports and scissors", shaderPaths));