1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2023 The Khronos Group Inc.
6  * Copyright (c) 2023 Google Inc.
7  * Copyright (c) 2023 LunarG, Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Android Hardware Buffer External Format Resolve Draw Tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktDrawAhbExternalFormatResolveTests.hpp"
27 
28 #include "vkCmdUtil.hpp"
29 #include "vkObjUtil.hpp"
30 #include "vktTestGroupUtil.hpp"
31 #include "vktDrawBaseClass.hpp"
32 
33 #include "../image/vktImageTestsUtil.hpp"
34 #include "../util/vktExternalMemoryUtil.hpp"
35 
36 #include "tcuTextureUtil.hpp"
37 #include "tcuVector.hpp"
38 
39 #include "deRandom.hpp"
40 
41 using namespace vkt::ExternalMemoryUtil;
42 using namespace vk;
43 using std::vector;
44 
45 namespace vkt
46 {
47 namespace Draw
48 {
49 namespace
50 {
51 
52 struct TestParams
53 {
54     vk::VkRect2D m_renderArea;
55     tcu::UVec2 m_imageSize;
56     AndroidHardwareBufferInstance::Format m_format;
57     AndroidHardwareBufferInstance::Usage m_usage;
58     GroupParams m_groupParams;
59     bool m_isClearOnly;
60     bool m_partialDraw;
61     bool m_isInputAttachment; // Tests input attachment
62 };
63 
64 struct DrawResources
65 {
66     Move<VkImage> m_androidExternalImage;
67     Move<VkDeviceMemory> m_androidExternalImageMemory;
68     Move<VkImageView> m_androidExternalImageView;
69     de::MovePtr<ImageWithMemory> m_androidColorAttachmentImage; // Used if nullColorAttachment is false
70     Move<VkImageView> m_androidColorAttachmentImageView;
71     de::MovePtr<BufferWithMemory> m_vertexBuffer;
72     Move<VkShaderModule> m_vertexShader;
73     Move<VkShaderModule> m_fragmentShaderBase;
74     Move<VkShaderModule> m_fragmentShaderInput;
75     Move<VkPipelineLayout> m_basePipelineLayout;
76     Move<VkPipeline> m_basePipeline; // Draws to external image
77     Move<VkPipelineLayout> m_inputAttachmentPipelineLayout;
78     Move<VkPipeline>
79         m_inputAttachmentPipeline; // Reads from input attachment (external image) and renders to vulkan image
80     Move<VkRenderPass> m_renderPass;
81     Move<VkFramebuffer> m_framebuffer;
82     Move<VkRenderPass> m_renderPassClear;
83     Move<VkFramebuffer> m_framebufferClear;
84 
85     // Resources for input attachment testing
86     de::MovePtr<ImageWithMemory>
87         m_resultAttachmentImage; // Used as render target when reading from external image as input attachment
88     Move<VkImageView> m_resultAttachmentImageView;
89     de::MovePtr<BufferWithMemory> m_resultBuffer;
90     Move<VkDescriptorPool> m_descriptorPool;
91     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
92     Move<VkDescriptorSet> m_descriptorSet;
93 };
94 
95 class AhbExternalFormatResolveTestInstance : public TestInstance
96 {
97 public:
98     AhbExternalFormatResolveTestInstance(Context &context, const TestParams &params);
~AhbExternalFormatResolveTestInstance(void)99     virtual ~AhbExternalFormatResolveTestInstance(void)
100     {
101     }
102 
103     tcu::TestStatus iterate(void) override;
104 
105 protected:
106     void renderToExternalFormat(AndroidHardwareBufferInstance &androidBuffer);
107     void clearAttachments(const vk::DeviceInterface &vk, vk::VkCommandBuffer commandBuffer);
108     void doRenderPass(const vk::DeviceInterface &vk, const vk::VkDevice device, const VkQueue queue,
109                       const uint32_t queueFamilyIndex, bool renderInputAttachment);
110     void copyImageToBuffer(const vk::DeviceInterface &vk, vk::VkCommandBuffer commandBuffer);
111     // Transitions all used attachments to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
112     void initialAttachmentTransition(const vk::DeviceInterface &vk, vk::VkCommandBuffer commandBuffer);
113     // Transition input attachment back to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL from VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
114     void transitionInputAttachmentToOutput(const vk::DeviceInterface &vk, vk::VkCommandBuffer commandBuffer);
115     bool checkExternalFormatTestingRequired(const AndroidHardwareBufferInstance &androidBuffer);
116     // ahbFormatVulkanFormatAlphaMismatch is used to know if the original AHB format does not have alpha but the texture level passed does.
117     // This is required to correctly build the image for inputAttachment tests. When reading from a format with no alpha, we will get maxValue
118     // which is the value we need to write to the reference image we are building.
119     void buildReferenceImage(tcu::TextureLevel &reference, bool performDownsample,
120                              bool ahbFormatVulkanFormatAlphaMismatch) const;
121 
122     Move<VkImageView> createImageView(VkImage image, vk::VkFormat format);
123     void createImagesAndViews(AndroidHardwareBufferInstance &androidBuffer);
124     void createRenderPass(void);
125     void createFramebuffer(void);
126     void createDescriptors(void);
127     void createPipelineLayouts(void);
128     void createPipelines(void);
129 
130     // Draw commands
131     void beginRender(VkCommandBuffer cmd, const vk::VkRect2D &renderArea, bool clearPass) const;
132     void endRender(VkCommandBuffer cmd) const;
133     // When drawToInputAttachment is true, first subpass that draws to the external format is skipped (values will be loaded from a previous draw)
134     // and the external format will be used as input
135     void drawCommands(VkCommandBuffer cmd, bool drawFromInputAttachment) const;
136 
137     DrawResources m_resources;
138     const vk::VkRect2D m_renderArea;
139     tcu::Vec4 m_clearColor;
140     uint64_t m_retrievedInternalFormat = 0u;
141     const AndroidHardwareBufferInstance::Format m_format;
142     const AndroidHardwareBufferInstance::Usage m_usage;
143     const uint32_t m_width;
144     const uint32_t m_height;
145     const uint32_t m_layers                = 1u;
146     vk::VkChromaLocation m_xChromaLocation = vk::VK_CHROMA_LOCATION_LAST;
147     vk::VkChromaLocation m_yChromaLocation = vk::VK_CHROMA_LOCATION_LAST;
148     vk::VkFormat m_colorAttachmentFormat   = vk::VK_FORMAT_UNDEFINED;
149     vk::VkBool32 m_nullColorAttachment     = VK_FALSE;
150     const GroupParams m_groupParams;
151     const bool m_isClearOnly;
152     bool m_partialDraw;
153     const bool m_isInputAttachment;
154 };
155 
AhbExternalFormatResolveTestInstance(Context & context,const TestParams & params)156 AhbExternalFormatResolveTestInstance::AhbExternalFormatResolveTestInstance(Context &context, const TestParams &params)
157     : TestInstance(context)
158     , m_renderArea(params.m_renderArea)
159     , m_format(params.m_format)
160     , m_usage(params.m_usage)
161     , m_width(params.m_imageSize.x())
162     , m_height(params.m_imageSize.y())
163     , m_groupParams(params.m_groupParams)
164     , m_isClearOnly(params.m_isClearOnly)
165     , m_partialDraw(params.m_partialDraw)
166     , m_isInputAttachment(params.m_isInputAttachment)
167 {
168 }
169 
iterate(void)170 tcu::TestStatus AhbExternalFormatResolveTestInstance::iterate(void)
171 {
172     tcu::TestLog &log = m_context.getTestContext().getLog();
173 
174     AndroidHardwareBufferInstance androidBuffer;
175 
176     if (!androidBuffer.allocate(m_format, m_width, m_height, m_layers, m_usage))
177     {
178         const std::string formatName = AndroidHardwareBufferInstance::getFormatName(m_format);
179         std::string skipReason = "Unable to allocate renderable AHB with parameters: width(" + std::to_string(m_width) +
180                                  "), height(" + std::to_string(m_height) + "), layers(" + std::to_string(m_layers) +
181                                  "), usage(" + std::to_string(m_usage) + ")";
182 
183         log << tcu::TestLog::Message << "Skipping format " << formatName << ". Reason: " << skipReason
184             << tcu::TestLog::EndMessage;
185 
186         TCU_THROW(NotSupportedError, "Failed to allocate buffer");
187     }
188 
189     if (!checkExternalFormatTestingRequired(androidBuffer))
190         return tcu::TestStatus::pass("Rendering to format was already supported");
191 
192     // Vulkan rendering
193     renderToExternalFormat(androidBuffer);
194 
195     tcu::TextureLevel cpuTexture;
196     tcu::ConstPixelBufferAccess resultAccess;
197     if (m_isInputAttachment)
198     {
199         const vk::DeviceInterface &vk = m_context.getDeviceInterface();
200         const vk::VkDevice device     = m_context.getDevice();
201         const Allocation &allocColor  = m_resources.m_resultBuffer->getAllocation();
202         invalidateAlloc(vk, device, allocColor);
203         resultAccess = tcu::ConstPixelBufferAccess(mapVkFormat(m_colorAttachmentFormat), m_width, m_height, 1u,
204                                                    allocColor.getHostPtr());
205     }
206     else
207     {
208         // Need to destroy Vulkan image that has a reference to the android hardware buffer
209         m_resources.~DrawResources();
210 
211         if (!androidBuffer.lock(AndroidHardwareBufferInstance::Usage::CPU_READ))
212         {
213             TCU_THROW(NotSupportedError, "Failed to lock buffer for CPU read");
214         }
215 
216         // Format must have a valid tcu::TextureFormat which should be enforced by the time we reach this
217         cpuTexture = tcu::TextureLevel(AndroidHardwareBufferInstance::formatToTextureFormat(m_format), m_width,
218                                        m_height, m_layers);
219 
220         // RAW16 can be represented as UINT16, so there's no need to have a compressed path for this format
221         if (androidBuffer.isRaw() && m_format != AndroidHardwareBufferInstance::Format::RAW16)
222         {
223             tcu::CompressedTexFormat compressedFormat = m_format == AndroidHardwareBufferInstance::Format::RAW10 ?
224                                                             tcu::COMPRESSEDTEXFORMAT_AHB_RAW10 :
225                                                             tcu::COMPRESSEDTEXFORMAT_AHB_RAW12;
226             tcu::CompressedTexture compressedTexture(compressedFormat, m_width, m_height, m_layers);
227             androidBuffer.copyAndroidBufferToCpuBufferCompressed(compressedTexture);
228             compressedTexture.decompress(cpuTexture.getAccess());
229         }
230         else
231             androidBuffer.copyAndroidBufferToCpuBuffer(cpuTexture);
232 
233         if (!androidBuffer.unlock())
234         {
235             TCU_THROW(NotSupportedError, "Failed to unlock buffer from CPU read");
236         }
237 
238         resultAccess = cpuTexture.getAccess();
239     }
240 
241     // Validate output
242     {
243         tcu::TextureFormat textureFormat = m_isInputAttachment ?
244                                                mapVkFormat(m_colorAttachmentFormat) :
245                                                AndroidHardwareBufferInstance::formatToTextureFormat(m_format);
246         tcu::TextureLevel reference(textureFormat, m_width, m_height, m_layers);
247         const bool alphaMismatch =
248             !AndroidHardwareBufferInstance::hasFormatAlpha(m_format) && hasAlphaChannel(textureFormat.order);
249         const bool isYuvFormat = AndroidHardwareBufferInstance::isFormatYuv(m_format);
250         buildReferenceImage(reference, isYuvFormat, alphaMismatch);
251         const tcu::ConstPixelBufferAccess referenceAccess = reference.getAccess();
252         const char *name                                  = "Render validation";
253         const char *description = "Validate output image was rendered according to expectation (if YUV and input test, "
254                                   "a follow up test is done for no downsample)";
255         // Some implementations of format YCbCr_P010 will have reduced range, which requires allowing for some threshold since we are rendering with 1.0f
256         const tcu::UVec4 threshold =
257             (m_format == AndroidHardwareBufferInstance::Format::YCbCr_P010) ? tcu::UVec4(4u) : tcu::UVec4(0u);
258 
259         if (!tcu::intThresholdCompare(log, name, description, referenceAccess, resultAccess, threshold,
260                                       tcu::COMPARE_LOG_ON_ERROR))
261             return tcu::TestStatus::fail("Result image does not match reference image");
262     }
263 
264     return tcu::TestStatus::pass("");
265 }
266 
renderToExternalFormat(AndroidHardwareBufferInstance & androidBuffer)267 void AhbExternalFormatResolveTestInstance::renderToExternalFormat(AndroidHardwareBufferInstance &androidBuffer)
268 {
269     const vk::DeviceInterface &vk   = m_context.getDeviceInterface();
270     const vk::VkDevice device       = m_context.getDevice();
271     const VkQueue queue             = m_context.getUniversalQueue();
272     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
273 
274     // Create required resources for test
275     createImagesAndViews(androidBuffer);
276     createRenderPass();
277     createFramebuffer();
278     const std::string shaderType = vkt::image::getGlslAttachmentType(m_colorAttachmentFormat);
279     m_resources.m_vertexShader   = vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"));
280     m_resources.m_fragmentShaderBase =
281         vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_" + shaderType));
282     if (m_isInputAttachment)
283     {
284         std::string swizzleOrder = vkt::image::isComponentSwizzled(m_colorAttachmentFormat) ? "bgr" : "rgb";
285         std::string shaderName   = "frag_input_" + shaderType + "_" + swizzleOrder;
286         m_resources.m_fragmentShaderInput =
287             vk::createShaderModule(vk, device, m_context.getBinaryCollection().get(shaderName));
288     }
289     createDescriptors();
290     createPipelineLayouts();
291     createPipelines();
292     {
293         const float vertices[] = {
294             -1.0f, -1.0f, // Bot left
295             +1.0f, -1.0f, // Bot right
296             -1.0f, +1.0f, // Top left
297             +1.0f, +1.0f, // Top right
298         };
299         m_resources.m_vertexBuffer = de::MovePtr<BufferWithMemory>(
300             new BufferWithMemory(vk, device, m_context.getDefaultAllocator(),
301                                  makeBufferCreateInfo(sizeof(vertices), vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
302                                  vk::MemoryRequirement::HostVisible));
303 
304         // Copy vertices
305         vk::Allocation &bufferAlloc = m_resources.m_vertexBuffer->getAllocation();
306         void *bufferPtr             = bufferAlloc.getHostPtr();
307         deMemcpy(bufferPtr, vertices, sizeof(vertices));
308         vk::flushAlloc(vk, device, bufferAlloc);
309     }
310 
311     {
312         Move<VkCommandPool> commandPool = vk::createCommandPool(vk, device, 0u, queueFamilyIndex);
313         Move<VkCommandBuffer> commandBuffer =
314             vk::allocateCommandBuffer(vk, device, commandPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
315         vk::beginCommandBuffer(vk, commandBuffer.get());
316 
317         initialAttachmentTransition(vk, commandBuffer.get());
318 
319         // Clear all images for clear only and partial rendering to ensure expected values outside
320         // of render area, since not all external formats may support VK_IMAGE_USAGE_TRANSFER_DST_BIT
321         // safest clear method is to clear on attachment load with render size of image and do nothing else
322         //if (m_isClearOnly || m_partialDraw)
323         clearAttachments(vk, commandBuffer.get());
324 
325         vk::endCommandBuffer(vk, commandBuffer.get());
326         vk::submitCommandsAndWait(vk, device, queue, commandBuffer.get());
327     }
328 
329     // Render to external format resolve
330     if (!m_isClearOnly)
331     {
332         // Render to external format
333         doRenderPass(vk, device, queue, queueFamilyIndex, false);
334 
335         // Need to split rendering into 2 to force chroma downsample
336         // If this does not force the chroma downsample, next idea to do would be destroying relevant
337         // resource and creating them again
338 
339         // Render to m_colorAttachmentFormat texture reading from external format
340         if (m_isInputAttachment)
341             doRenderPass(vk, device, queue, queueFamilyIndex, true);
342     }
343 }
344 
clearAttachments(const vk::DeviceInterface & vk,vk::VkCommandBuffer commandBuffer)345 void AhbExternalFormatResolveTestInstance::clearAttachments(const vk::DeviceInterface &vk,
346                                                             vk::VkCommandBuffer commandBuffer)
347 {
348     // Clear images on load without doing anything
349     beginRender(commandBuffer, makeRect2D(m_width, m_height), true);
350     if (m_isInputAttachment)
351     {
352         const vk::VkSubpassBeginInfo subpassBeginInfo = {
353             vk::VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO, // VkStructureType        sType
354             nullptr,                                  // const void*            pNext
355             vk::VK_SUBPASS_CONTENTS_INLINE            // VkSubpassContents    contents
356         };
357         const vk::VkSubpassEndInfo subpassEndInfo = {
358             vk::VK_STRUCTURE_TYPE_SUBPASS_END_INFO, // VkStructureType    sType
359             nullptr                                 // const void*        pNext
360         };
361         vk.cmdNextSubpass2(commandBuffer, &subpassBeginInfo, &subpassEndInfo);
362     }
363     endRender(commandBuffer);
364 
365     if (m_isInputAttachment)
366         transitionInputAttachmentToOutput(vk, commandBuffer);
367 }
368 
doRenderPass(const vk::DeviceInterface & vk,const vk::VkDevice device,const VkQueue queue,const uint32_t queueFamilyIndex,bool renderInputAttachment)369 void AhbExternalFormatResolveTestInstance::doRenderPass(const vk::DeviceInterface &vk, const vk::VkDevice device,
370                                                         const VkQueue queue, const uint32_t queueFamilyIndex,
371                                                         bool renderInputAttachment)
372 {
373     Move<VkCommandPool> commandPool = vk::createCommandPool(vk, device, 0u, queueFamilyIndex);
374     Move<VkCommandBuffer> primaryCommandBuffer =
375         vk::allocateCommandBuffer(vk, device, commandPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
376     Move<VkCommandBuffer> secondaryCommandBuffer =
377         vk::allocateCommandBuffer(vk, device, commandPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
378 
379     if (m_groupParams.useSecondaryCmdBuffer)
380     {
381         vk::VkExternalFormatANDROID externalFormat = {
382             vk::VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID, // VkStructureType    sType
383             nullptr,                                       // void*            pNext
384             m_retrievedInternalFormat                      // uint64_t            externalFormat
385         };
386 
387         const vk::VkFormat colorAttachmentFormat =
388             m_nullColorAttachment ? vk::VK_FORMAT_UNDEFINED : m_colorAttachmentFormat;
389         const vk::VkCommandBufferInheritanceRenderingInfo renderInfo = {
390             vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO, // VkStructureType            sType
391             &externalFormat,                                                 // const void*                pNext
392             0u,                                                              // VkRenderingFlags            flags
393             0u,                                                              // uint32_t                    viewMask
394             1u,                       // uint32_t                    colorAttachmentCount
395             &colorAttachmentFormat,   // const VkFormat*            pColorAttachmentFormats
396             vk::VK_FORMAT_UNDEFINED,  // VkFormat                    depthAttachmentFormat
397             vk::VK_FORMAT_UNDEFINED,  // VkFormat                    stencilAttachmentFormat
398             vk::VK_SAMPLE_COUNT_1_BIT // VkSampleCountFlagBits    rasterizationSamples
399         };
400 
401         const vk::VkCommandBufferInheritanceInfo inheritanceInfo = {
402             vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType                    sType
403             &renderInfo,                                           // const void*                        pNext
404             VK_NULL_HANDLE,                                        // VkRenderPass                        renderPass
405             0u,                                                    // uint32_t                            subpass
406             VK_NULL_HANDLE,                                        // VkFramebuffer                    framebuffer
407             VK_FALSE, // VkBool32                            occlusionQueryEnable
408             0u,       // VkQueryControlFlags                queryFlags
409             0u,       // VkQueryPipelineStatisticFlags    pipelineStatistics
410         };
411 
412         const vk::VkCommandBufferUsageFlags commandBufferBeginFlags =
413             m_groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass ?
414                 static_cast<vk::VkCommandBufferUsageFlags>(0u) :
415                 static_cast<vk::VkCommandBufferUsageFlags>(vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT);
416         const vk::VkCommandBufferBeginInfo commandBufBeginParams = {
417             vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType                    sType
418             DE_NULL,                                         // const void*                        pNext
419             commandBufferBeginFlags,                         // VkCommandBufferUsageFlags        flags
420             &inheritanceInfo                                 // VkCommandBufferInheritanceInfo    pInheritanceInfo
421         };
422         VK_CHECK(vk.beginCommandBuffer(secondaryCommandBuffer.get(), &commandBufBeginParams));
423 
424         if (m_groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
425             beginRender(secondaryCommandBuffer.get(), m_renderArea, false);
426 
427         drawCommands(secondaryCommandBuffer.get(), renderInputAttachment);
428 
429         if (m_groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
430             endRender(secondaryCommandBuffer.get());
431 
432         vk::endCommandBuffer(vk, secondaryCommandBuffer.get());
433     }
434 
435     vk::beginCommandBuffer(vk, primaryCommandBuffer.get());
436 
437     if (!m_groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
438         beginRender(primaryCommandBuffer.get(), m_renderArea, false);
439 
440     if (m_groupParams.useSecondaryCmdBuffer)
441         vk.cmdExecuteCommands(primaryCommandBuffer.get(), 1u, &secondaryCommandBuffer.get());
442     else
443         drawCommands(primaryCommandBuffer.get(), renderInputAttachment);
444 
445     if (!m_groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
446         endRender(primaryCommandBuffer.get());
447 
448     if (m_isInputAttachment)
449     {
450         if (!renderInputAttachment)
451             transitionInputAttachmentToOutput(vk, primaryCommandBuffer.get());
452         else
453             copyImageToBuffer(vk, primaryCommandBuffer.get());
454     }
455 
456     vk::endCommandBuffer(vk, primaryCommandBuffer.get());
457     vk::submitCommandsAndWait(vk, device, queue, primaryCommandBuffer.get());
458 }
459 
copyImageToBuffer(const vk::DeviceInterface & vk,vk::VkCommandBuffer commandBuffer)460 void AhbExternalFormatResolveTestInstance::copyImageToBuffer(const vk::DeviceInterface &vk,
461                                                              vk::VkCommandBuffer commandBuffer)
462 {
463     // Copy result image to host visible buffer for validation
464     if (m_isInputAttachment)
465     {
466         const vk::VkImageMemoryBarrier imageBarrier = {
467             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType
468             nullptr,                                    // const void*                pNext
469             vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,   // VkAccessFlags            srcAccessMask
470             vk::VK_ACCESS_TRANSFER_READ_BIT,            // VkAccessFlags            dstAccessMask
471             vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout            oldLayout
472             vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout            newLayout
473             VK_QUEUE_FAMILY_IGNORED,                    // uint32_t                    srcQueueFamilyIndex
474             VK_QUEUE_FAMILY_IGNORED,                    // uint32_t                    destQueueFamilyIndex
475             m_resources.m_resultAttachmentImage->get(), // VkImage                    image
476             vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageSubresourceRange    subresourceRange
477                                           0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS)};
478 
479         vk.cmdPipelineBarrier(commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
480                               0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
481 
482         const vk::VkImageSubresourceLayers subresource = {
483             vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
484             0u,                            // uint32_t                mipLevel
485             0u,                            // uint32_t                baseArrayLayer
486             1u                             // uint32_t                layerCount
487         };
488 
489         const vk::VkBufferImageCopy region = {
490             0ull,                               // VkDeviceSize                    bufferOffset
491             0u,                                 // uint32_t                        bufferRowLength
492             0u,                                 // uint32_t                        bufferImageHeight
493             subresource,                        // VkImageSubresourceLayers        imageSubresource
494             makeOffset3D(0, 0, 0),              // VkOffset3D                    imageOffset
495             makeExtent3D(m_width, m_height, 1u) // VkExtent3D                    imageExtent
496         };
497 
498         vk.cmdCopyImageToBuffer(commandBuffer, m_resources.m_resultAttachmentImage->get(),
499                                 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resources.m_resultBuffer->get(), 1u,
500                                 &region);
501     }
502 }
503 
initialAttachmentTransition(const vk::DeviceInterface & vk,vk::VkCommandBuffer commandBuffer)504 void AhbExternalFormatResolveTestInstance::initialAttachmentTransition(const vk::DeviceInterface &vk,
505                                                                        vk::VkCommandBuffer commandBuffer)
506 {
507     const vk::VkImage resultImage = m_isInputAttachment ? m_resources.m_resultAttachmentImage->get() : VK_NULL_HANDLE;
508     const vk::VkImageSubresourceRange subresourceRange = vk::makeImageSubresourceRange(
509         vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS);
510     const vk::VkImageMemoryBarrier imageBarriers[] = {
511         {
512             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType            sType
513             nullptr,                                      // const void*                pNext
514             vk::VK_ACCESS_MEMORY_READ_BIT,                // VkAccessFlags            srcAccessMask
515             vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // VkAccessFlags            dstAccessMask
516             vk::VK_IMAGE_LAYOUT_UNDEFINED,                // VkImageLayout            oldLayout
517             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout            newLayout
518             VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                    srcQueueFamilyIndex
519             VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                    destQueueFamilyIndex
520             m_resources.m_androidExternalImage.get(),     // VkImage                    image
521             subresourceRange                              // VkImageSubresourceRange    subresourceRange
522         },
523         {
524             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType            sType
525             nullptr,                                      // const void*                pNext
526             vk::VK_ACCESS_MEMORY_READ_BIT,                // VkAccessFlags            srcAccessMask
527             vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // VkAccessFlags            dstAccessMask
528             vk::VK_IMAGE_LAYOUT_UNDEFINED,                // VkImageLayout            oldLayout
529             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout            newLayout
530             VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                    srcQueueFamilyIndex
531             VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                    destQueueFamilyIndex
532             m_nullColorAttachment ? resultImage           // VkImage                    image
533                                     :
534                                     m_resources.m_androidColorAttachmentImage->get(),
535             subresourceRange // VkImageSubresourceRange    subresourceRange
536         },
537         {
538             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType            sType
539             nullptr,                                      // const void*                pNext
540             vk::VK_ACCESS_MEMORY_READ_BIT,                // VkAccessFlags            srcAccessMask
541             vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // VkAccessFlags            dstAccessMask
542             vk::VK_IMAGE_LAYOUT_UNDEFINED,                // VkImageLayout            oldLayout
543             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout            newLayout
544             VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                    srcQueueFamilyIndex
545             VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                    destQueueFamilyIndex
546             resultImage,                                  // VkImage                    image
547             subresourceRange                              // VkImageSubresourceRange    subresourceRange
548         },
549     };
550     uint32_t barrierCount = m_nullColorAttachment ? 1u : 2u;
551     barrierCount += m_isInputAttachment ? 1u : 0u;
552 
553     vk.cmdPipelineBarrier(commandBuffer, vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
554                           vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, barrierCount,
555                           imageBarriers);
556 }
557 
transitionInputAttachmentToOutput(const vk::DeviceInterface & vk,vk::VkCommandBuffer commandBuffer)558 void AhbExternalFormatResolveTestInstance::transitionInputAttachmentToOutput(const vk::DeviceInterface &vk,
559                                                                              vk::VkCommandBuffer commandBuffer)
560 {
561     const vk::VkImageSubresourceRange subresourceRange = vk::makeImageSubresourceRange(
562         vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS);
563     const vk::VkImageMemoryBarrier imageBarrier = {
564         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType            sType
565         nullptr,                                      // const void*                pNext
566         vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // VkAccessFlags            srcAccessMask
567         vk::VK_ACCESS_MEMORY_WRITE_BIT,               // VkAccessFlags            dstAccessMask
568         vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,     // VkImageLayout            oldLayout
569         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout            newLayout
570         VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                    srcQueueFamilyIndex
571         VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                    destQueueFamilyIndex
572         m_resources.m_resultAttachmentImage->get(),   // VkImage                    image
573         subresourceRange                              // VkImageSubresourceRange    subresourceRange
574     };
575     vk.cmdPipelineBarrier(commandBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
576                           vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
577 }
578 
checkExternalFormatTestingRequired(const AndroidHardwareBufferInstance & androidBuffer)579 bool AhbExternalFormatResolveTestInstance::checkExternalFormatTestingRequired(
580     const AndroidHardwareBufferInstance &androidBuffer)
581 {
582     const vk::DeviceInterface &vk = m_context.getDeviceInterface();
583     const vk::VkDevice device     = m_context.getDevice();
584 
585     vk::VkAndroidHardwareBufferFormatResolvePropertiesANDROID formatResolveProperties = {
586         vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID, // VkStructureType    sType
587         nullptr,                                                                         // void*            pNext
588         vk::VK_FORMAT_UNDEFINED // VkFormat            colorAttachmentFormat
589     };
590 
591     vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties = {
592         vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID, // VkStructureType                    sType
593         &formatResolveProperties, // void*                            pNext
594         vk::VK_FORMAT_UNDEFINED,  // VkFormat                            format
595         0u,                       // uint64_t                            externalFormat
596         0u,                       // VkFormatFeatureFlags                formatFeatures
597         vk::VkComponentMapping(), // VkComponentMapping                samplerYcbcrConversionComponents
598         vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, // VkSamplerYcbcrModelConversion    suggestedYcbcrModel
599         vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,                // VkSamplerYcbcrRange                suggestedYcbcrRange
600         vk::VK_CHROMA_LOCATION_COSITED_EVEN, // VkChromaLocation                    suggestedXChromaOffset
601         vk::VK_CHROMA_LOCATION_COSITED_EVEN  // VkChromaLocation                    suggestedYChromaOffset
602     };
603 
604     vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {
605         vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, // VkStructureType    sType
606         &formatProperties,                                                // void*            pNext
607         0u,                                                               // VkDeviceSize        allocationSize
608         0u                                                                // uint32_t            memoryTypeBits
609     };
610 
611     VK_CHECK(vk.getAndroidHardwareBufferPropertiesANDROID(device, androidBuffer.getHandle(), &bufferProperties));
612 
613     if (formatProperties.format != vk::VK_FORMAT_UNDEFINED)
614     {
615         vk::VkFormatProperties3 colorAttachmentFormatProperties =
616             m_context.getFormatProperties(formatProperties.format);
617         vk::VkFormatFeatureFlags requiredFlags =
618             vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
619 
620         if ((colorAttachmentFormatProperties.optimalTilingFeatures & requiredFlags) ||
621             (colorAttachmentFormatProperties.linearTilingFeatures & requiredFlags))
622             return false;
623     }
624 
625     // Ensure there's draw support
626     if (formatResolveProperties.colorAttachmentFormat == vk::VK_FORMAT_UNDEFINED)
627         TCU_THROW(TestError, "No draw support");
628 
629     {
630         vk::VkFormatProperties3 colorAttachmentFormatProperties =
631             m_context.getFormatProperties(formatResolveProperties.colorAttachmentFormat);
632 
633         // External formats require optimal tiling
634         if ((colorAttachmentFormatProperties.optimalTilingFeatures & vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0u)
635             TCU_THROW(TestError, "No draw support");
636     }
637 
638     m_retrievedInternalFormat = formatProperties.externalFormat;
639 
640     {
641         const vk::InstanceInterface &vki = m_context.getInstanceInterface();
642         vk::VkPhysicalDeviceExternalFormatResolvePropertiesANDROID externalFormatProperties = {
643             vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID, // VkStructureType    sType
644             nullptr,                                                                          // void*            pNext
645             VK_FALSE,                        // VkBool32            nullColorAttachmentWithExternalFormatResolve
646             vk::VK_CHROMA_LOCATION_MIDPOINT, // VkChromaLocation    externalFormatResolveChromaOffsetX
647             vk::VK_CHROMA_LOCATION_MIDPOINT  // VkChromaLocation    externalFormatResolveChromaOffsetY
648         };
649 
650         vk::VkPhysicalDeviceProperties2 physicalDeviceProperties = {
651             vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, // VkStructureType                sType
652             &externalFormatProperties,                          // void*                        pNext
653             vk::VkPhysicalDeviceProperties{}                    // VkPhysicalDeviceProperties    properties
654         };
655 
656         vki.getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &physicalDeviceProperties);
657 
658         m_nullColorAttachment   = externalFormatProperties.nullColorAttachmentWithExternalFormatResolve;
659         m_colorAttachmentFormat = formatResolveProperties.colorAttachmentFormat;
660         m_xChromaLocation       = externalFormatProperties.externalFormatResolveChromaOffsetX;
661         m_yChromaLocation       = externalFormatProperties.externalFormatResolveChromaOffsetY;
662     }
663 
664     if (m_isInputAttachment && (m_nullColorAttachment == VK_FALSE) &&
665         (formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0u)
666         TCU_THROW(NotSupportedError, "Format lacks input attachment usage: nullColorAttachment is VK_FALSE and format "
667                                      "does not support VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT");
668 
669     // Need to fetch correct max clear value since it'll depend on each format
670     const tcu::Vec4 formatMaxValue = tcu::getTextureFormatInfo(mapVkFormat(m_colorAttachmentFormat)).valueMax;
671     m_clearColor[0]                = formatMaxValue[0];
672     m_clearColor[3]                = formatMaxValue[3];
673 
674     return true;
675 }
676 
buildReferenceImage(tcu::TextureLevel & texture,bool performDownsample,bool ahbFormatVulkanFormatAlphaMismatch) const677 void AhbExternalFormatResolveTestInstance::buildReferenceImage(tcu::TextureLevel &texture, bool performDownsample,
678                                                                bool ahbFormatVulkanFormatAlphaMismatch) const
679 {
680     tcu::PixelBufferAccess access  = texture.getAccess();
681     const tcu::Vec4 formatMaxValue = tcu::getTextureFormatInfo(texture.getFormat()).valueMax;
682     tcu::Vec4 colors[4]            = {
683         // Modify alpha value to match output if original AHB format does not contain alpha
684         tcu::Vec4(0.0f, 0.0f, 0.0f, (ahbFormatVulkanFormatAlphaMismatch ? formatMaxValue.w() : 0.0f)), // black
685         tcu::Vec4(formatMaxValue.x(), 0.0f, 0.0f, formatMaxValue.w()),                                 // red
686         tcu::Vec4(0.0f, formatMaxValue.y(), 0.0f, formatMaxValue.w()), // green
687         tcu::Vec4(0.0f, 0.0f, formatMaxValue.z(), formatMaxValue.w()), // blue
688     };
689 
690     tcu::IVec2 renderAreaStart(m_renderArea.offset.x, m_renderArea.offset.y);
691     tcu::IVec2 renderAreaEnd(renderAreaStart.x() + m_renderArea.extent.width,
692                              renderAreaStart.y() + m_renderArea.extent.height);
693 
694     uint32_t colorIndex = 0u;
695     for (uint32_t y = 0u; y < m_height; ++y, colorIndex ^= 2u)
696     {
697         for (uint32_t x = 0u; x < m_width; ++x, colorIndex ^= 1u)
698         {
699             if (m_isClearOnly)
700                 access.setPixel(m_clearColor, x, y);
701             else
702             {
703                 bool isInsideRenderArea =
704                     ((renderAreaStart.x() <= static_cast<int32_t>(x)) &&
705                      (static_cast<int32_t>(x) < renderAreaEnd.x())) &&
706                     ((renderAreaStart.y() <= static_cast<int32_t>(y)) && (static_cast<int32_t>(y) < renderAreaEnd.y()));
707 
708                 if (isInsideRenderArea)
709                     access.setPixel(colors[colorIndex], x, y);
710                 else
711                     access.setPixel(m_clearColor, x, y);
712             }
713         }
714     }
715 
716     if (performDownsample)
717     {
718         // Reduce reference image according to chroma locations
719         AndroidHardwareBufferInstance::ChromaLocation xLocation =
720             AndroidHardwareBufferInstance::vkChromaLocationToChromaLocation(m_xChromaLocation);
721         AndroidHardwareBufferInstance::ChromaLocation yLocation =
722             AndroidHardwareBufferInstance::vkChromaLocationToChromaLocation(m_yChromaLocation);
723         AndroidHardwareBufferInstance::reduceYuvTexture(texture, m_format, xLocation, yLocation);
724     }
725 }
726 
createImageView(VkImage image,vk::VkFormat format)727 Move<VkImageView> AhbExternalFormatResolveTestInstance::createImageView(VkImage image, vk::VkFormat format)
728 {
729     const vk::DeviceInterface &vk              = m_context.getDeviceInterface();
730     const vk::VkDevice device                  = m_context.getDevice();
731     const vk::VkImageViewCreateInfo createInfo = {
732         vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,                // VkStructureType            sType
733         nullptr,                                                     // const void*                pNext
734         0u,                                                          // VkImageViewCreateFlags    flags
735         image,                                                       // VkImage                    image
736         vk::VK_IMAGE_VIEW_TYPE_2D,                                   // VkImageViewType            viewType
737         format,                                                      // VkFormat                    format
738         makeComponentMappingIdentity(),                              // VkComponentMapping        components
739         vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageSubresourceRange    subresourceRange
740                                       0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS)};
741 
742     return vk::createImageView(vk, device, &createInfo);
743 }
744 
createImagesAndViews(AndroidHardwareBufferInstance & androidBuffer)745 void AhbExternalFormatResolveTestInstance::createImagesAndViews(AndroidHardwareBufferInstance &androidBuffer)
746 {
747     const vk::DeviceInterface &vk   = m_context.getDeviceInterface();
748     const vk::VkDevice device       = m_context.getDevice();
749     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
750 
751     // Import android hardware buffer to Vulkan
752     {
753         // Create VkImage
754         {
755             vk::VkExternalFormatANDROID externalFormat = {
756                 vk::VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID, // VkStructureType    sType
757                 nullptr,                                       // void*            pNext
758                 m_retrievedInternalFormat                      // uint64_t            externalFormat
759             };
760 
761             const vk::VkExternalMemoryImageCreateInfo externalCreateInfo = {
762                 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, // VkStructureType    sType
763                 &externalFormat,                                         // const void*    pNext
764                 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID // VkExternalMemoryHandleTypeFlags    handleTypes
765             };
766 
767             vk::VkImageUsageFlags usage =
768                 (m_nullColorAttachment && m_isInputAttachment) ?
769                     (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) :
770                     vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
771             const vk::VkImageCreateInfo createInfo = {
772                 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
773                 &externalCreateInfo,                     // const void*                pNext
774                 0u,                                      // VkImageCreateFlags        flags
775                 vk::VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
776                 vk::VK_FORMAT_UNDEFINED,                 // VkFormat                    format
777                 {
778                     m_width,
779                     m_height,
780                     1u,
781                 },                             // VkExtent3D                extent
782                 1u,                            // uint32_t                    mipLevels
783                 m_layers,                      // uint32_t                    arrayLayers
784                 vk::VK_SAMPLE_COUNT_1_BIT,     // VkSampleCountFlagBits    samples
785                 vk::VK_IMAGE_TILING_OPTIMAL,   // VkImageTiling            tiling
786                 usage,                         // VkImageUsageFlags        usage
787                 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharingMode
788                 1,                             // uint32_t                    queueFamilyIndexCount
789                 &queueFamilyIndex,             // const uint32_t*            pQueueFamilyIndices
790                 vk::VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout            initialLayout
791             };
792 
793             m_resources.m_androidExternalImage = vk::createImage(vk, device, &createInfo);
794         }
795 
796         // Allocate VkDeviceMemory
797         {
798             vk::VkAndroidHardwareBufferPropertiesANDROID ahbProperties = {
799                 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, // VkStructureType    sType
800                 DE_NULL,                                                          // void*            pNext
801                 0u,                                                               // VkDeviceSize        allocationSize
802                 0u                                                                // uint32_t            memoryTypeBits
803             };
804 
805             vk.getAndroidHardwareBufferPropertiesANDROID(device, androidBuffer.getHandle(), &ahbProperties);
806 
807             const vk::VkImportAndroidHardwareBufferInfoANDROID importInfo = {
808                 vk::VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, // VkStructureType            sType
809                 DE_NULL,                                                           // const void*                pNext
810                 androidBuffer.getHandle()                                          // struct AHardwareBuffer*    buffer
811             };
812 
813             const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo = {
814                 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, // VkStructureType    sType
815                 &importInfo,                                              // const void*        pNext
816                 m_resources.m_androidExternalImage.get(),                 // VkImage            image
817                 DE_NULL,                                                  // VkBuffer            buffer
818             };
819 
820             const vk::VkMemoryAllocateInfo allocateInfo = {
821                 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,    // VkStructureType    sType
822                 (const void *)&dedicatedInfo,                  // const void*        pNext
823                 ahbProperties.allocationSize,                  // VkDeviceSize        allocationSize
824                 chooseMemoryType(ahbProperties.memoryTypeBits) // uint32_t            memoryTypeIndex
825             };
826 
827             m_resources.m_androidExternalImageMemory = vk::allocateMemory(vk, device, &allocateInfo);
828         }
829 
830         // Bind
831         VK_CHECK(vk.bindImageMemory(device, m_resources.m_androidExternalImage.get(),
832                                     m_resources.m_androidExternalImageMemory.get(), 0u));
833 
834         // Create view
835         m_resources.m_androidExternalImageView =
836             createImageView(m_resources.m_androidExternalImage.get(), vk::VK_FORMAT_UNDEFINED);
837     }
838 
839     vk::VkImageCreateInfo imageCreateInfo = {
840         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
841         nullptr,                                 // const void*                pNext
842         0u,                                      // VkImageCreateFlags        flags
843         vk::VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
844         m_colorAttachmentFormat,                 // VkFormat                    format
845         {
846             m_width,
847             m_height,
848             1u,
849         },                                       // VkExtent3D                extent
850         1u,                                      // uint32_t                    mipLevels
851         m_layers,                                // uint32_t                    arrayLayers
852         vk::VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits    samples
853         vk::VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling            tiling
854         vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags        usage
855         vk::VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode            sharingMode
856         1,                                       // uint32_t                    queueFamilyIndexCount
857         &queueFamilyIndex,                       // const uint32_t*            pQueueFamilyIndices
858         vk::VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout            initialLayout
859     };
860 
861     if (m_isInputAttachment)
862     {
863         imageCreateInfo.usage |= vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
864         m_resources.m_resultAttachmentImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
865             vk, device, m_context.getDefaultAllocator(), imageCreateInfo, vk::MemoryRequirement::Any));
866         m_resources.m_resultAttachmentImageView =
867             createImageView(m_resources.m_resultAttachmentImage->get(), m_colorAttachmentFormat);
868 
869         VkDeviceSize bufferSize = m_width * m_height * mapVkFormat(m_colorAttachmentFormat).getPixelSize();
870         vk::VkBufferCreateInfo bufferCreateInfo = {
871             vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType        sType
872             nullptr,                                  // const void*            pNext
873             0u,                                       // VkBufferCreateFlags    flags
874             bufferSize,                               // VkDeviceSize            size
875             vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags    usage
876             vk::VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode        sharingMode
877             1u,                                       // uint32_t                queueFamilyIndexCount
878             &queueFamilyIndex                         // const uint32_t*        pQueueFamilyIndices
879         };
880         m_resources.m_resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
881             vk, device, m_context.getDefaultAllocator(), bufferCreateInfo, vk::MemoryRequirement::HostVisible));
882     }
883 
884     if (m_nullColorAttachment == VK_FALSE)
885     {
886         imageCreateInfo.usage |=
887             m_isInputAttachment ? (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) :
888                                   vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
889         m_resources.m_androidColorAttachmentImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
890             vk, device, m_context.getDefaultAllocator(), imageCreateInfo, vk::MemoryRequirement::Any));
891         m_resources.m_androidColorAttachmentImageView =
892             createImageView(m_resources.m_androidColorAttachmentImage->get(), m_colorAttachmentFormat);
893     }
894 }
895 
createRenderPass(void)896 void AhbExternalFormatResolveTestInstance::createRenderPass(void)
897 {
898     if (m_groupParams.useDynamicRendering)
899         return;
900 
901     const vk::DeviceInterface &vk = m_context.getDeviceInterface();
902     const vk::VkDevice device     = m_context.getDevice();
903 
904     vk::VkExternalFormatANDROID externalFormat = {
905         vk::VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID, // VkStructureType    sType
906         nullptr,                                       // void*            pNext
907         m_retrievedInternalFormat                      // uint64_t            externalFormat
908     };
909 
910     vk::VkAttachmentDescription2 attachments[] = {
911         // Resolve attachment
912         {
913             vk::VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                    sType
914             &externalFormat,                                // const void*                        pNext
915             0u,                                             // VkAttachmentDescriptionFlags        flags
916             vk::VK_FORMAT_UNDEFINED,                        // VkFormat                            format
917             vk::VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits            samples
918             vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                // VkAttachmentLoadOp                loadOp
919             vk::VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp                storeOp
920             vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp                stencilLoadOp
921             vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp                stencilStoreOp
922             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout                    initialLayout
923             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL    // VkImageLayout                    finalLayout
924         },
925         // Color attachment
926         {
927             vk::VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                    sType
928             nullptr,                                        // const void*                        pNext
929             0u,                                             // VkAttachmentDescriptionFlags        flags
930             m_colorAttachmentFormat,                        // VkFormat                            format
931             vk::VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits            samples
932             vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                // VkAttachmentLoadOp                loadOp
933             vk::VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp                storeOp
934             vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp                stencilLoadOp
935             vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp                stencilStoreOp
936             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout                    initialLayout
937             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL    // VkImageLayout                    finalLayout
938         },
939         // Final attachment, only present when input attachment testing and nullColorAttachment is false
940         {
941             vk::VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType                    sType
942             nullptr,                                        // const void*                        pNext
943             0u,                                             // VkAttachmentDescriptionFlags        flags
944             m_colorAttachmentFormat,                        // VkFormat                            format
945             vk::VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits            samples
946             vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                // VkAttachmentLoadOp                loadOp
947             vk::VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp                storeOp
948             vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp                stencilLoadOp
949             vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp                stencilStoreOp
950             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout                    initialLayout
951             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL    // VkImageLayout                    finalLayout
952         }};
953 
954     const vk::VkAttachmentReference2 resolveAttachmentReference = {
955         vk::VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType        sType
956         nullptr,                                      // const void*            pNext
957         0u,                                           // uint32_t                attachment
958         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout        layout
959         vk::VK_IMAGE_ASPECT_COLOR_BIT                 // VkImageAspectFlags    aspectMask
960     };
961 
962     const vk::VkAttachmentReference2 colorAttachmentReference = {
963         vk::VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,      // VkStructureType        sType
964         nullptr,                                           // const void*            pNext
965         m_nullColorAttachment ? VK_ATTACHMENT_UNUSED : 1u, // uint32_t                attachment
966         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,      // VkImageLayout        layout
967         vk::VK_IMAGE_ASPECT_COLOR_BIT                      // VkImageAspectFlags    aspectMask
968     };
969 
970     const vk::VkAttachmentReference2 finalAttachmentReference = {
971         vk::VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType        sType
972         nullptr,                                      // const void*            pNext
973         m_nullColorAttachment ? 1u : 2u,              // uint32_t                attachment
974         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout        layout
975         vk::VK_IMAGE_ASPECT_COLOR_BIT                 // VkImageAspectFlags    aspectMask
976     };
977 
978     const vk::VkAttachmentReference2 inputAttachmentReference = {
979         vk::VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType        sType
980         nullptr,                                      // const void*            pNext
981         m_nullColorAttachment ? 0u : 1u,              // uint32_t                attachment
982         vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout        layout
983         vk::VK_IMAGE_ASPECT_COLOR_BIT                 // VkImageAspectFlags    aspectMask
984     };
985 
986     const vk::VkSubpassDescription2 subpassDescriptions[] = {
987         // Subpass 0
988         {
989             vk::VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, // VkStructureType                    sType
990             nullptr,                                     // const void*                        pNext
991             0u,                                          // VkSubpassDescriptionFlags        flags
992             vk::VK_PIPELINE_BIND_POINT_GRAPHICS,         // VkPipelineBindPoint                pipelineBindPoint
993             0u,                                          // uint32_t                            viewMask
994             0u,                                          // uint32_t                            inputAttachmentCount
995             nullptr,                                     // const VkAttachmentReference2*    pInputAttachments
996             1u,                                          // uint32_t                            colorAttachmentCount
997             &colorAttachmentReference,                   // const VkAttachmentReference2*    pColorAttachments
998             &resolveAttachmentReference,                 // const VkAttachmentReference2*    pResolveAttachments
999             nullptr,                                     // const VkAttachmentReference2*    pDepthStencilAttachment
1000             0u,                                          // uint32_t                            preserveAttachmentCount
1001             nullptr                                      // const uint32_t*                    pPreserveAttachments
1002         },
1003         // Subpass 1
1004         {
1005             vk::VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, // VkStructureType                    sType
1006             nullptr,                                     // const void*                        pNext
1007             0u,                                          // VkSubpassDescriptionFlags        flags
1008             vk::VK_PIPELINE_BIND_POINT_GRAPHICS,         // VkPipelineBindPoint                pipelineBindPoint
1009             0u,                                          // uint32_t                            viewMask
1010             m_isInputAttachment ? 1u : 0u,               // uint32_t                            inputAttachmentCount
1011             m_isInputAttachment ? &inputAttachmentReference :
1012                                   nullptr, // const VkAttachmentReference2*    pInputAttachments
1013             1u,                            // uint32_t                            colorAttachmentCount
1014             &finalAttachmentReference,     // const VkAttachmentReference2*    pColorAttachments
1015             nullptr,                       // const VkAttachmentReference2*    pResolveAttachments
1016             nullptr,                       // const VkAttachmentReference2*    pDepthStencilAttachment
1017             0u,                            // uint32_t                            preserveAttachmentCount
1018             nullptr                        // const uint32_t*                    pPreserveAttachments
1019         }};
1020 
1021     vk::VkSubpassDependency2 subpassDependencies[] = {
1022         {
1023             vk::VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,        // VkStructureType        sType
1024             nullptr,                                           // const void*            pNext
1025             VK_SUBPASS_EXTERNAL,                               // uint32_t                srcSubpass
1026             0u,                                                // uint32_t                dstSubpass
1027             vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,          // VkPipelineStageFlags    srcStageMask
1028             vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags    dstStageMask
1029             vk::VK_ACCESS_MEMORY_READ_BIT,                     // VkAccessFlags        srcAccessMask
1030             vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,          // VkAccessFlags        dstAccessMask
1031             vk::VK_DEPENDENCY_BY_REGION_BIT,                   // VkDependencyFlags    dependencyFlags
1032             0                                                  // int32_t                viewOffset
1033         },
1034         {
1035             vk::VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,        // VkStructureType        sType
1036             nullptr,                                           // const void*            pNext
1037             0u,                                                // uint32_t                srcSubpass
1038             1u,                                                // uint32_t                dstSubpass
1039             vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags    srcStageMask
1040             vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,         // VkPipelineStageFlags    dstStageMask
1041             vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,          // VkAccessFlags        srcAccessMask
1042             vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,           // VkAccessFlags        dstAccessMask
1043             vk::VK_DEPENDENCY_BY_REGION_BIT,                   // VkDependencyFlags    dependencyFlags
1044             0                                                  // int32_t                viewOffset
1045         }};
1046 
1047     uint32_t attachmentCount = 1u;
1048     attachmentCount += m_nullColorAttachment ? 0u : 1u;
1049 
1050     if (m_isInputAttachment)
1051     {
1052         attachments[attachmentCount].finalLayout = vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1053         attachmentCount += 1u;
1054     }
1055     const vk::VkRenderPassCreateInfo2 renderPassCreateInfo = {
1056         vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, // VkStructureType                    sType
1057         nullptr,                                         // const void*                        pNext
1058         0u,                                              // VkRenderPassCreateFlags            flags
1059         attachmentCount,                                 // uint32_t                            attachmentCount
1060         attachments,                                     // const VkAttachmentDescription2*    pAttachments
1061         m_isInputAttachment ? 2u : 1u,                   // uint32_t                            subpassCount
1062         subpassDescriptions,                             // const VkSubpassDescription2*        pSubpasses
1063         m_isInputAttachment ? 2u : 1u,                   // uint32_t                            dependencyCount
1064         subpassDependencies,                             // const VkSubpassDependency2*        pDependencies
1065         0u,                                              // uint32_t                            correlatedViewMaskCount
1066         nullptr                                          // const uint32_t*                    pCorrelatedViewMasks
1067     };
1068 
1069     // Render pass in charge of clearing
1070     m_resources.m_renderPassClear = vk::createRenderPass2(vk, device, &renderPassCreateInfo);
1071 
1072     // Draw render pass with load operation
1073     attachments[0].loadOp    = vk::VK_ATTACHMENT_LOAD_OP_LOAD;
1074     attachments[1].loadOp    = vk::VK_ATTACHMENT_LOAD_OP_LOAD;
1075     attachments[2].loadOp    = vk::VK_ATTACHMENT_LOAD_OP_LOAD;
1076     m_resources.m_renderPass = vk::createRenderPass2(vk, device, &renderPassCreateInfo);
1077 }
1078 
createFramebuffer(void)1079 void AhbExternalFormatResolveTestInstance::createFramebuffer(void)
1080 {
1081     if (m_groupParams.useDynamicRendering)
1082         return;
1083 
1084     const vk::DeviceInterface &vk = m_context.getDeviceInterface();
1085     const vk::VkDevice device     = m_context.getDevice();
1086 
1087     std::vector<VkImageView> imageViews;
1088     imageViews.emplace_back(m_resources.m_androidExternalImageView.get());
1089     if (m_nullColorAttachment == VK_FALSE)
1090         imageViews.emplace_back(m_resources.m_androidColorAttachmentImageView.get());
1091     if (m_isInputAttachment)
1092         imageViews.emplace_back(m_resources.m_resultAttachmentImageView.get());
1093 
1094     vk::VkFramebufferCreateInfo createInfo = {
1095         vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType            sType
1096         nullptr,                                       // const void*                pNext
1097         0u,                                            // VkFramebufferCreateFlags    flags
1098         m_resources.m_renderPassClear.get(),           // VkRenderPass                renderPass
1099         static_cast<uint32_t>(imageViews.size()),      // uint32_t                    attachmentCount
1100         imageViews.data(),                             // const VkImageView*        pAttachments
1101         m_width,                                       // uint32_t                    width
1102         m_height,                                      // uint32_t                    height
1103         m_layers                                       // uint32_t                    layers
1104     };
1105 
1106     m_resources.m_framebufferClear = vk::createFramebuffer(vk, device, &createInfo);
1107 
1108     createInfo.renderPass     = m_resources.m_renderPass.get();
1109     m_resources.m_framebuffer = vk::createFramebuffer(vk, device, &createInfo);
1110 }
1111 
createDescriptors(void)1112 void AhbExternalFormatResolveTestInstance::createDescriptors(void)
1113 {
1114     // Only needed when input attachment testing is happening
1115     if (!m_isInputAttachment)
1116         return;
1117 
1118     const vk::DeviceInterface &vk = m_context.getDeviceInterface();
1119     const vk::VkDevice device     = m_context.getDevice();
1120 
1121     const vk::VkDescriptorPoolSize poolSize = {
1122         vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType    type
1123         1u                                       // uint32_t            descriptorCount
1124     };
1125 
1126     // VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT added so we can destroy descriptors with Move<>
1127     const vk::VkDescriptorPoolCreateInfo poolCreateInfo = {
1128         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType                sType
1129         nullptr,                                           // const void*                    pNext
1130         VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags    flags
1131         1u,                                                // uint32_t                        maxSets
1132         1u,                                                // uint32_t                        poolSizeCount
1133         &poolSize                                          // const VkDescriptorPoolSize*    pPoolSizes
1134     };
1135 
1136     m_resources.m_descriptorPool = vk::createDescriptorPool(vk, device, &poolCreateInfo);
1137 
1138     const vk::VkDescriptorSetLayoutBinding binding = {
1139         0u,                                      // uint32_t                binding
1140         vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType        descriptorType
1141         1u,                                      // uint32_t                descriptorCount
1142         vk::VK_SHADER_STAGE_FRAGMENT_BIT,        // VkShaderStageFlags    stageFlags
1143         nullptr,                                 // const VkSampler*        pImmutableSamplers
1144     };
1145 
1146     const vk::VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo = {
1147         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType                        sType
1148         nullptr,                                                 // const void*                            pNext
1149         0u,                                                      // VkDescriptorSetLayoutCreateFlags        flags
1150         1u,                                                      // uint32_t                                bindingCount
1151         &binding                                                 // const VkDescriptorSetLayoutBinding*    pBindings
1152     };
1153 
1154     m_resources.m_descriptorSetLayout = vk::createDescriptorSetLayout(vk, device, &setLayoutCreateInfo);
1155 
1156     const vk::VkDescriptorSetAllocateInfo allocateInfo = {
1157         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType                sType
1158         nullptr,                                            // const void*                    pNext
1159         m_resources.m_descriptorPool.get(),                 // VkDescriptorPool                descriptorPool
1160         1u,                                                 // uint32_t                        descriptorSetCount
1161         &m_resources.m_descriptorSetLayout.get()            // const VkDescriptorSetLayout*    pSetLayouts
1162     };
1163 
1164     m_resources.m_descriptorSet = vk::allocateDescriptorSet(vk, device, &allocateInfo);
1165 
1166     const vk::VkDescriptorImageInfo imageInfo = {
1167         VK_NULL_HANDLE,                                                      // VkSampler        sampler
1168         m_nullColorAttachment ? m_resources.m_androidExternalImageView.get() // VkImageView        imageView
1169                                 :
1170                                 m_resources.m_androidColorAttachmentImageView.get(),
1171         vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout    imageLayout
1172     };
1173 
1174     const vk::VkWriteDescriptorSet descriptorWrite = {
1175         vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType                    sType
1176         nullptr,                                    // const void*                        pNext
1177         m_resources.m_descriptorSet.get(),          // VkDescriptorSet                    dstSet
1178         0u,                                         // uint32_t                            dstBinding
1179         0u,                                         // uint32_t                            dstArrayElement
1180         1u,                                         // uint32_t                            descriptorCount
1181         vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,    // VkDescriptorType                    descriptorType
1182         &imageInfo,                                 // const VkDescriptorImageInfo*        pImageInfo
1183         nullptr,                                    // const VkDescriptorBufferInfo*    pBufferInfo
1184         nullptr                                     // const VkBufferView*                pTexelBufferView
1185     };
1186 
1187     vk.updateDescriptorSets(device, 1u, &descriptorWrite, 0u, nullptr);
1188 }
1189 
createPipelineLayouts(void)1190 void AhbExternalFormatResolveTestInstance::createPipelineLayouts(void)
1191 {
1192     const vk::DeviceInterface &vk = m_context.getDeviceInterface();
1193     const vk::VkDevice device     = m_context.getDevice();
1194 
1195     vk::VkPipelineLayoutCreateInfo createInfo = {
1196         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType                sType
1197         nullptr,                                           // const void*                    pNext
1198         0u,                                                // VkPipelineLayoutCreateFlags    flags
1199         0u,                                                // uint32_t                        setLayoutCount
1200         nullptr,                                           // const VkDescriptorSetLayout*    pSetLayouts
1201         0u,                                                // uint32_t                        pushConstantRangeCount
1202         nullptr                                            // const VkPushConstantRange*    pPushConstantRanges
1203     };
1204 
1205     m_resources.m_basePipelineLayout = vk::createPipelineLayout(vk, device, &createInfo);
1206 
1207     if (m_isInputAttachment)
1208     {
1209         createInfo.setLayoutCount                   = 1u;
1210         createInfo.pSetLayouts                      = &m_resources.m_descriptorSetLayout.get();
1211         m_resources.m_inputAttachmentPipelineLayout = vk::createPipelineLayout(vk, device, &createInfo);
1212     }
1213 }
1214 
createPipelines(void)1215 void AhbExternalFormatResolveTestInstance::createPipelines(void)
1216 {
1217     const vk::DeviceInterface &vk = m_context.getDeviceInterface();
1218     const vk::VkDevice device     = m_context.getDevice();
1219 
1220     vk::VkPipelineShaderStageCreateInfo stages[] = {
1221         // vertex
1222         {
1223             vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType                    sType
1224             nullptr,                                                 // const void*                        pNext
1225             0u,                                                      // VkPipelineShaderStageCreateFlags    flags
1226             vk::VK_SHADER_STAGE_VERTEX_BIT,                          // VkShaderStageFlagBits            stage
1227             m_resources.m_vertexShader.get(),                        // VkShaderModule                    module
1228             "main",                                                  // const char*                        pName
1229             nullptr, // const VkSpecializationInfo*        pSpecializationInfo
1230         },
1231         // fragment
1232         {
1233             vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType                    sType
1234             nullptr,                                                 // const void*                        pNext
1235             0u,                                                      // VkPipelineShaderStageCreateFlags    flags
1236             vk::VK_SHADER_STAGE_FRAGMENT_BIT,                        // VkShaderStageFlagBits            stage
1237             m_resources.m_fragmentShaderBase.get(),                  // VkShaderModule                    module
1238             "main",                                                  // const char*                        pName
1239             nullptr, // const VkSpecializationInfo*        pSpecializationInfo
1240         }};
1241 
1242     const vk::VkVertexInputBindingDescription vertexInputBindDesc = {
1243         0u,                         //    uint32_t            binding
1244         sizeof(float) * 2,          //    uint32_t            stride
1245         VK_VERTEX_INPUT_RATE_VERTEX //    VkVertexInputRate    inputRate
1246     };
1247 
1248     const vk::VkVertexInputAttributeDescription vertexInputAttrDesc = {
1249         0u,                          // uint32_t    location
1250         0u,                          // uint32_t    binding
1251         vk::VK_FORMAT_R32G32_SFLOAT, // VkFormat    format
1252         0u                           // uint32_t    offset
1253     };
1254 
1255     const vk::VkPipelineVertexInputStateCreateInfo vertexInputState = {
1256         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                            sType
1257         nullptr,              // const void*                                pNext
1258         0u,                   // VkPipelineVertexInputStateCreateFlags    flags
1259         1u,                   // uint32_t                                    vertexBindingDescriptionCount
1260         &vertexInputBindDesc, // const VkVertexInputBindingDescription*    pVertexBindingDescriptions
1261         1u,                   // uint32_t                                    vertexAttributeDescriptionCount
1262         &vertexInputAttrDesc  // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
1263     };
1264 
1265     const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = {
1266         vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType                            sType
1267         nullptr,                                  // const void*                                pNext
1268         0u,                                       // VkPipelineInputAssemblyStateCreateFlags    flags
1269         vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology                        topology
1270         VK_FALSE                                  // VkBool32                                    primitiveRestartEnable
1271     };
1272 
1273     const vk::VkViewport viewport = makeViewport(m_width, m_height);
1274 
1275     const vk::VkPipelineViewportStateCreateInfo viewportState = {
1276         vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType                        sType
1277         nullptr,                                                   // const void*                            pNext
1278         0u,                                                        // VkPipelineViewportStateCreateFlags    flags
1279         1u,           // uint32_t                                viewportCount
1280         &viewport,    // const VkViewport*                    pViewports
1281         1u,           // uint32_t                                scissorCount
1282         &m_renderArea // const VkRect2D*                        pScissors
1283     };
1284 
1285     const vk::VkPipelineRasterizationStateCreateInfo rasterState = {
1286         vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                            sType
1287         nullptr,                             // const void*                                pNext
1288         0u,                                  // VkPipelineRasterizationStateCreateFlags    flags
1289         VK_FALSE,                            // VkBool32                                    depthClampEnable
1290         VK_FALSE,                            // VkBool32                                    rasterizerDiscardEnable
1291         vk::VK_POLYGON_MODE_FILL,            // VkPolygonMode                            polygonMode
1292         vk::VK_CULL_MODE_NONE,               // VkCullModeFlags                            cullMode
1293         vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace                                frontFace
1294         VK_FALSE,                            // VkBool32                                    depthBiasEnable
1295         0.0f,                                // float                                    depthBiasConstantFactor
1296         0.0f,                                // float                                    depthBiasClamp
1297         0.0f,                                // float                                    depthBiasSlopeFactor
1298         1.0f                                 // float                                    lineWidth
1299     };
1300 
1301     const vk::VkPipelineMultisampleStateCreateInfo msState = {
1302         vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType                            sType
1303         nullptr,                   // const void*                                pNext
1304         0u,                        // VkPipelineMultisampleStateCreateFlags    flags
1305         vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits                    rasterizationSamples
1306         VK_FALSE,                  // VkBool32                                    sampleShadingEnable
1307         0.0f,                      // float                                    minSampleShading
1308         nullptr,                   // const VkSampleMask*                        pSampleMask
1309         VK_FALSE,                  // VkBool32                                    alphaToCoverageEnable
1310         VK_FALSE                   // VkBool32                                    alphaToOneEnable
1311     };
1312 
1313     const vk::VkColorComponentFlags colorFlags = vk::VK_COLOR_COMPONENT_R_BIT | vk::VK_COLOR_COMPONENT_G_BIT |
1314                                                  vk::VK_COLOR_COMPONENT_B_BIT | vk::VK_COLOR_COMPONENT_A_BIT;
1315     const vk::VkPipelineColorBlendAttachmentState attBlend = {
1316         VK_FALSE,                // VkBool32                    blendEnable
1317         vk::VK_BLEND_FACTOR_ONE, // VkBlendFactor            srcColorBlendFactor
1318         vk::VK_BLEND_FACTOR_ONE, // VkBlendFactor            dstColorBlendFactor
1319         vk::VK_BLEND_OP_ADD,     // VkBlendOp                colorBlendOp
1320         vk::VK_BLEND_FACTOR_ONE, // VkBlendFactor            srcAlphaBlendFactor
1321         vk::VK_BLEND_FACTOR_ONE, // VkBlendFactor            dstAlphaBlendFactor
1322         vk::VK_BLEND_OP_ADD,     // VkBlendOp                alphaBlendOp
1323         colorFlags               // VkColorComponentFlags    colorWriteMask
1324     };
1325 
1326     const vk::VkPipelineColorBlendStateCreateInfo blendState = {
1327         vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                                sType
1328         nullptr,                 // const void*                                    pNext
1329         0u,                      // VkPipelineColorBlendStateCreateFlags            flags
1330         VK_FALSE,                // VkBool32                                        logicOpEnable
1331         vk::VK_LOGIC_OP_NO_OP,   // VkLogicOp                                    logicOp
1332         1u,                      // uint32_t                                        attachmentCount
1333         &attBlend,               // const VkPipelineColorBlendAttachmentState*    pAttachments
1334         {0.0f, 0.0f, 0.0f, 0.0f} // float                                        blendConstants[4]
1335     };
1336 
1337     vk::VkExternalFormatANDROID externalFormat = {
1338         vk::VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID, // VkStructureType    sType
1339         nullptr,                                       // void*            pNext
1340         m_retrievedInternalFormat                      // uint64_t            externalFormat
1341     };
1342 
1343     const vk::VkFormat colorAttachmentFormat =
1344         m_nullColorAttachment ? vk::VK_FORMAT_UNDEFINED : m_colorAttachmentFormat;
1345     vk::VkPipelineRenderingCreateInfo pipelineRenderingInfo = {
1346         vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, // VkStructureType    sType
1347         &externalFormat,                                      // const void*        pNext
1348         0u,                                                   // uint32_t            viewMask
1349         1u,                                                   // uint32_t            colorAttachmentCount
1350         &colorAttachmentFormat,                               // const VkFormat*    pColorAttachmentFormats
1351         vk::VK_FORMAT_UNDEFINED,                              // VkFormat            depthAttachmentFormat
1352         vk::VK_FORMAT_UNDEFINED                               // VkFormat            stencilAttachmentFormat
1353     };
1354 
1355     vk::VkGraphicsPipelineCreateInfo createInfo = {
1356         vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType                                    sType
1357         m_groupParams.useDynamicRendering ? &pipelineRenderingInfo :
1358                                             nullptr, // const void*                                        pNext
1359         0u,                                          // VkPipelineCreateFlags                            flags
1360         2u,                                          // uint32_t                                            stageCount
1361         stages,                                      // const VkPipelineShaderStageCreateInfo*            pStages
1362         &vertexInputState,   // const VkPipelineVertexInputStateCreateInfo*        pVertexInputState
1363         &inputAssemblyState, // const VkPipelineInputAssemblyStateCreateInfo*    pInputAssemblyState
1364         nullptr,             // const VkPipelineTessellationStateCreateInfo*        pTessellationState
1365         &viewportState,      // const VkPipelineViewportStateCreateInfo*            pViewportState
1366         &rasterState,        // const VkPipelineRasterizationStateCreateInfo*    pRasterizationState
1367         &msState,            // const VkPipelineMultisampleStateCreateInfo*        pMultisampleState
1368         nullptr,             // const VkPipelineDepthStencilStateCreateInfo*        pDepthStencilState
1369         &blendState,         // const VkPipelineColorBlendStateCreateInfo*        pColorBlendState
1370         nullptr,             // const VkPipelineDynamicStateCreateInfo*            pDynamicState
1371         m_resources.m_basePipelineLayout.get(), // VkPipelineLayout                                    layout
1372         m_resources.m_renderPass.get(),         // VkRenderPass                                        renderPass
1373         0u,                                     // uint32_t                                            subpass
1374         VK_NULL_HANDLE,                         // VkPipeline                                        basePipelineHandle
1375         0                                       // int32_t                                            basePipelineIndex
1376     };
1377 
1378     m_resources.m_basePipeline = vk::createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &createInfo);
1379 
1380     if (m_isInputAttachment)
1381     {
1382         stages[1].module                      = m_resources.m_fragmentShaderInput.get();
1383         createInfo.layout                     = m_resources.m_inputAttachmentPipelineLayout.get();
1384         createInfo.subpass                    = 1u;
1385         m_resources.m_inputAttachmentPipeline = vk::createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &createInfo);
1386     }
1387 }
1388 
beginRender(vk::VkCommandBuffer cmd,const vk::VkRect2D & renderArea,bool clearPass) const1389 void AhbExternalFormatResolveTestInstance::beginRender(vk::VkCommandBuffer cmd, const vk::VkRect2D &renderArea,
1390                                                        bool clearPass) const
1391 {
1392     const vk::DeviceInterface &vk = m_context.getDeviceInterface();
1393 
1394     if (m_groupParams.useDynamicRendering)
1395     {
1396         vk::VkRenderingFlags renderingFlags =
1397             m_groupParams.useSecondaryCmdBuffer &&
1398                     !m_groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass ?
1399                 static_cast<vk::VkRenderingFlags>(vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR) :
1400                 static_cast<vk::VkRenderingFlags>(0u);
1401         vk::VkClearValue clearValue =
1402             makeClearValueColorF32(m_clearColor.x(), m_clearColor.y(), m_clearColor.z(), m_clearColor.w());
1403         vk::VkRenderingAttachmentInfoKHR colorAttachment = {
1404             vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType                        sType
1405             nullptr,                                             // const void*                            pNext
1406             m_nullColorAttachment ?
1407                 VK_NULL_HANDLE :
1408                 m_resources.m_androidColorAttachmentImageView.get(), // VkImageView                            imageView
1409             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,            // VkImageLayout                        imageLayout
1410             VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID,      // VkResolveModeFlagBits                resolveMode
1411             m_resources.m_androidExternalImageView.get(), // VkImageView                            resolveImageView
1412             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout                        resolveImageLayout
1413             vk::VK_ATTACHMENT_LOAD_OP_CLEAR,              // VkAttachmentLoadOp                    loadOp
1414             VK_ATTACHMENT_STORE_OP_STORE,                 // VkAttachmentStoreOp                    storeOp
1415             clearValue                                    // VkClearValue                            clearValue
1416         };
1417 
1418         vk::VkRenderingInfoKHR renderingInfo{
1419             vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, // VkStructureType                        sType
1420             DE_NULL,                                  // const void*                            pNext
1421             renderingFlags,                           // VkRenderingFlagsKHR                    flags
1422             renderArea,                               // VkRect2D                                renderArea
1423             m_layers,                                 // uint32_t                                layerCount
1424             0u,                                       // uint32_t                                viewMask
1425             1u,                                       // uint32_t                                colorAttachmentCount
1426             &colorAttachment,                         // const VkRenderingAttachmentInfoKHR*    pColorAttachments
1427             DE_NULL,                                  // const VkRenderingAttachmentInfoKHR*    pDepthAttachment
1428             DE_NULL,                                  // const VkRenderingAttachmentInfoKHR*    pStencilAttachment
1429         };
1430         vk.cmdBeginRendering(cmd, &renderingInfo);
1431     }
1432     else
1433     {
1434         vk::VkSubpassContents subpassContents = vk::VK_SUBPASS_CONTENTS_INLINE;
1435         vector<vk::VkClearValue> clearColors(
1436             m_nullColorAttachment ? 1u : 2u,
1437             makeClearValueColorF32(m_clearColor.x(), m_clearColor.y(), m_clearColor.z(), m_clearColor.w()));
1438         if (m_isInputAttachment)
1439             clearColors.emplace_back(
1440                 clearColors.front()); // All images have the same maximums, so we can reuse clear colors
1441 
1442         const vk::VkRenderPassBeginInfo renderPassBeginInfo = {
1443             vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType        sType
1444             DE_NULL,                                      // const void*            pNext
1445             clearPass ? m_resources.m_renderPassClear.get() :
1446                         m_resources.m_renderPass.get(), // VkRenderPass            renderPass
1447             clearPass ? m_resources.m_framebufferClear.get() :
1448                         m_resources.m_framebuffer.get(), // VkFramebuffer        framebuffer
1449             renderArea,                                  // VkRect2D                renderArea
1450             (uint32_t)clearColors.size(),                // uint32_t                clearValueCount
1451             clearColors.data(),                          // const VkClearValue*    pClearValues
1452         };
1453 
1454         vk.cmdBeginRenderPass(cmd, &renderPassBeginInfo, subpassContents);
1455     }
1456 }
1457 
endRender(vk::VkCommandBuffer cmd) const1458 void AhbExternalFormatResolveTestInstance::endRender(vk::VkCommandBuffer cmd) const
1459 {
1460     const vk::DeviceInterface &vk = m_context.getDeviceInterface();
1461 
1462     if (m_groupParams.useDynamicRendering)
1463         vk::endRendering(vk, cmd);
1464     else
1465         vk::endRenderPass(vk, cmd);
1466 }
1467 
drawCommands(vk::VkCommandBuffer cmd,bool drawFromInputAttachment) const1468 void AhbExternalFormatResolveTestInstance::drawCommands(vk::VkCommandBuffer cmd, bool drawFromInputAttachment) const
1469 {
1470     const vk::DeviceInterface &vk = m_context.getDeviceInterface();
1471 
1472     if (!m_isClearOnly)
1473     {
1474         const VkDeviceSize vertexBufferOffset = 0;
1475         vk.cmdBindVertexBuffers(cmd, 0, 1, &m_resources.m_vertexBuffer->get(), &vertexBufferOffset);
1476 
1477         if (!drawFromInputAttachment)
1478         {
1479             vk.cmdBindPipeline(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_resources.m_basePipeline.get());
1480             vk.cmdDraw(cmd, 4u, 1u, 0u, 0u);
1481         }
1482 
1483         // Only true in renderpass tests
1484         if (m_isInputAttachment)
1485         {
1486             const vk::VkSubpassBeginInfo subpassBeginInfo = {
1487                 vk::VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO, // VkStructureType        sType
1488                 nullptr,                                  // const void*            pNext
1489                 vk::VK_SUBPASS_CONTENTS_INLINE            // VkSubpassContents    contents
1490             };
1491             const vk::VkSubpassEndInfo subpassEndInfo = {
1492                 vk::VK_STRUCTURE_TYPE_SUBPASS_END_INFO, // VkStructureType    sType
1493                 nullptr                                 // const void*        pNext
1494             };
1495             vk.cmdNextSubpass2(cmd, &subpassBeginInfo, &subpassEndInfo);
1496 
1497             if (drawFromInputAttachment)
1498             {
1499                 vk.cmdBindPipeline(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1500                                    m_resources.m_inputAttachmentPipeline.get());
1501                 vk.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1502                                          m_resources.m_inputAttachmentPipelineLayout.get(), 0u, 1u,
1503                                          &m_resources.m_descriptorSet.get(), 0u, nullptr);
1504                 vk.cmdDraw(cmd, 4u, 1u, 0u, 0u);
1505             }
1506         }
1507     }
1508 }
1509 
1510 class AhbExternalFormatResolveTestCase : public TestCase
1511 {
1512 public:
1513     AhbExternalFormatResolveTestCase(tcu::TestContext &context, const std::string &name, const TestParams &params);
~AhbExternalFormatResolveTestCase(void)1514     virtual ~AhbExternalFormatResolveTestCase(void)
1515     {
1516     }
1517 
1518     void initPrograms(SourceCollections &programCollection) const override;
1519     TestInstance *createInstance(Context &context) const override;
1520     void checkSupport(Context &context) const override;
1521 
1522 private:
1523     const TestParams m_params;
1524 };
1525 
AhbExternalFormatResolveTestCase(tcu::TestContext & context,const std::string & name,const TestParams & params)1526 AhbExternalFormatResolveTestCase::AhbExternalFormatResolveTestCase(tcu::TestContext &context, const std::string &name,
1527                                                                    const TestParams &params)
1528     : TestCase(context, name)
1529     , m_params(params)
1530 {
1531 }
1532 
initPrograms(SourceCollections & programCollection) const1533 void AhbExternalFormatResolveTestCase::initPrograms(SourceCollections &programCollection) const
1534 {
1535     {
1536         std::stringstream source;
1537         source << "#version 430\n"
1538                << "layout(location = 0) in vec2 in_position;\n"
1539 
1540                << "void main() {\n"
1541                << "    gl_Position  = vec4(in_position, 0.0f, 1.0f);\n"
1542                << "}\n";
1543 
1544         programCollection.glslSources.add("vert") << glu::VertexSource(source.str());
1545     }
1546 
1547     std::string intMax                                          = std::to_string(std::numeric_limits<int32_t>::max());
1548     std::string uintMax                                         = std::to_string(std::numeric_limits<uint32_t>::max());
1549     const std::pair<const char *, const char *> possibleTypes[] = {
1550         {"i", intMax.c_str()},  // int
1551         {"u", uintMax.c_str()}, // uint
1552         {"", "1.0f"},           // float
1553     };
1554     const uint32_t typeCount = sizeof(possibleTypes) / sizeof(possibleTypes[0]);
1555 
1556     for (uint32_t i = 0; i < typeCount; ++i)
1557     {
1558         std::string shaderName = "frag_" + std::string(possibleTypes[i].first) + "vec4";
1559         std::stringstream source;
1560         source << "#version 430\n"
1561                << "layout(location = 0) out " << possibleTypes[i].first << "vec4 out_color;\n"
1562 
1563                << "const " << possibleTypes[i].first << "vec4 reference_colors[] =\n"
1564                << "{\n"
1565                << "    " << possibleTypes[i].first << "vec4(0.0f, 0.0f, 0.0f, 0.0f),\n"
1566                << "    " << possibleTypes[i].first << "vec4(" << possibleTypes[i].second << ", 0.0f, 0.0f, "
1567                << possibleTypes[i].second << "),\n"
1568                << "    " << possibleTypes[i].first << "vec4(0.0f, " << possibleTypes[i].second << ", 0.0f, "
1569                << possibleTypes[i].second << "),\n"
1570                << "    " << possibleTypes[i].first << "vec4(0.0f, 0.0f, " << possibleTypes[i].second << ", "
1571                << possibleTypes[i].second << "),\n"
1572                << "};\n"
1573                << "void main()\n"
1574                << "{\n"
1575                << "    uvec4 fragmentPosition = uvec4(gl_FragCoord);\n"
1576                << "    uint color_index = (fragmentPosition.x & 1u) + ((fragmentPosition.y & 1u) << 1u);\n"
1577                << "    out_color = reference_colors[color_index];\n"
1578                << "}\n";
1579 
1580         programCollection.glslSources.add(shaderName) << glu::FragmentSource(source.str());
1581     }
1582 
1583     // No need for the input attachment shaders when no input attachment is used
1584     if (!m_params.m_isInputAttachment)
1585         return;
1586 
1587     // Required to allow CrYCb that are mapped to BGR formats to match output
1588     const uint32_t swizzleOrder[][3] = {
1589         {0, 1, 2}, // Identity (RGB)
1590         {2, 1, 0}, // First and last element are swapped (BGR)
1591     };
1592 
1593     const char *shaderIndex[] = {"r", "g", "b"};
1594 
1595     for (uint32_t i = 0; i < typeCount; ++i)
1596     {
1597         uint32_t swizzleCount =
1598             AndroidHardwareBufferInstance::isFormatYuv(m_params.m_format) ? DE_LENGTH_OF_ARRAY(swizzleOrder) : 1u;
1599         for (uint32_t swizzleIndex = 0u; swizzleIndex < swizzleCount; ++swizzleIndex)
1600         {
1601             const uint32_t *swizzle = swizzleOrder[swizzleIndex];
1602             std::string shaderName  = "frag_input_" + std::string(possibleTypes[i].first) + "vec4_" +
1603                                      shaderIndex[swizzle[0]] + shaderIndex[swizzle[1]] + shaderIndex[swizzle[2]];
1604             std::stringstream source;
1605             source << "#version 430\n"
1606                    << "layout(location = 0) out " << possibleTypes[i].first << "vec4 out_color;\n"
1607                    << "layout(input_attachment_index=0, set=0, binding=0) uniform " << possibleTypes[i].first
1608                    << "subpassInput input_attachment;"
1609 
1610                    << "void main()\n"
1611                    << "{\n"
1612                    << "    " << possibleTypes[i].first << "vec4 input_color = subpassLoad(input_attachment);\n"
1613                    << "    out_color = " << possibleTypes[i].first << "vec4(input_color." << shaderIndex[swizzle[0]]
1614                    << ","
1615                       "input_color."
1616                    << shaderIndex[swizzle[1]]
1617                    << ","
1618                       "input_color."
1619                    << shaderIndex[swizzle[2]]
1620                    << ","
1621                       "input_color.w);\n"
1622                    << "}\n";
1623 
1624             programCollection.glslSources.add(shaderName) << glu::FragmentSource(source.str());
1625         }
1626     }
1627 }
1628 
createInstance(Context & context) const1629 TestInstance *AhbExternalFormatResolveTestCase::createInstance(Context &context) const
1630 {
1631     return new AhbExternalFormatResolveTestInstance(context, m_params);
1632 }
1633 
checkSupport(Context & context) const1634 void AhbExternalFormatResolveTestCase::checkSupport(Context &context) const
1635 {
1636     context.requireDeviceFunctionality("VK_ANDROID_external_format_resolve");
1637 
1638     if (!AndroidHardwareBufferExternalApi::getInstance())
1639         TCU_THROW(NotSupportedError, "Android Hardware Buffer not present");
1640 
1641     if (m_params.m_groupParams.useDynamicRendering)
1642         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1643 }
1644 
createAhbExternalFormatResolveDrawTests(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)1645 void createAhbExternalFormatResolveDrawTests(tcu::TestCaseGroup *testGroup, const SharedGroupParams groupParams)
1646 {
1647     AndroidHardwareBufferInstance::Usage gpuFramebufferCpuRead = static_cast<AndroidHardwareBufferInstance::Usage>(
1648         AndroidHardwareBufferInstance::Usage::GPU_FRAMEBUFFER | AndroidHardwareBufferInstance::Usage::CPU_READ);
1649 
1650     AndroidHardwareBufferInstance::Usage gpuFramebufferSampled = static_cast<AndroidHardwareBufferInstance::Usage>(
1651         AndroidHardwareBufferInstance::Usage::GPU_FRAMEBUFFER | AndroidHardwareBufferInstance::Usage::GPU_SAMPLED);
1652     uint32_t imageDimension        = 64u;
1653     vk::VkRect2D defaultRenderArea = makeRect2D(imageDimension, imageDimension);
1654     TestParams params              = {
1655         defaultRenderArea, // vk::VkRect2D                                m_renderArea
1656         tcu::UVec2(imageDimension, imageDimension), // tcu::UVec2                                m_imageSize
1657         AndroidHardwareBufferInstance::Format::UNASSIGNED, // AndroidHardwareBufferInstance::Format    m_format
1658         gpuFramebufferCpuRead, // AndroidHardwareBufferInstance::Usage        m_usage
1659         *groupParams,          // GroupParams                                m_groupParams
1660         false,                 // bool                                        m_isClearOnly
1661         false,                 // bool                                        m_partialDraw
1662         false,                 // bool                                        m_isInputAttachment
1663     };
1664 
1665     std::vector<vk::VkRect2D> partialRenderAreas(10u);
1666     de::Random randomGenerator(10u);
1667     for (size_t i = 0u; i < partialRenderAreas.size(); ++i)
1668     {
1669         // Partial render areas need to render in multiple of size 2 texel squares to avoid reduction with undefined values due to subsampling
1670         uint32_t width        = (randomGenerator.getInt(0, static_cast<int32_t>(imageDimension))) & 0xFFFFFFFE;
1671         uint32_t height       = (randomGenerator.getInt(0, static_cast<int32_t>(imageDimension))) & 0xFFFFFFFE;
1672         int32_t xOffset       = (randomGenerator.getInt(0, static_cast<int32_t>(imageDimension - width))) & 0xFFFFFFFE;
1673         int32_t yOffset       = (randomGenerator.getInt(0, static_cast<int32_t>(imageDimension - height))) & 0xFFFFFFFE;
1674         partialRenderAreas[i] = makeRect2D(xOffset, yOffset, width, height);
1675     }
1676 
1677     tcu::TextureFormat invalidTextureFormat =
1678         AndroidHardwareBufferInstance::formatToTextureFormat(AndroidHardwareBufferInstance::Format::UNASSIGNED);
1679     // Draw tests
1680     tcu::TestCaseGroup *drawGroup       = new tcu::TestCaseGroup(testGroup->getTestContext(), "draw");
1681     tcu::TestCaseGroup *inputAttachment = new tcu::TestCaseGroup(testGroup->getTestContext(), "input_attachment");
1682     tcu::TestCaseGroup *clearGroup      = new tcu::TestCaseGroup(testGroup->getTestContext(), "clear");
1683     for (uint32_t i = 0; i < AndroidHardwareBufferInstance::Format::COUNT; ++i)
1684     {
1685         params.m_format = static_cast<AndroidHardwareBufferInstance::Format>(i);
1686 
1687         tcu::TextureFormat textureFormat = AndroidHardwareBufferInstance::formatToTextureFormat(params.m_format);
1688         bool isImplementationDefined = params.m_format == AndroidHardwareBufferInstance::Format::IMPLEMENTATION_DEFINED;
1689         bool isColorFormat           = AndroidHardwareBufferInstance::isFormatColor(params.m_format);
1690         bool isRawFormat             = AndroidHardwareBufferInstance::isFormatRaw(params.m_format);
1691         bool hasValidTextureFormat   = (invalidTextureFormat != textureFormat);
1692 
1693         if (isImplementationDefined || (!isColorFormat && !isRawFormat))
1694             continue;
1695 
1696         const std::string formatName = AndroidHardwareBufferInstance::getFormatName(params.m_format);
1697 
1698         // CPU side validation requires valid tcu::TextureFormat
1699         if (hasValidTextureFormat)
1700         {
1701             tcu::TestCaseGroup *formatGroup = new tcu::TestCaseGroup(testGroup->getTestContext(), formatName.c_str());
1702 
1703             params.m_renderArea = defaultRenderArea;
1704             // Draw to full render area of external format
1705             formatGroup->addChild(
1706                 new AhbExternalFormatResolveTestCase(testGroup->getTestContext(), "full_render_area", params));
1707 
1708             params.m_partialDraw = true;
1709             for (size_t renderAreaIndex = 0u; renderAreaIndex < partialRenderAreas.size(); ++renderAreaIndex)
1710             {
1711                 params.m_renderArea = partialRenderAreas[renderAreaIndex];
1712                 formatGroup->addChild(new AhbExternalFormatResolveTestCase(
1713                     testGroup->getTestContext(), "partial_render_area_" + std::to_string(renderAreaIndex), params));
1714             }
1715             params.m_partialDraw = false;
1716 
1717             drawGroup->addChild(formatGroup);
1718         }
1719 
1720         if (!params.m_groupParams.useDynamicRendering)
1721         {
1722             params.m_isInputAttachment = true;
1723             params.m_usage             = gpuFramebufferSampled;
1724             params.m_renderArea        = defaultRenderArea;
1725 
1726             tcu::TestCaseGroup *formatGroup = new tcu::TestCaseGroup(testGroup->getTestContext(), formatName.c_str());
1727 
1728             params.m_renderArea = defaultRenderArea;
1729             // Draw to full render area of external format
1730             formatGroup->addChild(
1731                 new AhbExternalFormatResolveTestCase(testGroup->getTestContext(), "full_render_area", params));
1732 
1733             params.m_partialDraw = true;
1734             for (size_t renderAreaIndex = 0u; renderAreaIndex < partialRenderAreas.size(); ++renderAreaIndex)
1735             {
1736                 params.m_renderArea = partialRenderAreas[renderAreaIndex];
1737                 formatGroup->addChild(new AhbExternalFormatResolveTestCase(
1738                     testGroup->getTestContext(), "partial_render_area_" + std::to_string(renderAreaIndex), params));
1739             }
1740             params.m_partialDraw = false;
1741 
1742             inputAttachment->addChild(formatGroup);
1743             params.m_usage             = gpuFramebufferCpuRead;
1744             params.m_isInputAttachment = false;
1745         }
1746 
1747         if (!params.m_groupParams.useSecondaryCmdBuffer ||
1748             params.m_groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1749         {
1750             // CPU side validation requires valid tcu::TextureFormat
1751             if (hasValidTextureFormat)
1752             {
1753                 params.m_isClearOnly = true;
1754                 params.m_renderArea  = defaultRenderArea;
1755                 clearGroup->addChild(
1756                     new AhbExternalFormatResolveTestCase(testGroup->getTestContext(), formatName, params));
1757                 params.m_isClearOnly = false;
1758             }
1759         }
1760     }
1761 
1762     testGroup->addChild(clearGroup);
1763     testGroup->addChild(drawGroup);
1764     testGroup->addChild(inputAttachment);
1765 }
1766 
1767 } // namespace
1768 
createAhbExternalFormatResolveTests(tcu::TestContext & testCtx,const SharedGroupParams & groupParams)1769 tcu::TestCaseGroup *createAhbExternalFormatResolveTests(tcu::TestContext &testCtx, const SharedGroupParams &groupParams)
1770 {
1771     // Draw tests using Android Hardware Buffer external formats
1772     return createTestGroup(testCtx, "ahb_external_format_resolve", createAhbExternalFormatResolveDrawTests,
1773                            groupParams);
1774 }
1775 
1776 } // namespace Draw
1777 } // namespace vkt
1778