xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/pipeline/vktPipelineEarlyDestroyTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
6  * Copyright (c) 2018 Google Inc.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Early pipeline destroying tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelineEarlyDestroyTests.hpp"
28 #include "vktTestCase.hpp"
29 #include "vktTestCaseUtil.hpp"
30 #include "vktTestGroupUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "deUniquePtr.hpp"
36 #include "tcuTexture.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkImageWithMemory.hpp"
39 #include "vkBufferWithMemory.hpp"
40 #include "vkCmdUtil.hpp"
41 
42 namespace vkt
43 {
44 namespace pipeline
45 {
46 
47 using namespace vk;
48 
49 namespace
50 {
51 
52 struct TestParams
53 {
54     PipelineConstructionType pipelineConstructionType;
55     bool usePipelineCache;
56     bool useMaintenance5;
57 };
58 
checkSupport(Context & context,TestParams testParams)59 void checkSupport(Context &context, TestParams testParams)
60 {
61     if (testParams.useMaintenance5)
62         context.requireDeviceFunctionality("VK_KHR_maintenance5");
63 
64     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
65                                           testParams.pipelineConstructionType);
66 }
67 
initPrograms(SourceCollections & programCollection,TestParams testParams)68 void initPrograms(SourceCollections &programCollection, TestParams testParams)
69 {
70     DE_UNREF(testParams.usePipelineCache);
71 
72     programCollection.glslSources.add("color_vert")
73         << glu::VertexSource("#version 450\n"
74                              "vec2 vertices[3];\n"
75                              "\n"
76                              "void main()\n"
77                              "{\n"
78                              "   vertices[0] = vec2(-1.0, -1.0);\n"
79                              "   vertices[1] = vec2( 1.0, -1.0);\n"
80                              "   vertices[2] = vec2( 0.0,  1.0);\n"
81                              "   gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n"
82                              "}\n");
83 
84     programCollection.glslSources.add("color_frag") << glu::FragmentSource("#version 450\n"
85                                                                            "\n"
86                                                                            "layout(location = 0) out vec4 uFragColor;\n"
87                                                                            "\n"
88                                                                            "void main()\n"
89                                                                            "{\n"
90                                                                            "   uFragColor = vec4(0,1,0,1);\n"
91                                                                            "}\n");
92 }
93 
testEarlyDestroy(Context & context,const TestParams & params,bool destroyLayout)94 tcu::TestStatus testEarlyDestroy(Context &context, const TestParams &params, bool destroyLayout)
95 {
96     const InstanceInterface &vki          = context.getInstanceInterface();
97     const DeviceInterface &vk             = context.getDeviceInterface();
98     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
99     const VkDevice vkDevice               = context.getDevice();
100     const ShaderWrapper vertexShaderModule(
101         ShaderWrapper(vk, vkDevice, context.getBinaryCollection().get("color_vert"), 0));
102 
103     const Unique<VkCommandPool> cmdPool(createCommandPool(
104         vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
105         context.getUniversalQueueFamilyIndex()));
106     const Unique<VkCommandBuffer> cmdBuffer(
107         allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
108 
109     const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
110         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
111         DE_NULL,                                       // const void* pNext;
112         0u,                                            // VkPipelineLayoutCreateFlags flags;
113         0u,                                            // uint32_t setLayoutCount;
114         DE_NULL,                                       // const VkDescriptorSetLayout* pSetLayouts;
115         0u,                                            // uint32_t pushConstantRangeCount;
116         DE_NULL                                        // const VkPushConstantRange* pPushConstantRanges;
117     };
118 
119     // Multiple passes for destroy layout in order to increase the chance of crashing if some resource/state gets carried over from previous iterations.
120     int numTests = destroyLayout ? 3 : 1;
121     for (int i = 0; i < numTests; ++i)
122     {
123         PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, vkDevice, &pipelineLayoutCreateInfo,
124                                              DE_NULL);
125         RenderPassWrapper renderPass(params.pipelineConstructionType, vk, vkDevice, VK_FORMAT_R8G8B8A8_UNORM);
126         const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
127             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
128             DE_NULL,                                                   // const void* pNext;
129             0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
130             0u,                                                        // uint32_t vertexBindingDescriptionCount;
131             DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
132             0u,      // uint32_t vertexAttributeDescriptionCount;
133             DE_NULL  // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
134         };
135         const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
136             VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
137             DE_NULL,                                                     // const void* pNext;
138             0u,                                   // VkPipelineInputAssemblyStateCreateFlags flags;
139             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology;
140             VK_FALSE                              // VkBool32 primitiveRestartEnable;
141         };
142         const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
143             VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
144             DE_NULL,                                                    // const void* pNext;
145             0u,                      // VkPipelineRasterizationStateCreateFlags flags;
146             VK_FALSE,                // VkBool32 depthClampEnable;
147             VK_TRUE,                 // VkBool32 rasterizerDiscardEnable;
148             VK_POLYGON_MODE_FILL,    // VkPolygonMode polygonMode;
149             VK_CULL_MODE_BACK_BIT,   // VkCullModeFlags cullMode;
150             VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace;
151             VK_FALSE,                // VkBool32 depthBiasEnable;
152             0.0f,                    // float depthBiasConstantFactor;
153             0.0f,                    // float depthBiasClamp;
154             0.0f,                    // float depthBiasSlopeFactor;
155             1.0f                     // float lineWidth;
156         };
157         const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
158             VK_FALSE,             // VkBool32 blendEnable;
159             VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor;
160             VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
161             VK_BLEND_OP_ADD,      // VkBlendOp colorBlendOp;
162             VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor;
163             VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
164             VK_BLEND_OP_ADD,      // VkBlendOp alphaBlendOp;
165             0xf                   // VkColorComponentFlags colorWriteMask;
166         };
167         const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
168             VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
169             DE_NULL,                                                  // const void* pNext;
170             0u,                                                       // VkPipelineColorBlendStateCreateFlags flags;
171             VK_FALSE,                                                 // VkBool32 logicOpEnable;
172             VK_LOGIC_OP_CLEAR,                                        // VkLogicOp logicOp;
173             1u,                                                       // uint32_t attachmentCount;
174             &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
175             {0.0f, 0.0f, 0.0f, 0.0f}    // float blendConstants[4];
176         };
177         const VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {
178             VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
179             DE_NULL,                                      // const void* pNext;
180 #ifndef CTS_USES_VULKANSC
181             (VkPipelineCacheCreateFlags)0u, // VkPipelineCacheCreateFlags flags;
182             0u,                             // size_t initialDataSize;
183             DE_NULL                         // const void* pInitialData;
184 #else
185             VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
186                 VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags flags;
187             context.getResourceInterface()->getCacheDataSize(),       // uintptr_t initialDataSize;
188             context.getResourceInterface()->getCacheData()            // const void* pInitialData;
189 #endif // CTS_USES_VULKANSC
190         };
191         const Unique<VkPipelineCache> pipelineCache(createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo));
192 
193         const std::vector<VkViewport> viewports{};
194         const std::vector<VkRect2D> scissors{};
195         GraphicsPipelineWrapper graphicsPipeline(vki, vk, physicalDevice, vkDevice, context.getDeviceExtensions(),
196                                                  params.pipelineConstructionType,
197                                                  VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT);
198 
199 #ifndef CTS_USES_VULKANSC
200         if (params.useMaintenance5)
201             graphicsPipeline.setPipelineCreateFlags2(VK_PIPELINE_CREATE_2_DISABLE_OPTIMIZATION_BIT_KHR);
202 #endif // CTS_USES_VULKANSC
203 
204         graphicsPipeline.disableViewportState()
205             .setDefaultMultisampleState()
206             .setDefaultDepthStencilState()
207             .setupVertexInputState(&vertexInputStateCreateInfo, &inputAssemblyStateCreateInfo)
208             .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertexShaderModule,
209                                               &rasterizationStateCreateInfo)
210             // Uninitialized so the pipeline wrapper does not add fragment stage.
211             // This avoids running into VUID-VkGraphicsPipelineCreateInfo-pStages-06894 due to enabled rasterizerDiscard
212             .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, vk::ShaderWrapper())
213             .setupFragmentOutputState(*renderPass, 0u, &colorBlendStateCreateInfo)
214             .setMonolithicPipelineLayout(pipelineLayout)
215             .buildPipeline(params.usePipelineCache ? *pipelineCache : DE_NULL);
216 
217         const uint32_t framebufferWidth  = 32;
218         const uint32_t framebufferHeight = 32;
219         if (destroyLayout)
220         {
221             // This will destroy the pipelineLayout when going out of enclosing scope
222             pipelineLayout.destroy();
223         }
224         const VkCommandBufferBeginInfo cmdBufferBeginInfo = {
225             VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType sType;
226             DE_NULL,                                        // const void* pNext;
227             0u,                                             // VkCommandBufferUsageFlags flags;
228             (const VkCommandBufferInheritanceInfo *)DE_NULL // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
229         };
230         if (!destroyLayout)
231         {
232             VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
233             VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
234         }
235         else
236         {
237             auto &allocator                        = context.getDefaultAllocator();
238             const auto queue                       = context.getUniversalQueue();
239             const VkFormat attachmentFormat        = VK_FORMAT_R8G8B8A8_UNORM;
240             const tcu::TextureFormat textureFormat = mapVkFormat(attachmentFormat);
241             const VkDeviceSize imageSize = framebufferWidth * framebufferHeight * textureFormat.getPixelSize();
242             const VkImageCreateInfo imageCreateInfo = {
243                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,       // VkStructureType sType;
244                 DE_NULL,                                   // const void* pNext;
245                 (VkImageCreateFlags)0,                     // VkImageCreateFlags flags;
246                 VK_IMAGE_TYPE_2D,                          // VkImageType imageType;
247                 attachmentFormat,                          // VkFormat format;
248                 {framebufferWidth, framebufferHeight, 1u}, // VkExtent3D extent;
249                 1u,                                        // uint32_t mipLevels;
250                 1u,                                        // uint32_t arrayLayers;
251                 VK_SAMPLE_COUNT_1_BIT,                     // VkSampleCountFlagBits samples;
252                 VK_IMAGE_TILING_OPTIMAL,                   // VkImageTiling tiling;
253                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
254                     VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage;
255                 VK_SHARING_MODE_EXCLUSIVE,               // VkSharingMode sharingMode;
256                 0u,                                      // uint32_t queueFamilyIndexCount;
257                 DE_NULL,                                 // const uint32_t* pQueueFamilyIndices;
258                 VK_IMAGE_LAYOUT_UNDEFINED                // VkImageLayout initialLayout;
259             };
260             const ImageWithMemory attachmentImage(vk, vkDevice, context.getDefaultAllocator(), imageCreateInfo,
261                                                   MemoryRequirement::Any);
262             const VkImageSubresourceRange colorSubresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u};
263             const Unique<VkImageView> attachmentImageView(vk::makeImageView(
264                 vk, vkDevice, *attachmentImage, VK_IMAGE_VIEW_TYPE_2D, attachmentFormat, colorSubresourceRange));
265             const VkBufferCreateInfo imageBufferCreateInfo =
266                 vk::makeBufferCreateInfo(imageSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
267             const BufferWithMemory imageBuffer(vk, vkDevice, allocator, imageBufferCreateInfo,
268                                                vk::MemoryRequirement::HostVisible);
269             renderPass.createFramebuffer(vk, vkDevice, *attachmentImage, *attachmentImageView, framebufferWidth,
270                                          framebufferHeight, 1u);
271 
272             VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
273             const tcu::Vec4 clearColor = {0.2f, 0.6f, 0.8f, 1.0f};
274             VkClearValue clearValue    = {
275                 {{clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w()}} // float float32[4];
276             };
277             VkClearAttachment attachment = {
278                 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
279                 0u,                        // uint32_t colorAttachment;
280                 clearValue                 // VkClearValue clearValue;
281             };
282             const VkRect2D renderArea = {{0, 0}, {framebufferWidth, framebufferHeight}};
283             const VkClearRect rect    = {
284                 renderArea, // VkRect2D                        rect
285                 0u,         // uint32_t                        baseArrayLayer
286                 1u          // uint32_t                        layerCount
287             };
288             renderPass.begin(vk, *cmdBuffer, renderArea, clearValue);
289             vk.cmdClearAttachments(*cmdBuffer, 1, &attachment, 1, &rect);
290             renderPass.end(vk, *cmdBuffer);
291             vk::copyImageToBuffer(vk, *cmdBuffer, *attachmentImage, *imageBuffer,
292                                   tcu::IVec2(framebufferWidth, framebufferHeight));
293             VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
294 
295             vk::submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
296             VK_CHECK(vk.resetCommandBuffer(*cmdBuffer, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT));
297             const auto &imageBufferAlloc = imageBuffer.getAllocation();
298             vk::invalidateAlloc(vk, vkDevice, imageBufferAlloc);
299 
300             const auto imageBufferPtr =
301                 reinterpret_cast<const char *>(imageBufferAlloc.getHostPtr()) + imageBufferAlloc.getOffset();
302             const tcu::ConstPixelBufferAccess imagePixels(textureFormat, framebufferWidth, framebufferHeight, 1u,
303                                                           imageBufferPtr);
304 
305 #ifdef CTS_USES_VULKANSC
306             if (context.getTestContext().getCommandLine().isSubProcess())
307 #endif // CTS_USES_VULKANSC
308             {
309                 for (int z = 0; z < imagePixels.getDepth(); ++z)
310                     for (int y = 0; y < imagePixels.getHeight(); ++y)
311                         for (int x = 0; x < imagePixels.getWidth(); ++x)
312                         {
313                             const auto pixel = imagePixels.getPixel(x, y, z);
314                             if (pixel != clearColor)
315                             {
316                                 std::ostringstream msg;
317                                 msg << "Pixel value mismatch after framebuffer clear."
318                                     << " diff: " << pixel << " vs " << clearColor;
319 
320                                 return tcu::TestStatus::fail(
321                                     msg.str() /*"Pixel value mismatch after framebuffer clear."*/);
322                             }
323                         }
324             }
325         }
326     }
327     // Passes as long as no crash occurred.
328     return tcu::TestStatus::pass("Pass");
329 }
330 
testEarlyDestroyKeepLayout(Context & context,TestParams params)331 tcu::TestStatus testEarlyDestroyKeepLayout(Context &context, TestParams params)
332 {
333     return testEarlyDestroy(context, params, false);
334 }
335 
testEarlyDestroyDestroyLayout(Context & context,TestParams params)336 tcu::TestStatus testEarlyDestroyDestroyLayout(Context &context, TestParams params)
337 {
338     return testEarlyDestroy(context, params, true);
339 }
340 
addEarlyDestroyTestCasesWithFunctions(tcu::TestCaseGroup * group,PipelineConstructionType pipelineConstructionType)341 void addEarlyDestroyTestCasesWithFunctions(tcu::TestCaseGroup *group, PipelineConstructionType pipelineConstructionType)
342 {
343     TestParams params{
344         pipelineConstructionType,
345         true,
346         false,
347     };
348 
349     addFunctionCaseWithPrograms(group, "cache", checkSupport, initPrograms, testEarlyDestroyKeepLayout, params);
350     params.usePipelineCache = false;
351     addFunctionCaseWithPrograms(group, "no_cache", checkSupport, initPrograms, testEarlyDestroyKeepLayout, params);
352     params.usePipelineCache = true;
353     addFunctionCaseWithPrograms(group, "cache_destroy_layout", checkSupport, initPrograms,
354                                 testEarlyDestroyDestroyLayout, params);
355     params.usePipelineCache = false;
356     addFunctionCaseWithPrograms(group, "no_cache_destroy_layout", checkSupport, initPrograms,
357                                 testEarlyDestroyDestroyLayout, params);
358     params.useMaintenance5 = true;
359     addFunctionCaseWithPrograms(group, "no_cache_destroy_layout_maintenance5", checkSupport, initPrograms,
360                                 testEarlyDestroyDestroyLayout, params);
361 }
362 
363 } // namespace
364 
createEarlyDestroyTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)365 tcu::TestCaseGroup *createEarlyDestroyTests(tcu::TestContext &testCtx,
366                                             PipelineConstructionType pipelineConstructionType)
367 {
368     return createTestGroup(testCtx, "early_destroy", addEarlyDestroyTestCasesWithFunctions, pipelineConstructionType);
369 }
370 
371 } // namespace pipeline
372 } // namespace vkt
373