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, ®ion);
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