1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 The Khronos Group Inc.
6 * Copyright (c) 2018 Danylo Piliaiev <[email protected]>
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 if (data.secondaryCommandBufferNested)
49 {
50 context.requireDeviceFunctionality("VK_EXT_nested_command_buffer");
51 const auto &features =
52 *vk::findStructure<vk::VkPhysicalDeviceNestedCommandBufferFeaturesEXT>(&context.getDeviceFeatures2());
53 if (!features.nestedCommandBuffer)
54 TCU_THROW(NotSupportedError, "nestedCommandBuffer is not supported");
55 }
56 }
57
checkNestedRenderPassCapabilities(vkt::Context & context)58 void checkNestedRenderPassCapabilities(vkt::Context &context)
59 {
60 context.requireDeviceFunctionality("VK_EXT_nested_command_buffer");
61 const auto &features =
62 *vk::findStructure<vk::VkPhysicalDeviceNestedCommandBufferFeaturesEXT>(&context.getDeviceFeatures2());
63 if (!features.nestedCommandBuffer)
64 TCU_THROW(NotSupportedError, "nestedCommandBuffer is not supported");
65 if (!features.nestedCommandBufferRendering)
66 TCU_THROW(NotSupportedError, "nestedCommandBufferRendering is not supported");
67 }
68
createConditionalRenderingBuffer(vkt::Context & context,const ConditionalData & data)69 de::SharedPtr<Draw::Buffer> createConditionalRenderingBuffer(vkt::Context &context, const ConditionalData &data)
70 {
71 const auto &vk = context.getDeviceInterface();
72 const auto device = context.getDevice();
73 const auto queueIndex = context.getUniversalQueueFamilyIndex();
74 const auto queue = context.getUniversalQueue();
75 auto &alloc = context.getDefaultAllocator();
76
77 // When padding the condition value, it will be surounded by two additional values with nonzero bytes in them.
78 // When choosing to apply an offset to the allocation, the offset will be four times the size of the condition variable.
79 const auto bufferSize =
80 static_cast<vk::VkDeviceSize>(sizeof(data.conditionValue)) * (data.padConditionValue ? 3ull : 1ull);
81 const auto dataOffset = static_cast<vk::VkDeviceSize>(data.padConditionValue ? sizeof(data.conditionValue) : 0);
82 const auto allocOffset =
83 static_cast<vk::VkDeviceSize>(sizeof(data.conditionValue) * (data.allocationOffset ? 4u : 0u));
84
85 // Create host-visible buffer. This may be the final buffer or only a staging buffer.
86 const auto hostUsage = ((data.memoryType == HOST) ? vk::VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT :
87 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
88 de::SharedPtr<Draw::Buffer> hostBuffer =
89 Draw::Buffer::createAndAlloc(vk, device, Draw::BufferCreateInfo(bufferSize, hostUsage), alloc,
90 vk::MemoryRequirement::HostVisible, allocOffset);
91
92 // Copy data to host buffer.
93 uint8_t *conditionBufferPtr = reinterpret_cast<uint8_t *>(hostBuffer->getHostPtr());
94 deMemset(conditionBufferPtr, 1, static_cast<size_t>(bufferSize));
95 deMemcpy(conditionBufferPtr + dataOffset, &data.conditionValue, sizeof(data.conditionValue));
96 vk::flushAlloc(vk, context.getDevice(), hostBuffer->getBoundMemory());
97
98 // Return host buffer if appropriate.
99 if (data.memoryType == HOST)
100 return hostBuffer;
101
102 // Create and return device-local buffer otherwise, after copying host-visible buffer contents to it.
103 const auto deviceLocalUsage =
104 (vk::VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
105 de::SharedPtr<Draw::Buffer> deviceLocalBuffer =
106 Draw::Buffer::createAndAlloc(vk, device, Draw::BufferCreateInfo(bufferSize, deviceLocalUsage), alloc,
107 vk::MemoryRequirement::Local, allocOffset);
108
109 const auto cmdPool = vk::makeCommandPool(vk, device, queueIndex);
110 const auto cmdBuffer = vk::allocateCommandBuffer(vk, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
111 const auto copyInfo = vk::makeBufferCopy(0ull, 0ull, bufferSize);
112
113 vk::beginCommandBuffer(vk, *cmdBuffer);
114 vk.cmdCopyBuffer(*cmdBuffer, hostBuffer->object(), deviceLocalBuffer->object(), 1, ©Info);
115 vk::endCommandBuffer(vk, *cmdBuffer);
116 vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
117
118 return deviceLocalBuffer;
119 }
120
beginConditionalRendering(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,Draw::Buffer & buffer,const ConditionalData & data)121 void beginConditionalRendering(const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, Draw::Buffer &buffer,
122 const ConditionalData &data)
123 {
124 vk::VkConditionalRenderingBeginInfoEXT conditionalRenderingBeginInfo;
125 conditionalRenderingBeginInfo.sType = vk::VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT;
126 conditionalRenderingBeginInfo.pNext = nullptr;
127 conditionalRenderingBeginInfo.buffer = buffer.object();
128 conditionalRenderingBeginInfo.offset =
129 static_cast<vk::VkDeviceSize>(data.padConditionValue ? sizeof(data.conditionValue) : 0u);
130 conditionalRenderingBeginInfo.flags = data.conditionInverted ? vk::VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT : 0;
131
132 vk.cmdBeginConditionalRenderingEXT(cmdBuffer, &conditionalRenderingBeginInfo);
133 }
134
operator <<(std::ostream & str,ConditionalData const & c)135 std::ostream &operator<<(std::ostream &str, ConditionalData const &c)
136 {
137 const bool conditionEnabled = c.conditionInPrimaryCommandBuffer || c.conditionInSecondaryCommandBuffer;
138 str << (conditionEnabled ? "condition" : "no_condition");
139 str << (c.memoryType ? "_host_memory" : "_local_memory");
140
141 if (c.conditionInSecondaryCommandBuffer || !conditionEnabled)
142 {
143 if (c.secondaryCommandBufferNested)
144 {
145 str << "_nested_buffer";
146 }
147 else
148 {
149 str << "_secondary_buffer";
150 }
151 }
152
153 if (c.conditionInherited)
154 {
155 if (c.secondaryCommandBufferNested)
156 {
157 str << "_nested_inherited";
158 }
159 else
160 {
161 str << "_inherited";
162 }
163 }
164
165 str << "_" << (c.expectCommandExecution ? "expect_execution" : "expect_noop");
166
167 if (c.conditionInverted)
168 {
169 str << "_inverted";
170 }
171
172 if (c.padConditionValue)
173 {
174 str << "_padded";
175 }
176
177 if (c.clearInRenderPass)
178 {
179 str << "_rp_clear";
180 }
181
182 return str;
183 }
184
185 } // namespace conditional
186 } // namespace vkt
187