• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (c) 2022 Valve 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 Test for conditional rendering with commands that ignore conditions
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktConditionalIgnoreTests.hpp"
26 #include "vktConditionalRenderingTestUtil.hpp"
27 
28 #include "vktTestCase.hpp"
29 #include "vkPrograms.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vktTestCaseUtil.hpp"
32 #include "vkImageWithMemory.hpp"
33 
34 #include "vktTestCase.hpp"
35 
36 #include "vkDefs.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkObjUtil.hpp"
40 #include "vkBufferWithMemory.hpp"
41 #include "vkImageWithMemory.hpp"
42 #include "vkBuilderUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkImageUtil.hpp"
45 #include "vkBarrierUtil.hpp"
46 
47 #include "tcuImageCompare.hpp"
48 #include "tcuDefs.hpp"
49 #include "tcuTextureUtil.hpp"
50 #include "tcuTestLog.hpp"
51 
52 #include <vector>
53 #include <sstream>
54 #include <algorithm>
55 #include <utility>
56 #include <iterator>
57 #include <string>
58 #include <limits>
59 #include <memory>
60 #include <functional>
61 #include <cstddef>
62 #include <set>
63 
64 
65 namespace vkt
66 {
67 namespace conditional
68 {
69 namespace
70 {
71 
72 using namespace vk;
73 
74 class ConditionalIgnoreClearTestCase : public vkt::TestCase
75 {
76 public:
77 	ConditionalIgnoreClearTestCase(tcu::TestContext& context, const std::string& name, const ConditionalData& data);
initPrograms(SourceCollections &) const78 	void            initPrograms            (SourceCollections&) const override { }
79 	TestInstance*   createInstance          (Context& context) const override;
checkSupport(Context & context) const80 	void            checkSupport            (Context& context) const override
81 	{
82 		context.requireDeviceFunctionality("VK_EXT_conditional_rendering");
83 		if (m_data.conditionInherited && !context.getConditionalRenderingFeaturesEXT().inheritedConditionalRendering)
84 			TCU_THROW(NotSupportedError, "Device does not support inherited conditional rendering");
85 	}
86 private:
87 	const ConditionalData m_data;
88 };
89 
90 
91 class ConditionalIgnoreClearTestInstance : public vkt::TestInstance
92 {
93 public:
ConditionalIgnoreClearTestInstance(Context & context,const ConditionalData & data)94 	ConditionalIgnoreClearTestInstance(Context& context, const ConditionalData& data)
95 		: vkt::TestInstance (context)
96 		, m_data(data)
97 	{ };
98 	virtual tcu::TestStatus iterate (void);
99 private:
100 	const ConditionalData m_data;
101 };
102 
103 
ConditionalIgnoreClearTestCase(tcu::TestContext & context,const std::string & name,const ConditionalData & data)104 ConditionalIgnoreClearTestCase::ConditionalIgnoreClearTestCase(tcu::TestContext& context, const std::string& name, const ConditionalData& data)
105 	: vkt::TestCase (context, name)
106 	, m_data(data)
107 { }
108 
createInstance(Context & context) const109 TestInstance* ConditionalIgnoreClearTestCase::createInstance(Context& context) const
110 {
111 	return new ConditionalIgnoreClearTestInstance(context, m_data);
112 }
113 
114 //make a buffer to read an image back after rendering
makeBufferForImage(const DeviceInterface & vkd,const VkDevice device,Allocator & allocator,VkFormat imageFormat,VkExtent3D imageExtent)115 std::unique_ptr<BufferWithMemory> makeBufferForImage(const DeviceInterface& vkd, const VkDevice device, Allocator& allocator, VkFormat imageFormat, VkExtent3D imageExtent)
116 {
117 	const auto	tcuFormat			= mapVkFormat(imageFormat);
118 	const auto	outBufferSize		= static_cast<VkDeviceSize>(static_cast<uint32_t>(tcu::getPixelSize(tcuFormat)) * imageExtent.width * imageExtent.height);
119 	const auto	outBufferUsage		= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
120 	const auto	outBufferInfo		= makeBufferCreateInfo(outBufferSize, outBufferUsage);
121 
122 	auto outBuffer = std::unique_ptr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, outBufferInfo, MemoryRequirement::HostVisible));
123 
124 	return outBuffer;
125 }
126 
iterate(void)127 tcu::TestStatus ConditionalIgnoreClearTestInstance::iterate(void)
128 {
129 	const auto& vkd				= m_context.getDeviceInterface();
130 	const auto  device			= m_context.getDevice();
131 	auto&		alloc			= m_context.getDefaultAllocator();
132 	const auto	imageFormat		= VK_FORMAT_R8G8B8A8_UNORM;
133 	const auto	depthFormat		= VK_FORMAT_D16_UNORM;
134 	const auto	imageExtent		= makeExtent3D(2, 2, 1u);
135 	const auto	qIndex			= m_context.getUniversalQueueFamilyIndex();
136 
137 	const auto							expected			= tcu::Vec4(0.0, 0.0, 0.0, 1.0);
138 
139 	const VkClearColorValue				clearColor			= { { 0.0, 0.0, 0.0, 1.0 } };
140 	const VkClearColorValue				clearColorWrong		= { { 1.0, 0.0, 0.0, 1.0 } };
141 
142 	const VkClearDepthStencilValue	depthClear			= {0.0, 0};
143 	const VkClearDepthStencilValue	depthClearWrong		= {1.0, 0};
144 
145 	const tcu::IVec3 imageDim	(static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), static_cast<int>(imageExtent.depth));
146 	const tcu::IVec2 imageSize	(imageDim.x(), imageDim.y());
147 
148 	de::MovePtr<ImageWithMemory>  colorAttachment;
149 	de::MovePtr<ImageWithMemory>  depthAttachment;
150 
151 	//create color image
152 	const auto  imageUsage      = static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
153 	const VkImageCreateInfo imageCreateInfo =
154 	{
155 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType				sType;
156 		nullptr,								//	const void*					pNext;
157 		0u,										//	VkImageCreateFlags			flags;
158 		VK_IMAGE_TYPE_2D,						//	VkImageType					imageType;
159 		imageFormat,							//	VkFormat					format;
160 		imageExtent,							//	VkExtent3D					extent;
161 		1u,										//	deUint32					mipLevels;
162 		1u,										//	deUint32					arrayLayers;
163 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits		samples;
164 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling				tiling;
165 		imageUsage,								//	VkImageUsageFlags			usage;
166 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode				sharingMode;
167 		0,										//	deUint32					queueFamilyIndexCount;
168 		nullptr,								//	const deUint32*				pQueueFamilyIndices;
169 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout				initialLayout;
170 	};
171 
172 	const auto colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
173 	colorAttachment						= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, alloc, imageCreateInfo, MemoryRequirement::Any));
174 	auto colorAttachmentView			= makeImageView(vkd, device, colorAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSubresourceRange);
175 
176 	//create depth image
177 	const auto  depthImageUsage =
178 		static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
179 	const VkImageCreateInfo depthImageCreateInfo =
180 	{
181 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
182 		nullptr,										// const void*				pNext;
183 		0u,												// VkImageCreateFlags		flags;
184 		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
185 		depthFormat,									// VkFormat					format;
186 		imageExtent,									// VkExtent3D				extent;
187 		1u,												// deUint32					mipLevels;
188 		1u,												// deUint32					arrayLayers;
189 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
190 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
191 		depthImageUsage,								// VkImageUsageFlags		usage;
192 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
193 		0u,												// deUint32					queueFamilyIndexCount;
194 		nullptr,										// const deUint32*			pQueueFamilyIndices;
195 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
196 	};
197 
198 	const auto depthSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
199 	depthAttachment						= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, alloc, depthImageCreateInfo, MemoryRequirement::Any));
200 	auto depthAttachmentView			= makeImageView(vkd, device, depthAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, depthFormat, depthSubresourceRange);
201 
202 	//buffers to read the outputs
203 	const auto outBuffer			= makeBufferForImage(vkd, device, alloc, imageFormat, imageExtent);
204 	const auto& outBufferAlloc	= outBuffer->getAllocation();
205 	const void* outBufferData		= outBufferAlloc.getHostPtr();
206 
207 	const auto outDepthBuffer		= makeBufferForImage(vkd, device, alloc, depthFormat, imageExtent);
208 	const auto& outDepthBufferAlloc	= outDepthBuffer->getAllocation();
209 	const void* outDepthBufferData	= outDepthBufferAlloc.getHostPtr();
210 
211 	const auto commandPool	= createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, qIndex);
212 	auto commandBuffer		= allocateCommandBuffer(vkd, device, commandPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
213 	auto commandBuffer2		= allocateCommandBuffer(vkd, device, commandPool.get(), VK_COMMAND_BUFFER_LEVEL_SECONDARY);
214 
215 	auto conditionalBuffer = createConditionalRenderingBuffer(m_context, m_data);
216 	//prepare command buffers
217 	const bool useSecondaryCmdBuffer = m_data.conditionInherited || m_data.conditionInSecondaryCommandBuffer;
218 
219 	VkCommandBufferInheritanceConditionalRenderingInfoEXT conditionalRenderingInheritanceInfo = initVulkanStructure();
220 	conditionalRenderingInheritanceInfo.conditionalRenderingEnable = m_data.conditionInherited ? VK_TRUE : VK_FALSE;
221 
222 	const VkCommandBufferInheritanceInfo inheritanceInfo =
223 	{
224 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
225 		&conditionalRenderingInheritanceInfo,
226 		VK_NULL_HANDLE,									        // renderPass
227 		0u,														// subpass
228 		VK_NULL_HANDLE,									        // framebuffer
229 		VK_FALSE,												// occlusionQueryEnable
230 		(VkQueryControlFlags)0u,								// queryFlags
231 		(VkQueryPipelineStatisticFlags)0u,						// pipelineStatistics
232 	};
233 
234 	const VkCommandBufferBeginInfo commandBufferBeginInfo =
235 	{
236 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
237 		nullptr,
238 		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
239 		&inheritanceInfo
240 	};
241 
242 	beginCommandBuffer(vkd, commandBuffer.get());
243 	//transition color and depth images
244 	VkImageMemoryBarrier colorTransition = makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
245 		VK_IMAGE_LAYOUT_GENERAL, colorAttachment.get()->get(), colorSubresourceRange);
246 	VkImageMemoryBarrier depthTransition = makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
247 		VK_IMAGE_LAYOUT_GENERAL, depthAttachment.get()->get(), depthSubresourceRange);
248 	VkImageMemoryBarrier barriers[] = {colorTransition, depthTransition};
249 	cmdPipelineImageMemoryBarrier(vkd, commandBuffer.get(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
250 		barriers, DE_LENGTH_OF_ARRAY(barriers));
251 
252 	//clear to the incorrect color
253 	vkd.cmdClearColorImage(commandBuffer.get(), colorAttachment.get()->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColorWrong, 1, &colorSubresourceRange);
254 	vkd.cmdClearDepthStencilImage(commandBuffer.get(), depthAttachment.get()->get(), VK_IMAGE_LAYOUT_GENERAL, &depthClearWrong, 1, &depthSubresourceRange);
255 
256 	const auto barrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT);
257 	cmdPipelineMemoryBarrier(vkd, commandBuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &barrier);
258 
259 	//do all combinations of clears
260 	if (useSecondaryCmdBuffer)
261 	{
262 		vkd.beginCommandBuffer(*commandBuffer2, &commandBufferBeginInfo);
263 		if (m_data.conditionInSecondaryCommandBuffer)
264 		{
265 			beginConditionalRendering(vkd, commandBuffer2.get(), *conditionalBuffer, m_data);
266 		}
267 		else
268 		{
269 			beginConditionalRendering(vkd, commandBuffer.get(), *conditionalBuffer, m_data);
270 		}
271 
272 		//clear to the correct colors
273 		vkd.cmdClearColorImage(commandBuffer2.get(), colorAttachment.get()->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &colorSubresourceRange);
274 		vkd.cmdClearDepthStencilImage(commandBuffer2.get(), depthAttachment.get()->get(), VK_IMAGE_LAYOUT_GENERAL, &depthClear, 1, &depthSubresourceRange);
275 
276 		if (m_data.conditionInSecondaryCommandBuffer)
277 		{
278 			vkd.cmdEndConditionalRenderingEXT(commandBuffer2.get());
279 		}
280 		else
281 		{
282 			vkd.cmdEndConditionalRenderingEXT(commandBuffer.get());
283 		}
284 
285 		vkd.endCommandBuffer(*commandBuffer2);
286 		vkd.cmdExecuteCommands(commandBuffer.get(), 1, &commandBuffer2.get());
287 	}
288 	else
289 	{
290 		beginConditionalRendering(vkd, commandBuffer.get(), *conditionalBuffer, m_data);
291 
292 		//clear to the correct colors
293 		vkd.cmdClearColorImage(commandBuffer.get(), colorAttachment.get()->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &colorSubresourceRange);
294 		vkd.cmdClearDepthStencilImage(commandBuffer.get(), depthAttachment.get()->get(), VK_IMAGE_LAYOUT_GENERAL, &depthClear, 1, &depthSubresourceRange);
295 
296 		vkd.cmdEndConditionalRenderingEXT(commandBuffer.get());
297 	}
298 	copyImageToBuffer(vkd, commandBuffer.get(), colorAttachment.get()->get(), (*outBuffer).get(), imageSize,
299 		VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
300 	copyImageToBuffer(vkd, commandBuffer.get(), depthAttachment.get()->get(), (*outDepthBuffer).get(), imageSize,
301 		VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, 1, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_ASPECT_DEPTH_BIT);
302 
303 	endCommandBuffer(vkd, commandBuffer.get());
304 	submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), commandBuffer.get());
305 
306 	invalidateAlloc(vkd, device, outBufferAlloc);
307 	invalidateAlloc(vkd, device, outDepthBufferAlloc);
308 	tcu::ConstPixelBufferAccess outPixels(mapVkFormat(imageFormat), imageDim, outBufferData);
309 	tcu::ConstPixelBufferAccess outDepth(mapVkFormat(depthFormat), imageDim, outDepthBufferData);
310 
311 	//the clears should happen in every case
312 	if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare color", "color image comparison", expected, outPixels, tcu::Vec4(0.0), tcu::COMPARE_LOG_ON_ERROR))
313 		return tcu::TestStatus::fail("Color image verification failed, check log for details");
314 	if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare depth", "depth image comparison", expected, outDepth, tcu::Vec4(0.0), tcu::COMPARE_LOG_ON_ERROR))
315 		return tcu::TestStatus::fail("Depth image verification failed, check log for details");
316 
317 	return tcu::TestStatus::pass("Pass");
318 }
319 
320 }	// anonymous
321 
322 // operations that ignore conditions
ConditionalIgnoreTests(tcu::TestContext & testCtx)323 ConditionalIgnoreTests::ConditionalIgnoreTests(tcu::TestContext &testCtx)
324 	: TestCaseGroup	(testCtx, "conditional_ignore")
325 { }
326 
~ConditionalIgnoreTests(void)327 ConditionalIgnoreTests::~ConditionalIgnoreTests(void)
328 {}
329 
init(void)330 void ConditionalIgnoreTests::init (void)
331 {
332 	for (int conditionNdx = 0; conditionNdx < DE_LENGTH_OF_ARRAY(conditional::s_testsData); conditionNdx++)
333 	{
334 		const ConditionalData& conditionData = conditional::s_testsData[conditionNdx];
335 
336 		if (conditionData.clearInRenderPass)
337 			continue;
338 
339 		// tests that some clear operations always happen
340 		addChild(new ConditionalIgnoreClearTestCase(m_testCtx, std::string("clear_") + de::toString(conditionData).c_str(), conditionData));
341 	}
342 }
343 
344 }	// conditional
345 }	// vkt
346