1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file vktSynchronizationNoneStageTests.cpp
21  * \brief Tests for VK_PIPELINE_STAGE_NONE{_2}_KHR that iterate over each writable layout
22           and over each readable layout. Data to tested image is writen using method
23           appropriate for the writable layout and read via readable layout appropriate method.
24           Betwean read and write operation there are bariers that use none stage.
25           Implemented tests are also testing generalized layouts (VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR,
26           VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR) and access flags (MEMORY_ACCESS_READ|WRITE_BIT) to
27           test contextual synchronization introduced with VK_KHR_synchronization2 extension.
28  *//*--------------------------------------------------------------------*/
29 
30 #include "vktSynchronizationNoneStageTests.hpp"
31 #include "vktSynchronizationOperation.hpp"
32 #include "vktSynchronizationUtil.hpp"
33 #include "vktTestCase.hpp"
34 
35 #include "vkBuilderUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 
42 #include "tcuImageCompare.hpp"
43 #include "tcuTextureUtil.hpp"
44 #include "tcuTestLog.hpp"
45 #include "tcuStringTemplate.hpp"
46 
47 #include "deUniquePtr.hpp"
48 
49 #include <vector>
50 
51 namespace vkt
52 {
53 namespace synchronization
54 {
55 
56 using namespace vk;
57 using namespace de;
58 using namespace tcu;
59 
60 namespace
61 {
62 
63 static const uint32_t IMAGE_ASPECT_DEPTH_STENCIL = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
64 static const uint32_t IMAGE_ASPECT_ALL           = 0u;
65 
66 struct TestParams
67 {
68     SynchronizationType type;
69     bool useGenericAccessFlags;
70     VkImageLayout writeLayout;
71     VkImageAspectFlags writeAspect;
72     VkImageLayout readLayout;
73     VkImageAspectFlags readAspect;
74 };
75 
76 // Helper class representing image
77 class ImageWrapper
78 {
79 public:
80     ImageWrapper() = default;
81     void create(Context &context, SimpleAllocator &alloc, VkFormat format, VkExtent3D extent, VkImageUsageFlags usage);
82 
83 public:
84     Move<VkImage> handle;
85     MovePtr<Allocation> memory;
86 };
87 
create(Context & context,SimpleAllocator & alloc,VkFormat format,VkExtent3D extent,VkImageUsageFlags usage)88 void ImageWrapper::create(Context &context, SimpleAllocator &alloc, VkFormat format, VkExtent3D extent,
89                           VkImageUsageFlags usage)
90 {
91     const DeviceInterface &vk       = context.getDeviceInterface();
92     const VkDevice &device          = context.getDevice();
93     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
94     const VkImageCreateInfo imageParams{
95         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
96         DE_NULL,                             // pNext
97         0u,                                  // flags
98         VK_IMAGE_TYPE_2D,                    // imageType
99         format,                              // format
100         extent,                              // extent
101         1u,                                  // mipLevels
102         1u,                                  // arraySize
103         VK_SAMPLE_COUNT_1_BIT,               // samples
104         VK_IMAGE_TILING_OPTIMAL,             // tiling
105         usage,                               // usage
106         VK_SHARING_MODE_EXCLUSIVE,           // sharingMode
107         1u,                                  // queueFamilyIndexCount
108         &queueFamilyIndex,                   // pQueueFamilyIndices
109         VK_IMAGE_LAYOUT_UNDEFINED,           // initialLayout
110     };
111 
112     handle = createImage(vk, device, &imageParams);
113     memory = alloc.allocate(getImageMemoryRequirements(vk, device, *handle), MemoryRequirement::Any);
114 
115     vk.bindImageMemory(device, *handle, memory->getMemory(), memory->getOffset());
116 }
117 
118 // Helper class representing buffer
119 class BufferWrapper
120 {
121 public:
122     BufferWrapper() = default;
123     void create(Context &context, SimpleAllocator &alloc, VkDeviceSize size, VkBufferUsageFlags usage);
124 
125 public:
126     Move<VkBuffer> handle;
127     MovePtr<Allocation> memory;
128 };
129 
create(Context & context,SimpleAllocator & alloc,VkDeviceSize size,VkBufferUsageFlags usage)130 void BufferWrapper::create(Context &context, SimpleAllocator &alloc, VkDeviceSize size, VkBufferUsageFlags usage)
131 {
132     const DeviceInterface &vk                 = context.getDeviceInterface();
133     const VkDevice &device                    = context.getDevice();
134     const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(size, usage);
135 
136     handle = createBuffer(vk, device, &bufferCreateInfo);
137     memory = alloc.allocate(getBufferMemoryRequirements(vk, device, *handle), MemoryRequirement::HostVisible);
138 
139     VK_CHECK(vk.bindBufferMemory(device, *handle, memory->getMemory(), memory->getOffset()));
140 }
141 
142 class NoneStageTestInstance : public vkt::TestInstance
143 {
144 public:
145     NoneStageTestInstance(Context &context, const TestParams &testParams);
146     virtual ~NoneStageTestInstance(void) = default;
147 
148     tcu::TestStatus iterate(void) override;
149 
150 protected:
151     VkAccessFlags2KHR getAccessFlag(VkAccessFlags2KHR access);
152     VkBufferImageCopy buildCopyRegion(VkExtent3D extent, VkImageAspectFlags aspect);
153     void buildVertexBuffer(void);
154     Move<VkRenderPass> buildBasicRenderPass(VkFormat outputFormat, VkImageLayout outputLayout,
155                                             VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE);
156     Move<VkRenderPass> buildComplexRenderPass(VkFormat intermediateFormat, VkImageLayout intermediateLayout,
157                                               VkImageAspectFlags intermediateAspect, VkFormat outputFormat,
158                                               VkImageLayout outputLayout);
159     Move<VkImageView> buildImageView(VkImage image, VkFormat format, const VkImageSubresourceRange &subresourceRange);
160     Move<VkFramebuffer> buildFramebuffer(VkRenderPass renderPass, const VkImageView *outView1,
161                                          const VkImageView *outView2 = DE_NULL);
162     Move<VkSampler> buildSampler(void);
163     Move<VkDescriptorSetLayout> buildDescriptorSetLayout(VkDescriptorType descriptorType);
164     Move<VkDescriptorPool> buildDescriptorPool(VkDescriptorType descriptorType);
165     Move<VkDescriptorSet> buildDescriptorSet(VkDescriptorPool descriptorPool, VkDescriptorSetLayout descriptorSetLayout,
166                                              VkDescriptorType descriptorType, VkImageView inputView,
167                                              VkImageLayout inputLayout, const VkSampler *sampler = DE_NULL);
168     Move<VkPipeline> buildPipeline(uint32_t subpass, VkImageAspectFlags resultAspect, VkPipelineLayout pipelineLayout,
169                                    VkShaderModule vertShaderModule, VkShaderModule fragShaderModule,
170                                    VkRenderPass renderPass);
171     bool verifyResult(const PixelBufferAccess &reference, const PixelBufferAccess &result);
172 
173 private:
174     const TestParams m_testParams;
175 
176     VkFormat m_referenceImageFormat;
177     VkFormat m_transitionImageFormat;
178     VkFormat m_readImageFormat;
179     VkImageSubresourceRange m_referenceSubresourceRange;
180     VkImageSubresourceRange m_transitionSubresourceRange;
181     VkImageSubresourceRange m_readSubresourceRange;
182     VkImageAspectFlags m_transitionImageAspect;
183 
184     VkExtent3D m_imageExtent;
185     VkImageLayout m_writeRenderPassOutputLayout;
186 
187     // flag indicating that graphics pipeline is constructed to write data to tested image
188     bool m_usePipelineToWrite;
189 
190     // flag indicating that graphics pipeline is constructed to read data from tested image
191     bool m_usePipelineToRead;
192 
193     // flag indicating that write pipeline should be constructed in a special way to fill stencil buffer
194     bool m_useStencilDuringWrite;
195 
196     // flag indicating that read pipeline should be constructed in a special way to use input attachment as a data source
197     bool m_useInputAttachmentToRead;
198 
199     VkPipelineStageFlags2KHR m_srcStageToNoneStageMask;
200     VkAccessFlags2KHR m_srcAccessToNoneAccessMask;
201     VkPipelineStageFlags2KHR m_dstStageFromNoneStageMask;
202     VkAccessFlags2KHR m_dstAccessFromNoneAccessMask;
203 
204     SimpleAllocator m_alloc;
205 
206     ImageWrapper m_referenceImage;
207     VkImageUsageFlags m_referenceImageUsage;
208 
209     // objects/variables initialized only when needed
210     ImageWrapper m_imageToWrite;
211     VkImageUsageFlags m_imageToWriteUsage;
212 
213     ImageWrapper m_imageToRead;
214 
215     BufferWrapper m_vertexBuffer;
216     std::vector<Move<VkImageView>> m_attachmentViews;
217 
218     std::string m_writeFragShaderName;
219     Move<VkShaderModule> m_writeVertShaderModule;
220     Move<VkShaderModule> m_writeFragShaderModule;
221     Move<VkRenderPass> m_writeRenderPass;
222     Move<VkSampler> m_writeSampler;
223     Move<VkDescriptorSetLayout> m_writeDescriptorSetLayout;
224     Move<VkDescriptorPool> m_writeDescriptorPool;
225     Move<VkDescriptorSet> m_writeDescriptorSet;
226     Move<VkPipelineLayout> m_writePipelineLayout;
227     Move<VkPipeline> m_writePipeline;
228     Move<VkFramebuffer> m_writeFramebuffer;
229 
230     std::string m_readFragShaderName;
231     Move<VkShaderModule> m_readVertShaderModule;
232     Move<VkShaderModule> m_readFragShaderModule;
233     Move<VkShaderModule> m_readFragShaderModule2;
234     Move<VkRenderPass> m_readRenderPass;
235     Move<VkSampler> m_readSampler;
236     Move<VkDescriptorSetLayout> m_readDescriptorSetLayout;
237     Move<VkDescriptorPool> m_readDescriptorPool;
238     Move<VkDescriptorSet> m_readDescriptorSet;
239     Move<VkPipelineLayout> m_readPipelineLayout;
240     Move<VkPipeline> m_readPipeline;
241     Move<VkFramebuffer> m_readFramebuffer;
242 };
243 
NoneStageTestInstance(Context & context,const TestParams & testParams)244 NoneStageTestInstance::NoneStageTestInstance(Context &context, const TestParams &testParams)
245     : vkt::TestInstance(context)
246     , m_testParams(testParams)
247     , m_imageExtent{32, 32, 1}
248     , m_alloc(m_context.getDeviceInterface(), m_context.getDevice(),
249               getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()))
250 {
251     // note: for clarity whole configuration of whats going on in iterate method was moved here
252 
253     const auto writeLayout = m_testParams.writeLayout;
254     const auto writeAspect = m_testParams.writeAspect;
255     const auto readLayout  = m_testParams.readLayout;
256     const auto readAspect  = m_testParams.readAspect;
257 
258     // When testing depth stencil combined images, the stencil aspect is only tested when depth aspect is in ATTACHMENT_OPTIMAL layout.
259     // - it is invalid to read depth using sampler or input attachment in such layout
260     const auto readStencilFromCombinedDepthStencil =
261         (readLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL);
262 
263     // select format that will be used for test
264     if ((writeAspect == VK_IMAGE_ASPECT_DEPTH_BIT) || (readAspect == VK_IMAGE_ASPECT_DEPTH_BIT))
265     {
266         m_transitionImageFormat       = VK_FORMAT_D32_SFLOAT;
267         m_transitionImageAspect       = VK_IMAGE_ASPECT_DEPTH_BIT;
268         m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
269     }
270     else if ((writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) || (readAspect == VK_IMAGE_ASPECT_STENCIL_BIT))
271     {
272         m_transitionImageFormat       = VK_FORMAT_S8_UINT;
273         m_transitionImageAspect       = VK_IMAGE_ASPECT_STENCIL_BIT;
274         m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
275     }
276     else if ((writeAspect == IMAGE_ASPECT_DEPTH_STENCIL) || (readAspect == IMAGE_ASPECT_DEPTH_STENCIL))
277     {
278         m_transitionImageFormat       = VK_FORMAT_D24_UNORM_S8_UINT;
279         m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
280 
281         if (readStencilFromCombinedDepthStencil)
282         {
283             m_transitionImageAspect = VK_IMAGE_ASPECT_STENCIL_BIT;
284         }
285         else
286         {
287             // note: in test we focus only on depth aspect; no need to check both in those cases
288             m_transitionImageAspect = VK_IMAGE_ASPECT_DEPTH_BIT;
289         }
290     }
291     else
292     {
293         m_transitionImageFormat       = VK_FORMAT_R8G8B8A8_UNORM;
294         m_transitionImageAspect       = VK_IMAGE_ASPECT_COLOR_BIT;
295         m_writeRenderPassOutputLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
296     }
297 
298     m_referenceSubresourceRange  = {m_transitionImageAspect, 0u, 1u, 0u, 1u};
299     m_transitionSubresourceRange = {m_transitionImageAspect, 0u, 1u, 0u, 1u};
300     m_readSubresourceRange       = {m_transitionImageAspect, 0u, 1u, 0u, 1u};
301     m_referenceImageFormat       = m_transitionImageFormat;
302     m_readImageFormat            = m_transitionImageFormat;
303     m_referenceImageUsage        = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
304     m_imageToWriteUsage          = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
305 
306     // pipeline is not created for transfer and general layouts (general layouts in tests follow same path as transfer layouts)
307     m_usePipelineToWrite =
308         (writeLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) && (writeLayout != VK_IMAGE_LAYOUT_GENERAL);
309     m_usePipelineToRead =
310         (readLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) && (readLayout != VK_IMAGE_LAYOUT_GENERAL);
311     m_useStencilDuringWrite = false;
312 
313     m_srcStageToNoneStageMask     = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
314     m_srcAccessToNoneAccessMask   = getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR);
315     m_dstStageFromNoneStageMask   = VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
316     m_dstAccessFromNoneAccessMask = getAccessFlag(VK_ACCESS_2_TRANSFER_READ_BIT_KHR);
317 
318     // when graphics pipelines are not created only image with gradient is used for test
319     if (!m_usePipelineToWrite && !m_usePipelineToRead)
320     {
321         m_referenceImageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
322         return;
323     }
324 
325     if (m_usePipelineToWrite)
326     {
327         // depth/stencil layouts need diferent configuration
328         if (writeAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
329         {
330             if ((writeAspect & VK_IMAGE_ASPECT_DEPTH_BIT) && !readStencilFromCombinedDepthStencil)
331             {
332                 m_referenceImageFormat = VK_FORMAT_R32_SFLOAT;
333                 m_referenceImageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
334                 m_referenceSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
335                 m_writeFragShaderName                  = "frag-color-to-depth";
336             }
337             else
338             {
339                 m_referenceImageUsage   = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
340                 m_useStencilDuringWrite = true;
341                 m_writeFragShaderName   = "frag-color-to-stencil";
342             }
343 
344             m_srcStageToNoneStageMask   = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR;
345             m_srcAccessToNoneAccessMask = getAccessFlag(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR);
346             m_imageToWriteUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
347         }
348         else
349         {
350             m_referenceImageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
351             m_srcStageToNoneStageMask   = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR;
352             m_srcAccessToNoneAccessMask = getAccessFlag(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR);
353             m_writeFragShaderName       = "frag-color";
354             m_imageToWriteUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
355         }
356     }
357 
358     if (m_usePipelineToRead)
359     {
360         m_dstStageFromNoneStageMask   = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR;
361         m_dstAccessFromNoneAccessMask = getAccessFlag(VK_ACCESS_2_SHADER_READ_BIT_KHR);
362 
363         m_readSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
364         if (((readAspect | writeAspect) & VK_IMAGE_ASPECT_DEPTH_BIT) && !readStencilFromCombinedDepthStencil)
365             m_readImageFormat = VK_FORMAT_R32_SFLOAT;
366         else if ((readAspect | writeAspect) & VK_IMAGE_ASPECT_STENCIL_BIT)
367             m_readImageFormat = VK_FORMAT_R8_UINT;
368 
369         // for layouts that operate on depth or stencil (not depth_stencil) use input attachment to read
370         if ((readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) &&
371             (readAspect != IMAGE_ASPECT_DEPTH_STENCIL))
372         {
373             m_useInputAttachmentToRead = true;
374             m_readFragShaderName       = "frag-depth-or-stencil-to-color";
375             m_imageToWriteUsage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
376             m_dstAccessFromNoneAccessMask = getAccessFlag(VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR);
377 
378             if (!m_usePipelineToWrite)
379                 m_referenceImageUsage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
380         }
381         else // use image sampler for color and depth_stencil layouts
382         {
383             m_useInputAttachmentToRead = false;
384             m_readFragShaderName       = "frag-color";
385             m_referenceImageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
386             m_imageToWriteUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
387 
388             // for depth_stencil layouts we need to have depth_stencil_attachment usage
389             if (!m_usePipelineToWrite && (readAspect & VK_IMAGE_ASPECT_STENCIL_BIT))
390                 m_referenceImageUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
391 
392             // when we read stencil as color we need to use usampler2D
393             if ((readAspect | writeAspect) == VK_IMAGE_ASPECT_STENCIL_BIT ||
394                 (readAspect == IMAGE_ASPECT_DEPTH_STENCIL && readStencilFromCombinedDepthStencil))
395                 m_readFragShaderName = "frag-stencil-to-color";
396         }
397         if (m_useInputAttachmentToRead && (m_testParams.readLayout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
398                                            m_testParams.readLayout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL))
399             m_referenceImageUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
400     }
401 }
402 
getAccessFlag(VkAccessFlags2KHR access)403 VkAccessFlags2KHR NoneStageTestInstance::getAccessFlag(VkAccessFlags2KHR access)
404 {
405     if (m_testParams.useGenericAccessFlags)
406     {
407         switch (access)
408         {
409         case VK_ACCESS_2_HOST_READ_BIT_KHR:
410         case VK_ACCESS_2_TRANSFER_READ_BIT_KHR:
411         case VK_ACCESS_2_SHADER_READ_BIT_KHR:
412         case VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR:
413             return VK_ACCESS_2_MEMORY_READ_BIT_KHR;
414 
415         case VK_ACCESS_2_HOST_WRITE_BIT_KHR:
416         case VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR:
417         case VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR:
418         case VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR:
419             return VK_ACCESS_2_MEMORY_WRITE_BIT_KHR;
420 
421         default:
422             TCU_THROW(TestError, "Unhandled access flag");
423         }
424     }
425     return access;
426 }
427 
buildCopyRegion(VkExtent3D extent,VkImageAspectFlags aspect)428 VkBufferImageCopy NoneStageTestInstance::buildCopyRegion(VkExtent3D extent, VkImageAspectFlags aspect)
429 {
430     return {
431         0u,                   // VkDeviceSize                    bufferOffset
432         extent.width,         // uint32_t                        bufferRowLength
433         extent.height,        // uint32_t                        bufferImageHeight
434         {aspect, 0u, 0u, 1u}, // VkImageSubresourceLayers        imageSubresource
435         {0, 0, 0},            // VkOffset3D                    imageOffset
436         extent                // VkExtent3D                    imageExtent
437     };
438 }
439 
buildVertexBuffer()440 void NoneStageTestInstance::buildVertexBuffer()
441 {
442     const DeviceInterface &vk = m_context.getDeviceInterface();
443     const VkDevice &device    = m_context.getDevice();
444 
445     std::vector<float> vertices{
446         1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f,
447     };
448     m_vertexBuffer.create(m_context, m_alloc, sizeof(float) * vertices.size(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
449 
450     deMemcpy(m_vertexBuffer.memory->getHostPtr(), vertices.data(), vertices.size() * sizeof(float));
451     flushAlloc(vk, device, *m_vertexBuffer.memory);
452 }
453 
buildBasicRenderPass(VkFormat outputFormat,VkImageLayout outputLayout,VkAttachmentLoadOp loadOp)454 Move<VkRenderPass> NoneStageTestInstance::buildBasicRenderPass(VkFormat outputFormat, VkImageLayout outputLayout,
455                                                                VkAttachmentLoadOp loadOp)
456 {
457     // output color/depth attachment
458     VkAttachmentDescription2 attachmentDescription{
459         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                    sType
460         DE_NULL,                                    // const void*                        pNext
461         (VkAttachmentDescriptionFlags)0,            // VkAttachmentDescriptionFlags        flags
462         outputFormat,                               // VkFormat                            format
463         VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits            samples
464         loadOp,                                     // VkAttachmentLoadOp                loadOp
465         VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp                storeOp
466         loadOp,                                     // VkAttachmentLoadOp                stencilLoadOp
467         VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp                stencilStoreOp
468         VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout                    initialLayout
469         outputLayout                                // VkImageLayout                    finalLayout
470     };
471 
472     VkImageAspectFlags imageAspect = getImageAspectFlags(mapVkFormat(outputFormat));
473     VkAttachmentReference2 attachmentRef{VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, DE_NULL, 0u, outputLayout,
474                                          imageAspect};
475 
476     VkAttachmentReference2 *pColorAttachment        = DE_NULL;
477     VkAttachmentReference2 *pDepthStencilAttachment = DE_NULL;
478     if (imageAspect == VK_IMAGE_ASPECT_COLOR_BIT)
479         pColorAttachment = &attachmentRef;
480     else
481         pDepthStencilAttachment = &attachmentRef;
482 
483     VkSubpassDescription2 subpassDescription{
484         VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
485         DE_NULL,
486         (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags        flags
487         VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint                pipelineBindPoint
488         0u,                              // uint32_t                            viewMask
489         0u,                              // uint32_t                            inputAttachmentCount
490         DE_NULL,                         // const VkAttachmentReference2*    pInputAttachments
491         !!pColorAttachment,              // uint32_t                            colorAttachmentCount
492         pColorAttachment,                // const VkAttachmentReference2*    pColorAttachments
493         DE_NULL,                         // const VkAttachmentReference2*    pResolveAttachments
494         pDepthStencilAttachment,         // const VkAttachmentReference2*    pDepthStencilAttachment
495         0u,                              // uint32_t                            preserveAttachmentCount
496         DE_NULL                          // const uint32_t*                    pPreserveAttachments
497     };
498 
499     const VkRenderPassCreateInfo2 renderPassInfo{
500         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
501         DE_NULL,                    // const void*                        pNext
502         (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags            flags
503         1u,                         // uint32_t                            attachmentCount
504         &attachmentDescription,     // const VkAttachmentDescription*    pAttachments
505         1u,                         // uint32_t                            subpassCount
506         &subpassDescription,        // const VkSubpassDescription*        pSubpasses
507         0u,                         // uint32_t                            dependencyCount
508         DE_NULL,                    // const VkSubpassDependency*        pDependencies
509         0u,                         // uint32_t                            correlatedViewMaskCount
510         DE_NULL                     // const uint32_t*                    pCorrelatedViewMasks
511     };
512 
513     return vk::createRenderPass2(m_context.getDeviceInterface(), m_context.getDevice(), &renderPassInfo);
514 }
515 
buildComplexRenderPass(VkFormat intermediateFormat,VkImageLayout intermediateLayout,VkImageAspectFlags intermediateAspect,VkFormat outputFormat,VkImageLayout outputLayout)516 Move<VkRenderPass> NoneStageTestInstance::buildComplexRenderPass(VkFormat intermediateFormat,
517                                                                  VkImageLayout intermediateLayout,
518                                                                  VkImageAspectFlags intermediateAspect,
519                                                                  VkFormat outputFormat, VkImageLayout outputLayout)
520 {
521     std::vector<VkAttachmentDescription2> attachmentDescriptions{
522         // depth/stencil attachment (when used in read pipeline it loads data filed in write pipeline)
523         {
524             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                    sType
525             DE_NULL,                                    // const void*                        pNext
526             (VkAttachmentDescriptionFlags)0,            // VkAttachmentDescriptionFlags        flags
527             intermediateFormat,                         // VkFormat                            format
528             VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits            samples
529             VK_ATTACHMENT_LOAD_OP_LOAD,                 // VkAttachmentLoadOp                loadOp
530             VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp                storeOp
531             VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp                stencilLoadOp
532             VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp                stencilStoreOp
533             intermediateLayout,                         // VkImageLayout                    initialLayout
534             intermediateLayout                          // VkImageLayout                    finalLayout
535         },
536         // color attachment
537         {
538             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                    sType
539             DE_NULL,                                    // const void*                        pNext
540             (VkAttachmentDescriptionFlags)0,            // VkAttachmentDescriptionFlags        flags
541             outputFormat,                               // VkFormat                            format
542             VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits            samples
543             VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp                loadOp
544             VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp                storeOp
545             VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp                stencilLoadOp
546             VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp                stencilStoreOp
547             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout                    initialLayout
548             outputLayout                                // VkImageLayout                    finalLayout
549         }};
550 
551     VkImageAspectFlags outputAspect = getImageAspectFlags(mapVkFormat(outputFormat));
552     std::vector<VkAttachmentReference2> attachmentRefs{
553         {VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, DE_NULL, 0u, intermediateLayout, intermediateAspect},
554         {VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, DE_NULL, 1u, outputLayout, outputAspect}};
555 
556     VkAttachmentReference2 *pDepthStencilAttachment = &attachmentRefs[0];
557     VkAttachmentReference2 *pColorAttachment        = &attachmentRefs[1];
558 
559     std::vector<VkSubpassDescription2> subpassDescriptions{{
560         VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, DE_NULL,
561         (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags        flags
562         VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint                pipelineBindPoint
563         0u,                              // uint32_t                            viewMask
564         1u,                              // uint32_t                            inputAttachmentCount
565         pDepthStencilAttachment,         // const VkAttachmentReference2*    pInputAttachments
566         1u,                              // uint32_t                            colorAttachmentCount
567         pColorAttachment,                // const VkAttachmentReference2*    pColorAttachments
568         DE_NULL,                         // const VkAttachmentReference2*    pResolveAttachments
569         DE_NULL,                         // const VkAttachmentReference2*    pDepthStencilAttachment
570         0u,                              // uint32_t                            preserveAttachmentCount
571         DE_NULL                          // uint32_t*                        pPreserveAttachments
572     }};
573 
574     const VkRenderPassCreateInfo2 renderPassInfo{
575         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
576         DE_NULL,                                 // const void*                        pNext
577         (VkRenderPassCreateFlags)0,              // VkRenderPassCreateFlags            flags
578         (uint32_t)attachmentDescriptions.size(), // uint32_t                            attachmentCount
579         attachmentDescriptions.data(),           // const VkAttachmentDescription*    pAttachments
580         (uint32_t)subpassDescriptions.size(),    // uint32_t                            subpassCount
581         subpassDescriptions.data(),              // const VkSubpassDescription*        pSubpasses
582         0u,                                      // uint32_t                            dependencyCount
583         DE_NULL,                                 // const VkSubpassDependency*        pDependencies
584         0u,                                      // uint32_t                            correlatedViewMaskCount
585         DE_NULL                                  // const uint32_t*                    pCorrelatedViewMasks
586     };
587 
588     return vk::createRenderPass2(m_context.getDeviceInterface(), m_context.getDevice(), &renderPassInfo);
589 }
590 
buildImageView(VkImage image,VkFormat format,const VkImageSubresourceRange & subresourceRange)591 Move<VkImageView> NoneStageTestInstance::buildImageView(VkImage image, VkFormat format,
592                                                         const VkImageSubresourceRange &subresourceRange)
593 {
594     const DeviceInterface &vk = m_context.getDeviceInterface();
595     const VkDevice &device    = m_context.getDevice();
596 
597     const VkImageViewCreateInfo imageViewParams{
598         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType                sType
599         DE_NULL,                                  // const void*                    pNext
600         0u,                                       // VkImageViewCreateFlags        flags
601         image,                                    // VkImage                        image
602         VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType                viewType
603         format,                                   // VkFormat                        format
604         makeComponentMappingRGBA(),               // VkComponentMapping            components
605         subresourceRange,                         // VkImageSubresourceRange        subresourceRange
606     };
607 
608     return createImageView(vk, device, &imageViewParams);
609 }
610 
buildFramebuffer(VkRenderPass renderPass,const VkImageView * outView1,const VkImageView * outView2)611 Move<VkFramebuffer> NoneStageTestInstance::buildFramebuffer(VkRenderPass renderPass, const VkImageView *outView1,
612                                                             const VkImageView *outView2)
613 {
614     const DeviceInterface &vk = m_context.getDeviceInterface();
615     const VkDevice &device    = m_context.getDevice();
616 
617     std::vector<VkImageView> imageViews = {*outView1};
618     if (outView2)
619         imageViews.push_back(*outView2);
620 
621     const VkFramebufferCreateInfo framebufferParams{
622         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType                sType
623         DE_NULL,                                   // const void*                    pNext
624         0u,                                        // VkFramebufferCreateFlags        flags
625         renderPass,                                // VkRenderPass                    renderPass
626         (uint32_t)imageViews.size(),               // uint32_t                        attachmentCount
627         imageViews.data(),                         // const VkImageView*            pAttachments
628         m_imageExtent.width,                       // uint32_t                        width
629         m_imageExtent.height,                      // uint32_t                        height
630         1u,                                        // uint32_t                        layers
631     };
632     return createFramebuffer(vk, device, &framebufferParams);
633 }
634 
buildSampler()635 Move<VkSampler> NoneStageTestInstance::buildSampler()
636 {
637     const DeviceInterface &vk = m_context.getDeviceInterface();
638     const VkDevice &device    = m_context.getDevice();
639 
640     const VkSamplerCreateInfo samplerInfo{
641         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // VkStructureType                sType
642         DE_NULL,                                 // const void*                    pNext
643         0u,                                      // VkSamplerCreateFlags            flags
644         VK_FILTER_NEAREST,                       // VkFilter                        magFilter
645         VK_FILTER_NEAREST,                       // VkFilter                        minFilter
646         VK_SAMPLER_MIPMAP_MODE_NEAREST,          // VkSamplerMipmapMode            mipmapMode
647         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode            addressModeU
648         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode            addressModeV
649         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode            addressModeW
650         0.0f,                                    // float                        mipLodBias
651         VK_FALSE,                                // VkBool32                        anisotropyEnable
652         1.0f,                                    // float                        maxAnisotropy
653         false,                                   // VkBool32                        compareEnable
654         VK_COMPARE_OP_ALWAYS,                    // VkCompareOp                    compareOp
655         0.0f,                                    // float                        minLod
656         0.0f,                                    // float                        maxLod
657         VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor                borderColor
658         VK_FALSE,                                // VkBool32                        unnormalizedCoords
659     };
660     return createSampler(vk, device, &samplerInfo);
661 }
662 
buildDescriptorSetLayout(VkDescriptorType descriptorType)663 Move<VkDescriptorSetLayout> NoneStageTestInstance::buildDescriptorSetLayout(VkDescriptorType descriptorType)
664 {
665     const DeviceInterface &vk = m_context.getDeviceInterface();
666     const VkDevice &device    = m_context.getDevice();
667 
668     return DescriptorSetLayoutBuilder()
669         .addSingleSamplerBinding(descriptorType, VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL)
670         .build(vk, device);
671 }
672 
buildDescriptorPool(VkDescriptorType descriptorType)673 Move<VkDescriptorPool> NoneStageTestInstance::buildDescriptorPool(VkDescriptorType descriptorType)
674 {
675     const DeviceInterface &vk = m_context.getDeviceInterface();
676     const VkDevice &device    = m_context.getDevice();
677 
678     return DescriptorPoolBuilder()
679         .addType(descriptorType, 1u)
680         .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
681 }
682 
buildDescriptorSet(VkDescriptorPool descriptorPool,VkDescriptorSetLayout descriptorSetLayout,VkDescriptorType descriptorType,VkImageView inputView,VkImageLayout inputLayout,const VkSampler * sampler)683 Move<VkDescriptorSet> NoneStageTestInstance::buildDescriptorSet(VkDescriptorPool descriptorPool,
684                                                                 VkDescriptorSetLayout descriptorSetLayout,
685                                                                 VkDescriptorType descriptorType, VkImageView inputView,
686                                                                 VkImageLayout inputLayout, const VkSampler *sampler)
687 {
688     const DeviceInterface &vk = m_context.getDeviceInterface();
689     const VkDevice &device    = m_context.getDevice();
690 
691     const VkDescriptorImageInfo inputImageInfo =
692         makeDescriptorImageInfo(sampler ? *sampler : 0u, inputView, inputLayout);
693     Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout);
694 
695     DescriptorSetUpdateBuilder()
696         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &inputImageInfo)
697         .update(vk, device);
698 
699     return descriptorSet;
700 }
701 
buildPipeline(uint32_t subpass,VkImageAspectFlags resultAspect,VkPipelineLayout pipelineLayout,VkShaderModule vertShaderModule,VkShaderModule fragShaderModule,VkRenderPass renderPass)702 Move<VkPipeline> NoneStageTestInstance::buildPipeline(uint32_t subpass, VkImageAspectFlags resultAspect,
703                                                       VkPipelineLayout pipelineLayout, VkShaderModule vertShaderModule,
704                                                       VkShaderModule fragShaderModule, VkRenderPass renderPass)
705 {
706     const DeviceInterface &vk = m_context.getDeviceInterface();
707     const VkDevice &device    = m_context.getDevice();
708     const std::vector<VkViewport> viewports{makeViewport(m_imageExtent)};
709     const std::vector<VkRect2D> scissors{makeRect2D(m_imageExtent)};
710     const bool useDepth   = resultAspect & VK_IMAGE_ASPECT_DEPTH_BIT;
711     const bool useStencil = resultAspect & VK_IMAGE_ASPECT_STENCIL_BIT;
712 
713     const VkStencilOpState stencilOpState = makeStencilOpState(VK_STENCIL_OP_REPLACE, // stencil fail
714                                                                VK_STENCIL_OP_REPLACE, // depth & stencil pass
715                                                                VK_STENCIL_OP_REPLACE, // depth only fail
716                                                                VK_COMPARE_OP_ALWAYS,  // compare op
717                                                                1u,                    // compare mask
718                                                                1u,                    // write mask
719                                                                1u);                   // reference
720 
721     const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo{
722         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                                sType
723         DE_NULL,                                   // const void*                                    pNext
724         (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags        flags
725         useDepth,                                  // VkBool32                                        depthTestEnable
726         useDepth,                                  // VkBool32                                        depthWriteEnable
727         VK_COMPARE_OP_ALWAYS,                      // VkCompareOp                                    depthCompareOp
728         VK_FALSE,       // VkBool32                                        depthBoundsTestEnable
729         useStencil,     // VkBool32                                        stencilTestEnable
730         stencilOpState, // VkStencilOpState                                front
731         stencilOpState, // VkStencilOpState                                back
732         0.0f,           // float                                        minDepthBounds
733         1.0f,           // float                                        maxDepthBounds
734     };
735 
736     return makeGraphicsPipeline(
737         vk,                                   // DeviceInterface&                                vk
738         device,                               // VkDevice                                        device
739         pipelineLayout,                       // VkPipelineLayout                                pipelineLayout
740         vertShaderModule,                     // VkShaderModule                                vertexShaderModule
741         DE_NULL,                              // VkShaderModule                                tessellationControlModule
742         DE_NULL,                              // VkShaderModule                                tessellationEvalModule
743         DE_NULL,                              // VkShaderModule                                geometryShaderModule
744         fragShaderModule,                     // VkShaderModule                                fragmentShaderModule
745         renderPass,                           // VkRenderPass                                    renderPass
746         viewports,                            // std::vector<VkViewport>&                        viewports
747         scissors,                             // std::vector<VkRect2D>&                        scissors
748         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology                            topology
749         subpass,                              // uint32_t                                        subpass
750         0u,                                   // uint32_t                                        patchControlPoints
751         DE_NULL,                              // VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
752         DE_NULL,                       // VkPipelineRasterizationStateCreateInfo*        rasterizationStateCreateInfo
753         DE_NULL,                       // VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
754         &depthStencilStateCreateInfo); // VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo
755 }
756 
iterate(void)757 tcu::TestStatus NoneStageTestInstance::iterate(void)
758 {
759     const DeviceInterface &vk       = m_context.getDeviceInterface();
760     const VkDevice &device          = m_context.getDevice();
761     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
762     VkQueue queue                   = m_context.getUniversalQueue();
763     Move<VkCommandPool> cmdPool =
764         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
765     Move<VkCommandBuffer> cmdBuffer                  = makeCommandBuffer(vk, device, *cmdPool);
766     const VkDeviceSize vertexBufferOffset            = 0;
767     ImageWrapper *transitionImagePtr                 = &m_referenceImage;
768     ImageWrapper *imageToVerifyPtr                   = &m_referenceImage;
769     const uint32_t imageSizeInBytes                  = m_imageExtent.width * m_imageExtent.height * 4;
770     SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(m_testParams.type, vk, false);
771     const VkRect2D renderArea                        = makeRect2D(0, 0, m_imageExtent.width, m_imageExtent.height);
772     const VkBufferImageCopy transitionCopyRegion     = buildCopyRegion(m_imageExtent, m_transitionImageAspect);
773     const VkBufferImageCopy colorCopyRegion          = buildCopyRegion(m_imageExtent, VK_IMAGE_ASPECT_COLOR_BIT);
774 
775     // create image that will have gradient (without data atm)
776     m_referenceImage.create(m_context, m_alloc, m_referenceImageFormat, m_imageExtent, m_referenceImageUsage);
777 
778     // create buffer used for gradient data source
779     BufferWrapper srcBuffer;
780     srcBuffer.create(m_context, m_alloc, imageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
781 
782     // generate gradient
783     std::vector<uint32_t> referenceData(m_imageExtent.width * m_imageExtent.height);
784     tcu::TextureFormat referenceFormat(mapVkFormat(m_referenceImageFormat));
785     if (m_testParams.readLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
786     {
787         // when testing stencil aspect of depth stencil combined image, prepare reference date only with stencil,
788         // as the copy operation (used when m_usePipelineToWrite == false) sources just one aspect
789 
790         // this format is used for tcu operations only - does not need to be supported by the Vulkan implementation
791         referenceFormat = mapVkFormat(VK_FORMAT_S8_UINT);
792     }
793     PixelBufferAccess referencePBA(referenceFormat, m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth,
794                                    referenceData.data());
795     fillWithComponentGradients(referencePBA, tcu::Vec4(0.0f), tcu::Vec4(1.0f));
796     deMemcpy(srcBuffer.memory->getHostPtr(), referenceData.data(), static_cast<size_t>(imageSizeInBytes));
797     flushAlloc(vk, device, *srcBuffer.memory);
798 
799     // create buffer for result transfer
800     BufferWrapper dstBuffer;
801     tcu::TextureFormat resultFormat(mapVkFormat(m_readImageFormat));
802     dstBuffer.create(m_context, m_alloc, imageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
803 
804     if (m_usePipelineToWrite || m_usePipelineToRead)
805     {
806         buildVertexBuffer();
807 
808         // create image view for reference image (its always at index 0)
809         m_attachmentViews.push_back(
810             buildImageView(*m_referenceImage.handle, m_referenceImageFormat, m_referenceSubresourceRange));
811 
812         // create graphics pipeline used to write image data
813         if (m_usePipelineToWrite)
814         {
815             // create image that will be used as attachment to write to
816             m_imageToWrite.create(m_context, m_alloc, m_transitionImageFormat, m_imageExtent, m_imageToWriteUsage);
817             m_attachmentViews.push_back(
818                 buildImageView(*m_imageToWrite.handle, m_transitionImageFormat, m_transitionSubresourceRange));
819 
820             m_writeVertShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
821             m_writeFragShaderModule =
822                 createShaderModule(vk, device, m_context.getBinaryCollection().get(m_writeFragShaderName), 0);
823 
824             if (m_useStencilDuringWrite)
825             {
826                 // this is used only for cases where writable layout is VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL
827                 // in this case generated gradient is only used for verification
828                 m_writeRenderPass     = buildBasicRenderPass(m_transitionImageFormat, m_writeRenderPassOutputLayout,
829                                                              VK_ATTACHMENT_LOAD_OP_CLEAR);
830                 m_writePipelineLayout = makePipelineLayout(vk, device, DE_NULL);
831                 m_writePipeline       = buildPipeline(0u, m_transitionImageAspect, *m_writePipelineLayout,
832                                                       *m_writeVertShaderModule, *m_writeFragShaderModule, *m_writeRenderPass);
833                 m_writeFramebuffer    = buildFramebuffer(*m_writeRenderPass, &m_attachmentViews[1].get());
834             }
835             else
836             {
837                 m_writeRenderPass = buildBasicRenderPass(m_transitionImageFormat, m_writeRenderPassOutputLayout);
838                 m_writeSampler    = buildSampler();
839                 m_writeDescriptorSetLayout = buildDescriptorSetLayout(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
840                 m_writeDescriptorPool      = buildDescriptorPool(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
841                 m_writeDescriptorSet       = buildDescriptorSet(
842                     *m_writeDescriptorPool, *m_writeDescriptorSetLayout, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
843                     *m_attachmentViews[0], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, &m_writeSampler.get());
844                 m_writePipelineLayout = makePipelineLayout(vk, device, *m_writeDescriptorSetLayout);
845                 m_writePipeline       = buildPipeline(0u, m_transitionImageAspect, *m_writePipelineLayout,
846                                                       *m_writeVertShaderModule, *m_writeFragShaderModule, *m_writeRenderPass);
847                 m_writeFramebuffer    = buildFramebuffer(*m_writeRenderPass, &m_attachmentViews[1].get());
848             }
849 
850             transitionImagePtr = &m_imageToWrite;
851             imageToVerifyPtr   = &m_imageToWrite;
852         }
853 
854         // create graphics pipeline used to read image data
855         if (m_usePipelineToRead)
856         {
857             m_imageToRead.create(m_context, m_alloc, m_readImageFormat, m_imageExtent,
858                                  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
859             m_attachmentViews.push_back(
860                 buildImageView(*m_imageToRead.handle, m_readImageFormat, m_readSubresourceRange));
861             imageToVerifyPtr = &m_imageToRead;
862 
863             m_readVertShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
864             m_readFragShaderModule =
865                 createShaderModule(vk, device, m_context.getBinaryCollection().get(m_readFragShaderName), 0);
866 
867             if (m_useInputAttachmentToRead)
868             {
869                 m_readDescriptorSetLayout = buildDescriptorSetLayout(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
870                 m_readDescriptorPool      = buildDescriptorPool(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
871                 m_readDescriptorSet       = buildDescriptorSet(
872                     *m_readDescriptorPool, *m_readDescriptorSetLayout, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
873                     *m_attachmentViews[m_usePipelineToWrite], m_testParams.readLayout);
874                 m_readRenderPass =
875                     buildComplexRenderPass(m_transitionImageFormat, m_testParams.readLayout, m_transitionImageAspect,
876                                            m_readImageFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
877                 m_readFramebuffer = buildFramebuffer(*m_readRenderPass, &m_attachmentViews[m_usePipelineToWrite].get(),
878                                                      &m_attachmentViews[m_usePipelineToWrite + 1].get());
879                 m_readPipelineLayout = makePipelineLayout(vk, device, *m_readDescriptorSetLayout);
880                 m_readPipeline       = buildPipeline(0u, VK_IMAGE_ASPECT_COLOR_BIT, *m_readPipelineLayout,
881                                                      *m_readVertShaderModule, *m_readFragShaderModule, *m_readRenderPass);
882             }
883             else
884             {
885                 m_readSampler             = buildSampler();
886                 m_readDescriptorSetLayout = buildDescriptorSetLayout(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
887                 m_readDescriptorPool      = buildDescriptorPool(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
888                 m_readDescriptorSet       = buildDescriptorSet(
889                     *m_readDescriptorPool, *m_readDescriptorSetLayout, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
890                     *m_attachmentViews[m_usePipelineToWrite], m_testParams.readLayout, &m_readSampler.get());
891                 m_readRenderPass = buildBasicRenderPass(m_readImageFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
892                 m_readFramebuffer =
893                     buildFramebuffer(*m_readRenderPass, &m_attachmentViews[m_usePipelineToWrite + 1].get());
894                 m_readPipelineLayout = makePipelineLayout(vk, device, *m_readDescriptorSetLayout);
895                 m_readPipeline       = buildPipeline(0u, m_transitionImageAspect, *m_readPipelineLayout,
896                                                      *m_readVertShaderModule, *m_readFragShaderModule, *m_readRenderPass);
897             }
898         }
899     }
900 
901     beginCommandBuffer(vk, *cmdBuffer);
902 
903     // write data from buffer with gradient to image (for stencil_attachment cases we dont need to do that)
904     if (!m_useStencilDuringWrite)
905     {
906         // wait for reference data to be in buffer
907         const VkBufferMemoryBarrier2KHR preBufferMemoryBarrier2 = makeBufferMemoryBarrier2(
908             VK_PIPELINE_STAGE_2_HOST_BIT_KHR,                 // VkPipelineStageFlags2KHR            srcStageMask
909             getAccessFlag(VK_ACCESS_2_HOST_WRITE_BIT_KHR),    // VkAccessFlags2KHR                srcAccessMask
910             VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,             // VkPipelineStageFlags2KHR            dstStageMask
911             getAccessFlag(VK_ACCESS_2_TRANSFER_READ_BIT_KHR), // VkAccessFlags2KHR                dstAccessMask
912             *srcBuffer.handle,                                // VkBuffer                            buffer
913             0u,                                               // VkDeviceSize                        offset
914             imageSizeInBytes                                  // VkDeviceSize                        size
915         );
916 
917         VkImageLayout copyBufferToImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
918         if (m_testParams.writeLayout == VK_IMAGE_LAYOUT_GENERAL)
919             copyBufferToImageLayout = VK_IMAGE_LAYOUT_GENERAL;
920 
921         // change image layout so that we can copy to it data from buffer
922         const VkImageMemoryBarrier2KHR preImageMemoryBarrier2 = makeImageMemoryBarrier2(
923             VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,              // VkPipelineStageFlags2KHR            srcStageMask
924             getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR                srcAccessMask
925             VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,              // VkPipelineStageFlags2KHR            dstStageMask
926             getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR                dstAccessMask
927             VK_IMAGE_LAYOUT_UNDEFINED,                         // VkImageLayout                    oldLayout
928             copyBufferToImageLayout,                           // VkImageLayout                    newLayout
929             *m_referenceImage.handle,                          // VkImage                            image
930             m_referenceSubresourceRange                        // VkImageSubresourceRange            subresourceRange
931         );
932         VkDependencyInfoKHR buffDependencyInfo =
933             makeCommonDependencyInfo(DE_NULL, &preBufferMemoryBarrier2, &preImageMemoryBarrier2);
934         synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &buffDependencyInfo);
935 
936         const VkBufferImageCopy *copyRegion = m_usePipelineToWrite ? &colorCopyRegion : &transitionCopyRegion;
937         vk.cmdCopyBufferToImage(*cmdBuffer, *srcBuffer.handle, *m_referenceImage.handle, copyBufferToImageLayout, 1u,
938                                 copyRegion);
939     }
940 
941     if (m_usePipelineToWrite)
942     {
943         // wait till data is transfered to image (in all cases except when stencil_attachment is tested)
944         if (!m_useStencilDuringWrite)
945         {
946             const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
947                 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,              // VkPipelineStageFlags2KHR            srcStageMask
948                 getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR                srcAccessMask
949                 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR,       // VkPipelineStageFlags2KHR            dstStageMask
950                 getAccessFlag(VK_ACCESS_2_SHADER_READ_BIT_KHR),    // VkAccessFlags2KHR                dstAccessMask
951                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,              // VkImageLayout                    oldLayout
952                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,          // VkImageLayout                    newLayout
953                 *m_referenceImage.handle,                          // VkImage                            image
954                 m_referenceSubresourceRange // VkImageSubresourceRange            subresourceRange
955             );
956             VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
957             synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo);
958         }
959 
960         beginRenderPass(vk, *cmdBuffer, *m_writeRenderPass, *m_writeFramebuffer, renderArea,
961                         tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
962 
963         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_writePipeline);
964         vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &m_vertexBuffer.handle.get(), &vertexBufferOffset);
965         if (m_useStencilDuringWrite)
966         {
967             // when writing to stencil buffer draw single triangle (to simulate gradient over 1bit)
968             vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
969         }
970         else
971         {
972             vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_writePipelineLayout, 0, 1,
973                                      &m_writeDescriptorSet.get(), 0, DE_NULL);
974             vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
975         }
976 
977         endRenderPass(vk, *cmdBuffer);
978     }
979 
980     // use none stage to wait till data is transfered to image
981     {
982         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 =
983             makeImageMemoryBarrier2(m_srcStageToNoneStageMask,    // VkPipelineStageFlags2KHR            srcStageMask
984                                     m_srcAccessToNoneAccessMask,  // VkAccessFlags2KHR                srcAccessMask
985                                     VK_PIPELINE_STAGE_2_NONE_KHR, // VkPipelineStageFlags2KHR            dstStageMask
986                                     VK_ACCESS_2_NONE_KHR,         // VkAccessFlags2KHR                dstAccessMask
987                                     m_testParams.writeLayout,     // VkImageLayout                    oldLayout
988                                     m_testParams.writeLayout,     // VkImageLayout                    newLayout
989                                     *transitionImagePtr->handle,  // VkImage                            image
990                                     m_transitionSubresourceRange  // VkImageSubresourceRange            subresourceRange
991             );
992         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
993         synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo);
994     }
995 
996     // use all commands stage to change image layout
997     {
998         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
999             VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR, // VkPipelineStageFlags2KHR            srcStageMask
1000             VK_ACCESS_2_NONE_KHR,                     // VkAccessFlags2KHR                srcAccessMask
1001             m_dstStageFromNoneStageMask,              // VkPipelineStageFlags2KHR            dstStageMask
1002             m_dstAccessFromNoneAccessMask,            // VkAccessFlags2KHR                dstAccessMask
1003             m_testParams.writeLayout,                 // VkImageLayout                    oldLayout
1004             m_testParams.readLayout,                  // VkImageLayout                    newLayout
1005             *transitionImagePtr->handle,              // VkImage                            image
1006             m_transitionSubresourceRange              // VkImageSubresourceRange            subresourceRange
1007         );
1008         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1009         synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo);
1010     }
1011 
1012     VkImageLayout copyImageToBufferLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1013     if (m_testParams.readLayout == VK_IMAGE_LAYOUT_GENERAL)
1014         copyImageToBufferLayout = VK_IMAGE_LAYOUT_GENERAL;
1015 
1016     if (m_usePipelineToRead)
1017     {
1018         beginRenderPass(vk, *cmdBuffer, *m_readRenderPass, *m_readFramebuffer, renderArea);
1019 
1020         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_readPipeline);
1021         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_readPipelineLayout, 0, 1,
1022                                  &m_readDescriptorSet.get(), 0, DE_NULL);
1023         vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &m_vertexBuffer.handle.get(), &vertexBufferOffset);
1024         vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1025 
1026         endRenderPass(vk, *cmdBuffer);
1027 
1028         // wait till data is transfered to image
1029         const VkImageMemoryBarrier2KHR imageMemoryBarrier2 = makeImageMemoryBarrier2(
1030             VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, // VkPipelineStageFlags2KHR            srcStageMask
1031             VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,          // VkAccessFlags2KHR                srcAccessMask
1032             VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,                // VkPipelineStageFlags2KHR            dstStageMask
1033             getAccessFlag(VK_ACCESS_2_TRANSFER_READ_BIT_KHR),    // VkAccessFlags2KHR                dstAccessMask
1034             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,            // VkImageLayout                    oldLayout
1035             copyImageToBufferLayout,                             // VkImageLayout                    newLayout
1036             *imageToVerifyPtr->handle,                           // VkImage                            image
1037             m_readSubresourceRange                               // VkImageSubresourceRange            subresourceRange
1038         );
1039         VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
1040         synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &dependencyInfo);
1041     }
1042 
1043     // read back image
1044     {
1045         const VkBufferImageCopy *copyRegion = m_usePipelineToRead ? &colorCopyRegion : &transitionCopyRegion;
1046         vk.cmdCopyImageToBuffer(*cmdBuffer, *imageToVerifyPtr->handle, copyImageToBufferLayout, *dstBuffer.handle, 1u,
1047                                 copyRegion);
1048 
1049         const VkBufferMemoryBarrier2KHR postBufferMemoryBarrier2 = makeBufferMemoryBarrier2(
1050             VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,              // VkPipelineStageFlags2KHR            srcStageMask
1051             getAccessFlag(VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR), // VkAccessFlags2KHR                srcAccessMask
1052             VK_PIPELINE_STAGE_2_HOST_BIT_KHR,                  // VkPipelineStageFlags2KHR            dstStageMask
1053             getAccessFlag(VK_ACCESS_2_HOST_READ_BIT_KHR),      // VkAccessFlags2KHR                dstAccessMask
1054             *dstBuffer.handle,                                 // VkBuffer                            buffer
1055             0u,                                                // VkDeviceSize                        offset
1056             imageSizeInBytes                                   // VkDeviceSize                        size
1057         );
1058         VkDependencyInfoKHR bufDependencyInfo = makeCommonDependencyInfo(DE_NULL, &postBufferMemoryBarrier2);
1059         synchronizationWrapper->cmdPipelineBarrier(*cmdBuffer, &bufDependencyInfo);
1060     }
1061 
1062     endCommandBuffer(vk, *cmdBuffer);
1063 
1064     Move<VkFence> fence                         = createFence(vk, device);
1065     VkCommandBufferSubmitInfoKHR cmdBuffersInfo = makeCommonCommandBufferSubmitInfo(*cmdBuffer);
1066     synchronizationWrapper->addSubmitInfo(0u, DE_NULL, 1u, &cmdBuffersInfo, 0u, DE_NULL);
1067     VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
1068     VK_CHECK(vk.waitForFences(device, 1, &fence.get(), VK_TRUE, ~0ull));
1069 
1070     // read image data
1071     invalidateAlloc(vk, device, *dstBuffer.memory);
1072     PixelBufferAccess resultPBA(resultFormat, m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth,
1073                                 dstBuffer.memory->getHostPtr());
1074 
1075     // if result/reference is depth-stencil format then focus only on tested component
1076     if (isCombinedDepthStencilType(referenceFormat.type))
1077         referencePBA = getEffectiveDepthStencilAccess(
1078             referencePBA, (m_referenceSubresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) ?
1079                               tcu::Sampler::MODE_DEPTH :
1080                               tcu::Sampler::MODE_STENCIL);
1081     if (isCombinedDepthStencilType(resultFormat.type))
1082         resultPBA = getEffectiveDepthStencilAccess(
1083             resultPBA, (m_readSubresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) ? tcu::Sampler::MODE_DEPTH :
1084                                                                                          tcu::Sampler::MODE_STENCIL);
1085 
1086     if (verifyResult(referencePBA, resultPBA))
1087         return TestStatus::pass("Pass");
1088     return TestStatus::fail("Fail");
1089 }
1090 
verifyResult(const PixelBufferAccess & reference,const PixelBufferAccess & result)1091 bool NoneStageTestInstance::verifyResult(const PixelBufferAccess &reference, const PixelBufferAccess &result)
1092 {
1093     TestLog &log = m_context.getTestContext().getLog();
1094 
1095     const auto forceStencil = (m_testParams.readLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL);
1096 
1097     if (isIntFormat(m_referenceImageFormat) || isUintFormat(m_referenceImageFormat) || forceStencil)
1098     {
1099         // special case for stencil (1bit gradient - top-left of image is 0, bottom-right is 1)
1100 
1101         bool isResultCorrect = true;
1102         TextureLevel errorMaskStorage(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), m_imageExtent.width,
1103                                       m_imageExtent.height, 1);
1104         PixelBufferAccess errorMask = errorMaskStorage.getAccess();
1105 
1106         for (uint32_t y = 0; y < m_imageExtent.height; y++)
1107             for (uint32_t x = 0; x < m_imageExtent.width; x++)
1108             {
1109                 // skip textels on diagonal (gradient lights texels on diagonal and stencil operation in test does not)
1110                 if ((x + y) == (m_imageExtent.width - 1))
1111                 {
1112                     errorMask.setPixel(IVec4(0, 0xff, 0, 0xff), x, y, 0);
1113                     continue;
1114                 }
1115 
1116                 IVec4 refPix = reference.getPixelInt(x, y, 0);
1117                 IVec4 cmpPix = result.getPixelInt(x, y, 0);
1118                 bool isOk    = (refPix[0] == cmpPix[0]);
1119                 errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, 0);
1120                 isResultCorrect &= isOk;
1121             }
1122 
1123         Vec4 pixelBias(0.0f);
1124         Vec4 pixelScale(1.0f);
1125         if (isResultCorrect)
1126         {
1127             log << TestLog::ImageSet("Image comparison", "")
1128                 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) << TestLog::EndImageSet;
1129             return true;
1130         }
1131 
1132         log << TestLog::ImageSet("Image comparison", "")
1133             << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
1134             << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
1135             << TestLog::Image("ErrorMask", "Error mask", errorMask) << TestLog::EndImageSet;
1136         return false;
1137     }
1138 
1139     return floatThresholdCompare(log, "Image comparison", "", reference, result, tcu::Vec4(0.01f),
1140                                  tcu::COMPARE_LOG_RESULT);
1141 }
1142 
1143 class NoneStageTestCase : public vkt::TestCase
1144 {
1145 public:
1146     NoneStageTestCase(tcu::TestContext &testContext, const std::string &name, const TestParams &testParams);
1147     ~NoneStageTestCase(void) = default;
1148 
1149     void initPrograms(SourceCollections &sourceCollections) const override;
1150     TestInstance *createInstance(Context &context) const override;
1151     void checkSupport(Context &context) const override;
1152 
1153 private:
1154     const TestParams m_testParams;
1155 };
1156 
NoneStageTestCase(tcu::TestContext & testContext,const std::string & name,const TestParams & testParams)1157 NoneStageTestCase::NoneStageTestCase(tcu::TestContext &testContext, const std::string &name,
1158                                      const TestParams &testParams)
1159     : vkt::TestCase(testContext, name)
1160     , m_testParams(testParams)
1161 {
1162 }
1163 
initPrograms(SourceCollections & sourceCollections) const1164 void NoneStageTestCase::initPrograms(SourceCollections &sourceCollections) const
1165 {
1166     const auto writeLayout = m_testParams.writeLayout;
1167     const auto writeAspect = m_testParams.writeAspect;
1168     const auto readLayout  = m_testParams.readLayout;
1169     const auto readAspect  = m_testParams.readAspect;
1170 
1171     // for tests that use only transfer and general layouts we don't create pipeline
1172     if (((writeLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) || (readLayout == VK_IMAGE_LAYOUT_GENERAL)) &&
1173         ((writeLayout == VK_IMAGE_LAYOUT_GENERAL) || (readLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)))
1174         return;
1175 
1176     sourceCollections.glslSources.add("vert")
1177         << glu::VertexSource("#version 450\n"
1178                              "layout(location = 0) in  vec4 inPosition;\n"
1179                              "layout(location = 0) out vec2 outUV;\n"
1180                              "void main(void)\n"
1181                              "{\n"
1182                              "  outUV = vec2(inPosition.x * 0.5 + 0.5, inPosition.y * 0.5 + 0.5);\n"
1183                              "  gl_Position = inPosition;\n"
1184                              "}\n");
1185 
1186     sourceCollections.glslSources.add("frag-color")
1187         << glu::FragmentSource("#version 450\n"
1188                                "layout(binding = 0) uniform sampler2D u_sampler;\n"
1189                                "layout(location = 0) in vec2 inUV;\n"
1190                                "layout(location = 0) out vec4 fragColor;\n"
1191                                "void main(void)\n"
1192                                "{\n"
1193                                "  fragColor = texture(u_sampler, inUV);\n"
1194                                "}\n");
1195 
1196     if (writeAspect & VK_IMAGE_ASPECT_DEPTH_BIT)
1197     {
1198         sourceCollections.glslSources.add("frag-color-to-depth")
1199             << glu::FragmentSource("#version 450\n"
1200                                    "layout(binding = 0) uniform sampler2D u_sampler;\n"
1201                                    "layout(location = 0) in vec2 inUV;\n"
1202                                    "void main(void)\n"
1203                                    "{\n"
1204                                    "  gl_FragDepth = texture(u_sampler, inUV).r;\n"
1205                                    "}\n");
1206     }
1207 
1208     if (writeAspect & VK_IMAGE_ASPECT_STENCIL_BIT)
1209     {
1210         sourceCollections.glslSources.add("frag-color-to-stencil") << glu::FragmentSource("#version 450\n"
1211                                                                                           "void main(void)\n"
1212                                                                                           "{\n"
1213                                                                                           "}\n");
1214     }
1215     if ((readLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) && (readLayout != VK_IMAGE_LAYOUT_GENERAL) &&
1216         ((readAspect | writeAspect) == VK_IMAGE_ASPECT_STENCIL_BIT ||
1217          (readAspect == IMAGE_ASPECT_DEPTH_STENCIL &&
1218           m_testParams.readLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)))
1219     {
1220         // use usampler2D and uvec4 for color
1221         sourceCollections.glslSources.add("frag-stencil-to-color")
1222             << glu::FragmentSource("#version 450\n"
1223                                    "layout(binding = 0) uniform usampler2D u_sampler;\n"
1224                                    "layout(location = 0) in vec2 inUV;\n"
1225                                    "layout(location = 0) out uvec4 fragColor;\n"
1226                                    "void main(void)\n"
1227                                    "{\n"
1228                                    "  fragColor = texture(u_sampler, inUV);\n"
1229                                    "}\n");
1230     }
1231 
1232     if (readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
1233     {
1234         // for stencil only cases we need to use usubpassInput (for depth and depth_stencil we need to use subpassInput)
1235         const bool readDepth = readAspect & VK_IMAGE_ASPECT_DEPTH_BIT;
1236         const std::map<std::string, std::string> specializations{
1237             {"SUBPASS_INPUT", (readDepth ? "subpassInput" : "usubpassInput")},
1238             {"VALUE_TYPE", (readDepth ? "float" : "uint")}};
1239 
1240         std::string source =
1241             "#version 450\n"
1242             "layout (input_attachment_index = 0, binding = 0) uniform ${SUBPASS_INPUT} depthOrStencilInput;\n"
1243             "layout(location = 0) in vec2 inUV;\n"
1244             "layout(location = 0) out ${VALUE_TYPE} fragColor;\n"
1245             "void main (void)\n"
1246             "{\n"
1247             "  fragColor = subpassLoad(depthOrStencilInput).x;\n"
1248             "}\n";
1249         sourceCollections.glslSources.add("frag-depth-or-stencil-to-color")
1250             << glu::FragmentSource(tcu::StringTemplate(source).specialize(specializations));
1251     }
1252 }
1253 
createInstance(Context & context) const1254 TestInstance *NoneStageTestCase::createInstance(Context &context) const
1255 {
1256     return new NoneStageTestInstance(context, m_testParams);
1257 }
1258 
checkSupport(Context & context) const1259 void NoneStageTestCase::checkSupport(Context &context) const
1260 {
1261     context.requireDeviceFunctionality("VK_KHR_synchronization2");
1262 
1263     const auto writeAspect = m_testParams.writeAspect;
1264     const auto readAspect  = m_testParams.readAspect;
1265 
1266     // check whether implementation supports separate depth/stencil layouts
1267     if (((writeAspect == VK_IMAGE_ASPECT_DEPTH_BIT) && (readAspect == VK_IMAGE_ASPECT_DEPTH_BIT)) ||
1268         ((writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) && (readAspect == VK_IMAGE_ASPECT_STENCIL_BIT)))
1269     {
1270         if (!context.getSeparateDepthStencilLayoutsFeatures().separateDepthStencilLayouts)
1271             TCU_THROW(NotSupportedError, "Implementation does not support separateDepthStencilLayouts");
1272     }
1273 
1274     const auto writeLayout = m_testParams.writeLayout;
1275     const auto readLayout  = m_testParams.readLayout;
1276     bool usePipelineToWrite =
1277         (writeLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) && (writeLayout != VK_IMAGE_LAYOUT_GENERAL);
1278     bool usePipelineToRead =
1279         (readLayout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) && (readLayout != VK_IMAGE_LAYOUT_GENERAL);
1280 
1281     if (!usePipelineToWrite && !usePipelineToRead)
1282         return;
1283 
1284     VkFormat transitionImageFormat = VK_FORMAT_R8G8B8A8_UNORM;
1285     if ((writeAspect == VK_IMAGE_ASPECT_DEPTH_BIT) || (readAspect == VK_IMAGE_ASPECT_DEPTH_BIT))
1286         transitionImageFormat = VK_FORMAT_D32_SFLOAT;
1287     else if ((writeAspect == VK_IMAGE_ASPECT_STENCIL_BIT) || (readAspect == VK_IMAGE_ASPECT_STENCIL_BIT))
1288         transitionImageFormat = VK_FORMAT_S8_UINT;
1289     else if ((writeAspect == IMAGE_ASPECT_DEPTH_STENCIL) || (readAspect == IMAGE_ASPECT_DEPTH_STENCIL))
1290         transitionImageFormat = VK_FORMAT_D24_UNORM_S8_UINT;
1291 
1292     struct FormatToCheck
1293     {
1294         VkFormat format;
1295         VkImageUsageFlags usage;
1296     };
1297     std::vector<FormatToCheck> formatsToCheck{
1298         // reference image
1299         {transitionImageFormat, (VkImageUsageFlags)VK_IMAGE_USAGE_TRANSFER_DST_BIT},
1300 
1301         // image to write
1302         {transitionImageFormat, (VkImageUsageFlags)VK_IMAGE_USAGE_TRANSFER_SRC_BIT}};
1303 
1304     // note: conditions here are analogic to conditions in test case constructor
1305     //       everything not needed was cout out leaving only logic related to
1306     //       m_referenceImage and m_imageToWrite
1307     if (usePipelineToWrite)
1308     {
1309         if (writeAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
1310         {
1311             if (writeAspect & VK_IMAGE_ASPECT_DEPTH_BIT)
1312             {
1313                 formatsToCheck[0].format = VK_FORMAT_R32_SFLOAT;
1314                 formatsToCheck[0].usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
1315             }
1316             else
1317                 formatsToCheck[0].usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1318 
1319             formatsToCheck[1].usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1320         }
1321         else
1322         {
1323             formatsToCheck[0].usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
1324             formatsToCheck[1].usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1325         }
1326     }
1327 
1328     if (usePipelineToRead)
1329     {
1330         // for layouts that operate on depth or stencil (not depth_stencil) use input attachment to read
1331         if ((readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) &&
1332             (readAspect != IMAGE_ASPECT_DEPTH_STENCIL))
1333         {
1334             formatsToCheck[1].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1335 
1336             if (!usePipelineToWrite)
1337                 formatsToCheck[0].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1338         }
1339         else // use image sampler for color and depth_stencil layouts
1340         {
1341             formatsToCheck[0].usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
1342 
1343             // for depth_stencil layouts we need to have depth_stencil_attachment usage
1344             if (!usePipelineToWrite && (readAspect & VK_IMAGE_ASPECT_STENCIL_BIT))
1345                 formatsToCheck[0].usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1346         }
1347         if ((readAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) &&
1348             (readAspect != IMAGE_ASPECT_DEPTH_STENCIL))
1349             if ((m_testParams.readLayout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
1350                  m_testParams.readLayout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL))
1351                 formatsToCheck[0].usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1352     }
1353 
1354     // it simplifies logic to pop image to write then to add conditions everywhere above
1355     if (!usePipelineToWrite)
1356         formatsToCheck.pop_back();
1357 
1358     for (const auto &formatData : formatsToCheck)
1359     {
1360         VkImageFormatProperties properties;
1361         const vk::InstanceInterface &vki = context.getInstanceInterface();
1362         if (vki.getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(), formatData.format, VK_IMAGE_TYPE_2D,
1363                                                        VK_IMAGE_TILING_OPTIMAL, formatData.usage, 0,
1364                                                        &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
1365         {
1366             std::string error = std::string("Format (") + vk::getFormatName(formatData.format) +
1367                                 ") doesn't support required capabilities.";
1368             TCU_THROW(NotSupportedError, error.c_str());
1369         }
1370     }
1371 }
1372 
1373 } // namespace
1374 
createNoneStageTests(tcu::TestContext & testCtx)1375 tcu::TestCaseGroup *createNoneStageTests(tcu::TestContext &testCtx)
1376 {
1377     de::MovePtr<tcu::TestCaseGroup> noneStageTests(new tcu::TestCaseGroup(testCtx, "none_stage"));
1378 
1379     struct LayoutData
1380     {
1381         VkImageLayout token;
1382         VkImageAspectFlags aspect;
1383         std::string name;
1384     };
1385 
1386     const std::vector<LayoutData> writableLayoutsData{
1387         {VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, IMAGE_ASPECT_ALL, "transfer_dst"},
1388         {VK_IMAGE_LAYOUT_GENERAL, IMAGE_ASPECT_ALL, "general"},
1389         {VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, "color_attachment"},
1390         {VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL, "depth_stencil_attachment"},
1391         {VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT, "depth_attachment"},
1392         {VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_STENCIL_BIT, "stencil_attachment"},
1393         {VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_ASPECT_COLOR_BIT, "generic_color_attachment"},
1394         {VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_ASPECT_DEPTH_BIT, "generic_depth_attachment"},
1395         {VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_ASPECT_STENCIL_BIT, "generic_stencil_attachment"},
1396         {VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, IMAGE_ASPECT_DEPTH_STENCIL, "generic_depth_stencil_attachment"},
1397     };
1398     const std::vector<LayoutData> readableLayoutsData{
1399         {VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, IMAGE_ASPECT_ALL, "transfer_src"},
1400         {VK_IMAGE_LAYOUT_GENERAL, IMAGE_ASPECT_ALL, "general"},
1401         {VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, IMAGE_ASPECT_ALL, "shader_read"},
1402         {VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL, "depth_stencil_read"},
1403         {VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL,
1404          "depth_read_stencil_attachment"},
1405         {VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, IMAGE_ASPECT_DEPTH_STENCIL,
1406          "depth_attachment_stencil_read"},
1407         {VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT, "depth_read"},
1408         {VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_STENCIL_BIT, "stencil_read"},
1409         {VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, IMAGE_ASPECT_ALL, "generic_color_read"},
1410         {VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_ASPECT_DEPTH_BIT, "generic_depth_read"},
1411         {VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, VK_IMAGE_ASPECT_STENCIL_BIT, "generic_stencil_read"},
1412         {VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR, IMAGE_ASPECT_DEPTH_STENCIL, "generic_depth_stencil_read"},
1413     };
1414 
1415     struct SynchronizationData
1416     {
1417         SynchronizationType type;
1418         std::string casePrefix;
1419         bool useGenericAccessFlags;
1420     };
1421     std::vector<SynchronizationData> synchronizationData{{SynchronizationType::SYNCHRONIZATION2, "", true},
1422                                                          {SynchronizationType::SYNCHRONIZATION2, "old_access_", false},
1423 
1424                                                          // using legacy synchronization structures with NONE_STAGE
1425                                                          {SynchronizationType::LEGACY, "legacy_", false}};
1426 
1427     for (const auto &syncData : synchronizationData)
1428     {
1429         for (const auto &writeData : writableLayoutsData)
1430         {
1431             for (const auto &readData : readableLayoutsData)
1432             {
1433                 if (readData.aspect && writeData.aspect && (readData.aspect != writeData.aspect))
1434                     continue;
1435 
1436                 const std::string name = syncData.casePrefix + writeData.name + "_to_" + readData.name;
1437                 noneStageTests->addChild(
1438                     new NoneStageTestCase(testCtx, name,
1439                                           {syncData.type, syncData.useGenericAccessFlags, writeData.token,
1440                                            writeData.aspect, readData.token, readData.aspect}));
1441             }
1442         }
1443     }
1444 
1445     return noneStageTests.release();
1446 }
1447 
1448 } // namespace synchronization
1449 } // namespace vkt
1450