Home | History | Annotate | Download | only in dynamic_state
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2015 The Khronos Group Inc.
      6  * Copyright (c) 2015 Intel Corporation
      7  *
      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
     11  *
     12  *      http://www.apache.org/licenses/LICENSE-2.0
     13  *
     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.
     19  *
     20  *//*!
     21  * \file
     22  * \brief Dynamic State Viewport Tests
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktDynamicStateVPTests.hpp"
     26 
     27 #include "vktDynamicStateBaseClass.hpp"
     28 #include "vktDynamicStateTestCaseUtil.hpp"
     29 
     30 #include "vkImageUtil.hpp"
     31 
     32 #include "tcuTextureUtil.hpp"
     33 #include "tcuImageCompare.hpp"
     34 #include "tcuRGBA.hpp"
     35 
     36 namespace vkt
     37 {
     38 namespace DynamicState
     39 {
     40 
     41 using namespace Draw;
     42 
     43 namespace
     44 {
     45 
     46 class ViewportStateBaseCase : public DynamicStateBaseClass
     47 {
     48 public:
     49 	ViewportStateBaseCase (Context& context, const char* vertexShaderName, const char* fragmentShaderName)
     50 		: DynamicStateBaseClass	(context, vertexShaderName, fragmentShaderName)
     51 	{}
     52 
     53 	void initialize(void)
     54 	{
     55 		m_topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
     56 
     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()));
     61 
     62 		DynamicStateBaseClass::initialize();
     63 	}
     64 
     65 	virtual tcu::Texture2D buildReferenceFrame (void)
     66 	{
     67 		DE_ASSERT(false);
     68 		return tcu::Texture2D(tcu::TextureFormat(), 0, 0);
     69 	}
     70 
     71 	virtual void setDynamicStates (void)
     72 	{
     73 		DE_ASSERT(false);
     74 	}
     75 
     76 	virtual tcu::TestStatus iterate (void)
     77 	{
     78 		tcu::TestLog &log			= m_context.getTestContext().getLog();
     79 		const vk::VkQueue queue		= m_context.getUniversalQueue();
     80 
     81 		beginRenderPass();
     82 
     83 		// set states here
     84 		setDynamicStates();
     85 
     86 		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
     87 
     88 		const vk::VkDeviceSize vertexBufferOffset = 0;
     89 		const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
     90 		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
     91 
     92 		m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
     93 
     94 		m_vk.cmdEndRenderPass(*m_cmdBuffer);
     95 		m_vk.endCommandBuffer(*m_cmdBuffer);
     96 
     97 		vk::VkSubmitInfo submitInfo =
     98 		{
     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;
    108 		};
    109 		m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
    110 
    111 		// validation
    112 		{
    113 			VK_CHECK(m_vk.queueWaitIdle(queue));
    114 
    115 			tcu::Texture2D referenceFrame = buildReferenceFrame();
    116 
    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);
    120 
    121 			if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
    122 				referenceFrame.getLevel(0), renderedFrame, 0.05f,
    123 				tcu::COMPARE_LOG_RESULT))
    124 			{
    125 				return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
    126 			}
    127 
    128 			return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
    129 		}
    130 	}
    131 };
    132 
    133 class ViewportParamTestInstane : public ViewportStateBaseCase
    134 {
    135 public:
    136 	ViewportParamTestInstane (Context& context, ShaderMap shaders)
    137 		: ViewportStateBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
    138 	{
    139 		ViewportStateBaseCase::initialize();
    140 	}
    141 
    142 	virtual void setDynamicStates(void)
    143 	{
    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 } };
    146 
    147 		setDynamicViewportState(1, &viewport, &scissor);
    148 		setDynamicRasterizationState();
    149 		setDynamicBlendState();
    150 		setDynamicDepthStencilState();
    151 	}
    152 
    153 	virtual tcu::Texture2D buildReferenceFrame (void)
    154 	{
    155 		tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
    156 		referenceFrame.allocLevel(0);
    157 
    158 		const deInt32 frameWidth	= referenceFrame.getWidth();
    159 		const deInt32 frameHeight	= referenceFrame.getHeight();
    160 
    161 		tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
    162 
    163 		for (int y = 0; y < frameHeight; y++)
    164 		{
    165 			const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
    166 
    167 			for (int x = 0; x < frameWidth; x++)
    168 			{
    169 				const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
    170 
    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);
    173 			}
    174 		}
    175 
    176 		return referenceFrame;
    177 	}
    178 };
    179 
    180 class ScissorParamTestInstance : public ViewportStateBaseCase
    181 {
    182 public:
    183 	ScissorParamTestInstance (Context& context, ShaderMap shaders)
    184 		: ViewportStateBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
    185 	{
    186 		ViewportStateBaseCase::initialize();
    187 	}
    188 
    189 	virtual void setDynamicStates (void)
    190 	{
    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 } };
    193 
    194 		setDynamicViewportState(1, &viewport, &scissor);
    195 		setDynamicRasterizationState();
    196 		setDynamicBlendState();
    197 		setDynamicDepthStencilState();
    198 	}
    199 
    200 	virtual tcu::Texture2D buildReferenceFrame (void)
    201 	{
    202 		tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
    203 		referenceFrame.allocLevel(0);
    204 
    205 		const deInt32 frameWidth	= referenceFrame.getWidth();
    206 		const deInt32 frameHeight	= referenceFrame.getHeight();
    207 
    208 		tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
    209 
    210 		for (int y = 0; y < frameHeight; y++)
    211 		{
    212 			const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
    213 
    214 			for (int x = 0; x < frameWidth; x++)
    215 			{
    216 				const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
    217 
    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);
    220 			}
    221 		}
    222 
    223 		return referenceFrame;
    224 	}
    225 };
    226 
    227 class ViewportArrayTestInstance : public DynamicStateBaseClass
    228 {
    229 protected:
    230 	std::string m_geometryShaderName;
    231 
    232 public:
    233 
    234 	ViewportArrayTestInstance (Context& context, ShaderMap shaders)
    235 		: DynamicStateBaseClass	(context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
    236 		, m_geometryShaderName	(shaders[glu::SHADERTYPE_GEOMETRY])
    237 	{
    238 		// Check geometry shader support
    239 		{
    240 			const vk::VkPhysicalDeviceFeatures& deviceFeatures = m_context.getDeviceFeatures();
    241 
    242 			if (!deviceFeatures.multiViewport)
    243 				throw tcu::NotSupportedError("Multi-viewport is not supported");
    244 
    245 			if (!deviceFeatures.geometryShader)
    246 				throw tcu::NotSupportedError("Geometry shaders are not supported");
    247 		}
    248 
    249 		for (int i = 0; i < 4; i++)
    250 		{
    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()));
    255 		}
    256 
    257 		DynamicStateBaseClass::initialize();
    258 	}
    259 
    260 	virtual void initPipeline (const vk::VkDevice device)
    261 	{
    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));
    265 
    266 		const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
    267 
    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());
    280 
    281 		m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
    282 	}
    283 
    284 	virtual tcu::TestStatus iterate (void)
    285 	{
    286 		tcu::TestLog &log = m_context.getTestContext().getLog();
    287 		const vk::VkQueue queue = m_context.getUniversalQueue();
    288 
    289 		beginRenderPass();
    290 
    291 		// set states here
    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;
    296 
    297 		const vk::VkViewport viewports[4] =
    298 		{
    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 }
    303 		};
    304 
    305 		const vk::VkRect2D scissors[4] =
    306 		{
    307 			{ { quarterWidth, quarterHeight }, { quarterWidth, quarterHeight } },
    308 			{ { (deInt32)halfWidth, quarterHeight }, { quarterWidth, quarterHeight } },
    309 			{ { (deInt32)halfWidth, (deInt32)halfHeight }, { quarterWidth, quarterHeight } },
    310 			{ { quarterWidth, (deInt32)halfHeight }, { quarterWidth, quarterHeight } },
    311 		};
    312 
    313 		setDynamicViewportState(4, viewports, scissors);
    314 		setDynamicRasterizationState();
    315 		setDynamicBlendState();
    316 		setDynamicDepthStencilState();
    317 
    318 		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
    319 
    320 		const vk::VkDeviceSize vertexBufferOffset = 0;
    321 		const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
    322 		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
    323 
    324 		m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
    325 
    326 		m_vk.cmdEndRenderPass(*m_cmdBuffer);
    327 		m_vk.endCommandBuffer(*m_cmdBuffer);
    328 
    329 		vk::VkSubmitInfo submitInfo =
    330 		{
    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;
    340 		};
    341 		m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
    342 
    343 		// validation
    344 		{
    345 			VK_CHECK(m_vk.queueWaitIdle(queue));
    346 
    347 			tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
    348 			referenceFrame.allocLevel(0);
    349 
    350 			const deInt32 frameWidth = referenceFrame.getWidth();
    351 			const deInt32 frameHeight = referenceFrame.getHeight();
    352 
    353 			tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
    354 
    355 			for (int y = 0; y < frameHeight; y++)
    356 			{
    357 				const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
    358 
    359 				for (int x = 0; x < frameWidth; x++)
    360 				{
    361 					const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
    362 
    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);
    365 				}
    366 			}
    367 
    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);
    371 
    372 			if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
    373 				referenceFrame.getLevel(0), renderedFrame, 0.05f,
    374 				tcu::COMPARE_LOG_RESULT))
    375 			{
    376 				return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
    377 			}
    378 
    379 			return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
    380 		}
    381 	}
    382 };
    383 
    384 } //anonymous
    385 
    386 DynamicStateVPTests::DynamicStateVPTests (tcu::TestContext& testCtx)
    387 	: TestCaseGroup (testCtx, "vp_state", "Tests for viewport state")
    388 {
    389 	/* Left blank on purpose */
    390 }
    391 
    392 DynamicStateVPTests::~DynamicStateVPTests ()
    393 {
    394 }
    395 
    396 void DynamicStateVPTests::init (void)
    397 {
    398 	ShaderMap shaderPaths;
    399 	shaderPaths[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
    400 	shaderPaths[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
    401 
    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));
    404 
    405 	shaderPaths[glu::SHADERTYPE_GEOMETRY] = "vulkan/dynamic_state/ViewportArray.geom";
    406 	addChild(new InstanceFactory<ViewportArrayTestInstance>(m_testCtx, "viewport_array", "Multiple viewports and scissors", shaderPaths));
    407 }
    408 
    409 } // DynamicState
    410 } // vkt
    411