• 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 namespace vkt
65 {
66 namespace conditional
67 {
68 namespace
69 {
70 
71 using namespace vk;
72 
73 class ConditionalIgnoreClearTestCase : public vkt::TestCase
74 {
75 public:
76     ConditionalIgnoreClearTestCase(tcu::TestContext &context, const std::string &name, const ConditionalData &data);
initPrograms(SourceCollections &) const77     void initPrograms(SourceCollections &) const override
78     {
79     }
80     TestInstance *createInstance(Context &context) const override;
checkSupport(Context & context) const81     void checkSupport(Context &context) const override
82     {
83         context.requireDeviceFunctionality("VK_EXT_conditional_rendering");
84         if (m_data.conditionInherited && !context.getConditionalRenderingFeaturesEXT().inheritedConditionalRendering)
85             TCU_THROW(NotSupportedError, "Device does not support inherited conditional rendering");
86     }
87 
88 private:
89     const ConditionalData m_data;
90 };
91 
92 class ConditionalIgnoreClearTestInstance : public vkt::TestInstance
93 {
94 public:
ConditionalIgnoreClearTestInstance(Context & context,const ConditionalData & data)95     ConditionalIgnoreClearTestInstance(Context &context, const ConditionalData &data)
96         : vkt::TestInstance(context)
97         , m_data(data){};
98     virtual tcu::TestStatus iterate(void);
99 
100 private:
101     const ConditionalData m_data;
102 };
103 
ConditionalIgnoreClearTestCase(tcu::TestContext & context,const std::string & name,const ConditionalData & data)104 ConditionalIgnoreClearTestCase::ConditionalIgnoreClearTestCase(tcu::TestContext &context, const std::string &name,
105                                                                const ConditionalData &data)
106     : vkt::TestCase(context, name)
107     , m_data(data)
108 {
109 }
110 
createInstance(Context & context) const111 TestInstance *ConditionalIgnoreClearTestCase::createInstance(Context &context) const
112 {
113     return new ConditionalIgnoreClearTestInstance(context, m_data);
114 }
115 
116 //make a buffer to read an image back after rendering
makeBufferForImage(const DeviceInterface & vkd,const VkDevice device,Allocator & allocator,VkFormat imageFormat,VkExtent3D imageExtent)117 std::unique_ptr<BufferWithMemory> makeBufferForImage(const DeviceInterface &vkd, const VkDevice device,
118                                                      Allocator &allocator, VkFormat imageFormat, VkExtent3D imageExtent)
119 {
120     const auto tcuFormat      = mapVkFormat(imageFormat);
121     const auto outBufferSize  = static_cast<VkDeviceSize>(static_cast<uint32_t>(tcu::getPixelSize(tcuFormat)) *
122                                                          imageExtent.width * imageExtent.height);
123     const auto outBufferUsage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
124     const auto outBufferInfo  = makeBufferCreateInfo(outBufferSize, outBufferUsage);
125 
126     auto outBuffer = std::unique_ptr<BufferWithMemory>(
127         new BufferWithMemory(vkd, device, allocator, outBufferInfo, MemoryRequirement::HostVisible));
128 
129     return outBuffer;
130 }
131 
iterate(void)132 tcu::TestStatus ConditionalIgnoreClearTestInstance::iterate(void)
133 {
134     const auto &vkd        = m_context.getDeviceInterface();
135     const auto device      = m_context.getDevice();
136     auto &alloc            = m_context.getDefaultAllocator();
137     const auto imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
138     const auto depthFormat = VK_FORMAT_D16_UNORM;
139     const auto imageExtent = makeExtent3D(2, 2, 1u);
140     const auto qIndex      = m_context.getUniversalQueueFamilyIndex();
141 
142     const auto expected = tcu::Vec4(0.0, 0.0, 0.0, 1.0);
143 
144     const VkClearColorValue clearColor      = {{0.0, 0.0, 0.0, 1.0}};
145     const VkClearColorValue clearColorWrong = {{1.0, 0.0, 0.0, 1.0}};
146 
147     const VkClearDepthStencilValue depthClear      = {0.0, 0};
148     const VkClearDepthStencilValue depthClearWrong = {1.0, 0};
149 
150     const tcu::IVec3 imageDim(static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height),
151                               static_cast<int>(imageExtent.depth));
152     const tcu::IVec2 imageSize(imageDim.x(), imageDim.y());
153 
154     de::MovePtr<ImageWithMemory> colorAttachment;
155     de::MovePtr<ImageWithMemory> depthAttachment;
156 
157     //create color image
158     const auto imageUsage = static_cast<VkImageUsageFlags>(
159         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
160     const VkImageCreateInfo imageCreateInfo = {
161         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
162         nullptr,                             // const void* pNext;
163         0u,                                  // VkImageCreateFlags flags;
164         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
165         imageFormat,                         // VkFormat format;
166         imageExtent,                         // VkExtent3D extent;
167         1u,                                  // uint32_t mipLevels;
168         1u,                                  // uint32_t arrayLayers;
169         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
170         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
171         imageUsage,                          // VkImageUsageFlags usage;
172         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
173         0,                                   // uint32_t queueFamilyIndexCount;
174         nullptr,                             // const uint32_t* pQueueFamilyIndices;
175         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
176     };
177 
178     const auto colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
179     colorAttachment =
180         de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, alloc, imageCreateInfo, MemoryRequirement::Any));
181     auto colorAttachmentView =
182         makeImageView(vkd, device, colorAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSubresourceRange);
183 
184     //create depth image
185     const auto depthImageUsage =
186         static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
187                                        VK_IMAGE_USAGE_TRANSFER_DST_BIT);
188     const VkImageCreateInfo depthImageCreateInfo = {
189         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
190         nullptr,                             // const void* pNext;
191         0u,                                  // VkImageCreateFlags flags;
192         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
193         depthFormat,                         // VkFormat format;
194         imageExtent,                         // VkExtent3D extent;
195         1u,                                  // uint32_t mipLevels;
196         1u,                                  // uint32_t arrayLayers;
197         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
198         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
199         depthImageUsage,                     // VkImageUsageFlags usage;
200         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
201         0u,                                  // uint32_t queueFamilyIndexCount;
202         nullptr,                             // const uint32_t* pQueueFamilyIndices;
203         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
204     };
205 
206     const auto depthSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
207     depthAttachment                  = de::MovePtr<ImageWithMemory>(
208         new ImageWithMemory(vkd, device, alloc, depthImageCreateInfo, MemoryRequirement::Any));
209     auto depthAttachmentView =
210         makeImageView(vkd, device, depthAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, depthFormat, depthSubresourceRange);
211 
212     //buffers to read the outputs
213     const auto outBuffer       = makeBufferForImage(vkd, device, alloc, imageFormat, imageExtent);
214     const auto &outBufferAlloc = outBuffer->getAllocation();
215     const void *outBufferData  = outBufferAlloc.getHostPtr();
216 
217     const auto outDepthBuffer       = makeBufferForImage(vkd, device, alloc, depthFormat, imageExtent);
218     const auto &outDepthBufferAlloc = outDepthBuffer->getAllocation();
219     const void *outDepthBufferData  = outDepthBufferAlloc.getHostPtr();
220 
221     const auto commandPool = createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, qIndex);
222     auto commandBuffer     = allocateCommandBuffer(vkd, device, commandPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
223     auto commandBuffer2    = allocateCommandBuffer(vkd, device, commandPool.get(), VK_COMMAND_BUFFER_LEVEL_SECONDARY);
224     auto commandBuffer3    = allocateCommandBuffer(vkd, device, commandPool.get(), VK_COMMAND_BUFFER_LEVEL_SECONDARY);
225 
226     auto conditionalBuffer = createConditionalRenderingBuffer(m_context, m_data);
227     //prepare command buffers
228     const bool useSecondaryCmdBuffer = m_data.conditionInherited || m_data.conditionInSecondaryCommandBuffer;
229 
230     if (m_data.secondaryCommandBufferNested)
231     {
232         m_context.requireDeviceFunctionality("VK_EXT_nested_command_buffer");
233         const auto &features =
234             *findStructure<VkPhysicalDeviceNestedCommandBufferFeaturesEXT>(&m_context.getDeviceFeatures2());
235         if (!features.nestedCommandBuffer)
236             TCU_THROW(NotSupportedError, "nestedCommandBuffer is not supported");
237     }
238 
239     VkCommandBufferInheritanceConditionalRenderingInfoEXT conditionalRenderingInheritanceInfo = initVulkanStructure();
240     conditionalRenderingInheritanceInfo.conditionalRenderingEnable = m_data.conditionInherited ? VK_TRUE : VK_FALSE;
241 
242     const VkCommandBufferInheritanceInfo inheritanceInfo = {
243         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
244         &conditionalRenderingInheritanceInfo,
245         VK_NULL_HANDLE,                    // renderPass
246         0u,                                // subpass
247         VK_NULL_HANDLE,                    // framebuffer
248         VK_FALSE,                          // occlusionQueryEnable
249         (VkQueryControlFlags)0u,           // queryFlags
250         (VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
251     };
252 
253     const VkCommandBufferBeginInfo commandBufferBeginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr,
254                                                              VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
255                                                              &inheritanceInfo};
256 
257     beginCommandBuffer(vkd, commandBuffer.get());
258     //transition color and depth images
259     VkImageMemoryBarrier colorTransition =
260         makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
261                                colorAttachment.get()->get(), colorSubresourceRange);
262     VkImageMemoryBarrier depthTransition =
263         makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
264                                depthAttachment.get()->get(), depthSubresourceRange);
265     VkImageMemoryBarrier barriers[] = {colorTransition, depthTransition};
266     cmdPipelineImageMemoryBarrier(vkd, commandBuffer.get(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
267                                   VK_PIPELINE_STAGE_TRANSFER_BIT, barriers, DE_LENGTH_OF_ARRAY(barriers));
268 
269     //clear to the incorrect color
270     vkd.cmdClearColorImage(commandBuffer.get(), colorAttachment.get()->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColorWrong,
271                            1, &colorSubresourceRange);
272     vkd.cmdClearDepthStencilImage(commandBuffer.get(), depthAttachment.get()->get(), VK_IMAGE_LAYOUT_GENERAL,
273                                   &depthClearWrong, 1, &depthSubresourceRange);
274 
275     const auto barrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT);
276     cmdPipelineMemoryBarrier(vkd, commandBuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
277                              &barrier);
278 
279     //do all combinations of clears
280     if (useSecondaryCmdBuffer)
281     {
282         if (m_data.secondaryCommandBufferNested)
283         {
284             vkd.beginCommandBuffer(*commandBuffer3, &commandBufferBeginInfo);
285         }
286 
287         vkd.beginCommandBuffer(*commandBuffer2, &commandBufferBeginInfo);
288         if (m_data.conditionInSecondaryCommandBuffer)
289         {
290             beginConditionalRendering(vkd, commandBuffer2.get(), *conditionalBuffer, m_data);
291         }
292         else
293         {
294             beginConditionalRendering(vkd, commandBuffer.get(), *conditionalBuffer, m_data);
295         }
296 
297         //clear to the correct colors
298         vkd.cmdClearColorImage(commandBuffer2.get(), colorAttachment.get()->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColor,
299                                1, &colorSubresourceRange);
300         vkd.cmdClearDepthStencilImage(commandBuffer2.get(), depthAttachment.get()->get(), VK_IMAGE_LAYOUT_GENERAL,
301                                       &depthClear, 1, &depthSubresourceRange);
302 
303         if (m_data.conditionInSecondaryCommandBuffer)
304         {
305             vkd.cmdEndConditionalRenderingEXT(commandBuffer2.get());
306         }
307         else
308         {
309             vkd.cmdEndConditionalRenderingEXT(commandBuffer.get());
310         }
311 
312         vkd.endCommandBuffer(*commandBuffer2);
313         if (m_data.secondaryCommandBufferNested)
314         {
315             vkd.cmdExecuteCommands(commandBuffer3.get(), 1, &commandBuffer2.get());
316             vkd.endCommandBuffer(*commandBuffer3);
317             vkd.cmdExecuteCommands(commandBuffer.get(), 1, &commandBuffer3.get());
318         }
319         else
320         {
321             vkd.cmdExecuteCommands(commandBuffer.get(), 1, &commandBuffer2.get());
322         }
323     }
324     else
325     {
326         beginConditionalRendering(vkd, commandBuffer.get(), *conditionalBuffer, m_data);
327 
328         //clear to the correct colors
329         vkd.cmdClearColorImage(commandBuffer.get(), colorAttachment.get()->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColor,
330                                1, &colorSubresourceRange);
331         vkd.cmdClearDepthStencilImage(commandBuffer.get(), depthAttachment.get()->get(), VK_IMAGE_LAYOUT_GENERAL,
332                                       &depthClear, 1, &depthSubresourceRange);
333 
334         vkd.cmdEndConditionalRenderingEXT(commandBuffer.get());
335     }
336     copyImageToBuffer(vkd, commandBuffer.get(), colorAttachment.get()->get(), (*outBuffer).get(), imageSize,
337                       VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
338     copyImageToBuffer(vkd, commandBuffer.get(), depthAttachment.get()->get(), (*outDepthBuffer).get(), imageSize,
339                       VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, 1, VK_IMAGE_ASPECT_DEPTH_BIT,
340                       VK_IMAGE_ASPECT_DEPTH_BIT);
341 
342     endCommandBuffer(vkd, commandBuffer.get());
343     submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), commandBuffer.get());
344 
345     invalidateAlloc(vkd, device, outBufferAlloc);
346     invalidateAlloc(vkd, device, outDepthBufferAlloc);
347     tcu::ConstPixelBufferAccess outPixels(mapVkFormat(imageFormat), imageDim, outBufferData);
348     tcu::ConstPixelBufferAccess outDepth(mapVkFormat(depthFormat), imageDim, outDepthBufferData);
349 
350     //the clears should happen in every case
351     if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare color", "color image comparison",
352                                     expected, outPixels, tcu::Vec4(0.0), tcu::COMPARE_LOG_ON_ERROR))
353         return tcu::TestStatus::fail("Color image verification failed, check log for details");
354     if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare depth", "depth image comparison",
355                                     expected, outDepth, tcu::Vec4(0.0), tcu::COMPARE_LOG_ON_ERROR))
356         return tcu::TestStatus::fail("Depth image verification failed, check log for details");
357 
358     return tcu::TestStatus::pass("Pass");
359 }
360 
361 } // namespace
362 
363 // operations that ignore conditions
ConditionalIgnoreTests(tcu::TestContext & testCtx)364 ConditionalIgnoreTests::ConditionalIgnoreTests(tcu::TestContext &testCtx) : TestCaseGroup(testCtx, "conditional_ignore")
365 {
366 }
367 
~ConditionalIgnoreTests(void)368 ConditionalIgnoreTests::~ConditionalIgnoreTests(void)
369 {
370 }
371 
init(void)372 void ConditionalIgnoreTests::init(void)
373 {
374     for (int conditionNdx = 0; conditionNdx < DE_LENGTH_OF_ARRAY(conditional::s_testsData); conditionNdx++)
375     {
376         const ConditionalData &conditionData = conditional::s_testsData[conditionNdx];
377 
378         if (conditionData.clearInRenderPass)
379             continue;
380 
381         // tests that some clear operations always happen
382         addChild(new ConditionalIgnoreClearTestCase(
383             m_testCtx, std::string("clear_") + de::toString(conditionData).c_str(), conditionData));
384     }
385 }
386 
387 } // namespace conditional
388 } // namespace vkt
389