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 ¶ms);
~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 ¶ms)
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 ®ion);
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 ¶ms);
~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 ¶ms)
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