xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/draw/vktDrawAhbTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  * Copyright (c) 2020 Google LLC
7  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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 Draw Tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktDrawAhbTests.hpp"
27 
28 #include "vktDrawBaseClass.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vktTestGroupUtil.hpp"
33 
34 #include "../util/vktExternalMemoryUtil.hpp"
35 
36 #include "deDefs.h"
37 #include "deRandom.hpp"
38 
39 #include "tcuTestCase.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuVectorUtil.hpp"
43 #include "tcuTestLog.hpp"
44 
45 #include "rrRenderer.hpp"
46 
47 #include <string>
48 
49 using namespace vkt::ExternalMemoryUtil;
50 using namespace vk;
51 using std::vector;
52 
53 namespace vkt
54 {
55 namespace Draw
56 {
57 namespace
58 {
59 
60 const uint32_t SEED = 0xc2a39fu;
61 
62 struct DrawParams
63 {
DrawParamsvkt::Draw::__anonf0300b330111::DrawParams64     DrawParams(uint32_t numVertices, uint32_t numLayers) : m_numVertices(numVertices), m_numLayers(numLayers)
65     {
66     }
67 
68     uint32_t m_numVertices;
69     uint32_t m_numLayers;
70     vector<PositionColorVertex> m_vertices;
71 };
72 
73 // Reference renderer shaders
74 class PassthruVertShader : public rr::VertexShader
75 {
76 public:
PassthruVertShader(void)77     PassthruVertShader(void) : rr::VertexShader(2, 1)
78     {
79         m_inputs[0].type  = rr::GENERICVECTYPE_FLOAT;
80         m_inputs[1].type  = rr::GENERICVECTYPE_FLOAT;
81         m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
82     }
83 
~PassthruVertShader()84     virtual ~PassthruVertShader()
85     {
86     }
87 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const88     void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
89     {
90         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
91         {
92             packets[packetNdx]->position =
93                 rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
94 
95             tcu::Vec4 color =
96                 rr::readVertexAttribFloat(inputs[1], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
97 
98             packets[packetNdx]->outputs[0] = color;
99         }
100     }
101 };
102 
103 class PassthruFragShader : public rr::FragmentShader
104 {
105 public:
PassthruFragShader(void)106     PassthruFragShader(void) : rr::FragmentShader(1, 1)
107     {
108         m_inputs[0].type  = rr::GENERICVECTYPE_FLOAT;
109         m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
110     }
111 
~PassthruFragShader()112     virtual ~PassthruFragShader()
113     {
114     }
115 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const116     void shadeFragments(rr::FragmentPacket *packets, const int numPackets,
117                         const rr::FragmentShadingContext &context) const
118     {
119         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
120         {
121             rr::FragmentPacket &packet = packets[packetNdx];
122             for (uint32_t fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
123             {
124                 tcu::Vec4 color = rr::readVarying<float>(packet, context, 0, fragNdx);
125                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
126             }
127         }
128     }
129 };
130 
131 class AhbTestInstance : public TestInstance
132 {
133 public:
134     AhbTestInstance(Context &context, DrawParams data);
135     ~AhbTestInstance(void);
136 
137     tcu::TestStatus iterate(void);
138 
139 private:
140     void generateDrawData(void);
141     void generateRefImage(const tcu::PixelBufferAccess &access, const vector<tcu::Vec4> &vertices,
142                           const vector<tcu::Vec4> &colors) const;
143 
144     DrawParams m_data;
145 
146     enum
147     {
148         WIDTH  = 256,
149         HEIGHT = 256
150     };
151 };
152 
AhbTestInstance(Context & context,DrawParams data)153 AhbTestInstance::AhbTestInstance(Context &context, DrawParams data) : vkt::TestInstance(context), m_data(data)
154 {
155     generateDrawData();
156 }
157 
~AhbTestInstance(void)158 AhbTestInstance::~AhbTestInstance(void)
159 {
160 }
161 
generateRefImage(const tcu::PixelBufferAccess & access,const vector<tcu::Vec4> & vertices,const vector<tcu::Vec4> & colors) const162 void AhbTestInstance::generateRefImage(const tcu::PixelBufferAccess &access, const vector<tcu::Vec4> &vertices,
163                                        const vector<tcu::Vec4> &colors) const
164 {
165     const PassthruVertShader vertShader;
166     const PassthruFragShader fragShader;
167     const rr::Program program(&vertShader, &fragShader);
168     const rr::MultisamplePixelBufferAccess colorBuffer =
169         rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(access);
170     const rr::RenderTarget renderTarget(colorBuffer);
171     const rr::RenderState renderState((rr::ViewportState(colorBuffer)),
172                                       m_context.getDeviceProperties().limits.subPixelPrecisionBits);
173     const rr::Renderer renderer;
174 
175     const rr::VertexAttrib vertexAttribs[] = {
176         rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vertices[0]),
177         rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0])};
178 
179     renderer.draw(rr::DrawCommand(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs),
180                                   &vertexAttribs[0],
181                                   rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, (uint32_t)vertices.size(), 0)));
182 }
183 
184 class AhbTestCase : public TestCase
185 {
186 public:
187     AhbTestCase(tcu::TestContext &context, const char *name, const DrawParams data);
188     ~AhbTestCase(void);
189     virtual void initPrograms(SourceCollections &programCollection) const;
190     virtual void initShaderSources(void);
191     virtual void checkSupport(Context &context) const;
192     virtual TestInstance *createInstance(Context &context) const;
193 
194 private:
195     DrawParams m_data;
196     std::string m_vertShaderSource;
197     std::string m_fragShaderSource;
198 };
199 
AhbTestCase(tcu::TestContext & context,const char * name,const DrawParams data)200 AhbTestCase::AhbTestCase(tcu::TestContext &context, const char *name, const DrawParams data)
201     : vkt::TestCase(context, name)
202     , m_data(data)
203 {
204     initShaderSources();
205 }
206 
~AhbTestCase(void)207 AhbTestCase::~AhbTestCase(void)
208 {
209 }
210 
initPrograms(SourceCollections & programCollection) const211 void AhbTestCase::initPrograms(SourceCollections &programCollection) const
212 {
213     programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
214     programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
215 }
216 
checkSupport(Context & context) const217 void AhbTestCase::checkSupport(Context &context) const
218 {
219     const InstanceInterface &vki                    = context.getInstanceInterface();
220     vk::VkPhysicalDevice physicalDevice             = context.getPhysicalDevice();
221     const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
222 
223     // Each layer is exposed as its own color attachment.
224     if (m_data.m_numLayers > properties.limits.maxColorAttachments)
225         TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
226 }
227 
initShaderSources(void)228 void AhbTestCase::initShaderSources(void)
229 {
230     std::stringstream vertShader;
231     vertShader << "#version 430\n"
232                << "layout(location = 0) in vec4 in_position;\n"
233                << "layout(location = 1) in vec4 in_color;\n"
234                << "layout(location = 0) out vec4 out_color;\n"
235 
236                << "void main() {\n"
237                << "    gl_Position  = in_position;\n"
238                << "    out_color    = in_color;\n"
239                << "}\n";
240 
241     m_vertShaderSource = vertShader.str();
242 
243     std::stringstream fragShader;
244     fragShader << "#version 430\n"
245                << "layout(location = 0) in vec4 in_color;\n"
246                << "layout(location = 0) out vec4 out_color;\n"
247 
248                << "void main()\n"
249                << "{\n"
250                << "    out_color = in_color;\n"
251                << "}\n";
252 
253     m_fragShaderSource = fragShader.str();
254 }
255 
createInstance(Context & context) const256 TestInstance *AhbTestCase::createInstance(Context &context) const
257 {
258     return new AhbTestInstance(context, m_data);
259 }
260 
generateDrawData(void)261 void AhbTestInstance::generateDrawData(void)
262 {
263     de::Random rnd(SEED ^ m_data.m_numLayers ^ m_data.m_numVertices);
264 
265     for (uint32_t i = 0; i < m_data.m_numVertices; i++)
266     {
267         const float f0 = rnd.getFloat(-1.0f, 1.0f);
268         const float f1 = rnd.getFloat(-1.0f, 1.0f);
269 
270         m_data.m_vertices.push_back(PositionColorVertex(tcu::Vec4(f0, f1, 1.0f, 1.0f), // Coord
271                                                         tcu::randomVec4(rnd)));        // Color
272     }
273 }
274 
iterate(void)275 tcu::TestStatus AhbTestInstance::iterate(void)
276 {
277     const DeviceInterface &vk            = m_context.getDeviceInterface();
278     const VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
279     tcu::TestLog &log                    = m_context.getTestContext().getLog();
280     const VkQueue queue                  = m_context.getUniversalQueue();
281     const VkDevice device                = m_context.getDevice();
282     const uint32_t queueFamilyIndex      = m_context.getUniversalQueueFamilyIndex();
283     const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
284     const Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(vk, device, &pipelineLayoutCreateInfo));
285     vector<Move<VkBuffer>> resultBuffers;
286     vector<de::MovePtr<Allocation>> resultBufferAllocations;
287 
288     for (uint32_t i = 0u; i < m_data.m_numLayers; i++)
289     {
290         const VkBufferUsageFlags bufferUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
291         const VkDeviceSize pixelSize        = mapVkFormat(colorAttachmentFormat).getPixelSize();
292         const VkBufferCreateInfo createInfo = {
293             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType        sType
294             DE_NULL,                              // const void*            pNext
295             0u,                                   // VkBufferCreateFlags    flags
296             WIDTH * HEIGHT * pixelSize,           // VkDeviceSize            size
297             bufferUsage,                          // VkBufferUsageFlags    usage
298             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode        sharingMode
299             0u,                                   // uint32_t                queueFamilyIndexCount
300             DE_NULL                               // const uint32_t*        pQueueFamilyIndices
301         };
302 
303         resultBuffers.push_back(createBuffer(vk, device, &createInfo));
304         resultBufferAllocations.push_back(m_context.getDefaultAllocator().allocate(
305             getBufferMemoryRequirements(vk, device, *resultBuffers.back()), MemoryRequirement::HostVisible));
306         VK_CHECK(vk.bindBufferMemory(device, *resultBuffers.back(), resultBufferAllocations.back()->getMemory(),
307                                      resultBufferAllocations.back()->getOffset()));
308     }
309 
310     const VkExtent3D targetImageExtent = {WIDTH, HEIGHT, 1};
311     const ImageCreateInfo targetImageCreateInfo(VK_IMAGE_TYPE_2D, colorAttachmentFormat, targetImageExtent, 1,
312                                                 m_data.m_numLayers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL,
313                                                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
314                                                     VK_IMAGE_USAGE_TRANSFER_DST_BIT);
315 
316     // Enable this to use non-AHB images for color output.
317 #if 0
318     const Unique<VkImage>                        colorTargetImage        (createImage(vk, device, &targetImageCreateInfo, DE_NULL));
319     de::MovePtr<Allocation>                        m_colorImageAllocation = m_context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, device, *colorTargetImage), MemoryRequirement::Any);
320     VK_CHECK(vk.bindImageMemory(device, *colorTargetImage, m_colorImageAllocation->getMemory(), m_colorImageAllocation->getOffset()));
321 #else
322     AndroidHardwareBufferExternalApi *ahbApi = AndroidHardwareBufferExternalApi::getInstance();
323 
324     if (!ahbApi)
325         TCU_THROW(NotSupportedError, "Android Hardware Buffer not supported");
326 
327     m_context.requireDeviceFunctionality("VK_ANDROID_external_memory_android_hardware_buffer");
328 
329     uint64_t requiredAhbUsage = ahbApi->vkUsageToAhbUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
330 
331     pt::AndroidHardwareBufferPtr ahb =
332         ahbApi->allocate(WIDTH, HEIGHT, targetImageCreateInfo.arrayLayers,
333                          ahbApi->vkFormatToAhbFormat(colorAttachmentFormat), requiredAhbUsage);
334 
335     if (ahb.internal == DE_NULL)
336         TCU_THROW(NotSupportedError, "Required number of layers for Android Hardware Buffer not supported");
337 
338     NativeHandle nativeHandle(ahb);
339     const Unique<VkImage> colorTargetImage(createExternalImage(
340         vk, device, queueFamilyIndex, VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
341         colorAttachmentFormat, WIDTH, HEIGHT, VK_IMAGE_TILING_OPTIMAL, 0u, targetImageCreateInfo.usage,
342         targetImageCreateInfo.mipLevels, targetImageCreateInfo.arrayLayers));
343 
344     uint32_t ahbFormat = 0;
345     ahbApi->describe(nativeHandle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, DE_NULL, DE_NULL);
346 
347     VkAndroidHardwareBufferPropertiesANDROID ahbProperties = {
348         VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, // VkStructureType    sType
349         DE_NULL,                                                      // void*              pNext
350         0u,                                                           // VkDeviceSize       allocationSize
351         0u                                                            // uint32_t           memoryTypeBits
352     };
353 
354     vk.getAndroidHardwareBufferPropertiesANDROID(device, nativeHandle.getAndroidHardwareBuffer(), &ahbProperties);
355 
356     const VkImportAndroidHardwareBufferInfoANDROID importInfo = {
357         VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, // VkStructureType            sType
358         DE_NULL,                                                       // const void*                pNext
359         nativeHandle.getAndroidHardwareBuffer()                        // struct AHardwareBuffer*    buffer
360     };
361 
362     const VkMemoryDedicatedAllocateInfo dedicatedInfo = {
363         VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, // VkStructureType    sType
364         &importInfo,                                          // const void*        pNext
365         *colorTargetImage,                                    // VkImage            image
366         DE_NULL,                                              // VkBuffer           buffer
367     };
368 
369     const VkMemoryAllocateInfo allocateInfo = {
370         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,        // VkStructureType    sType
371         (const void *)&dedicatedInfo,                  // const void*        pNext
372         ahbProperties.allocationSize,                  // VkDeviceSize       allocationSize
373         chooseMemoryType(ahbProperties.memoryTypeBits) // uint32_t           memoryTypeIndex
374     };
375 
376     const Unique<VkDeviceMemory> colorImageMemory(allocateMemory(vk, device, &allocateInfo));
377     VK_CHECK(vk.bindImageMemory(device, *colorTargetImage, *colorImageMemory, 0u));
378 #endif
379 
380     vector<Move<VkImageView>> imageViews;
381     vector<VkImageView> colorAttachments;
382     RenderPassCreateInfo renderPassCreateInfo;
383 
384     for (uint32_t i = 0u; i < m_data.m_numLayers; i++)
385     {
386         const VkImageSubresourceRange subresourceRange = {
387             VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
388             0u,                        // uint32_t              baseMipLevel
389             1u,                        // uint32_t              levelCount
390             i,                         // uint32_t              baseArrayLayer
391             1u,                        // uint32_t              layerCount
392         };
393 
394         const VkImageViewCreateInfo imageViewCreateInfo = {
395             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType            sType
396             DE_NULL,                                  // const void*                pNext
397             0u,                                       // VkImageViewCreateFlags     flags
398             *colorTargetImage,                        // VkImage                    image
399             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType            viewType
400             colorAttachmentFormat,                    // VkFormat                   format
401             ComponentMapping(),                       // VkComponentMapping         components
402             subresourceRange                          // VkImageSubresourceRange    subresourceRange
403         };
404 
405         imageViews.push_back(createImageView(vk, device, &imageViewCreateInfo));
406         colorAttachments.push_back(*imageViews.back());
407 
408         renderPassCreateInfo.addAttachment(AttachmentDescription(
409             colorAttachmentFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
410             VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
411             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
412 
413         const VkAttachmentReference colorAttachmentReference = {i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
414 
415         renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, DE_NULL, 1u,
416                                                            &colorAttachmentReference, DE_NULL, AttachmentReference(), 0,
417                                                            DE_NULL));
418     }
419 
420     Unique<VkRenderPass> renderPass(createRenderPass(vk, device, &renderPassCreateInfo));
421 
422     const FramebufferCreateInfo framebufferCreateInfo(*renderPass, colorAttachments, WIDTH, HEIGHT, 1);
423     Unique<VkFramebuffer> framebuffer(createFramebuffer(vk, device, &framebufferCreateInfo));
424 
425     const VkVertexInputBindingDescription vertexInputBindingDescription = {
426         0,                               // uint32_t             binding
427         (uint32_t)sizeof(tcu::Vec4) * 2, // uint32_t             stride
428         VK_VERTEX_INPUT_RATE_VERTEX,     // VkVertexInputRate    inputRate
429     };
430 
431     const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
432 
433         {
434             0u,                            // uint32_t    location
435             0u,                            // uint32_t    binding
436             VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat    format
437             0u                             // uint32_t    offset
438         },
439         {
440             1u,                            // uint32_t    location
441             0u,                            // uint32_t    binding
442             VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat    format
443             (uint32_t)(sizeof(float) * 4), // uint32_t    offset
444         }};
445 
446     PipelineCreateInfo::VertexInputState vertexInputState =
447         PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
448     const VkDeviceSize dataSize = m_data.m_vertices.size() * sizeof(PositionColorVertex);
449     de::SharedPtr<Buffer> vertexBuffer =
450         Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
451                                m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
452     uint8_t *ptr = reinterpret_cast<uint8_t *>(vertexBuffer->getBoundMemory().getHostPtr());
453 
454     deMemcpy(ptr, &(m_data.m_vertices[0]), static_cast<size_t>(dataSize));
455     flushAlloc(vk, device, vertexBuffer->getBoundMemory());
456 
457     const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
458     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, &cmdPoolCreateInfo));
459     const Unique<VkCommandBuffer> cmdBuffer(
460         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
461     const Unique<VkShaderModule> vs(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
462     const Unique<VkShaderModule> fs(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
463     VkViewport viewport = makeViewport(WIDTH, HEIGHT);
464     VkRect2D scissor    = makeRect2D(WIDTH, HEIGHT);
465     vector<Move<VkPipeline>> pipelines;
466 
467     PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
468     pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
469     pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
470     pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
471     pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
472     PipelineCreateInfo::ColorBlendState::Attachment attachment;
473     pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1u, &attachment));
474     pipelineCreateInfo.addState(
475         PipelineCreateInfo::ViewportState(1, vector<VkViewport>(1, viewport), vector<VkRect2D>(1, scissor)));
476     pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
477     pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
478     pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
479 
480     for (uint32_t i = 0; i < m_data.m_numLayers; i++)
481     {
482         pipelineCreateInfo.subpass = i;
483         pipelines.push_back(createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo));
484     }
485 
486     beginCommandBuffer(vk, *cmdBuffer, 0u);
487 
488     const VkImageMemoryBarrier initialTransition = {
489         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType    sType
490         DE_NULL,                                  // const void*        pNext
491         0u,                                       // VkAccessFlags    srcAccessMask
492         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // VkAccessFlags    dstAccessMask
493         VK_IMAGE_LAYOUT_UNDEFINED,                // VkImageLayout    oldLayout
494         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout    newLayout
495         VK_QUEUE_FAMILY_IGNORED,                  // uint32_t            srcQueueFamilyIndex
496         VK_QUEUE_FAMILY_IGNORED,                  // uint32_t            destQueueFamilyIndex
497         *colorTargetImage,                        // VkImage            image
498         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0,
499                                   m_data.m_numLayers) // VkImageSubresourceRange    subresourceRange
500     };
501 
502     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
503                           (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, 0,
504                           (const vk::VkBufferMemoryBarrier *)DE_NULL, 1, &initialTransition);
505 
506     const VkRect2D renderArea = makeRect2D(WIDTH, HEIGHT);
507 
508     vector<VkClearValue> clearColors(m_data.m_numLayers, makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f));
509 
510     const VkRenderPassBeginInfo renderPassBeginInfo = {
511         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType         sType
512         DE_NULL,                                  // const void*             pNext
513         *renderPass,                              // VkRenderPass            renderPass
514         *framebuffer,                             // VkFramebuffer           framebuffer
515         renderArea,                               // VkRect2D                renderArea
516         (uint32_t)clearColors.size(),             // uint32_t                clearValueCount
517         clearColors.data(),                       // const VkClearValue*     pClearValues
518     };
519 
520     vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
521 
522     const VkDeviceSize vertexBufferOffset = 0;
523     const VkBuffer vertexBufferObj        = vertexBuffer->object();
524 
525     vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBufferObj, &vertexBufferOffset);
526     for (uint32_t i = 0; i < m_data.m_numLayers; i++)
527     {
528         if (i != 0)
529             vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
530 
531         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelines[i]);
532         vk.cmdDraw(*cmdBuffer, 9u, 1u, i * 9u, 0u);
533     }
534 
535     endRenderPass(vk, *cmdBuffer);
536 
537     const VkImageMemoryBarrier imageBarrier = {
538         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType            sType
539         DE_NULL,                                  // const void*                pNext
540         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // VkAccessFlags            srcAccessMask
541         VK_ACCESS_TRANSFER_READ_BIT,              // VkAccessFlags            dstAccessMask
542         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout            oldLayout
543         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,     // VkImageLayout            newLayout
544         VK_QUEUE_FAMILY_IGNORED,                  // uint32_t                    srcQueueFamilyIndex
545         VK_QUEUE_FAMILY_IGNORED,                  // uint32_t                    destQueueFamilyIndex
546         *colorTargetImage,                        // VkImage                    image
547         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0,
548                                   m_data.m_numLayers) // VkImageSubresourceRange subresourceRange;
549     };
550 
551     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
552                           DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
553 
554     for (uint32_t i = 0; i < m_data.m_numLayers; i++)
555     {
556         const VkImageSubresourceLayers subresource = {
557             VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
558             0u,                        // uint32_t                mipLevel
559             i,                         // uint32_t                baseArrayLayer
560             1u                         // uint32_t                layerCount
561         };
562 
563         const VkBufferImageCopy region = {
564             0ull,                           // VkDeviceSize                    bufferOffset
565             0u,                             // uint32_t                        bufferRowLength
566             0u,                             // uint32_t                        bufferImageHeight
567             subresource,                    // VkImageSubresourceLayers        imageSubresource
568             makeOffset3D(0, 0, 0),          // VkOffset3D                    imageOffset
569             makeExtent3D(WIDTH, HEIGHT, 1u) // VkExtent3D                    imageExtent
570         };
571 
572         vk.cmdCopyImageToBuffer(*cmdBuffer, *colorTargetImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *resultBuffers[i],
573                                 1u, &region);
574 
575         const VkBufferMemoryBarrier bufferBarrier = {
576             VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType    sType
577             DE_NULL,                                 // const void*        pNext
578             VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags    srcAccessMask
579             VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags    dstAccessMask
580             VK_QUEUE_FAMILY_IGNORED,                 // uint32_t            srcQueueFamilyIndex
581             VK_QUEUE_FAMILY_IGNORED,                 // uint32_t            dstQueueFamilyIndex
582             *resultBuffers[i],                       // VkBuffer            buffer
583             0ull,                                    // VkDeviceSize        offset
584             VK_WHOLE_SIZE                            // VkDeviceSize        size
585         };
586 
587         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL,
588                               1u, &bufferBarrier, 0u, DE_NULL);
589     }
590 
591     endCommandBuffer(vk, *cmdBuffer);
592 
593     submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
594 
595     qpTestResult res = QP_TEST_RESULT_PASS;
596 
597     for (uint32_t i = 0; i < m_data.m_numLayers; i++)
598     {
599         invalidateMappedMemoryRange(vk, m_context.getDevice(), resultBufferAllocations[i]->getMemory(),
600                                     resultBufferAllocations[i]->getOffset(), VK_WHOLE_SIZE);
601 
602         tcu::TextureLevel refImage(mapVkFormat(colorAttachmentFormat), WIDTH, HEIGHT);
603         tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
604 
605         vector<tcu::Vec4> vertices;
606         vector<tcu::Vec4> colors;
607 
608         for (int v = 0; v < 9; v++)
609         {
610             int idx = i * 9 + v;
611             vertices.push_back(m_data.m_vertices[idx].position);
612             colors.push_back(m_data.m_vertices[idx].color);
613         }
614 
615         generateRefImage(refImage.getAccess(), vertices, colors);
616 
617         const tcu::TextureFormat format(mapVkFormat(colorAttachmentFormat));
618         const void *const ptrResult(resultBufferAllocations[i]->getHostPtr());
619         const tcu::ConstPixelBufferAccess renderedFrame(format, WIDTH, HEIGHT, 1, ptrResult);
620 
621         if (!tcu::fuzzyCompare(log, "Result", "Image comparison result", refImage.getAccess(), renderedFrame, 0.053f,
622                                tcu::COMPARE_LOG_RESULT))
623             res = QP_TEST_RESULT_FAIL;
624     }
625 
626     return tcu::TestStatus(res, qpGetTestResultName(res));
627 }
628 
createAhbDrawTests(tcu::TestCaseGroup * testGroup)629 void createAhbDrawTests(tcu::TestCaseGroup *testGroup)
630 {
631     // Draw triangle list to a single layer color buffer
632     testGroup->addChild(new AhbTestCase(testGroup->getTestContext(), "triangle_list", DrawParams(9u, 1u)));
633 
634     // Draw triangle list to a color buffer with three layers
635     testGroup->addChild(
636         new AhbTestCase(testGroup->getTestContext(), "triangle_list_layers_3", DrawParams(9u * 3u, 3u)));
637 
638     // Draw triangle list to a color buffer with five layers
639     testGroup->addChild(
640         new AhbTestCase(testGroup->getTestContext(), "triangle_list_layers_5", DrawParams(9u * 5u, 5u)));
641 
642     // Draw triangle list to a color buffer with eight layers
643     testGroup->addChild(
644         new AhbTestCase(testGroup->getTestContext(), "triangle_list_layers_8", DrawParams(9u * 8u, 8u)));
645 }
646 
647 } // namespace
648 
createAhbTests(tcu::TestContext & testCtx)649 tcu::TestCaseGroup *createAhbTests(tcu::TestContext &testCtx)
650 {
651     // Draw tests using Android Hardware Buffer
652     return createTestGroup(testCtx, "ahb", createAhbDrawTests);
653 }
654 
655 } // namespace Draw
656 } // namespace vkt
657