1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2023 LunarG, Inc.
6  * Copyright (c) 2023 Nintendo
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 Shader Object Pipeline Interaction Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktShaderObjectCreateTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkBarrierUtil.hpp"
32 #include "vktShaderObjectCreateUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "deRandom.hpp"
35 #include "vkBuilderUtil.hpp"
36 
37 namespace vkt
38 {
39 namespace ShaderObject
40 {
41 
42 namespace
43 {
44 
45 enum TestType
46 {
47     SHADER_OBJECT = 0,
48     MAX_PIPELINE,
49     MAX_PIPELINE_SHADER_OBJECT_MAX_PIPELINE,
50     SHADER_OBJECT_MAX_PIPELINE_SHADER_OBJECT,
51     MIN_PIPELINE_SHADER_OBJECT,
52     RENDER_PASS_PIPELINE_SHADER_OBJECT,
53     RENDER_PASS_PIPELINE_SHADER_OBJECT_AFTER_BEGIN,
54     SHADER_OBJECT_MIN_PIPELINE,
55     COMPUTE_SHADER_OBJECT_MIN_PIPELINE,
56     SHADER_OBJECT_COMPUTE_PIPELINE,
57 };
58 
59 struct TestParams
60 {
61     TestType testType;
62 };
63 
64 struct StageTestParams
65 {
66     bool vertShader;
67     bool tessShader;
68     bool geomShader;
69     bool fragShader;
70 };
71 
72 class ShaderObjectPipelineInteractionInstance : public vkt::TestInstance
73 {
74 public:
ShaderObjectPipelineInteractionInstance(Context & context,const TestParams & params)75     ShaderObjectPipelineInteractionInstance(Context &context, const TestParams &params)
76         : vkt::TestInstance(context)
77         , m_params(params)
78     {
79     }
~ShaderObjectPipelineInteractionInstance(void)80     virtual ~ShaderObjectPipelineInteractionInstance(void)
81     {
82     }
83 
84     tcu::TestStatus iterate(void) override;
85 
86 private:
87     bool verifyImage(de::MovePtr<vk::BufferWithMemory> &outputBuffer, uint32_t drawCount);
88     uint32_t getDrawCount(void);
89     TestParams m_params;
90 
91     const vk::VkFormat colorAttachmentFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
92     const vk::VkRect2D renderArea            = {{
93                                          0u,
94                                          0u,
95                                      },
96                                                 {
97                                          32u,
98                                          32u,
99                                      }};
100 };
101 
getDrawCount(void)102 uint32_t ShaderObjectPipelineInteractionInstance::getDrawCount(void)
103 {
104     switch (m_params.testType)
105     {
106     case SHADER_OBJECT:
107         return 1;
108     case MAX_PIPELINE:
109         return 1;
110     case MAX_PIPELINE_SHADER_OBJECT_MAX_PIPELINE:
111         return 3;
112     case SHADER_OBJECT_MAX_PIPELINE_SHADER_OBJECT:
113         return 3;
114     case MIN_PIPELINE_SHADER_OBJECT:
115         return 2;
116     case RENDER_PASS_PIPELINE_SHADER_OBJECT:
117         return 1;
118     case RENDER_PASS_PIPELINE_SHADER_OBJECT_AFTER_BEGIN:
119         return 1;
120     case SHADER_OBJECT_MIN_PIPELINE:
121         return 2;
122     case COMPUTE_SHADER_OBJECT_MIN_PIPELINE:
123         return 1;
124     case SHADER_OBJECT_COMPUTE_PIPELINE:
125         return 1;
126     }
127     return 0;
128 }
129 
extensionEnabled(const std::vector<std::string> & deviceExtensions,const std::string & ext)130 bool extensionEnabled(const std::vector<std::string> &deviceExtensions, const std::string &ext)
131 {
132     return std::find(deviceExtensions.begin(), deviceExtensions.end(), ext) != deviceExtensions.end();
133 }
134 
iterate(void)135 tcu::TestStatus ShaderObjectPipelineInteractionInstance::iterate(void)
136 {
137     const vk::DeviceInterface &vk   = m_context.getDeviceInterface();
138     const vk::VkDevice device       = m_context.getDevice();
139     const vk::VkQueue queue         = m_context.getUniversalQueue();
140     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
141     auto &alloc                     = m_context.getDefaultAllocator();
142     const auto deviceExtensions     = vk::removeUnsupportedShaderObjectExtensions(
143         m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
144     const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
145     const bool geometrySupported     = m_context.getDeviceFeatures().geometryShader;
146     const bool taskSupported         = m_context.getMeshShaderFeaturesEXT().taskShader;
147     const bool meshSupported         = m_context.getMeshShaderFeaturesEXT().meshShader;
148 
149     const auto subresourceRange = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
150 
151     const vk::VkImageCreateInfo createInfo = {
152         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                // VkStructureType            sType
153         DE_NULL,                                                // const void*                pNext
154         0u,                                                     // VkImageCreateFlags        flags
155         vk::VK_IMAGE_TYPE_2D,                                   // VkImageType                imageType
156         colorAttachmentFormat,                                  // VkFormat                    format
157         {renderArea.extent.width, renderArea.extent.height, 1}, // VkExtent3D                extent
158         1u,                                                     // uint32_t                    mipLevels
159         1u,                                                     // uint32_t                    arrayLayers
160         vk::VK_SAMPLE_COUNT_1_BIT,                              // VkSampleCountFlagBits    samples
161         vk::VK_IMAGE_TILING_OPTIMAL,                            // VkImageTiling            tiling
162         vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags        usage
163         vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharingMode
164         0,                             // uint32_t                    queueFamilyIndexCount
165         DE_NULL,                       // const uint32_t*            pQueueFamilyIndices
166         vk::VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout            initialLayout
167     };
168 
169     de::MovePtr<vk::ImageWithMemory> image = de::MovePtr<vk::ImageWithMemory>(
170         new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
171     const auto imageView =
172         vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
173 
174     const vk::VkDeviceSize colorOutputBufferSize =
175         renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
176     de::MovePtr<vk::BufferWithMemory> colorOutputBuffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
177         vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT),
178         vk::MemoryRequirement::HostVisible));
179 
180     const vk::VkCommandPoolCreateInfo cmdPoolInfo = {
181         vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType
182         DE_NULL,                                             // pNext
183         vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
184         queueFamilyIndex,                                    // queuefamilyindex
185     };
186 
187     const vk::Move<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, &cmdPoolInfo));
188     const vk::Move<vk::VkCommandBuffer> cmdBuffer(
189         allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
190     const vk::Move<vk::VkCommandBuffer> copyCmdBuffer(
191         allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
192 
193     const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
194         vk::DescriptorSetLayoutBuilder()
195             .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
196             .build(vk, device));
197 
198     const vk::Unique<vk::VkDescriptorPool> descriptorPool(
199         vk::DescriptorPoolBuilder()
200             .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
201             .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
202 
203     const auto pipelineLayout        = makePipelineLayout(vk, device);
204     const auto computePipelineLayout = makePipelineLayout(vk, device, descriptorSetLayout.get());
205 
206     const auto &binaries = m_context.getBinaryCollection();
207     const auto &vert1    = binaries.get("vert1");
208     const auto &vert2    = binaries.get("vert2");
209     const auto &vert3    = binaries.get("vert3");
210     const auto &tesc     = binaries.get("tesc");
211     const auto &tese     = binaries.get("tese");
212     const auto &geom     = binaries.get("geom");
213     const auto &frag1    = binaries.get("frag1");
214     const auto &frag2    = binaries.get("frag2");
215     const auto &frag3    = binaries.get("frag3");
216     const auto &comp     = binaries.get("comp");
217 
218     // Todo
219     vk::VkDescriptorSetLayout layout = descriptorSetLayout.get();
220 
221     vk::VkShaderCreateInfoEXT vertCreateInfo1 =
222         vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, vert1, tessellationSupported, geometrySupported);
223     vk::VkShaderCreateInfoEXT vertCreateInfo2 =
224         vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, vert2, tessellationSupported, geometrySupported);
225     vk::VkShaderCreateInfoEXT vertCreateInfo3 =
226         vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, vert3, tessellationSupported, geometrySupported);
227     vk::VkShaderCreateInfoEXT tescCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
228                                                                         tesc, tessellationSupported, geometrySupported);
229     vk::VkShaderCreateInfoEXT teseCreateInfo = vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
230                                                                         tese, tessellationSupported, geometrySupported);
231     vk::VkShaderCreateInfoEXT geomCreateInfo =
232         vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, geom, tessellationSupported, geometrySupported);
233     vk::VkShaderCreateInfoEXT fragCreateInfo1 =
234         vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, frag1, tessellationSupported, geometrySupported);
235     vk::VkShaderCreateInfoEXT fragCreateInfo2 =
236         vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, frag2, tessellationSupported, geometrySupported);
237     vk::VkShaderCreateInfoEXT fragCreateInfo3 =
238         vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, frag3, tessellationSupported, geometrySupported);
239     vk::VkShaderCreateInfoEXT compCreateInfo = vk::makeShaderCreateInfo(
240         vk::VK_SHADER_STAGE_COMPUTE_BIT, comp, tessellationSupported, geometrySupported, &layout);
241 
242     vk::Move<vk::VkShaderEXT> vertShader1 = vk::createShader(vk, device, vertCreateInfo1);
243     vk::Move<vk::VkShaderEXT> vertShader2 = vk::createShader(vk, device, vertCreateInfo2);
244     vk::Move<vk::VkShaderEXT> vertShader3 = vk::createShader(vk, device, vertCreateInfo3);
245     vk::Move<vk::VkShaderEXT> tescShader  = vk::createShader(vk, device, tescCreateInfo);
246     vk::Move<vk::VkShaderEXT> teseShader  = vk::createShader(vk, device, teseCreateInfo);
247     vk::Move<vk::VkShaderEXT> geomShader  = vk::createShader(vk, device, geomCreateInfo);
248     vk::Move<vk::VkShaderEXT> fragShader1 = vk::createShader(vk, device, fragCreateInfo1);
249     vk::Move<vk::VkShaderEXT> fragShader2 = vk::createShader(vk, device, fragCreateInfo2);
250     vk::Move<vk::VkShaderEXT> fragShader3 = vk::createShader(vk, device, fragCreateInfo3);
251     vk::Move<vk::VkShaderEXT> compShader  = vk::createShader(vk, device, compCreateInfo);
252 
253     const auto vertShaderModule1 = createShaderModule(vk, device, vert1);
254     const auto vertShaderModule2 = createShaderModule(vk, device, vert2);
255     const auto vertShaderModule3 = createShaderModule(vk, device, vert3);
256     const auto tescShaderModule  = createShaderModule(vk, device, tesc);
257     const auto teseShaderModule  = createShaderModule(vk, device, tese);
258     const auto geomShaderModule  = createShaderModule(vk, device, geom);
259     const auto fragShaderModule1 = createShaderModule(vk, device, frag1);
260     const auto fragShaderModule2 = createShaderModule(vk, device, frag2);
261     const auto fragShaderModule3 = createShaderModule(vk, device, frag3);
262     const auto compShaderModule  = createShaderModule(vk, device, comp);
263 
264     const auto renderPass  = vk::makeRenderPass(vk, device, colorAttachmentFormat, vk::VK_FORMAT_UNDEFINED,
265                                                 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, vk::VK_IMAGE_LAYOUT_GENERAL);
266     const auto framebuffer = vk::makeFramebuffer(vk, device, *renderPass, 1u, &*imageView, renderArea.extent.width,
267                                                  renderArea.extent.height);
268 
269     const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
270         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
271         DE_NULL,                                                       // const void* pNext;
272         0u,                                                            // VkPipelineVertexInputStateCreateFlags flags;
273         0u,                                                            // uint32_t vertexBindingDescriptionCount;
274         DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
275         0u,      // uint32_t vertexAttributeDescriptionCount;
276         DE_NULL  // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
277     };
278 
279     const vk::VkPipelineTessellationStateCreateInfo tessStateCreateInfo = {
280         vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
281         DE_NULL,                                                       // const void* pNext;
282         0u,                                                            // VkPipelineTessellationStateCreateFlags flags;
283         4u,                                                            // uint32_t patchControlPoints;
284     };
285 
286     const vk::VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = {
287         vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType                             sType;
288         DE_NULL,                                         // const void*                                 pNext;
289         (vk::VkPipelineInputAssemblyStateCreateFlags)0u, // VkPipelineInputAssemblyStateCreateFlags     flags;
290         vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,            // VkPrimitiveTopology                         topology;
291         VK_FALSE, // VkBool32                                    primitiveRestartEnable;
292     };
293 
294     vk::VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo = {
295         vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, // VkStructureType    sType
296         DE_NULL,                                              // const void*        pNext
297         0u,                                                   // uint32_t            viewMask
298         1u,                                                   // uint32_t            colorAttachmentCount
299         &colorAttachmentFormat,                               // const VkFormat*    pColorAttachmentFormats
300         vk::VK_FORMAT_UNDEFINED,                              // VkFormat            depthAttachmentFormat
301         vk::VK_FORMAT_UNDEFINED,                              // VkFormat            stencilAttachmentFormat
302     };
303 
304     const vk::VkViewport viewport = vk::makeViewport(renderArea.extent);
305     const vk::VkRect2D scissor    = vk::makeRect2D(renderArea.extent);
306 
307     bool createDynamicPipeline = m_params.testType != MIN_PIPELINE_SHADER_OBJECT &&
308                                  m_params.testType != SHADER_OBJECT_MIN_PIPELINE &&
309                                  m_params.testType != COMPUTE_SHADER_OBJECT_MIN_PIPELINE &&
310                                  m_params.testType != RENDER_PASS_PIPELINE_SHADER_OBJECT &&
311                                  m_params.testType != RENDER_PASS_PIPELINE_SHADER_OBJECT_AFTER_BEGIN;
312 
313     const vk::VkPipelineViewportStateCreateInfo viewportStateCreateInfo = {
314         vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType                             sType
315         DE_NULL,                                                   // const void*                                 pNext
316         (vk::VkPipelineViewportStateCreateFlags)0u,                // VkPipelineViewportStateCreateFlags          flags
317         createDynamicPipeline ? 0u : 1u, // uint32_t                                    viewportCount
318         &viewport,                       // const VkViewport*                           pViewports
319         createDynamicPipeline ? 0u : 1u, // uint32_t                                    scissorCount
320         &scissor,                        // const VkRect2D*                             pScissors
321     };
322 
323     const auto &edsFeatures  = m_context.getExtendedDynamicStateFeaturesEXT();
324     const auto &eds2Features = m_context.getExtendedDynamicState2FeaturesEXT();
325     const auto &eds3Features = m_context.getExtendedDynamicState3FeaturesEXT();
326     const auto &viFeatures   = m_context.getVertexInputDynamicStateFeaturesEXT();
327 
328     std::vector<vk::VkDynamicState> dynamicStates = {
329         vk::VK_DYNAMIC_STATE_LINE_WIDTH,           vk::VK_DYNAMIC_STATE_DEPTH_BIAS,
330         vk::VK_DYNAMIC_STATE_BLEND_CONSTANTS,      vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS,
331         vk::VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, vk::VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
332         vk::VK_DYNAMIC_STATE_STENCIL_REFERENCE,
333     };
334 
335     if (edsFeatures.extendedDynamicState)
336     {
337         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CULL_MODE_EXT);
338         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT);
339         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT);
340         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
341         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
342         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT);
343         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT);
344         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT);
345         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT);
346         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT);
347         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT);
348         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT);
349     }
350     else
351     {
352         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT);
353         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR);
354     }
355     if (eds2Features.extendedDynamicState2)
356     {
357         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE);
358         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE);
359         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE);
360     }
361     if (eds2Features.extendedDynamicState2LogicOp)
362         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_EXT);
363     if (eds2Features.extendedDynamicState2PatchControlPoints)
364         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
365 
366     if (eds3Features.extendedDynamicState3TessellationDomainOrigin)
367         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT);
368     if (eds3Features.extendedDynamicState3DepthClampEnable)
369         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT);
370     if (eds3Features.extendedDynamicState3PolygonMode)
371         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_POLYGON_MODE_EXT);
372     if (eds3Features.extendedDynamicState3RasterizationSamples)
373         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
374     if (eds3Features.extendedDynamicState3SampleMask)
375         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_MASK_EXT);
376     if (eds3Features.extendedDynamicState3AlphaToCoverageEnable)
377         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT);
378     if (eds3Features.extendedDynamicState3AlphaToOneEnable)
379         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT);
380     if (eds3Features.extendedDynamicState3LogicOpEnable)
381         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT);
382     if (eds3Features.extendedDynamicState3ColorBlendEnable)
383         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
384     if (eds3Features.extendedDynamicState3ColorBlendEquation)
385         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
386     if (eds3Features.extendedDynamicState3ColorWriteMask)
387         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT);
388     if (viFeatures.vertexInputDynamicState)
389         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
390 
391     if (extensionEnabled(deviceExtensions, "VK_EXT_transform_feedback") &&
392         eds3Features.extendedDynamicState3RasterizationStream)
393         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT);
394     if (extensionEnabled(deviceExtensions, "VK_EXT_blend_operation_advanced") &&
395         eds3Features.extendedDynamicState3ColorBlendAdvanced)
396         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT);
397     if (extensionEnabled(deviceExtensions, "VK_EXT_conservative_rasterization") &&
398         eds3Features.extendedDynamicState3ConservativeRasterizationMode)
399         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT);
400     if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples") &&
401         eds3Features.extendedDynamicState3CoverageModulationMode)
402         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV);
403     if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples") &&
404         eds3Features.extendedDynamicState3CoverageModulationTableEnable)
405         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV);
406     if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples") &&
407         eds3Features.extendedDynamicState3CoverageModulationTable)
408         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV);
409     if (extensionEnabled(deviceExtensions, "VK_NV_coverage_reduction_mode") &&
410         eds3Features.extendedDynamicState3CoverageReductionMode)
411         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV);
412     if (extensionEnabled(deviceExtensions, "VK_NV_fragment_coverage_to_color") &&
413         eds3Features.extendedDynamicState3CoverageToColorEnable)
414         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV);
415     if (extensionEnabled(deviceExtensions, "VK_NV_fragment_coverage_to_color") &&
416         eds3Features.extendedDynamicState3CoverageToColorLocation)
417         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV);
418     if (extensionEnabled(deviceExtensions, "VK_EXT_depth_clip_enable") &&
419         eds3Features.extendedDynamicState3DepthClipEnable)
420         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT);
421     if (extensionEnabled(deviceExtensions, "VK_EXT_depth_clip_control") &&
422         eds3Features.extendedDynamicState3DepthClipNegativeOneToOne)
423         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT);
424     if (extensionEnabled(deviceExtensions, "VK_EXT_color_write_enable"))
425         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
426     if (extensionEnabled(deviceExtensions, "VK_EXT_conservative_rasterization") &&
427         eds3Features.extendedDynamicState3ExtraPrimitiveOverestimationSize)
428         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT);
429     if ((extensionEnabled(deviceExtensions, "VK_KHR_line_rasterization") ||
430          extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization")) &&
431         eds3Features.extendedDynamicState3LineRasterizationMode)
432         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT);
433     if ((extensionEnabled(deviceExtensions, "VK_KHR_line_rasterization") ||
434          extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization")) &&
435         eds3Features.extendedDynamicState3LineStippleEnable)
436         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
437     if ((extensionEnabled(deviceExtensions, "VK_KHR_line_rasterization") ||
438          extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization")))
439         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_EXT);
440     if (extensionEnabled(deviceExtensions, "VK_EXT_provoking_vertex") &&
441         eds3Features.extendedDynamicState3ProvokingVertexMode)
442         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT);
443     if (extensionEnabled(deviceExtensions, "VK_KHR_fragment_shading_rate"))
444         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR);
445     if (extensionEnabled(deviceExtensions, "VK_NV_representative_fragment_test") &&
446         eds3Features.extendedDynamicState3RepresentativeFragmentTestEnable)
447         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV);
448     if (extensionEnabled(deviceExtensions, "VK_EXT_sample_locations") &&
449         eds3Features.extendedDynamicState3SampleLocationsEnable)
450         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
451     if (extensionEnabled(deviceExtensions, "VK_EXT_sample_locations"))
452         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
453     if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image") &&
454         eds3Features.extendedDynamicState3ShadingRateImageEnable)
455         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV);
456     if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image"))
457         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV);
458     if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image"))
459         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV);
460     if (extensionEnabled(deviceExtensions, "VK_NV_viewport_swizzle") &&
461         eds3Features.extendedDynamicState3ViewportSwizzle)
462         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV);
463     if (extensionEnabled(deviceExtensions, "VK_NV_clip_space_w_scaling") &&
464         eds3Features.extendedDynamicState3ViewportWScalingEnable)
465         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV);
466     if (extensionEnabled(deviceExtensions, "VK_NV_clip_space_w_scaling"))
467         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV);
468     if (extensionEnabled(deviceExtensions, "VK_NV_scissor_exclusive"))
469         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV);
470     if (extensionEnabled(deviceExtensions, "VK_NV_scissor_exclusive"))
471         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV);
472     if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
473         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT);
474     if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
475         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
476     if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
477         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT);
478     if (extensionEnabled(deviceExtensions, "VK_EXT_attachment_feedback_loop_dynamic_state"))
479         dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
480 
481     const vk::VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
482         vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
483         DE_NULL,                                                  // const void* pNext;
484         (vk::VkPipelineDynamicStateCreateFlags)0u,                // VkPipelineDynamicStateCreateFlags flags;
485         static_cast<uint32_t>(dynamicStates.size()),              // uint32_t dynamicStateCount;
486         dynamicStates.data(),                                     // const VkDynamicState* pDynamicStates;
487     };
488     const vk::VkPipelineDynamicStateCreateInfo *pipelineDynamicState =
489         (createDynamicPipeline) ? &dynamicStateCreateInfo : DE_NULL;
490 
491     const vk::VkDeviceSize bufferSizeBytes = sizeof(uint32_t) * 4;
492 
493     const vk::Unique<vk::VkDescriptorSet> descriptorSet(
494         makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
495     const vk::BufferWithMemory outputBuffer(
496         vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
497         vk::MemoryRequirement::HostVisible);
498 
499     const vk::VkDescriptorBufferInfo descriptorInfo =
500         vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
501     vk::DescriptorSetUpdateBuilder()
502         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
503                      vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
504         .update(vk, device);
505 
506     vk::VkPipelineRenderingCreateInfo *pPipelineRenderingCreateInfo = &pipelineRenderingCreateInfo;
507     vk::VkRenderPass renderPassHandle                               = VK_NULL_HANDLE;
508     if (m_params.testType == RENDER_PASS_PIPELINE_SHADER_OBJECT ||
509         m_params.testType == RENDER_PASS_PIPELINE_SHADER_OBJECT_AFTER_BEGIN)
510     {
511         pPipelineRenderingCreateInfo = DE_NULL;
512         renderPassHandle             = *renderPass;
513     }
514 
515     const auto pipeline1 = makeGraphicsPipeline(
516         vk, device, pipelineLayout.get(), vertShaderModule1.get(), tescShaderModule.get(), teseShaderModule.get(),
517         geomShaderModule.get(), fragShaderModule1.get(), renderPassHandle, 0u, &vertexInputStateParams,
518         &pipelineInputAssemblyStateInfo, &tessStateCreateInfo, &viewportStateCreateInfo, DE_NULL, DE_NULL, DE_NULL,
519         DE_NULL, pipelineDynamicState, pPipelineRenderingCreateInfo);
520     const auto pipeline2 = makeGraphicsPipeline(
521         vk, device, pipelineLayout.get(), vertShaderModule2.get(), tescShaderModule.get(), teseShaderModule.get(),
522         geomShaderModule.get(), fragShaderModule2.get(), renderPassHandle, 0u, &vertexInputStateParams,
523         &pipelineInputAssemblyStateInfo, &tessStateCreateInfo, &viewportStateCreateInfo, DE_NULL, DE_NULL, DE_NULL,
524         DE_NULL, pipelineDynamicState, pPipelineRenderingCreateInfo);
525     const auto pipeline3 = makeGraphicsPipeline(
526         vk, device, pipelineLayout.get(), vertShaderModule3.get(), tescShaderModule.get(), teseShaderModule.get(),
527         geomShaderModule.get(), fragShaderModule3.get(), renderPassHandle, 0u, &vertexInputStateParams,
528         &pipelineInputAssemblyStateInfo, &tessStateCreateInfo, &viewportStateCreateInfo, DE_NULL, DE_NULL, DE_NULL,
529         DE_NULL, pipelineDynamicState, pPipelineRenderingCreateInfo);
530     const auto computePipeline =
531         vk::makeComputePipeline(vk, device, computePipelineLayout.get(), compShaderModule.get());
532 
533     const vk::VkClearValue clearValue = vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
534     vk::VkImageMemoryBarrier initialBarrier =
535         vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED,
536                                    vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
537 
538     const vk::VkDeviceSize bufferSize        = 64;
539     de::MovePtr<vk::BufferWithMemory> buffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
540         vk, device, alloc, vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
541         vk::MemoryRequirement::HostVisible));
542 
543     vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
544 
545     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
546                           vk::VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0, DE_NULL, 0, DE_NULL, 1,
547                           &initialBarrier);
548 
549     if (m_params.testType == RENDER_PASS_PIPELINE_SHADER_OBJECT)
550     {
551         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
552     }
553 
554     if (m_params.testType != COMPUTE_SHADER_OBJECT_MIN_PIPELINE && m_params.testType != SHADER_OBJECT_COMPUTE_PIPELINE)
555         vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
556                            vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
557 
558     vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
559                                             false,
560                                             !m_context.getExtendedDynamicStateFeaturesEXT().extendedDynamicState);
561     vk::bindNullTaskMeshShaders(vk, *cmdBuffer, m_context.getMeshShaderFeaturesEXT());
562 
563     vk::VkDeviceSize offset = 0u;
564     vk::VkDeviceSize stride = 16u;
565     vk.cmdBindVertexBuffers2(*cmdBuffer, 0u, 1u, &**buffer, &offset, &bufferSize, &stride);
566 
567     if (m_params.testType == SHADER_OBJECT)
568     {
569         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader1, *tescShader, *teseShader, *geomShader, *fragShader1,
570                                 taskSupported, meshSupported);
571         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
572     }
573     else if (m_params.testType == MAX_PIPELINE)
574     {
575         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
576         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
577     }
578     else if (m_params.testType == MAX_PIPELINE_SHADER_OBJECT_MAX_PIPELINE)
579     {
580         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
581         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
582 
583         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader2, *tescShader, *teseShader, *geomShader, *fragShader2,
584                                 taskSupported, meshSupported);
585         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
586 
587         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline3);
588         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
589     }
590     else if (m_params.testType == SHADER_OBJECT_MAX_PIPELINE_SHADER_OBJECT)
591     {
592         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader1, *tescShader, *teseShader, *geomShader, *fragShader1,
593                                 taskSupported, meshSupported);
594         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
595 
596         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline2);
597         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
598 
599         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader3, *tescShader, *teseShader, *geomShader, *fragShader3,
600                                 taskSupported, meshSupported);
601         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
602     }
603     else if (m_params.testType == MIN_PIPELINE_SHADER_OBJECT)
604     {
605         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
606         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
607 
608         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader2, *tescShader, *teseShader, *geomShader, *fragShader2,
609                                 taskSupported, meshSupported);
610         vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
611                                                 false,
612                                                 !m_context.getExtendedDynamicStateFeaturesEXT().extendedDynamicState);
613         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
614     }
615     else if (m_params.testType == RENDER_PASS_PIPELINE_SHADER_OBJECT)
616     {
617         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader1, *tescShader, *teseShader, *geomShader, *fragShader1,
618                                 taskSupported, meshSupported);
619         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
620     }
621     else if (m_params.testType == RENDER_PASS_PIPELINE_SHADER_OBJECT_AFTER_BEGIN)
622     {
623         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
624         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader1, *tescShader, *teseShader, *geomShader, *fragShader1,
625                                 taskSupported, meshSupported);
626         vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
627                                                 false,
628                                                 !m_context.getExtendedDynamicStateFeaturesEXT().extendedDynamicState);
629         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
630     }
631     else if (m_params.testType == SHADER_OBJECT_MIN_PIPELINE)
632     {
633         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader1, *tescShader, *teseShader, *geomShader, *fragShader1,
634                                 taskSupported, meshSupported);
635         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
636 
637         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline2);
638         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
639     }
640     else if (m_params.testType == COMPUTE_SHADER_OBJECT_MIN_PIPELINE)
641     {
642         vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get(), 0, 1,
643                                  &descriptorSet.get(), 0, DE_NULL);
644 
645         vk::VkShaderStageFlagBits stages[] = {vk::VK_SHADER_STAGE_COMPUTE_BIT};
646         vk.cmdBindShadersEXT(*cmdBuffer, 1, stages, &*compShader);
647         vk.cmdDispatch(*cmdBuffer, 4, 1, 1);
648 
649         vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
650                            vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
651         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline1);
652         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
653         vk::endRendering(vk, *cmdBuffer);
654     }
655     else if (m_params.testType == SHADER_OBJECT_COMPUTE_PIPELINE)
656     {
657         vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get(), 0, 1,
658                                  &descriptorSet.get(), 0, DE_NULL);
659 
660         vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
661                            vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
662         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader1, *tescShader, *teseShader, *geomShader, *fragShader1,
663                                 taskSupported, meshSupported);
664         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
665         vk::endRendering(vk, *cmdBuffer);
666 
667         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
668         vk.cmdDispatch(*cmdBuffer, 4, 1, 1);
669     }
670 
671     if (m_params.testType != COMPUTE_SHADER_OBJECT_MIN_PIPELINE && m_params.testType != SHADER_OBJECT_COMPUTE_PIPELINE)
672         vk::endRendering(vk, *cmdBuffer);
673 
674     vk::endCommandBuffer(vk, *cmdBuffer);
675 
676     submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
677 
678     const vk::VkBufferImageCopy copyRegion = {
679         0u, // VkDeviceSize bufferOffset;
680         0u, // uint32_t bufferRowLength;
681         0u, // uint32_t bufferImageHeight;
682         {
683             vk::VK_IMAGE_ASPECT_COLOR_BIT,                     // VkImageAspectFlags aspect;
684             0u,                                                // uint32_t mipLevel;
685             0u,                                                // uint32_t baseArrayLayer;
686             1u,                                                // uint32_t layerCount;
687         },                                                     // VkImageSubresourceLayers imageSubresource;
688         {0, 0, 0},                                             // VkOffset3D imageOffset;
689         {renderArea.extent.width, renderArea.extent.height, 1} // VkExtent3D imageExtent;
690     };
691 
692     vk::beginCommandBuffer(vk, *copyCmdBuffer, 0u);
693     vk.cmdCopyImageToBuffer(*copyCmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u, &copyRegion);
694     vk::endCommandBuffer(vk, *copyCmdBuffer);
695     submitCommandsAndWait(vk, device, queue, copyCmdBuffer.get());
696 
697     if (!verifyImage(colorOutputBuffer, getDrawCount()))
698         return tcu::TestStatus::fail("Fail");
699 
700     if (m_params.testType == COMPUTE_SHADER_OBJECT_MIN_PIPELINE || m_params.testType == SHADER_OBJECT_COMPUTE_PIPELINE)
701     {
702         const vk::Allocation &outputBufferAllocation = outputBuffer.getAllocation();
703         invalidateAlloc(vk, device, outputBufferAllocation);
704 
705         const uint32_t *bufferPtr = static_cast<uint32_t *>(outputBufferAllocation.getHostPtr());
706 
707         for (uint32_t i = 0; i < 4; ++i)
708         {
709             if (bufferPtr[i] != i)
710                 return tcu::TestStatus::fail("Fail");
711         }
712     }
713 
714     return tcu::TestStatus::pass("Pass");
715 }
716 
verifyImage(de::MovePtr<vk::BufferWithMemory> & outputBuffer,uint32_t drawCount)717 bool ShaderObjectPipelineInteractionInstance::verifyImage(de::MovePtr<vk::BufferWithMemory> &outputBuffer,
718                                                           uint32_t drawCount)
719 {
720     tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(
721         vk::mapVkFormat(vk::VK_FORMAT_R8G8B8A8_UNORM), renderArea.extent.width, renderArea.extent.height, 1,
722         (const void *)outputBuffer->getAllocation().getHostPtr());
723 
724     const tcu::Vec4 red   = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
725     const tcu::Vec4 green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
726     const tcu::Vec4 blue  = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
727     const int32_t width   = resultBuffer.getWidth();
728     const int32_t height  = resultBuffer.getHeight();
729 
730     for (int32_t j = 0; j < height; ++j)
731     {
732         for (int32_t i = 0; i < width; ++i)
733         {
734             const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
735             if (i < width / 2 && j < height / 2 && drawCount > 0)
736             {
737                 if (color != red)
738                     return false;
739             }
740             else if (i >= width / 2 && j < height / 2 && drawCount > 1)
741             {
742                 if (color != green)
743                     return false;
744             }
745             else if (i < width / 2 && j >= height / 2 && drawCount > 2)
746             {
747                 if (color != blue)
748                     return false;
749             }
750         }
751     }
752 
753     return true;
754 }
755 
756 class ShaderObjectPipelineInteractionCase : public vkt::TestCase
757 {
758 public:
ShaderObjectPipelineInteractionCase(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)759     ShaderObjectPipelineInteractionCase(tcu::TestContext &testCtx, const std::string &name, const TestParams &params)
760         : vkt::TestCase(testCtx, name)
761         , m_params(params)
762     {
763     }
~ShaderObjectPipelineInteractionCase(void)764     virtual ~ShaderObjectPipelineInteractionCase(void)
765     {
766     }
767 
768     void checkSupport(vkt::Context &context) const override;
769     virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const770     TestInstance *createInstance(Context &context) const override
771     {
772         return new ShaderObjectPipelineInteractionInstance(context, m_params);
773     }
774 
775 private:
776     TestParams m_params;
777 };
778 
initPrograms(vk::SourceCollections & programCollection) const779 void ShaderObjectPipelineInteractionCase::initPrograms(vk::SourceCollections &programCollection) const
780 {
781     std::stringstream vert1, vert2, vert3;
782     std::stringstream geom;
783     std::stringstream tesc;
784     std::stringstream tese;
785     std::stringstream frag1, frag2, frag3;
786     std::stringstream comp;
787 
788     vert1 << "#version 450\n"
789           << "void main() {\n"
790           << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
791           << "    gl_Position = vec4(pos * 0.5f - vec2(0.5f, 0.5f), 0.0f, 1.0f);\n"
792           << "}\n";
793     vert2 << "#version 450\n"
794           << "void main() {\n"
795           << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
796           << "    gl_Position = vec4(pos * 0.5f - vec2(0.0f, 0.5f), 0.0f, 1.0f);\n"
797           << "}\n";
798     vert3 << "#version 450\n"
799           << "void main() {\n"
800           << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
801           << "    gl_Position = vec4(pos * 0.5f - vec2(0.5f, 0.0f), 0.0f, 1.0f);\n"
802           << "}\n";
803 
804     tesc << "#version 450\n"
805          << "\n"
806          << "layout(vertices = 4) out;\n"
807          << "\n"
808          << "void main (void)\n"
809          << "{\n"
810          << "    if (gl_InvocationID == 0) {\n"
811          << "        gl_TessLevelInner[0] = 1.0;\n"
812          << "        gl_TessLevelInner[1] = 1.0;\n"
813          << "        gl_TessLevelOuter[0] = 1.0;\n"
814          << "        gl_TessLevelOuter[1] = 1.0;\n"
815          << "        gl_TessLevelOuter[2] = 1.0;\n"
816          << "        gl_TessLevelOuter[3] = 1.0;\n"
817          << "    }\n"
818          << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
819          << "}\n";
820 
821     tese << "#version 450\n"
822          << "\n"
823          << "layout(quads, equal_spacing) in;\n"
824          << "\n"
825          << "void main (void)\n"
826          << "{\n"
827          << "    float u = gl_TessCoord.x;\n"
828          << "    float v = gl_TessCoord.y;\n"
829          << "    float omu = 1.0f - u;\n"
830          << "    float omv = 1.0f - v;\n"
831          << "    gl_Position = omu * omv * gl_in[0].gl_Position + u * omv * gl_in[2].gl_Position + u * v * "
832             "gl_in[3].gl_Position + omu * v * gl_in[1].gl_Position;\n"
833          << "    gl_Position.x *= 2.0f;\n"
834          << "}\n";
835 
836     geom << "#version 450\n"
837          << "layout(triangles) in;\n"
838          << "layout(triangle_strip, max_vertices = 4) out;\n"
839          << "\n"
840          << "void main(void)\n"
841          << "{\n"
842          << "    gl_Position = gl_in[0].gl_Position;\n"
843          << "    gl_Position.y *= 2.0f;\n"
844          << "    EmitVertex();\n"
845          << "    gl_Position = gl_in[1].gl_Position;\n"
846          << "    gl_Position.y *= 2.0f;\n"
847          << "    EmitVertex();\n"
848          << "    gl_Position = gl_in[2].gl_Position;\n"
849          << "    gl_Position.y *= 2.0f;\n"
850          << "    EmitVertex();\n"
851          << "    EndPrimitive();\n"
852          << "}\n";
853 
854     frag1 << "#version 450\n"
855           << "layout (location=0) out vec4 outColor;\n"
856           << "void main() {\n"
857           << "    outColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
858           << "}\n";
859     frag2 << "#version 450\n"
860           << "layout (location=0) out vec4 outColor;\n"
861           << "void main() {\n"
862           << "    outColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
863           << "}\n";
864     frag3 << "#version 450\n"
865           << "layout (location=0) out vec4 outColor;\n"
866           << "void main() {\n"
867           << "    outColor = vec4(0.0f, 0.0f, 1.0f, 1.0f);\n"
868           << "}\n";
869 
870     comp << "#version 450\n"
871          << "layout(local_size_x=16, local_size_x=1, local_size_x=1) in;\n"
872          << "layout(binding = 0) buffer Output {\n"
873          << "    uint values[16];\n"
874          << "} buffer_out;\n\n"
875          << "void main() {\n"
876          << "    buffer_out.values[gl_LocalInvocationID.x] = gl_LocalInvocationID.x;\n"
877          << "}\n";
878 
879     programCollection.glslSources.add("vert1") << glu::VertexSource(vert1.str());
880     programCollection.glslSources.add("vert2") << glu::VertexSource(vert2.str());
881     programCollection.glslSources.add("vert3") << glu::VertexSource(vert3.str());
882     programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
883     programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
884     programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
885     programCollection.glslSources.add("frag1") << glu::FragmentSource(frag1.str());
886     programCollection.glslSources.add("frag2") << glu::FragmentSource(frag2.str());
887     programCollection.glslSources.add("frag3") << glu::FragmentSource(frag3.str());
888     programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
889 }
890 
checkSupport(Context & context) const891 void ShaderObjectPipelineInteractionCase::checkSupport(Context &context) const
892 {
893     context.requireDeviceFunctionality("VK_EXT_shader_object");
894 
895     context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
896     context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
897 }
898 
899 class ShaderObjectStageBindingInstance : public vkt::TestInstance
900 {
901 public:
ShaderObjectStageBindingInstance(Context & context,const StageTestParams & params)902     ShaderObjectStageBindingInstance(Context &context, const StageTestParams &params)
903         : vkt::TestInstance(context)
904         , m_params(params)
905     {
906     }
~ShaderObjectStageBindingInstance(void)907     virtual ~ShaderObjectStageBindingInstance(void)
908     {
909     }
910 
911     tcu::TestStatus iterate(void) override;
912 
913 private:
914     bool verifyImage(de::MovePtr<vk::BufferWithMemory> &outputBuffer);
915     StageTestParams m_params;
916 
917     const vk::VkFormat colorAttachmentFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
918     const vk::VkRect2D renderArea            = {{
919                                          0u,
920                                          0u,
921                                      },
922                                                 {
923                                          32u,
924                                          32u,
925                                      }};
926 };
927 
iterate(void)928 tcu::TestStatus ShaderObjectStageBindingInstance::iterate(void)
929 {
930     const vk::DeviceInterface &vk   = m_context.getDeviceInterface();
931     const vk::VkDevice device       = m_context.getDevice();
932     const vk::VkQueue queue         = m_context.getUniversalQueue();
933     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
934     auto &alloc                     = m_context.getDefaultAllocator();
935     const auto deviceExtensions     = vk::removeUnsupportedShaderObjectExtensions(
936         m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
937     const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
938     const bool geometrySupported     = m_context.getDeviceFeatures().geometryShader;
939     const bool taskSupported         = m_context.getMeshShaderFeaturesEXT().taskShader;
940     const bool meshSupported         = m_context.getMeshShaderFeaturesEXT().meshShader;
941 
942     const auto subresourceRange = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
943 
944     const vk::VkImageCreateInfo createInfo = {
945         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                // VkStructureType            sType
946         DE_NULL,                                                // const void*                pNext
947         0u,                                                     // VkImageCreateFlags        flags
948         vk::VK_IMAGE_TYPE_2D,                                   // VkImageType                imageType
949         colorAttachmentFormat,                                  // VkFormat                    format
950         {renderArea.extent.width, renderArea.extent.height, 1}, // VkExtent3D                extent
951         1u,                                                     // uint32_t                    mipLevels
952         1u,                                                     // uint32_t                    arrayLayers
953         vk::VK_SAMPLE_COUNT_1_BIT,                              // VkSampleCountFlagBits    samples
954         vk::VK_IMAGE_TILING_OPTIMAL,                            // VkImageTiling            tiling
955         vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags        usage
956         vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharingMode
957         0,                             // uint32_t                    queueFamilyIndexCount
958         DE_NULL,                       // const uint32_t*            pQueueFamilyIndices
959         vk::VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout            initialLayout
960     };
961 
962     de::MovePtr<vk::ImageWithMemory> image = de::MovePtr<vk::ImageWithMemory>(
963         new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
964     const auto imageView =
965         vk::makeImageView(vk, device, **image, vk::VK_IMAGE_VIEW_TYPE_2D, colorAttachmentFormat, subresourceRange);
966 
967     const vk::VkDeviceSize colorOutputBufferSize =
968         renderArea.extent.width * renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(colorAttachmentFormat));
969     de::MovePtr<vk::BufferWithMemory> colorOutputBuffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
970         vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT),
971         vk::MemoryRequirement::HostVisible));
972 
973     const vk::VkCommandPoolCreateInfo cmdPoolInfo = {
974         vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType
975         DE_NULL,                                             // pNext
976         vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
977         queueFamilyIndex,                                    // queuefamilyindex
978     };
979 
980     const vk::Move<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, &cmdPoolInfo));
981     const vk::Move<vk::VkCommandBuffer> cmdBuffer(
982         allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
983     const vk::Move<vk::VkCommandBuffer> copyCmdBuffer(
984         allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
985 
986     const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
987         vk::DescriptorSetLayoutBuilder()
988             .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_ALL_GRAPHICS)
989             .build(vk, device));
990 
991     const vk::Unique<vk::VkDescriptorPool> descriptorPool(
992         vk::DescriptorPoolBuilder()
993             .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
994             .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
995 
996     const auto topology =
997         m_params.tessShader ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
998 
999     const auto pipelineLayout      = makePipelineLayout(vk, device, descriptorSetLayout.get());
1000     const auto emptyPipelineLayout = makePipelineLayout(vk, device);
1001 
1002     const auto &binaries = m_context.getBinaryCollection();
1003     const auto &vert     = binaries.get("vert");
1004     const auto &tesc     = binaries.get("tesc");
1005     const auto &tese     = binaries.get("tese");
1006     const auto &geom     = binaries.get("geom");
1007     const auto &frag     = binaries.get("frag");
1008 
1009     const auto &pipeline_vert = binaries.get("pipeline_vert");
1010     const auto &pipeline_tesc = binaries.get("pipeline_tesc");
1011     const auto &pipeline_tese = binaries.get("pipeline_tese");
1012     const auto &pipeline_geom = binaries.get("pipeline_geom");
1013     const auto &pipeline_frag = binaries.get("pipeline_frag");
1014 
1015     vk::VkDescriptorSetLayout layout = descriptorSetLayout.get();
1016 
1017     vk::VkShaderCreateInfoEXT vertCreateInfo = vk::makeShaderCreateInfo(
1018         vk::VK_SHADER_STAGE_VERTEX_BIT, vert, tessellationSupported, geometrySupported, &layout);
1019     vk::VkShaderCreateInfoEXT tescCreateInfo = vk::makeShaderCreateInfo(
1020         vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, tesc, tessellationSupported, geometrySupported, &layout);
1021     vk::VkShaderCreateInfoEXT teseCreateInfo = vk::makeShaderCreateInfo(
1022         vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, tese, tessellationSupported, geometrySupported, &layout);
1023     vk::VkShaderCreateInfoEXT geomCreateInfo = vk::makeShaderCreateInfo(
1024         vk::VK_SHADER_STAGE_GEOMETRY_BIT, geom, tessellationSupported, geometrySupported, &layout);
1025     vk::VkShaderCreateInfoEXT fragCreateInfo = vk::makeShaderCreateInfo(
1026         vk::VK_SHADER_STAGE_FRAGMENT_BIT, frag, tessellationSupported, geometrySupported, &layout);
1027 
1028     vk::Move<vk::VkShaderEXT> vertShader = vk::createShader(vk, device, vertCreateInfo);
1029     vk::Move<vk::VkShaderEXT> tescShader;
1030     vk::Move<vk::VkShaderEXT> teseShader;
1031     vk::Move<vk::VkShaderEXT> geomShader;
1032     vk::Move<vk::VkShaderEXT> fragShader = vk::createShader(vk, device, fragCreateInfo);
1033 
1034     vk::Move<vk::VkShaderModule> vertShaderModule = createShaderModule(vk, device, pipeline_vert);
1035     vk::Move<vk::VkShaderModule> tescShaderModule;
1036     vk::Move<vk::VkShaderModule> teseShaderModule;
1037     vk::Move<vk::VkShaderModule> geomShaderModule;
1038     vk::Move<vk::VkShaderModule> fragShaderModule = createShaderModule(vk, device, pipeline_frag);
1039 
1040     if (m_params.tessShader)
1041     {
1042         tescShader = vk::createShader(vk, device, tescCreateInfo);
1043         teseShader = vk::createShader(vk, device, teseCreateInfo);
1044 
1045         tescShaderModule = createShaderModule(vk, device, pipeline_tesc);
1046         teseShaderModule = createShaderModule(vk, device, pipeline_tese);
1047     }
1048     if (m_params.geomShader)
1049     {
1050         geomShader = vk::createShader(vk, device, geomCreateInfo);
1051 
1052         geomShaderModule = createShaderModule(vk, device, pipeline_geom);
1053     }
1054 
1055     const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
1056         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1057         DE_NULL,                                                       // const void* pNext;
1058         0u,                                                            // VkPipelineVertexInputStateCreateFlags flags;
1059         0u,                                                            // uint32_t vertexBindingDescriptionCount;
1060         DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1061         0u,      // uint32_t vertexAttributeDescriptionCount;
1062         DE_NULL  // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1063     };
1064 
1065     const vk::VkPipelineTessellationStateCreateInfo tessStateCreateInfo = {
1066         vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
1067         DE_NULL,                                                       // const void* pNext;
1068         0u,                                                            // VkPipelineTessellationStateCreateFlags flags;
1069         4u,                                                            // uint32_t patchControlPoints;
1070     };
1071 
1072     const vk::VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = {
1073         vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType                             sType;
1074         DE_NULL,                                         // const void*                                 pNext;
1075         (vk::VkPipelineInputAssemblyStateCreateFlags)0u, // VkPipelineInputAssemblyStateCreateFlags     flags;
1076         topology,                                        // VkPrimitiveTopology                         topology;
1077         VK_FALSE, // VkBool32                                    primitiveRestartEnable;
1078     };
1079 
1080     vk::VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo = {
1081         vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, // VkStructureType    sType
1082         DE_NULL,                                              // const void*        pNext
1083         0u,                                                   // uint32_t            viewMask
1084         1u,                                                   // uint32_t            colorAttachmentCount
1085         &colorAttachmentFormat,                               // const VkFormat*    pColorAttachmentFormats
1086         vk::VK_FORMAT_UNDEFINED,                              // VkFormat            depthAttachmentFormat
1087         vk::VK_FORMAT_UNDEFINED,                              // VkFormat            stencilAttachmentFormat
1088     };
1089 
1090     const vk::VkViewport viewport =
1091         vk::makeViewport((float)renderArea.extent.width, 0.0f, (float)renderArea.extent.width,
1092                          (float)renderArea.extent.height, 0.0f, 1.0f);
1093     const vk::VkRect2D scissor = vk::makeRect2D(renderArea.extent);
1094 
1095     const vk::VkPipelineViewportStateCreateInfo viewportStateCreateInfo = {
1096         vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType                             sType
1097         DE_NULL,                                                   // const void*                                 pNext
1098         (vk::VkPipelineViewportStateCreateFlags)0u,                // VkPipelineViewportStateCreateFlags          flags
1099         1u,        // uint32_t                                    viewportCount
1100         &viewport, // const VkViewport*                           pViewports
1101         1u,        // uint32_t                                    scissorCount
1102         &scissor   // const VkRect2D*                             pScissors
1103     };
1104 
1105     const auto pipeline = makeGraphicsPipeline(
1106         vk, device, emptyPipelineLayout.get(), vertShaderModule.get(), tescShaderModule.get(), teseShaderModule.get(),
1107         geomShaderModule.get(), fragShaderModule.get(), VK_NULL_HANDLE, 0u, &vertexInputStateParams,
1108         &pipelineInputAssemblyStateInfo, &tessStateCreateInfo, &viewportStateCreateInfo, DE_NULL, DE_NULL, DE_NULL,
1109         DE_NULL, DE_NULL, &pipelineRenderingCreateInfo);
1110 
1111     const vk::VkDeviceSize bufferSizeBytes = sizeof(uint32_t) * 4;
1112 
1113     const vk::Unique<vk::VkDescriptorSet> descriptorSet(
1114         makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1115     const vk::BufferWithMemory outputBuffer(
1116         vk, device, alloc, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
1117         vk::MemoryRequirement::HostVisible);
1118 
1119     const vk::VkDescriptorBufferInfo descriptorInfo =
1120         vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
1121     vk::DescriptorSetUpdateBuilder()
1122         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
1123                      vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
1124         .update(vk, device);
1125 
1126     const vk::VkClearValue clearValue = vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
1127     vk::VkImageMemoryBarrier initialBarrier =
1128         vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED,
1129                                    vk::VK_IMAGE_LAYOUT_GENERAL, **image, subresourceRange);
1130 
1131     vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
1132 
1133     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1134                           vk::VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0, DE_NULL, 0, DE_NULL, 1,
1135                           &initialBarrier);
1136 
1137     vk::beginRendering(vk, *cmdBuffer, *imageView, renderArea, clearValue, vk::VK_IMAGE_LAYOUT_GENERAL,
1138                        vk::VK_ATTACHMENT_LOAD_OP_CLEAR);
1139 
1140     vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1141     vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
1142 
1143     vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0, 1,
1144                              &descriptorSet.get(), 0, DE_NULL);
1145     vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, topology, false,
1146                                             !m_context.getExtendedDynamicStateFeaturesEXT().extendedDynamicState);
1147 
1148     vk::bindGraphicsShaders(vk, *cmdBuffer, (m_params.vertShader) ? *vertShader : VK_NULL_HANDLE,
1149                             (m_params.tessShader) ? *tescShader : VK_NULL_HANDLE,
1150                             (m_params.tessShader) ? *teseShader : VK_NULL_HANDLE,
1151                             (m_params.geomShader) ? *geomShader : VK_NULL_HANDLE,
1152                             (m_params.fragShader) ? *fragShader : VK_NULL_HANDLE, taskSupported, meshSupported);
1153 
1154     vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
1155 
1156     vk::endRendering(vk, *cmdBuffer);
1157 
1158     vk::endCommandBuffer(vk, *cmdBuffer);
1159 
1160     submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1161 
1162     if (m_params.fragShader)
1163     {
1164         const vk::VkBufferImageCopy copyRegion = {
1165             0u, // VkDeviceSize bufferOffset;
1166             0u, // uint32_t bufferRowLength;
1167             0u, // uint32_t bufferImageHeight;
1168             {
1169                 vk::VK_IMAGE_ASPECT_COLOR_BIT,                     // VkImageAspectFlags aspect;
1170                 0u,                                                // uint32_t mipLevel;
1171                 0u,                                                // uint32_t baseArrayLayer;
1172                 1u,                                                // uint32_t layerCount;
1173             },                                                     // VkImageSubresourceLayers imageSubresource;
1174             {0, 0, 0},                                             // VkOffset3D imageOffset;
1175             {renderArea.extent.width, renderArea.extent.height, 1} // VkExtent3D imageExtent;
1176         };
1177 
1178         vk::beginCommandBuffer(vk, *copyCmdBuffer, 0u);
1179         vk.cmdCopyImageToBuffer(*copyCmdBuffer, **image, vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffer, 1u,
1180                                 &copyRegion);
1181         vk::endCommandBuffer(vk, *copyCmdBuffer);
1182         submitCommandsAndWait(vk, device, queue, copyCmdBuffer.get());
1183 
1184         if (!verifyImage(colorOutputBuffer))
1185             return tcu::TestStatus::fail("Fail");
1186     }
1187 
1188     const vk::Allocation &outputBufferAllocation = outputBuffer.getAllocation();
1189     invalidateAlloc(vk, device, outputBufferAllocation);
1190 
1191     const uint32_t *bufferPtr = static_cast<uint32_t *>(outputBufferAllocation.getHostPtr());
1192 
1193     if (m_params.vertShader && bufferPtr[0] != 1u)
1194         return tcu::TestStatus::fail("Fail");
1195     if (m_params.tessShader && bufferPtr[1] != 2u)
1196         return tcu::TestStatus::fail("Fail");
1197     if (m_params.geomShader && bufferPtr[2] != 3u)
1198         return tcu::TestStatus::fail("Fail");
1199 
1200     return tcu::TestStatus::pass("Pass");
1201 }
1202 
verifyImage(de::MovePtr<vk::BufferWithMemory> & outputBuffer)1203 bool ShaderObjectStageBindingInstance::verifyImage(de::MovePtr<vk::BufferWithMemory> &outputBuffer)
1204 {
1205     tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(
1206         vk::mapVkFormat(vk::VK_FORMAT_R8G8B8A8_UNORM), renderArea.extent.width, renderArea.extent.height, 1,
1207         (const void *)outputBuffer->getAllocation().getHostPtr());
1208 
1209     const tcu::Vec4 black = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1210     const tcu::Vec4 white = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1211     const int32_t width   = resultBuffer.getWidth();
1212     const int32_t height  = resultBuffer.getHeight();
1213 
1214     const int32_t xOffset = m_params.tessShader ? 4 : 8;
1215     const int32_t yOffset = m_params.geomShader ? 4 : 8;
1216 
1217     for (int32_t j = 0; j < height; ++j)
1218     {
1219         for (int32_t i = 0; i < width; ++i)
1220         {
1221             const tcu::Vec4 color = resultBuffer.getPixel(i, j).asFloat();
1222             if (i >= xOffset && i < width - xOffset && j >= yOffset && j < height - yOffset)
1223             {
1224                 if (color != white)
1225                     return false;
1226             }
1227             else
1228             {
1229                 if (color != black)
1230                     return false;
1231             }
1232         }
1233     }
1234 
1235     return true;
1236 }
1237 
1238 class ShaderObjectStageBindingCase : public vkt::TestCase
1239 {
1240 public:
ShaderObjectStageBindingCase(tcu::TestContext & testCtx,const std::string & name,const StageTestParams & params)1241     ShaderObjectStageBindingCase(tcu::TestContext &testCtx, const std::string &name, const StageTestParams &params)
1242         : vkt::TestCase(testCtx, name)
1243         , m_params(params)
1244     {
1245     }
~ShaderObjectStageBindingCase(void)1246     virtual ~ShaderObjectStageBindingCase(void)
1247     {
1248     }
1249 
1250     void checkSupport(vkt::Context &context) const override;
1251     virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const1252     TestInstance *createInstance(Context &context) const override
1253     {
1254         return new ShaderObjectStageBindingInstance(context, m_params);
1255     }
1256 
1257 private:
1258     StageTestParams m_params;
1259 };
1260 
checkSupport(Context & context) const1261 void ShaderObjectStageBindingCase::checkSupport(Context &context) const
1262 {
1263     context.requireDeviceFunctionality("VK_EXT_shader_object");
1264 
1265     if (m_params.tessShader)
1266         context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1267 
1268     if (m_params.geomShader)
1269         context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1270 }
1271 
initPrograms(vk::SourceCollections & programCollection) const1272 void ShaderObjectStageBindingCase::initPrograms(vk::SourceCollections &programCollection) const
1273 {
1274     std::stringstream vert;
1275     std::stringstream geom;
1276     std::stringstream tesc;
1277     std::stringstream tese;
1278     std::stringstream frag;
1279 
1280     std::stringstream pipeline_vert;
1281     std::stringstream pipeline_geom;
1282     std::stringstream pipeline_tesc;
1283     std::stringstream pipeline_tese;
1284     std::stringstream pipeline_frag;
1285 
1286     vert << "#version 450\n"
1287          << "layout(set = 0, binding = 0) buffer Output {\n"
1288          << "    uint values[4];\n"
1289          << "} buffer_out;\n\n"
1290          << "void main() {\n"
1291          << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
1292          << "    gl_Position = vec4(pos - 0.5f, 0.0f, 1.0f);\n"
1293          << "    if (gl_VertexIndex == 0u)\n"
1294          << "        buffer_out.values[0] = 1u;\n"
1295          << "}\n";
1296 
1297     tesc << "#version 450\n"
1298          << "\n"
1299          << "layout(vertices = 4) out;\n"
1300          << "layout(set = 0, binding = 0) buffer Output {\n"
1301          << "    uint values[4];\n"
1302          << "} buffer_out;\n\n"
1303          << "\n"
1304          << "void main (void)\n"
1305          << "{\n"
1306          << "    if (gl_InvocationID == 0) {\n"
1307          << "        gl_TessLevelInner[0] = 1.0;\n"
1308          << "        gl_TessLevelInner[1] = 1.0;\n"
1309          << "        gl_TessLevelOuter[0] = 1.0;\n"
1310          << "        gl_TessLevelOuter[1] = 1.0;\n"
1311          << "        gl_TessLevelOuter[2] = 1.0;\n"
1312          << "        gl_TessLevelOuter[3] = 1.0;\n"
1313          << "        buffer_out.values[1] = 2u;\n"
1314          << "    }\n"
1315          << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1316          << "}\n";
1317 
1318     tese << "#version 450\n"
1319          << "\n"
1320          << "layout(quads, equal_spacing) in;\n"
1321          << "\n"
1322          << "void main (void)\n"
1323          << "{\n"
1324          << "    float u = gl_TessCoord.x;\n"
1325          << "    float v = gl_TessCoord.y;\n"
1326          << "    float omu = 1.0f - u;\n"
1327          << "    float omv = 1.0f - v;\n"
1328          << "    gl_Position = omu * omv * gl_in[0].gl_Position + u * omv * gl_in[2].gl_Position + u * v * "
1329             "gl_in[3].gl_Position + omu * v * gl_in[1].gl_Position;\n"
1330          << "    gl_Position.x *= 1.5f;\n"
1331          << "}\n";
1332 
1333     geom << "#version 450\n"
1334          << "layout(triangles) in;\n"
1335          << "layout(triangle_strip, max_vertices = 4) out;\n"
1336          << "layout(set = 0, binding = 0) buffer Output {\n"
1337          << "    uint values[4];\n"
1338          << "} buffer_out;\n\n"
1339          << "\n"
1340          << "void main(void)\n"
1341          << "{\n"
1342          << "    gl_Position = gl_in[0].gl_Position;\n"
1343          << "    gl_Position.y *= 1.5f;\n"
1344          << "    EmitVertex();\n"
1345          << "    gl_Position = gl_in[1].gl_Position;\n"
1346          << "    gl_Position.y *= 1.5f;\n"
1347          << "    EmitVertex();\n"
1348          << "    gl_Position = gl_in[2].gl_Position;\n"
1349          << "    gl_Position.y *= 1.5f;\n"
1350          << "    EmitVertex();\n"
1351          << "    EndPrimitive();\n"
1352          << "    if (gl_InvocationID == 0u)\n"
1353          << "        buffer_out.values[2] = 3u;\n"
1354          << "}\n";
1355 
1356     frag << "#version 450\n"
1357          << "layout (location=0) out vec4 outColor;\n"
1358          << "void main() {\n"
1359          << "    outColor = vec4(1.0f);\n"
1360          << "}\n";
1361 
1362     pipeline_vert << "#version 450\n"
1363                   << "void main() {\n"
1364                   << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
1365                   << "    gl_Position = vec4(pos - 0.5f, 0.0f, 1.0f);\n"
1366                   << "}\n";
1367 
1368     pipeline_tesc << "#version 450\n"
1369                   << "\n"
1370                   << "layout(vertices = 4) out;\n"
1371                   << "\n"
1372                   << "void main (void)\n"
1373                   << "{\n"
1374                   << "    if (gl_InvocationID == 0) {\n"
1375                   << "        gl_TessLevelInner[0] = 1.0;\n"
1376                   << "        gl_TessLevelInner[1] = 1.0;\n"
1377                   << "        gl_TessLevelOuter[0] = 1.0;\n"
1378                   << "        gl_TessLevelOuter[1] = 1.0;\n"
1379                   << "        gl_TessLevelOuter[2] = 1.0;\n"
1380                   << "        gl_TessLevelOuter[3] = 1.0;\n"
1381                   << "    }\n"
1382                   << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1383                   << "}\n";
1384 
1385     pipeline_tese << "#version 450\n"
1386                   << "\n"
1387                   << "layout(quads, equal_spacing) in;\n"
1388                   << "\n"
1389                   << "void main (void)\n"
1390                   << "{\n"
1391                   << "    float u = gl_TessCoord.x;\n"
1392                   << "    float v = gl_TessCoord.y;\n"
1393                   << "    float omu = 1.0f - u;\n"
1394                   << "    float omv = 1.0f - v;\n"
1395                   << "    gl_Position = omu * omv * gl_in[0].gl_Position + u * omv * gl_in[2].gl_Position + u * v * "
1396                      "gl_in[3].gl_Position + omu * v * gl_in[1].gl_Position;\n"
1397                   << "    gl_Position.x *= 0.5f;\n"
1398                   << "    gl_Position.y *= 0.5f;\n"
1399                   << "}\n";
1400 
1401     pipeline_geom << "#version 450\n"
1402                   << "layout(triangles) in;\n"
1403                   << "layout(triangle_strip, max_vertices = 4) out;\n"
1404                   << "\n"
1405                   << "void main(void)\n"
1406                   << "{\n"
1407                   << "    gl_Position = gl_in[0].gl_Position;\n"
1408                   << "    gl_Position.x += 0.25f;\n"
1409                   << "    gl_Position.y += 0.25f;\n"
1410                   << "    EmitVertex();\n"
1411                   << "    gl_Position = gl_in[1].gl_Position;\n"
1412                   << "    gl_Position.x += 0.25f;\n"
1413                   << "    gl_Position.y += 0.25f;\n"
1414                   << "    EmitVertex();\n"
1415                   << "    gl_Position = gl_in[2].gl_Position;\n"
1416                   << "    gl_Position.x += 0.25f;\n"
1417                   << "    gl_Position.y += 0.25f;\n"
1418                   << "    EmitVertex();\n"
1419                   << "    EndPrimitive();\n"
1420                   << "}\n";
1421 
1422     pipeline_frag << "#version 450\n"
1423                   << "layout (location=0) out vec4 outColor;\n"
1424                   << "void main() {\n"
1425                   << "    outColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
1426                   << "}\n";
1427 
1428     programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
1429     programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
1430     programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
1431     programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
1432     programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1433 
1434     programCollection.glslSources.add("pipeline_vert") << glu::VertexSource(pipeline_vert.str());
1435     programCollection.glslSources.add("pipeline_tesc") << glu::TessellationControlSource(pipeline_tesc.str());
1436     programCollection.glslSources.add("pipeline_tese") << glu::TessellationEvaluationSource(pipeline_tese.str());
1437     programCollection.glslSources.add("pipeline_geom") << glu::GeometrySource(pipeline_geom.str());
1438     programCollection.glslSources.add("pipeline_frag") << glu::FragmentSource(pipeline_frag.str());
1439 }
1440 
1441 } // namespace
1442 
createShaderObjectPipelineInteractionTests(tcu::TestContext & testCtx)1443 tcu::TestCaseGroup *createShaderObjectPipelineInteractionTests(tcu::TestContext &testCtx)
1444 {
1445     de::MovePtr<tcu::TestCaseGroup> pipelineInteractionGroup(new tcu::TestCaseGroup(testCtx, "pipeline_interaction"));
1446 
1447     const struct
1448     {
1449         TestType testType;
1450         const char *name;
1451     } tests[] = {
1452         {SHADER_OBJECT, "shader_object"},
1453         {MAX_PIPELINE, "max_pipeline"},
1454         {MAX_PIPELINE_SHADER_OBJECT_MAX_PIPELINE, "max_pipeline_shader_object_max_pipeline"},
1455         {SHADER_OBJECT_MAX_PIPELINE_SHADER_OBJECT, "shader_object_max_pipeline_shader_object"},
1456         {MIN_PIPELINE_SHADER_OBJECT, "min_pipeline_shader_object"},
1457         {SHADER_OBJECT_MIN_PIPELINE, "shader_object_min_pipeline"},
1458         {RENDER_PASS_PIPELINE_SHADER_OBJECT, "render_pass_pipeline_shader_object"},
1459         {RENDER_PASS_PIPELINE_SHADER_OBJECT_AFTER_BEGIN, "render_pass_pipeline_shader_object_after_begin"},
1460         {COMPUTE_SHADER_OBJECT_MIN_PIPELINE, "compute_shader_object_min_pipeline"},
1461         {SHADER_OBJECT_COMPUTE_PIPELINE, "shader_object_compute_pipeline"},
1462     };
1463 
1464     for (const auto &test : tests)
1465     {
1466         TestParams params;
1467         params.testType = test.testType;
1468 
1469         pipelineInteractionGroup->addChild(new ShaderObjectPipelineInteractionCase(testCtx, test.name, params));
1470     }
1471 
1472     const struct
1473     {
1474         StageTestParams shaders;
1475         const char *name;
1476     } shaderBindTests[] = {
1477         {{true, false, false, false}, "vert"},         {{true, true, false, false}, "vert_tess"},
1478         {{true, false, true, false}, "vert_geom"},     {{true, false, false, true}, "vert_frag"},
1479         {{true, true, true, false}, "vert_tess_geom"}, {{true, true, false, true}, "vert_tess_frag"},
1480         {{true, false, true, true}, "vert_geom_frag"}, {{true, true, true, true}, "vert_tess_geom_frag"},
1481     };
1482 
1483     for (const auto &shaderBindTest : shaderBindTests)
1484     {
1485         pipelineInteractionGroup->addChild(
1486             new ShaderObjectStageBindingCase(testCtx, shaderBindTest.name, shaderBindTest.shaders));
1487     }
1488 
1489     return pipelineInteractionGroup.release();
1490 }
1491 
1492 } // namespace ShaderObject
1493 } // namespace vkt
1494