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"
37 #include "vktDynamicStateBaseClass.hpp"
39 #include "vktDynamicStateTestCaseUtil.hpp"
40 #include "tcuTextureUtil.hpp"
44 namespace DynamicState
49 class ViewportStateBaseCase : public DynamicStateBaseClass
52 ViewportStateBaseCase (Context &context, const char* vertexShaderName, const char* fragmentShaderName)
53 : DynamicStateBaseClass (context, vertexShaderName, fragmentShaderName)
58 m_topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
60 m_data.push_back(Vec4RGBA(tcu::Vec4(-0.5f, 0.5f, 1.0f, 1.0f), vec4Green()));
61 m_data.push_back(Vec4RGBA(tcu::Vec4(0.5f, 0.5f, 1.0f, 1.0f), vec4Green()));
62 m_data.push_back(Vec4RGBA(tcu::Vec4(-0.5f, -0.5f, 1.0f, 1.0f), vec4Green()));
63 m_data.push_back(Vec4RGBA(tcu::Vec4(0.5f, -0.5f, 1.0f, 1.0f), vec4Green()));
65 DynamicStateBaseClass::initialize();
68 virtual tcu::Texture2D buildReferenceFrame (void)
70 TCU_FAIL("Implement buildReferenceFrame() method and return valid surface!");
73 virtual void setDynamicStates (void)
75 TCU_FAIL("Implement setDynamicStates() method!");
78 virtual tcu::TestStatus iterate (void)
80 tcu::TestLog &log = m_context.getTestContext().getLog();
81 const vk::VkDevice device = m_context.getDevice();
82 const vk::VkQueue queue = m_context.getUniversalQueue();
89 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
91 const vk::VkDeviceSize vertexBufferOffset = 0;
92 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
93 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
95 m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
97 m_vk.cmdEndRenderPass(*m_cmdBuffer);
98 m_vk.endCommandBuffer(*m_cmdBuffer);
100 const vk::VkCmdBuffer cmdBuffer = *m_cmdBuffer;
101 VK_CHECK(m_vk.queueSubmit(queue, 1, &cmdBuffer, DE_NULL));
105 VK_CHECK(m_vk.queueWaitIdle(queue));
107 tcu::Texture2D referenceFrame = buildReferenceFrame();
109 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
110 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
111 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR);
113 qpTestResult res = QP_TEST_RESULT_PASS;
115 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
116 referenceFrame.getLevel(0), renderedFrame, 0.05f,
117 tcu::COMPARE_LOG_RESULT))
119 res = QP_TEST_RESULT_FAIL;
122 return tcu::TestStatus(res, qpGetTestResultName(res));
127 class ViewportParamTestInstane : public ViewportStateBaseCase
130 ViewportParamTestInstane (Context &context, ShaderMap shaders)
131 : ViewportStateBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
133 ViewportStateBaseCase::initialize();
136 virtual void setDynamicStates(void)
138 const vk::VkViewport viewport = { 0.0f, 0.0f, (float)WIDTH * 2, (float)HEIGHT * 2, 0.0f, 0.0f };
139 const vk::VkRect2D scissor = { { 0, 0 }, { WIDTH, HEIGHT } };
141 setDynamicViewportState(1, &viewport, &scissor);
142 setDynamicRasterState();
143 setDynamicBlendState();
144 setDynamicDepthStencilState();
147 virtual tcu::Texture2D buildReferenceFrame (void)
149 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
150 referenceFrame.allocLevel(0);
152 const deInt32 frameWidth = referenceFrame.getWidth();
153 const deInt32 frameHeight = referenceFrame.getHeight();
155 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
157 for (int y = 0; y < frameHeight; y++)
159 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
161 for (int x = 0; x < frameWidth; x++)
163 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
165 if (xCoord >= 0.0f && xCoord <= 1.0f && yCoord >= 0.0f && yCoord <= 1.0f)
166 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
170 return referenceFrame;
174 class ScissorParamTestInstance : public ViewportStateBaseCase
177 ScissorParamTestInstance (Context &context, ShaderMap shaders)
178 : ViewportStateBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
180 ViewportStateBaseCase::initialize();
183 virtual void setDynamicStates (void)
185 const vk::VkViewport viewport = { 0.0f, 0.0f, (float)WIDTH, (float)HEIGHT, 0.0f, 0.0f };
186 const vk::VkRect2D scissor = { { 0, 0 }, { WIDTH / 2, HEIGHT / 2 } };
188 setDynamicViewportState(1, &viewport, &scissor);
189 setDynamicRasterState();
190 setDynamicBlendState();
191 setDynamicDepthStencilState();
194 virtual tcu::Texture2D buildReferenceFrame (void)
196 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
197 referenceFrame.allocLevel(0);
199 const deInt32 frameWidth = referenceFrame.getWidth();
200 const deInt32 frameHeight = referenceFrame.getHeight();
202 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
204 for (int y = 0; y < frameHeight; y++)
206 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
208 for (int x = 0; x < frameWidth; x++)
210 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
212 if (xCoord >= -0.5f && xCoord <= 0.0f && yCoord >= -0.5f && yCoord <= 0.0f)
213 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
217 return referenceFrame;
222 class ViewportArrayTestInstance : public DynamicStateBaseClass
225 std::string m_geometryShaderName;
229 ViewportArrayTestInstance (Context &context, ShaderMap shaders)
230 : DynamicStateBaseClass (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
231 , m_geometryShaderName (shaders[glu::SHADERTYPE_GEOMETRY])
233 for (int i = 0; i < 4; i++)
235 m_data.push_back(Vec4RGBA(tcu::Vec4(-1.0f, 1.0f, (float)i, 1.0f), vec4Green()));
236 m_data.push_back(Vec4RGBA(tcu::Vec4(1.0f, 1.0f, (float)i, 1.0f), vec4Green()));
237 m_data.push_back(Vec4RGBA(tcu::Vec4(-1.0f, -1.0f, (float)i, 1.0f), vec4Green()));
238 m_data.push_back(Vec4RGBA(tcu::Vec4(1.0f, -1.0f, (float)i, 1.0f), vec4Green()));
241 DynamicStateBaseClass::initialize();
244 virtual void initPipeline (const vk::VkDevice device)
246 const vk::Unique<vk::VkShader> vs(createShader(m_vk, device,
247 *createShaderModule(m_vk, device, m_context.getBinaryCollection().get(m_vertexShaderName), 0),
248 "main", vk::VK_SHADER_STAGE_VERTEX));
250 const vk::Unique<vk::VkShader> gs(createShader(m_vk, device,
251 *createShaderModule(m_vk, device, m_context.getBinaryCollection().get(m_geometryShaderName), 0),
252 "main", vk::VK_SHADER_STAGE_GEOMETRY));
254 const vk::Unique<vk::VkShader> fs(createShader(m_vk, device,
255 *createShaderModule(m_vk, device, m_context.getBinaryCollection().get(m_fragmentShaderName), 0),
256 "main", vk::VK_SHADER_STAGE_FRAGMENT));
258 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
260 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
261 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, vk::VK_SHADER_STAGE_VERTEX));
262 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*gs, vk::VK_SHADER_STAGE_GEOMETRY));
263 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, vk::VK_SHADER_STAGE_FRAGMENT));
264 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
265 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_topology));
266 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
267 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(4));
268 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
269 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
270 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
271 pipelineCreateInfo.addState(PipelineCreateInfo::DynamicState());
273 m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
276 virtual tcu::TestStatus iterate (void)
278 tcu::TestLog &log = m_context.getTestContext().getLog();
279 const vk::VkQueue queue = m_context.getUniversalQueue();
284 const float halfWidth = (float)WIDTH / 2;
285 const float halfHeight = (float)HEIGHT / 2;
286 const deInt32 quarterWidth = WIDTH / 4;
287 const deInt32 quarterHeight = HEIGHT / 4;
289 const vk::VkViewport viewports[4] =
291 { 0.0f, 0.0f, (float)halfWidth, (float)halfHeight, 0.0f, 0.0f },
292 { halfWidth, 0.0f, (float)halfWidth, (float)halfHeight, 0.0f, 0.0f },
293 { halfWidth, halfHeight, (float)halfWidth, (float)halfHeight, 0.0f, 0.0f },
294 { 0.0f, halfHeight, (float)halfWidth, (float)halfHeight, 0.0f, 0.0f }
297 const vk::VkRect2D scissors[4] =
299 { { quarterWidth, quarterHeight }, { quarterWidth, quarterHeight } },
300 { { halfWidth, quarterHeight }, { quarterWidth, quarterHeight } },
301 { { halfWidth, halfHeight }, { quarterWidth, quarterHeight } },
302 { { quarterWidth, halfHeight }, { quarterWidth, quarterHeight } },
305 setDynamicViewportState(4, viewports, scissors);
306 setDynamicRasterState();
307 setDynamicBlendState();
308 setDynamicDepthStencilState();
310 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
312 const vk::VkDeviceSize vertexBufferOffset = 0;
313 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
314 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
316 m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
318 m_vk.cmdEndRenderPass(*m_cmdBuffer);
319 m_vk.endCommandBuffer(*m_cmdBuffer);
321 const vk::VkCmdBuffer cmdBuffer = *m_cmdBuffer;
322 VK_CHECK(m_vk.queueSubmit(queue, 1, &cmdBuffer, DE_NULL));
326 VK_CHECK(m_vk.queueWaitIdle(queue));
328 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
329 referenceFrame.allocLevel(0);
331 const deInt32 frameWidth = referenceFrame.getWidth();
332 const deInt32 frameHeight = referenceFrame.getHeight();
334 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
336 for (int y = 0; y < frameHeight; y++)
338 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
340 for (int x = 0; x < frameWidth; x++)
342 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
344 if (xCoord >= -0.5f && xCoord <= 0.5f && yCoord >= -0.5f && yCoord <= 0.5f)
345 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
349 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
350 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
351 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR);
353 qpTestResult res = QP_TEST_RESULT_PASS;
355 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
356 referenceFrame.getLevel(0), renderedFrame, 0.05f,
357 tcu::COMPARE_LOG_RESULT))
359 res = QP_TEST_RESULT_FAIL;
362 return tcu::TestStatus(res, qpGetTestResultName(res));
369 DynamicStateVPTests::DynamicStateVPTests (tcu::TestContext &testCtx)
370 : TestCaseGroup (testCtx, "vp_state", "Tests for viewport state")
372 /* Left blank on purpose */
375 DynamicStateVPTests::~DynamicStateVPTests () {}
377 void DynamicStateVPTests::init (void)
379 ShaderMap shaderPaths;
380 shaderPaths[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
381 shaderPaths[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
383 addChild(new InstanceFactory<ViewportParamTestInstane>(m_testCtx, "viewport", "Set viewport which is twice bigger than screen size", shaderPaths));
384 addChild(new InstanceFactory<ScissorParamTestInstance>(m_testCtx, "scissor", "Perform a scissor test on 1/4 bottom-left part of the surface", shaderPaths));
386 shaderPaths[glu::SHADERTYPE_GEOMETRY] = "vulkan/dynamic_state/ViewportArray.geom";
387 addChild(new InstanceFactory<ViewportArrayTestInstance>(m_testCtx, "viewport_array", "Multiple viewports and scissors", shaderPaths));