1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel Corporation
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Dynamic State Viewport Tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktDynamicStateVPTests.hpp"
27 #include "vktDynamicStateBaseClass.hpp"
28 #include "vktDynamicStateTestCaseUtil.hpp"
30 #include "vkImageUtil.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuImageCompare.hpp"
34 #include "tcuRGBA.hpp"
38 namespace DynamicState
46 class ViewportStateBaseCase : public DynamicStateBaseClass
49 ViewportStateBaseCase (Context& context, const char* vertexShaderName, const char* fragmentShaderName)
50 : DynamicStateBaseClass (context, vertexShaderName, fragmentShaderName)
55 m_topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
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()));
62 DynamicStateBaseClass::initialize();
65 virtual tcu::Texture2D buildReferenceFrame (void)
68 return tcu::Texture2D(tcu::TextureFormat(), 0, 0);
71 virtual void setDynamicStates (void)
76 virtual tcu::TestStatus iterate (void)
78 tcu::TestLog &log = m_context.getTestContext().getLog();
79 const vk::VkQueue queue = m_context.getUniversalQueue();
86 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
88 const vk::VkDeviceSize vertexBufferOffset = 0;
89 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
90 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
92 m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
94 m_vk.cmdEndRenderPass(*m_cmdBuffer);
95 m_vk.endCommandBuffer(*m_cmdBuffer);
97 vk::VkSubmitInfo submitInfo =
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;
109 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
113 VK_CHECK(m_vk.queueWaitIdle(queue));
115 tcu::Texture2D referenceFrame = buildReferenceFrame();
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);
121 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
122 referenceFrame.getLevel(0), renderedFrame, 0.05f,
123 tcu::COMPARE_LOG_RESULT))
125 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
128 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
133 class ViewportParamTestInstane : public ViewportStateBaseCase
136 ViewportParamTestInstane (Context& context, ShaderMap shaders)
137 : ViewportStateBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
139 ViewportStateBaseCase::initialize();
142 virtual void setDynamicStates(void)
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 } };
147 setDynamicViewportState(1, &viewport, &scissor);
148 setDynamicRasterizationState();
149 setDynamicBlendState();
150 setDynamicDepthStencilState();
153 virtual tcu::Texture2D buildReferenceFrame (void)
155 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
156 referenceFrame.allocLevel(0);
158 const deInt32 frameWidth = referenceFrame.getWidth();
159 const deInt32 frameHeight = referenceFrame.getHeight();
161 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
163 for (int y = 0; y < frameHeight; y++)
165 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
167 for (int x = 0; x < frameWidth; x++)
169 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
176 return referenceFrame;
180 class ScissorParamTestInstance : public ViewportStateBaseCase
183 ScissorParamTestInstance (Context& context, ShaderMap shaders)
184 : ViewportStateBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
186 ViewportStateBaseCase::initialize();
189 virtual void setDynamicStates (void)
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 } };
194 setDynamicViewportState(1, &viewport, &scissor);
195 setDynamicRasterizationState();
196 setDynamicBlendState();
197 setDynamicDepthStencilState();
200 virtual tcu::Texture2D buildReferenceFrame (void)
202 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
203 referenceFrame.allocLevel(0);
205 const deInt32 frameWidth = referenceFrame.getWidth();
206 const deInt32 frameHeight = referenceFrame.getHeight();
208 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
210 for (int y = 0; y < frameHeight; y++)
212 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
214 for (int x = 0; x < frameWidth; x++)
216 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
223 return referenceFrame;
227 class ViewportArrayTestInstance : public DynamicStateBaseClass
230 std::string m_geometryShaderName;
234 ViewportArrayTestInstance (Context& context, ShaderMap shaders)
235 : DynamicStateBaseClass (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
236 , m_geometryShaderName (shaders[glu::SHADERTYPE_GEOMETRY])
238 // Check geometry shader support
240 const vk::VkPhysicalDeviceFeatures& deviceFeatures = m_context.getDeviceFeatures();
242 if (!deviceFeatures.multiViewport)
243 throw tcu::NotSupportedError("Multi-viewport is not supported");
245 if (!deviceFeatures.geometryShader)
246 throw tcu::NotSupportedError("Geometry shaders are not supported");
249 for (int i = 0; i < 4; i++)
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()));
257 DynamicStateBaseClass::initialize();
260 virtual void initPipeline (const vk::VkDevice device)
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));
266 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
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());
281 m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
284 virtual tcu::TestStatus iterate (void)
286 tcu::TestLog &log = m_context.getTestContext().getLog();
287 const vk::VkQueue queue = m_context.getUniversalQueue();
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;
297 const vk::VkViewport viewports[4] =
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 }
305 const vk::VkRect2D scissors[4] =
307 { { quarterWidth, quarterHeight }, { quarterWidth, quarterHeight } },
308 { { (deInt32)halfWidth, quarterHeight }, { quarterWidth, quarterHeight } },
309 { { (deInt32)halfWidth, (deInt32)halfHeight }, { quarterWidth, quarterHeight } },
310 { { quarterWidth, (deInt32)halfHeight }, { quarterWidth, quarterHeight } },
313 setDynamicViewportState(4, viewports, scissors);
314 setDynamicRasterizationState();
315 setDynamicBlendState();
316 setDynamicDepthStencilState();
318 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
320 const vk::VkDeviceSize vertexBufferOffset = 0;
321 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
322 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
324 m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
326 m_vk.cmdEndRenderPass(*m_cmdBuffer);
327 m_vk.endCommandBuffer(*m_cmdBuffer);
329 vk::VkSubmitInfo submitInfo =
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;
341 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
345 VK_CHECK(m_vk.queueWaitIdle(queue));
347 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
348 referenceFrame.allocLevel(0);
350 const deInt32 frameWidth = referenceFrame.getWidth();
351 const deInt32 frameHeight = referenceFrame.getHeight();
353 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
355 for (int y = 0; y < frameHeight; y++)
357 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
359 for (int x = 0; x < frameWidth; x++)
361 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
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);
372 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
373 referenceFrame.getLevel(0), renderedFrame, 0.05f,
374 tcu::COMPARE_LOG_RESULT))
376 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
379 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
386 DynamicStateVPTests::DynamicStateVPTests (tcu::TestContext& testCtx)
387 : TestCaseGroup (testCtx, "vp_state", "Tests for viewport state")
389 /* Left blank on purpose */
392 DynamicStateVPTests::~DynamicStateVPTests ()
396 void DynamicStateVPTests::init (void)
398 ShaderMap shaderPaths;
399 shaderPaths[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
400 shaderPaths[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
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));
405 shaderPaths[glu::SHADERTYPE_GEOMETRY] = "vulkan/dynamic_state/ViewportArray.geom";
406 addChild(new InstanceFactory<ViewportArrayTestInstance>(m_testCtx, "viewport_array", "Multiple viewports and scissors", shaderPaths));