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 Conditional Rendering Test Utils
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktConditionalRenderingTestUtil.hpp"
26 #include "vktDrawCreateInfoUtil.hpp"
27 #include "vkQueryUtil.hpp"
28 #include "vkCmdUtil.hpp"
29 #include "vkTypeUtil.hpp"
30 
31 namespace vkt
32 {
33 namespace conditional
34 {
35 
checkConditionalRenderingCapabilities(vkt::Context& context, const ConditionalData& data)36 void checkConditionalRenderingCapabilities (vkt::Context& context, const ConditionalData& data)
37 {
38 	context.requireDeviceFunctionality("VK_EXT_conditional_rendering");
39 
40 	const auto& conditionalRenderingFeatures = context.getConditionalRenderingFeaturesEXT();
41 
42 	if (conditionalRenderingFeatures.conditionalRendering == VK_FALSE)
43 		TCU_FAIL("conditionalRendering feature not supported but VK_EXT_conditional_rendering present");
44 
45 	if (data.conditionInherited && !conditionalRenderingFeatures.inheritedConditionalRendering)
46 		TCU_THROW(NotSupportedError, "Device does not support inherited conditional rendering");
47 }
48 
createConditionalRenderingBuffer(vkt::Context& context, const ConditionalData& data)49 de::SharedPtr<Draw::Buffer>	createConditionalRenderingBuffer (vkt::Context& context, const ConditionalData& data)
50 {
51 	const auto&	vk			= context.getDeviceInterface();
52 	const auto	device		= context.getDevice();
53 	const auto	queueIndex	= context.getUniversalQueueFamilyIndex();
54 	const auto	queue		= context.getUniversalQueue();
55 	auto&		alloc		= context.getDefaultAllocator();
56 
57 	// When padding the condition value, it will be surounded by two additional values with nonzero bytes in them.
58 	// When choosing to apply an offset to the allocation, the offset will be four times the size of the condition variable.
59 	const auto					bufferSize	= static_cast<vk::VkDeviceSize>(sizeof(data.conditionValue)) * (data.padConditionValue ? 3ull : 1ull);
60 	const auto					dataOffset	= static_cast<vk::VkDeviceSize>(data.padConditionValue ? sizeof(data.conditionValue) : 0);
61 	const auto					allocOffset	= static_cast<vk::VkDeviceSize>(sizeof(data.conditionValue) * (data.allocationOffset ? 4u : 0u));
62 
63 	// Create host-visible buffer. This may be the final buffer or only a staging buffer.
64 	const auto					hostUsage	= ((data.memoryType == HOST) ? vk::VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT : vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
65 	de::SharedPtr<Draw::Buffer>	hostBuffer	= Draw::Buffer::createAndAlloc(vk, device,
66 												Draw::BufferCreateInfo(bufferSize, hostUsage),
67 												alloc,
68 												vk::MemoryRequirement::HostVisible,
69 												allocOffset);
70 
71 	// Copy data to host buffer.
72 	deUint8* conditionBufferPtr = reinterpret_cast<deUint8*>(hostBuffer->getHostPtr());
73 	deMemset(conditionBufferPtr, 1, static_cast<size_t>(bufferSize));
74 	deMemcpy(conditionBufferPtr + dataOffset, &data.conditionValue, sizeof(data.conditionValue));
75 	vk::flushAlloc(vk, context.getDevice(), hostBuffer->getBoundMemory());
76 
77 	// Return host buffer if appropriate.
78 	if (data.memoryType == HOST)
79 		return hostBuffer;
80 
81 	// Create and return device-local buffer otherwise, after copying host-visible buffer contents to it.
82 	const auto					deviceLocalUsage	= (vk::VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
83 	de::SharedPtr<Draw::Buffer>	deviceLocalBuffer	= Draw::Buffer::createAndAlloc(vk, device,
84 														Draw::BufferCreateInfo(bufferSize, deviceLocalUsage),
85 														alloc,
86 														vk::MemoryRequirement::Local,
87 														allocOffset);
88 
89 	const auto cmdPool		= vk::makeCommandPool(vk, device, queueIndex);
90 	const auto cmdBuffer	= vk::allocateCommandBuffer (vk, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
91 	const auto copyInfo		= vk::makeBufferCopy(0ull, 0ull, bufferSize);
92 
93 	vk::beginCommandBuffer(vk, *cmdBuffer);
94 	vk.cmdCopyBuffer(*cmdBuffer, hostBuffer->object(), deviceLocalBuffer->object(), 1, &copyInfo);
95 	vk::endCommandBuffer(vk, *cmdBuffer);
96 	vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
97 
98 	return deviceLocalBuffer;
99 }
100 
beginConditionalRendering(const vk::DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, Draw::Buffer& buffer, const ConditionalData& data)101 void beginConditionalRendering (const vk::DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, Draw::Buffer& buffer, const ConditionalData& data)
102 {
103 	vk::VkConditionalRenderingBeginInfoEXT conditionalRenderingBeginInfo;
104 	conditionalRenderingBeginInfo.sType		= vk::VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT;
105 	conditionalRenderingBeginInfo.pNext		= nullptr;
106 	conditionalRenderingBeginInfo.buffer	= buffer.object();
107 	conditionalRenderingBeginInfo.offset	= static_cast<vk::VkDeviceSize>(data.padConditionValue ? sizeof(data.conditionValue) : 0u);
108 	conditionalRenderingBeginInfo.flags		= data.conditionInverted ? vk::VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT : 0;
109 
110 	vk.cmdBeginConditionalRenderingEXT(cmdBuffer, &conditionalRenderingBeginInfo);
111 }
112 
operator <<(std::ostream& str, ConditionalData const& c)113 std::ostream& operator<< (std::ostream& str, ConditionalData const& c)
114 {
115 	const bool conditionEnabled = c.conditionInPrimaryCommandBuffer || c.conditionInSecondaryCommandBuffer;
116 	str << (conditionEnabled ? "condition" : "no_condition");
117 	str << (c.memoryType ? "_host_memory" : "_local_memory");
118 
119 
120 	if (c.conditionInSecondaryCommandBuffer || !conditionEnabled)
121 	{
122 		str << "_secondary_buffer";
123 	}
124 
125 	if (c.conditionInherited)
126 	{
127 		str << "_inherited";
128 	}
129 
130 	str << "_" << (c.expectCommandExecution ? "expect_execution" : "expect_noop");
131 
132 	if (c.conditionInverted)
133 	{
134 		str << "_inverted";
135 	}
136 
137 	if (c.padConditionValue)
138 	{
139 		str << "_padded";
140 	}
141 
142 	if (c.clearInRenderPass)
143 	{
144 		str << "_rp_clear";
145 	}
146 
147 	return str;
148 }
149 
150 }   // conditional
151 }	// vkt
152