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 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.
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.
33 * \brief Dynamic State Viewport Tests
34 *//*--------------------------------------------------------------------*/
36 #include "vktDynamicStateVPTests.hpp"
38 #include "vktDynamicStateBaseClass.hpp"
39 #include "vktDynamicStateTestCaseUtil.hpp"
41 #include "vkImageUtil.hpp"
43 #include "tcuTextureUtil.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuRGBA.hpp"
49 namespace DynamicState
54 class ViewportStateBaseCase : public DynamicStateBaseClass
57 ViewportStateBaseCase (Context& context, const char* vertexShaderName, const char* fragmentShaderName)
58 : DynamicStateBaseClass (context, vertexShaderName, fragmentShaderName)
63 m_topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
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()));
70 DynamicStateBaseClass::initialize();
73 virtual tcu::Texture2D buildReferenceFrame (void)
76 return tcu::Texture2D(tcu::TextureFormat(), 0, 0);
79 virtual void setDynamicStates (void)
84 virtual tcu::TestStatus iterate (void)
86 tcu::TestLog &log = m_context.getTestContext().getLog();
87 const vk::VkQueue queue = m_context.getUniversalQueue();
94 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
96 const vk::VkDeviceSize vertexBufferOffset = 0;
97 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
98 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
100 m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
102 m_vk.cmdEndRenderPass(*m_cmdBuffer);
103 m_vk.endCommandBuffer(*m_cmdBuffer);
105 vk::VkSubmitInfo submitInfo =
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;
117 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
121 VK_CHECK(m_vk.queueWaitIdle(queue));
123 tcu::Texture2D referenceFrame = buildReferenceFrame();
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);
129 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
130 referenceFrame.getLevel(0), renderedFrame, 0.05f,
131 tcu::COMPARE_LOG_RESULT))
133 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
136 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
141 class ViewportParamTestInstane : public ViewportStateBaseCase
144 ViewportParamTestInstane (Context& context, ShaderMap shaders)
145 : ViewportStateBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
147 ViewportStateBaseCase::initialize();
150 virtual void setDynamicStates(void)
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 } };
155 setDynamicViewportState(1, &viewport, &scissor);
156 setDynamicRasterizationState();
157 setDynamicBlendState();
158 setDynamicDepthStencilState();
161 virtual tcu::Texture2D buildReferenceFrame (void)
163 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
164 referenceFrame.allocLevel(0);
166 const deInt32 frameWidth = referenceFrame.getWidth();
167 const deInt32 frameHeight = referenceFrame.getHeight();
169 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
171 for (int y = 0; y < frameHeight; y++)
173 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
175 for (int x = 0; x < frameWidth; x++)
177 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
184 return referenceFrame;
188 class ScissorParamTestInstance : public ViewportStateBaseCase
191 ScissorParamTestInstance (Context& context, ShaderMap shaders)
192 : ViewportStateBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
194 ViewportStateBaseCase::initialize();
197 virtual void setDynamicStates (void)
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 } };
202 setDynamicViewportState(1, &viewport, &scissor);
203 setDynamicRasterizationState();
204 setDynamicBlendState();
205 setDynamicDepthStencilState();
208 virtual tcu::Texture2D buildReferenceFrame (void)
210 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
211 referenceFrame.allocLevel(0);
213 const deInt32 frameWidth = referenceFrame.getWidth();
214 const deInt32 frameHeight = referenceFrame.getHeight();
216 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
218 for (int y = 0; y < frameHeight; y++)
220 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
222 for (int x = 0; x < frameWidth; x++)
224 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
231 return referenceFrame;
235 class ViewportArrayTestInstance : public DynamicStateBaseClass
238 std::string m_geometryShaderName;
242 ViewportArrayTestInstance (Context& context, ShaderMap shaders)
243 : DynamicStateBaseClass (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
244 , m_geometryShaderName (shaders[glu::SHADERTYPE_GEOMETRY])
246 // Check geometry shader support
248 const vk::VkPhysicalDeviceFeatures& deviceFeatures = m_context.getDeviceFeatures();
250 if (!deviceFeatures.multiViewport)
251 throw tcu::NotSupportedError("Multi-viewport is not supported");
253 if (!deviceFeatures.geometryShader)
254 throw tcu::NotSupportedError("Geometry shaders are not supported");
257 for (int i = 0; i < 4; i++)
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()));
265 DynamicStateBaseClass::initialize();
268 virtual void initPipeline (const vk::VkDevice device)
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));
274 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
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());
289 m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
292 virtual tcu::TestStatus iterate (void)
294 tcu::TestLog &log = m_context.getTestContext().getLog();
295 const vk::VkQueue queue = m_context.getUniversalQueue();
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;
305 const vk::VkViewport viewports[4] =
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 }
313 const vk::VkRect2D scissors[4] =
315 { { quarterWidth, quarterHeight }, { quarterWidth, quarterHeight } },
316 { { (deInt32)halfWidth, quarterHeight }, { quarterWidth, quarterHeight } },
317 { { (deInt32)halfWidth, (deInt32)halfHeight }, { quarterWidth, quarterHeight } },
318 { { quarterWidth, (deInt32)halfHeight }, { quarterWidth, quarterHeight } },
321 setDynamicViewportState(4, viewports, scissors);
322 setDynamicRasterizationState();
323 setDynamicBlendState();
324 setDynamicDepthStencilState();
326 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
328 const vk::VkDeviceSize vertexBufferOffset = 0;
329 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
330 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
332 m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
334 m_vk.cmdEndRenderPass(*m_cmdBuffer);
335 m_vk.endCommandBuffer(*m_cmdBuffer);
337 vk::VkSubmitInfo submitInfo =
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;
349 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
353 VK_CHECK(m_vk.queueWaitIdle(queue));
355 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
356 referenceFrame.allocLevel(0);
358 const deInt32 frameWidth = referenceFrame.getWidth();
359 const deInt32 frameHeight = referenceFrame.getHeight();
361 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
363 for (int y = 0; y < frameHeight; y++)
365 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
367 for (int x = 0; x < frameWidth; x++)
369 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
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);
380 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
381 referenceFrame.getLevel(0), renderedFrame, 0.05f,
382 tcu::COMPARE_LOG_RESULT))
384 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
387 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
394 DynamicStateVPTests::DynamicStateVPTests (tcu::TestContext& testCtx)
395 : TestCaseGroup (testCtx, "vp_state", "Tests for viewport state")
397 /* Left blank on purpose */
400 DynamicStateVPTests::~DynamicStateVPTests ()
404 void DynamicStateVPTests::init (void)
406 ShaderMap shaderPaths;
407 shaderPaths[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
408 shaderPaths[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
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));
413 shaderPaths[glu::SHADERTYPE_GEOMETRY] = "vulkan/dynamic_state/ViewportArray.geom";
414 addChild(new InstanceFactory<ViewportArrayTestInstance>(m_testCtx, "viewport_array", "Multiple viewports and scissors", shaderPaths));