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 Matched attachments tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelineMatchedAttachmentsTests.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 "deUniquePtr.hpp"
35 
36 namespace vkt
37 {
38 namespace pipeline
39 {
40 
41 using namespace vk;
42 
43 namespace
44 {
45 
46 struct MatchedAttachmentsTestParams
47 {
48     PipelineConstructionType pipelineConstructionType;
49     bool usePipelineCache;
50 };
51 
checkSupport(Context & context,const MatchedAttachmentsTestParams params)52 void checkSupport(Context &context, const MatchedAttachmentsTestParams params)
53 {
54     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
55                                           params.pipelineConstructionType);
56 }
57 
initPrograms(SourceCollections & programCollection,const MatchedAttachmentsTestParams params)58 void initPrograms(SourceCollections &programCollection, const MatchedAttachmentsTestParams params)
59 {
60     DE_UNREF(params);
61 
62     programCollection.glslSources.add("color_vert") << glu::VertexSource("#version 450\n"
63                                                                          "\n"
64                                                                          "void main(){\n"
65                                                                          "    gl_Position = vec4(1);\n"
66                                                                          "}\n");
67 
68     programCollection.glslSources.add("color_frag")
69         << glu::FragmentSource("#version 450\n"
70                                "\n"
71                                "layout(input_attachment_index=0, set=0, binding=0) uniform subpassInput x;\n"
72                                "layout(location=0) out vec4 color;\n"
73                                "void main() {\n"
74                                "   color = subpassLoad(x);\n"
75                                "}\n");
76 }
77 
testMatchedAttachments(Context & context,const MatchedAttachmentsTestParams params)78 tcu::TestStatus testMatchedAttachments(Context &context, const MatchedAttachmentsTestParams params)
79 {
80     const InstanceInterface &vki          = context.getInstanceInterface();
81     const DeviceInterface &vk             = context.getDeviceInterface();
82     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
83     const VkDevice vkDevice               = context.getDevice();
84     const ShaderWrapper vertexShaderModule(
85         ShaderWrapper(vk, vkDevice, context.getBinaryCollection().get("color_vert"), 0));
86     const ShaderWrapper fragmentShaderModule(
87         ShaderWrapper(vk, vkDevice, context.getBinaryCollection().get("color_frag"), 0));
88 
89     const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {
90         0u,                                  // uint32_t              binding;
91         VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType      descriptorType;
92         1u,                                  // uint32_t              descriptorCount;
93         VK_SHADER_STAGE_FRAGMENT_BIT,        // VkShaderStageFlags    stageFlags;
94         DE_NULL                              // const VkSampler*      pImmutableSamplers;
95     };
96 
97     const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
98         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType                        sType;
99         DE_NULL,                                             // const void*                            pNext;
100         0u,                                                  // VkDescriptorSetLayoutCreateFlags       flags;
101         1u,                                                  // uint32_t                               bindingCount;
102         &descriptorSetLayoutBinding                          // const VkDescriptorSetLayoutBinding*    pBindings;
103     };
104 
105     const Unique<VkDescriptorSetLayout> descriptorSetLayout(
106         createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutCreateInfo, DE_NULL));
107 
108     const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
109         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType                 sType;
110         DE_NULL,                                       // const void*                     pNext;
111         0u,                                            // VkPipelineLayoutCreateFlags     flags;
112         1u,                                            // uint32_t                        setLayoutCount;
113         &(*descriptorSetLayout),                       // const VkDescriptorSetLayout*    pSetLayouts;
114         0u,                                            // uint32_t                        pushConstantRangeCount;
115         DE_NULL                                        // const VkPushConstantRange*      pPushConstantRanges;
116     };
117 
118     const PipelineLayoutWrapper pipelineLayout(params.pipelineConstructionType, vk, vkDevice, &pipelineLayoutCreateInfo,
119                                                DE_NULL);
120 
121     const VkAttachmentDescription descs[2] = {
122         {
123             0u,                                       // VkAttachmentDescriptionFlags    flags;
124             VK_FORMAT_R8G8B8A8_UNORM,                 // VkFormat                        format;
125             VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits           samples;
126             VK_ATTACHMENT_LOAD_OP_LOAD,               // VkAttachmentLoadOp              loadOp;
127             VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp             storeOp;
128             VK_ATTACHMENT_LOAD_OP_LOAD,               // VkAttachmentLoadOp              stencilLoadOp;
129             VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp             stencilStoreOp;
130             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout                   initialLayout;
131             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL  // VkImageLayout                   finalLayout;
132         },
133         {
134             0u,                           // VkAttachmentDescriptionFlags    flags;
135             VK_FORMAT_R8G8B8A8_UNORM,     // VkFormat                        format;
136             VK_SAMPLE_COUNT_1_BIT,        // VkSampleCountFlagBits           samples;
137             VK_ATTACHMENT_LOAD_OP_LOAD,   // VkAttachmentLoadOp              loadOp;
138             VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp             storeOp;
139             VK_ATTACHMENT_LOAD_OP_LOAD,   // VkAttachmentLoadOp              stencilLoadOp;
140             VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp             stencilStoreOp;
141             VK_IMAGE_LAYOUT_GENERAL,      // VkImageLayout                   initialLayout;
142             VK_IMAGE_LAYOUT_GENERAL       // VkImageLayout                   finalLayout;
143         }};
144 
145     const VkAttachmentReference color = {
146         0u,                                      // uint32_t         attachment;
147         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout    layout;
148     };
149 
150     const VkAttachmentReference input = {
151         1u,                     // uint32_t         attachment;
152         VK_IMAGE_LAYOUT_GENERAL // VkImageLayout    layout;
153     };
154 
155     const VkSubpassDescription subpassDescription = {
156         0u,                              // VkSubpassDescriptionFlags       flags;
157         VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint             pipelineBindPoint;
158         1u,                              // uint32_t                        inputAttachmentCount;
159         &input,                          // const VkAttachmentReference*    pInputAttachments;
160         1u,                              // uint32_t                        colorAttachmentCount;
161         &color,                          // const VkAttachmentReference*    pColorAttachments;
162         DE_NULL,                         // const VkAttachmentReference*    pResolveAttachments;
163         DE_NULL,                         // const VkAttachmentReference*    pDepthStencilAttachment;
164         0u,                              // uint32_t                        preserveAttachmentCount;
165         DE_NULL                          // const uint32_t*                 pPreserveAttachments;
166     };
167 
168     const VkRenderPassCreateInfo renderPassCreateInfo = {
169         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType                   sType;
170         DE_NULL,                                   // const void*                       pNext;
171         0u,                                        // VkRenderPassCreateFlags           flags;
172         2u,                                        // uint32_t                          attachmentCount;
173         descs,                                     // const VkAttachmentDescription*    pAttachments;
174         1u,                                        // uint32_t                          subpassCount;
175         &subpassDescription,                       // const VkSubpassDescription*       pSubpasses;
176         0u,                                        // uint32_t                          dependencyCount;
177         DE_NULL                                    // const VkSubpassDependency*        pDependencies;
178     };
179 
180     RenderPassWrapper renderPass(params.pipelineConstructionType, vk, vkDevice, &renderPassCreateInfo);
181 
182     const VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {
183         VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType               sType;
184         DE_NULL,                                      // const void*                   pNext;
185 #ifndef CTS_USES_VULKANSC
186         (VkPipelineCacheCreateFlags)0u, // VkPipelineCacheCreateFlags    flags;
187         0u,                             // size_t                        initialDataSize;
188         DE_NULL                         // const void*                   pInitialData;
189 #else
190         VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
191             VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags        flags;
192         context.getResourceInterface()->getCacheDataSize(),       // uintptr_t                         initialDataSize;
193         context.getResourceInterface()->getCacheData()            // const void*                       pInitialData;
194 #endif // CTS_USES_VULKANSC
195     };
196 
197     const Unique<VkPipelineCache> pipelineCache(createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo));
198 
199     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
200         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                             sType;
201         DE_NULL,                                                   // const void*                                 pNext;
202         0u,                                                        // VkPipelineVertexInputStateCreateFlags       flags;
203         0u,      // uint32_t                                    vertexBindingDescriptionCount;
204         DE_NULL, // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
205         0u,      // uint32_t                                    vertexAttributeDescriptionCount;
206         DE_NULL  // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
207     };
208 
209     const VkDynamicState dynamicState[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
210 
211     const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
212         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType                      sType;
213         DE_NULL,                                              // const void*                          pNext;
214         0u,                                                   // VkPipelineDynamicStateCreateFlags    flags;
215         2u,                                                   // uint32_t                             dynamicStateCount;
216         dynamicState                                          // const VkDynamicState*                pDynamicStates;
217     };
218 
219     const std::vector<VkViewport> viewport{};
220     const std::vector<VkRect2D> scissor{};
221     GraphicsPipelineWrapper graphicsPipeline(vki, vk, physicalDevice, vkDevice, context.getDeviceExtensions(),
222                                              params.pipelineConstructionType);
223     graphicsPipeline.setDynamicState(&dynamicStateCreateInfo)
224         .setDefaultRasterizationState()
225         .setDefaultMultisampleState()
226         .setDefaultColorBlendState()
227         .setupVertexInputState(&vertexInputStateCreateInfo)
228         .setupPreRasterizationShaderState(viewport, scissor, pipelineLayout, *renderPass, 0u, vertexShaderModule)
229         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragmentShaderModule)
230         .setupFragmentOutputState(*renderPass, 0u)
231         .setMonolithicPipelineLayout(pipelineLayout)
232         .buildPipeline(params.usePipelineCache ? *pipelineCache : DE_NULL);
233 
234     // Passes as long as createGraphicsPipeline didn't crash.
235     return tcu::TestStatus::pass("Pass");
236 }
237 
addMatchedAttachmentsTestCasesWithFunctions(tcu::TestCaseGroup * group,PipelineConstructionType pipelineConstructionType)238 void addMatchedAttachmentsTestCasesWithFunctions(tcu::TestCaseGroup *group,
239                                                  PipelineConstructionType pipelineConstructionType)
240 {
241     // Input attachments are not supported with dynamic rendering
242     if (!isConstructionTypeShaderObject(pipelineConstructionType))
243     {
244         const MatchedAttachmentsTestParams useCache = {pipelineConstructionType, true};
245         addFunctionCaseWithPrograms(group, "cache", checkSupport, initPrograms, testMatchedAttachments, useCache);
246 
247         const MatchedAttachmentsTestParams noCache = {pipelineConstructionType, false};
248         addFunctionCaseWithPrograms(group, "no_cache", checkSupport, initPrograms, testMatchedAttachments, noCache);
249     }
250 }
251 
252 } // namespace
253 
createMatchedAttachmentsTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)254 tcu::TestCaseGroup *createMatchedAttachmentsTests(tcu::TestContext &testCtx,
255                                                   PipelineConstructionType pipelineConstructionType)
256 {
257     return createTestGroup(testCtx, "matched_attachments", addMatchedAttachmentsTestCasesWithFunctions,
258                            pipelineConstructionType);
259 }
260 
261 } // namespace pipeline
262 } // namespace vkt
263