1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
6  * Copyright (c) 2018 Danylo Piliaiev <danylo.piliaiev@gmail.com>
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 Test for conditional rendering of vkCmdClearAttachments
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktConditionalClearAttachmentTests.hpp"
26 #include "vktConditionalRenderingTestUtil.hpp"
27 
28 #include "vktTestCaseUtil.hpp"
29 #include "vktDrawTestCaseUtil.hpp"
30 
31 #include "vktDrawBaseClass.hpp"
32 
33 #include "tcuTestLog.hpp"
34 #include "tcuResource.hpp"
35 #include "tcuImageCompare.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuRGBA.hpp"
38 
39 #include "vkDefs.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkTypeUtil.hpp"
42 
43 namespace vkt
44 {
45 namespace conditional
46 {
47 namespace
48 {
49 
50 struct ConditionalTestSpec : public Draw::TestSpecBase
51 {
52 	ConditionalData	conditionalData;
53 };
54 
55 class ConditionalClearAttachmentTest : public Draw::DrawTestsBaseClass
56 {
57 public:
58 	typedef		ConditionalTestSpec	TestSpec;
59 
60 								ConditionalClearAttachmentTest	(Context &context, ConditionalTestSpec testSpec);
61 
62 	virtual		tcu::TestStatus iterate							(void);
63 protected:
64 	const ConditionalData			m_conditionalData;
65 	de::SharedPtr<Draw::Buffer>		m_conditionalBuffer;
66 
67 	vk::Move<vk::VkCommandBuffer>	m_secondaryCmdBuffer;
68 };
69 
ConditionalClearAttachmentTest(Context & context,ConditionalTestSpec testSpec)70 ConditionalClearAttachmentTest::ConditionalClearAttachmentTest (Context &context, ConditionalTestSpec testSpec)
71 	: Draw::DrawTestsBaseClass(context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
72 	, m_conditionalData(testSpec.conditionalData)
73 {
74 	checkConditionalRenderingCapabilities(context, m_conditionalData);
75 
76 	m_data.push_back(Draw::VertexElementData(tcu::Vec4(0.0f), tcu::Vec4(0.0f), 0));
77 
78 	initialize();
79 
80 	m_secondaryCmdBuffer = vk::allocateCommandBuffer(m_vk, m_context.getDevice(), *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
81 };
82 
iterate(void)83 tcu::TestStatus ConditionalClearAttachmentTest::iterate (void)
84 {
85 	tcu::TestLog&		log		= m_context.getTestContext().getLog();
86 	const vk::VkQueue	queue	= m_context.getUniversalQueue();
87 	const vk::VkDevice	device	= m_context.getDevice();
88 
89 	const tcu::Vec4 clearColor	= tcu::RGBA::black().toVec();
90 	const tcu::Vec4 drawColor	= tcu::RGBA::blue().toVec();
91 
92 	beginRenderPass(m_conditionalData.useSecondaryBuffer ? vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : vk::VK_SUBPASS_CONTENTS_INLINE);
93 
94 	vk::VkCommandBuffer targetCmdBuffer = *m_cmdBuffer;
95 
96 	if (m_conditionalData.useSecondaryBuffer)
97 	{
98 		const vk::VkCommandBufferInheritanceConditionalRenderingInfoEXT conditionalRenderingInheritanceInfo =
99 		{
100 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT,
101 			DE_NULL,
102 			VK_TRUE														// conditionalRenderingEnable
103 		};
104 
105 		const vk::VkCommandBufferInheritanceInfo inheritanceInfo =
106 		{
107 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
108 			&conditionalRenderingInheritanceInfo,
109 			*m_renderPass,										        // renderPass
110 			0u,															// subpass
111 			*m_framebuffer,										        // framebuffer
112 			VK_FALSE,													// occlusionQueryEnable
113 			(vk::VkQueryControlFlags)0u,								// queryFlags
114 			(vk::VkQueryPipelineStatisticFlags)0u,						// pipelineStatistics
115 		};
116 
117 		const vk::VkCommandBufferBeginInfo commandBufferBeginInfo =
118 		{
119 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
120 			DE_NULL,
121 			vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
122 			&inheritanceInfo
123 		};
124 
125 		m_vk.beginCommandBuffer(*m_secondaryCmdBuffer, &commandBufferBeginInfo);
126 
127 		targetCmdBuffer = *m_secondaryCmdBuffer;
128 	}
129 
130 	m_vk.cmdBindPipeline(targetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
131 
132 	const vk::VkClearAttachment	clearAttachment	=
133 	{
134 		vk::VK_IMAGE_ASPECT_COLOR_BIT,			// VkImageAspectFlags	aspectMask;
135 		0u,										// deUint32				colorAttachment;
136 		vk::makeClearValueColor(drawColor)		// VkClearValue			clearValue;
137 	};
138 
139 	const vk::VkClearRect rect =
140 	{
141 		vk::makeRect2D(WIDTH, HEIGHT),	// VkRect2D    rect;
142 		0u,								// uint32_t    baseArrayLayer;
143 		1u,								// uint32_t    layerCount;
144 	};
145 
146 	if (m_conditionalData.useSecondaryBuffer)
147 	{
148 		m_vk.cmdClearAttachments(*m_secondaryCmdBuffer, 1, &clearAttachment, 1, &rect);
149 	}
150 
151 	if (m_conditionalData.conditionEnabled)
152 	{
153 		m_conditionalBuffer = createConditionalRenderingBuffer(m_context, m_conditionalData);
154 		beginConditionalRendering(m_vk, *m_cmdBuffer, *m_conditionalBuffer, m_conditionalData);
155 	}
156 
157 	if (!m_conditionalData.useSecondaryBuffer)
158 	{
159 		m_vk.cmdClearAttachments(*m_cmdBuffer, 1, &clearAttachment, 1, &rect);
160 	}
161 
162 	if (m_conditionalData.useSecondaryBuffer)
163 	{
164 		m_vk.endCommandBuffer(*m_secondaryCmdBuffer);
165 
166 		m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
167 	}
168 
169 	if (m_conditionalData.conditionEnabled)
170 	{
171 		m_vk.cmdEndConditionalRenderingEXT(*m_cmdBuffer);
172 	}
173 
174 	endRenderPass(m_vk, *m_cmdBuffer);
175 	endCommandBuffer(m_vk, *m_cmdBuffer);
176 
177 	submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
178 
179 	// Validation
180 	tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
181 								  referenceFrame.allocLevel(0);
182 
183 	const deInt32 frameWidth	= referenceFrame.getWidth();
184 	const deInt32 frameHeight	= referenceFrame.getHeight();
185 
186 	tcu::clear(referenceFrame.getLevel(0), clearColor);
187 
188 	const tcu::Vec4 referenceColor = m_conditionalData.expectCommandExecution ?
189 										drawColor : clearColor;
190 
191 	for (int y = 0; y < frameHeight; y++)
192 	{
193 		for (int x = 0; x < frameWidth; x++)
194 		{
195 			referenceFrame.getLevel(0).setPixel(referenceColor, x, y);
196 		}
197 	}
198 
199 	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
200 	const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
201 		vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
202 
203 	qpTestResult res = QP_TEST_RESULT_PASS;
204 
205 	if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
206 		referenceFrame.getLevel(0), renderedFrame, 0.05f,
207 		tcu::COMPARE_LOG_RESULT))
208 	{
209 		res = QP_TEST_RESULT_FAIL;
210 	}
211 
212 	return tcu::TestStatus(res, qpGetTestResultName(res));
213 };
214 
215 }	// anonymous
216 
ConditionalClearAttachmentTests(tcu::TestContext & testCtx)217 ConditionalClearAttachmentTests::ConditionalClearAttachmentTests (tcu::TestContext &testCtx)
218 	: TestCaseGroup	(testCtx, "clear_attachments", "vkCmdClearAttachments with conditional rendering")
219 {
220 	/* Left blank on purpose */
221 }
222 
~ConditionalClearAttachmentTests(void)223 ConditionalClearAttachmentTests::~ConditionalClearAttachmentTests (void) {}
224 
init(void)225 void ConditionalClearAttachmentTests::init (void)
226 {
227 	for (int conditionNdx = 0; conditionNdx < DE_LENGTH_OF_ARRAY(conditional::s_testsData); conditionNdx++)
228 	{
229 		const ConditionalData& conditionData = conditional::s_testsData[conditionNdx];
230 
231 		tcu::TestCaseGroup* conditionalDrawRootGroup = new tcu::TestCaseGroup(m_testCtx, de::toString(conditionData).c_str(), "");
232 
233 		ConditionalTestSpec testSpec;
234 		testSpec.conditionalData = conditionData;
235 		testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
236 		testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
237 
238 		conditionalDrawRootGroup->addChild(new Draw::InstanceFactory<ConditionalClearAttachmentTest>(m_testCtx, "clear_attachments", "", testSpec));
239 
240 		addChild(conditionalDrawRootGroup);
241 	}
242 }
243 
244 }	// conditional
245 }	// vkt
246