• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Intel Corporation
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Dynamic State Tests - General
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktDynamicStateGeneralTests.hpp"
28 
29 #include "vktTestCaseUtil.hpp"
30 #include "vktDynamicStateTestCaseUtil.hpp"
31 #include "vktDynamicStateBaseClass.hpp"
32 #include "vktDrawCreateInfoUtil.hpp"
33 #include "vktDrawImageObjectUtil.hpp"
34 #include "vktDrawBufferObjectUtil.hpp"
35 
36 #include "vkImageUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 
39 #include "tcuTestLog.hpp"
40 #include "tcuResource.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuTextureUtil.hpp"
43 #include "tcuRGBA.hpp"
44 
45 #include "vkDefs.hpp"
46 #include "vkCmdUtil.hpp"
47 
48 namespace vkt
49 {
50 namespace DynamicState
51 {
52 
53 using namespace Draw;
54 
55 namespace
56 {
57 
58 class StateSwitchTestInstance : public DynamicStateBaseClass
59 {
60 public:
StateSwitchTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const ShaderMap & shaders)61 	StateSwitchTestInstance (Context &context, vk::PipelineConstructionType pipelineConstructionType, const ShaderMap& shaders)
62 		: DynamicStateBaseClass (context, pipelineConstructionType, shaders.at(glu::SHADERTYPE_VERTEX), shaders.at(glu::SHADERTYPE_FRAGMENT), shaders.at(glu::SHADERTYPE_MESH))
63 	{
64 		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
65 		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
66 		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
67 		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
68 
69 		DynamicStateBaseClass::initialize();
70 	}
71 
iterate(void)72 	virtual tcu::TestStatus iterate (void)
73 	{
74 		tcu::TestLog&		log		= m_context.getTestContext().getLog();
75 		const vk::VkQueue	queue	= m_context.getUniversalQueue();
76 		const vk::VkDevice	device	= m_context.getDevice();
77 
78 		beginRenderPass();
79 
80 		// bind states here
81 		vk::VkViewport viewport = { 0, 0, (float)WIDTH, (float)HEIGHT, 0.0f, 0.0f };
82 		vk::VkRect2D scissor_1	= { { 0, 0 }, { WIDTH / 2, HEIGHT / 2 } };
83 		vk::VkRect2D scissor_2	= { { WIDTH / 2, HEIGHT / 2 }, { WIDTH / 2, HEIGHT / 2 } };
84 
85 		setDynamicRasterizationState();
86 		setDynamicBlendState();
87 		setDynamicDepthStencilState();
88 
89 		m_pipeline.bind(*m_cmdBuffer);
90 
91 #ifndef CTS_USES_VULKANSC
92 		if (m_isMesh)
93 		{
94 			const auto numVert = static_cast<uint32_t>(m_data.size());
95 			DE_ASSERT(numVert >= 2u);
96 
97 			m_vk.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u, nullptr);
98 			pushVertexOffset(0u, *m_pipelineLayout);
99 
100 			// bind first state
101 			setDynamicViewportState(1, &viewport, &scissor_1);
102 			m_vk.cmdDrawMeshTasksEXT(*m_cmdBuffer, numVert - 2u, 1u, 1u);
103 
104 			// bind second state
105 			setDynamicViewportState(1, &viewport, &scissor_2);
106 			m_vk.cmdDrawMeshTasksEXT(*m_cmdBuffer, numVert - 2u, 1u, 1u);
107 		}
108 		else
109 #endif // CTS_USES_VULKANSC
110 		{
111 			const vk::VkDeviceSize vertexBufferOffset	= 0;
112 			const vk::VkBuffer vertexBuffer				= m_vertexBuffer->object();
113 			m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
114 
115 			// bind first state
116 			setDynamicViewportState(1, &viewport, &scissor_1);
117 			m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
118 
119 			// bind second state
120 			setDynamicViewportState(1, &viewport, &scissor_2);
121 			m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
122 		}
123 
124 		m_renderPass.end(m_vk, *m_cmdBuffer);
125 		endCommandBuffer(m_vk, *m_cmdBuffer);
126 
127 		submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
128 
129 		//validation
130 		tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
131 		referenceFrame.allocLevel(0);
132 
133 		const deInt32 frameWidth	= referenceFrame.getWidth();
134 		const deInt32 frameHeight	= referenceFrame.getHeight();
135 
136 		tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
137 
138 		for (int y = 0; y < frameHeight; y++)
139 		{
140 			const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
141 
142 			for (int x = 0; x < frameWidth; x++)
143 			{
144 				const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
145 
146 				if ((yCoord >= -1.0f && yCoord <= 0.0f && xCoord >= -1.0f && xCoord <= 0.0f) ||
147 					(yCoord > 0.0f && yCoord <= 1.0f && xCoord > 0.0f && xCoord < 1.0f))
148 					referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
149 			}
150 		}
151 
152 		const vk::VkOffset3D zeroOffset					= { 0, 0, 0 };
153 		const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
154 																						  vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT,
155 																						  vk::VK_IMAGE_ASPECT_COLOR_BIT);
156 
157 		if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
158 			referenceFrame.getLevel(0), renderedFrame, 0.05f,
159 			tcu::COMPARE_LOG_RESULT))
160 		{
161 
162 			return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
163 		}
164 
165 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
166 	}
167 };
168 
169 class BindOrderTestInstance : public DynamicStateBaseClass
170 {
171 public:
BindOrderTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const ShaderMap & shaders)172 	BindOrderTestInstance (Context& context, vk::PipelineConstructionType pipelineConstructionType, const ShaderMap& shaders)
173 		: DynamicStateBaseClass (context, pipelineConstructionType, shaders.at(glu::SHADERTYPE_VERTEX), shaders.at(glu::SHADERTYPE_FRAGMENT), shaders.at(glu::SHADERTYPE_MESH))
174 	{
175 		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
176 		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
177 		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
178 		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
179 
180 		DynamicStateBaseClass::initialize();
181 	}
182 
iterate(void)183 	virtual tcu::TestStatus iterate (void)
184 	{
185 		tcu::TestLog		&log	= m_context.getTestContext().getLog();
186 		const vk::VkQueue	queue	= m_context.getUniversalQueue();
187 		const vk::VkDevice	device	= m_context.getDevice();
188 
189 		beginRenderPass();
190 
191 		// bind states here
192 		vk::VkViewport viewport = { 0.0f, 0.0f, (float)WIDTH, (float)HEIGHT, 0.0f, 0.0f };
193 		vk::VkRect2D scissor_1	= { { 0, 0 }, { WIDTH / 2, HEIGHT / 2 } };
194 		vk::VkRect2D scissor_2	= { { WIDTH / 2, HEIGHT / 2 }, { WIDTH / 2, HEIGHT / 2 } };
195 
196 		setDynamicRasterizationState();
197 		setDynamicBlendState();
198 		setDynamicDepthStencilState();
199 		setDynamicViewportState(1, &viewport, &scissor_1);
200 
201 		m_pipeline.bind(*m_cmdBuffer);
202 
203 #ifndef CTS_USES_VULKANSC
204 		if (m_isMesh)
205 		{
206 			const auto numVert = static_cast<uint32_t>(m_data.size());
207 			DE_ASSERT(numVert >= 2u);
208 
209 			m_vk.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u, nullptr);
210 			pushVertexOffset(0u, *m_pipelineLayout);
211 
212 			// rebind in different order
213 			setDynamicBlendState();
214 			setDynamicRasterizationState();
215 			setDynamicDepthStencilState();
216 
217 			// bind first state
218 			setDynamicViewportState(1, &viewport, &scissor_1);
219 			m_vk.cmdDrawMeshTasksEXT(*m_cmdBuffer, numVert - 2u, 1u, 1u);
220 
221 			setDynamicViewportState(1, &viewport, &scissor_2);
222 			m_vk.cmdDrawMeshTasksEXT(*m_cmdBuffer, numVert - 2u, 1u, 1u);
223 		}
224 		else
225 #endif // CTS_USES_VULKANSC
226 		{
227 			const vk::VkDeviceSize vertexBufferOffset = 0;
228 			const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
229 			m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
230 
231 			// rebind in different order
232 			setDynamicBlendState();
233 			setDynamicRasterizationState();
234 			setDynamicDepthStencilState();
235 
236 			// bind first state
237 			setDynamicViewportState(1, &viewport, &scissor_1);
238 			m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
239 
240 			setDynamicViewportState(1, &viewport, &scissor_2);
241 			m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
242 		}
243 
244 		m_renderPass.end(m_vk, *m_cmdBuffer);
245 		endCommandBuffer(m_vk, *m_cmdBuffer);
246 
247 		submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
248 
249 		//validation
250 		tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
251 		referenceFrame.allocLevel(0);
252 
253 		const deInt32 frameWidth = referenceFrame.getWidth();
254 		const deInt32 frameHeight = referenceFrame.getHeight();
255 
256 		tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
257 
258 		for (int y = 0; y < frameHeight; y++)
259 		{
260 			const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
261 
262 			for (int x = 0; x < frameWidth; x++)
263 			{
264 				const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
265 
266 				if ((yCoord >= -1.0f && yCoord <= 0.0f && xCoord >= -1.0f && xCoord <= 0.0f) ||
267 					(yCoord > 0.0f && yCoord <= 1.0f && xCoord > 0.0f && xCoord < 1.0f))
268 					referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
269 			}
270 		}
271 
272 		const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
273 		const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
274 			vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
275 
276 		if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
277 			referenceFrame.getLevel(0), renderedFrame, 0.05f,
278 			tcu::COMPARE_LOG_RESULT))
279 		{
280 			return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
281 		}
282 
283 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
284 	}
285 };
286 
287 class StatePersistenceTestInstance : public DynamicStateBaseClass
288 {
289 protected:
290 	vk::GraphicsPipelineWrapper	m_pipelineAdditional;
291 
292 public:
StatePersistenceTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const ShaderMap & shaders)293 	StatePersistenceTestInstance (Context& context, vk::PipelineConstructionType pipelineConstructionType, const ShaderMap& shaders)
294 		: DynamicStateBaseClass (context, pipelineConstructionType, shaders.at(glu::SHADERTYPE_VERTEX), shaders.at(glu::SHADERTYPE_FRAGMENT), shaders.at(glu::SHADERTYPE_MESH))
295 		, m_pipelineAdditional	(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType)
296 	{
297 		// This test does not make sense for mesh shader variants.
298 		DE_ASSERT(!m_isMesh);
299 
300 		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
301 		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
302 		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
303 		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
304 
305 		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
306 		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
307 		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
308 		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
309 		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
310 		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
311 
312 		DynamicStateBaseClass::initialize();
313 	}
initPipeline(const vk::VkDevice device)314 	virtual void initPipeline (const vk::VkDevice device)
315 	{
316 		const vk::ShaderWrapper					vs			(vk::ShaderWrapper(m_vk, device, m_context.getBinaryCollection().get(m_vertexShaderName), 0));
317 		const vk::ShaderWrapper					fs			(vk::ShaderWrapper(m_vk, device, m_context.getBinaryCollection().get(m_fragmentShaderName), 0));
318 		std::vector<vk::VkViewport>				viewports	{ { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } };
319 		std::vector<vk::VkRect2D>				scissors	{ { { 0u, 0u }, { 0u, 0u } } };
320 
321 		const PipelineCreateInfo::ColorBlendState::Attachment	attachmentState;
322 		const PipelineCreateInfo::ColorBlendState				colorBlendState(1, static_cast<const vk::VkPipelineColorBlendAttachmentState*>(&attachmentState));
323 		const PipelineCreateInfo::RasterizerState				rasterizerState;
324 		const PipelineCreateInfo::DepthStencilState				depthStencilState;
325 		const PipelineCreateInfo::DynamicState					dynamicState;
326 
327 		m_pipeline.setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
328 				  .setDynamicState(static_cast<const vk::VkPipelineDynamicStateCreateInfo*>(&dynamicState))
329 				  .setDefaultMultisampleState()
330 				  .setupVertexInputState(&m_vertexInputState)
331 				  .setupPreRasterizationShaderState(viewports,
332 													scissors,
333 													m_pipelineLayout,
334 													*m_renderPass,
335 													0u,
336 													vs,
337 													static_cast<const vk::VkPipelineRasterizationStateCreateInfo*>(&rasterizerState))
338 				  .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, fs, static_cast<const vk::VkPipelineDepthStencilStateCreateInfo*>(&depthStencilState))
339 				  .setupFragmentOutputState(*m_renderPass, 0u, static_cast<const vk::VkPipelineColorBlendStateCreateInfo*>(&colorBlendState))
340 				  .setMonolithicPipelineLayout(m_pipelineLayout)
341 				  .buildPipeline();
342 
343 		m_pipelineAdditional.setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
344 				  .setDynamicState(static_cast<const vk::VkPipelineDynamicStateCreateInfo*>(&dynamicState))
345 				  .setDefaultMultisampleState()
346 				  .setupVertexInputState(&m_vertexInputState)
347 				  .setupPreRasterizationShaderState(viewports,
348 													scissors,
349 													m_pipelineLayout,
350 													*m_renderPass,
351 													0u,
352 													vs,
353 													static_cast<const vk::VkPipelineRasterizationStateCreateInfo*>(&rasterizerState))
354 				  .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, fs, static_cast<const vk::VkPipelineDepthStencilStateCreateInfo*>(&depthStencilState))
355 				  .setupFragmentOutputState(*m_renderPass, 0u, static_cast<const vk::VkPipelineColorBlendStateCreateInfo*>(&colorBlendState))
356 				  .setMonolithicPipelineLayout(m_pipelineLayout)
357 				  .buildPipeline();
358 	}
359 
iterate(void)360 	virtual tcu::TestStatus iterate(void)
361 	{
362 		tcu::TestLog&		log			= m_context.getTestContext().getLog();
363 		const vk::VkQueue	queue		= m_context.getUniversalQueue();
364 		const vk::VkDevice	device		= m_context.getDevice();
365 
366 		beginRenderPass();
367 
368 		// bind states here
369 		const vk::VkViewport viewport	= { 0.0f, 0.0f, (float)WIDTH, (float)HEIGHT, 0.0f, 0.0f };
370 		const vk::VkRect2D scissor_1	= { { 0, 0 }, { WIDTH / 2, HEIGHT / 2 } };
371 		const vk::VkRect2D scissor_2	= { { WIDTH / 2, HEIGHT / 2 }, { WIDTH / 2, HEIGHT / 2 } };
372 
373 		setDynamicRasterizationState();
374 		setDynamicBlendState();
375 		setDynamicDepthStencilState();
376 
377 		m_pipeline.bind(*m_cmdBuffer);
378 
379 		const vk::VkDeviceSize vertexBufferOffset = 0;
380 		const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
381 		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
382 
383 		// bind first state
384 		setDynamicViewportState(1, &viewport, &scissor_1);
385 		// draw quad using vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
386 		m_vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
387 
388 		m_pipelineAdditional.bind(*m_cmdBuffer);
389 
390 		// bind second state
391 		setDynamicViewportState(1, &viewport, &scissor_2);
392 		// draw quad using vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
393 		m_vk.cmdDraw(*m_cmdBuffer, 6, 1, 4, 0);
394 
395 		m_renderPass.end(m_vk, *m_cmdBuffer);
396 		endCommandBuffer(m_vk, *m_cmdBuffer);
397 
398 		submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
399 
400 		//validation
401 		tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
402 		referenceFrame.allocLevel(0);
403 
404 		const deInt32 frameWidth	= referenceFrame.getWidth();
405 		const deInt32 frameHeight	= referenceFrame.getHeight();
406 
407 		tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
408 
409 		for (int y = 0; y < frameHeight; y++)
410 		{
411 			const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
412 
413 			for (int x = 0; x < frameWidth; x++)
414 			{
415 				const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
416 
417 				if (yCoord >= -1.0f && yCoord <= 0.0f && xCoord >= -1.0f && xCoord <= 0.0f)
418 					referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
419 				else if (yCoord > 0.0f && yCoord <= 1.0f && xCoord > 0.0f && xCoord < 1.0f)
420 					referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
421 			}
422 		}
423 
424 		const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
425 		const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
426 			vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
427 
428 		if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
429 			referenceFrame.getLevel(0), renderedFrame, 0.05f,
430 			tcu::COMPARE_LOG_RESULT))
431 		{
432 			return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
433 		}
434 
435 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
436 	}
437 };
438 
439 #ifndef CTS_USES_VULKANSC
checkMeshShaderSupport(Context & context)440 void checkMeshShaderSupport (Context& context)
441 {
442 	context.requireDeviceFunctionality("VK_EXT_mesh_shader");
443 }
444 #endif // CTS_USES_VULKANSC
445 
checkNothing(Context &)446 void checkNothing (Context&)
447 {
448 }
449 
450 } //anonymous
451 
452 // General tests for dynamic states
DynamicStateGeneralTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)453 DynamicStateGeneralTests::DynamicStateGeneralTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
454 	: TestCaseGroup					(testCtx, "general_state")
455 	, m_pipelineConstructionType	(pipelineConstructionType)
456 {
457 	/* Left blank on purpose */
458 }
459 
~DynamicStateGeneralTests(void)460 DynamicStateGeneralTests::~DynamicStateGeneralTests (void) {}
461 
init(void)462 void DynamicStateGeneralTests::init (void)
463 {
464 	ShaderMap basePaths;
465 	basePaths[glu::SHADERTYPE_FRAGMENT]	= "vulkan/dynamic_state/VertexFetch.frag";
466 	basePaths[glu::SHADERTYPE_MESH]		= nullptr;
467 	basePaths[glu::SHADERTYPE_VERTEX]	= nullptr;
468 
469 	for (int i = 0; i < 2; ++i)
470 	{
471 		const bool					isMesh				= (i > 0);
472 		ShaderMap					shaderPaths			(basePaths);
473 		std::string					nameSuffix;
474 		FunctionSupport0::Function	checkSupportFunc;
475 
476 		if (isMesh)
477 		{
478 #ifndef CTS_USES_VULKANSC
479 			shaderPaths[glu::SHADERTYPE_MESH] = "vulkan/dynamic_state/VertexFetch.mesh";
480 			nameSuffix = "_mesh";
481 			checkSupportFunc = checkMeshShaderSupport;
482 #else
483 			continue;
484 #endif // CTS_USES_VULKANSC
485 		}
486 		else
487 		{
488 			shaderPaths[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
489 			checkSupportFunc = checkNothing;
490 		}
491 
492 		// Perform multiple draws with different VP states (scissor test)
493 		addChild(new InstanceFactory<StateSwitchTestInstance, FunctionSupport0>(m_testCtx, "state_switch" + nameSuffix, m_pipelineConstructionType, shaderPaths, checkSupportFunc));
494 		// Check if binding order is not important for pipeline configuration
495 		addChild(new InstanceFactory<BindOrderTestInstance, FunctionSupport0>(m_testCtx, "bind_order" + nameSuffix, m_pipelineConstructionType, shaderPaths, checkSupportFunc));
496 		if (!isMesh) {
497 			// Check if bound states are persistent across pipelines
498 			addChild(new InstanceFactory<StatePersistenceTestInstance>(m_testCtx, "state_persistence" + nameSuffix, m_pipelineConstructionType, shaderPaths));
499 		}
500 	}
501 }
502 
503 } // DynamicState
504 } // vkt
505