/*------------------------------------------------------------------------ * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2020 The Khronos Group Inc. * Copyright (c) 2020 Google LLC * Copyright (c) 2016 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Android Hardware Buffer Draw Tests *//*--------------------------------------------------------------------*/ #include "vktDrawAhbTests.hpp" #include "vktDrawBaseClass.hpp" #include "vkQueryUtil.hpp" #include "vkCmdUtil.hpp" #include "vkTypeUtil.hpp" #include "vktTestGroupUtil.hpp" #include "../util/vktExternalMemoryUtil.hpp" #include "deDefs.h" #include "deRandom.hpp" #include "tcuTestCase.hpp" #include "tcuTextureUtil.hpp" #include "tcuImageCompare.hpp" #include "tcuVectorUtil.hpp" #include "tcuTestLog.hpp" #include "rrRenderer.hpp" #include using namespace vkt::ExternalMemoryUtil; using namespace vk; using std::vector; namespace vkt { namespace Draw { namespace { const deUint32 SEED = 0xc2a39fu; struct DrawParams { DrawParams (deUint32 numVertices, deUint32 numLayers) : m_numVertices(numVertices), m_numLayers(numLayers) {} deUint32 m_numVertices; deUint32 m_numLayers; vector m_vertices; }; // Reference renderer shaders class PassthruVertShader : public rr::VertexShader { public: PassthruVertShader (void) : rr::VertexShader (2, 1) { m_inputs[0].type = rr::GENERICVECTYPE_FLOAT; m_inputs[1].type = rr::GENERICVECTYPE_FLOAT; m_outputs[0].type = rr::GENERICVECTYPE_FLOAT; } void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const { for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) { packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx); tcu::Vec4 color = rr::readVertexAttribFloat(inputs[1], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx); packets[packetNdx]->outputs[0] = color; } } }; class PassthruFragShader : public rr::FragmentShader { public: PassthruFragShader (void) : rr::FragmentShader(1, 1) { m_inputs[0].type = rr::GENERICVECTYPE_FLOAT; m_outputs[0].type = rr::GENERICVECTYPE_FLOAT; } void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const { for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) { rr::FragmentPacket& packet = packets[packetNdx]; for (deUint32 fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx) { tcu::Vec4 color = rr::readVarying(packet, context, 0, fragNdx); rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color); } } } }; class AhbTestInstance : public TestInstance { public: AhbTestInstance (Context& context, DrawParams data); ~AhbTestInstance (void); tcu::TestStatus iterate (void); private: void generateDrawData (void); void generateRefImage (const tcu::PixelBufferAccess& access, const vector& vertices, const vector& colors) const; DrawParams m_data; enum { WIDTH = 256, HEIGHT = 256 }; }; AhbTestInstance::AhbTestInstance (Context& context, DrawParams data) : vkt::TestInstance (context) , m_data (data) { generateDrawData(); } AhbTestInstance::~AhbTestInstance (void) { } void AhbTestInstance::generateRefImage (const tcu::PixelBufferAccess& access, const vector& vertices, const vector& colors) const { const PassthruVertShader vertShader; const PassthruFragShader fragShader; const rr::Program program (&vertShader, &fragShader); const rr::MultisamplePixelBufferAccess colorBuffer = rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(access); const rr::RenderTarget renderTarget (colorBuffer); const rr::RenderState renderState ((rr::ViewportState(colorBuffer)), m_context.getDeviceProperties().limits.subPixelPrecisionBits); const rr::Renderer renderer; const rr::VertexAttrib vertexAttribs[] = { rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vertices[0]), rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0]) }; renderer.draw(rr::DrawCommand(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), &vertexAttribs[0], rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, (deUint32)vertices.size(), 0))); } class AhbTestCase : public TestCase { public: AhbTestCase (tcu::TestContext& context, const char* name, const char* desc, const DrawParams data); ~AhbTestCase (void); virtual void initPrograms (SourceCollections& programCollection) const; virtual void initShaderSources (void); virtual void checkSupport (Context& context) const; virtual TestInstance* createInstance (Context& context) const; private: DrawParams m_data; std::string m_vertShaderSource; std::string m_fragShaderSource; }; AhbTestCase::AhbTestCase (tcu::TestContext& context, const char* name, const char* desc, const DrawParams data) : vkt::TestCase (context, name, desc) , m_data (data) { initShaderSources(); } AhbTestCase::~AhbTestCase (void) { } void AhbTestCase::initPrograms (SourceCollections& programCollection) const { programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource); programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource); } void AhbTestCase::checkSupport (Context& context) const { const InstanceInterface& vki = context.getInstanceInterface(); vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(vki, physicalDevice); // Each layer is exposed as its own color attachment. if (m_data.m_numLayers > properties.limits.maxColorAttachments) TCU_THROW(NotSupportedError, "Required number of color attachments not supported."); } void AhbTestCase::initShaderSources (void) { std::stringstream vertShader; vertShader << "#version 430\n" << "layout(location = 0) in vec4 in_position;\n" << "layout(location = 1) in vec4 in_color;\n" << "layout(location = 0) out vec4 out_color;\n" << "void main() {\n" << " gl_Position = in_position;\n" << " out_color = in_color;\n" << "}\n"; m_vertShaderSource = vertShader.str(); std::stringstream fragShader; fragShader << "#version 430\n" << "layout(location = 0) in vec4 in_color;\n" << "layout(location = 0) out vec4 out_color;\n" << "void main()\n" << "{\n" << " out_color = in_color;\n" << "}\n"; m_fragShaderSource = fragShader.str(); } TestInstance* AhbTestCase::createInstance (Context& context) const { return new AhbTestInstance(context, m_data); } void AhbTestInstance::generateDrawData (void) { de::Random rnd (SEED ^ m_data.m_numLayers ^ m_data.m_numVertices); for (deUint32 i = 0; i < m_data.m_numVertices; i++) { const float f0 = rnd.getFloat(-1.0f, 1.0f); const float f1 = rnd.getFloat(-1.0f, 1.0f); m_data.m_vertices.push_back(PositionColorVertex( tcu::Vec4(f0, f1, 1.0f, 1.0f), // Coord tcu::randomVec4(rnd))); // Color } } tcu::TestStatus AhbTestInstance::iterate (void) { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM; tcu::TestLog &log = m_context.getTestContext().getLog(); const VkQueue queue = m_context.getUniversalQueue(); const VkDevice device = m_context.getDevice(); const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); const PipelineLayoutCreateInfo pipelineLayoutCreateInfo; const Unique pipelineLayout (createPipelineLayout(vk, device, &pipelineLayoutCreateInfo)); vector> resultBuffers; vector> resultBufferAllocations; for (deUint32 i = 0u; i < m_data.m_numLayers; i++) { const VkBufferUsageFlags bufferUsage (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); const VkDeviceSize pixelSize = mapVkFormat(colorAttachmentFormat).getPixelSize(); const VkBufferCreateInfo createInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType DE_NULL, // const void* pNext 0u, // VkBufferCreateFlags flags WIDTH * HEIGHT * pixelSize, // VkDeviceSize size bufferUsage, // VkBufferUsageFlags usage VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode 0u, // uint32_t queueFamilyIndexCount DE_NULL // const uint32_t* pQueueFamilyIndices }; resultBuffers.push_back(createBuffer(vk, device, &createInfo)); resultBufferAllocations.push_back(m_context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, device, *resultBuffers.back()), MemoryRequirement::HostVisible)); VK_CHECK(vk.bindBufferMemory(device, *resultBuffers.back(), resultBufferAllocations.back()->getMemory(), resultBufferAllocations.back()->getOffset())); } const VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 }; const ImageCreateInfo targetImageCreateInfo (VK_IMAGE_TYPE_2D, colorAttachmentFormat, targetImageExtent, 1, m_data.m_numLayers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); // Enable this to use non-AHB images for color output. #if 0 const Unique colorTargetImage (createImage(vk, device, &targetImageCreateInfo, DE_NULL)); de::MovePtr m_colorImageAllocation = m_context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, device, *colorTargetImage), MemoryRequirement::Any); VK_CHECK(vk.bindImageMemory(device, *colorTargetImage, m_colorImageAllocation->getMemory(), m_colorImageAllocation->getOffset())); #else AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance(); if (!ahbApi) TCU_THROW(NotSupportedError, "Android Hardware Buffer not supported"); m_context.requireDeviceFunctionality("VK_ANDROID_external_memory_android_hardware_buffer"); deUint64 requiredAhbUsage = ahbApi->vkUsageToAhbUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(WIDTH, HEIGHT, targetImageCreateInfo.arrayLayers, ahbApi->vkFormatToAhbFormat(colorAttachmentFormat), requiredAhbUsage); if (ahb.internal == DE_NULL) TCU_THROW(NotSupportedError, "Required number of layers for Android Hardware Buffer not supported"); NativeHandle nativeHandle(ahb); const Unique colorTargetImage (createExternalImage(vk, device, queueFamilyIndex, VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, colorAttachmentFormat, WIDTH, HEIGHT, VK_IMAGE_TILING_OPTIMAL, 0u, targetImageCreateInfo.usage, targetImageCreateInfo.mipLevels, targetImageCreateInfo.arrayLayers)); deUint32 ahbFormat = 0; ahbApi->describe(nativeHandle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, DE_NULL, DE_NULL); VkAndroidHardwareBufferPropertiesANDROID ahbProperties = { VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, // VkStructureType sType DE_NULL, // void* pNext 0u, // VkDeviceSize allocationSize 0u // uint32_t memoryTypeBits }; vk.getAndroidHardwareBufferPropertiesANDROID(device, nativeHandle.getAndroidHardwareBuffer(), &ahbProperties); const VkImportAndroidHardwareBufferInfoANDROID importInfo = { VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, // VkStructureType sType DE_NULL, // const void* pNext nativeHandle.getAndroidHardwareBuffer() // struct AHardwareBuffer* buffer }; const VkMemoryDedicatedAllocateInfo dedicatedInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, // VkStructureType sType &importInfo, // const void* pNext *colorTargetImage, // VkImage image DE_NULL, // VkBuffer buffer }; const VkMemoryAllocateInfo allocateInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType (const void*)&dedicatedInfo, // const void* pNext ahbProperties.allocationSize, // VkDeviceSize allocationSize chooseMemoryType(ahbProperties.memoryTypeBits) // uint32_t memoryTypeIndex }; const Unique colorImageMemory (allocateMemory(vk, device, &allocateInfo)); VK_CHECK(vk.bindImageMemory(device, *colorTargetImage, *colorImageMemory, 0u)); #endif vector> imageViews; vector colorAttachments; RenderPassCreateInfo renderPassCreateInfo; for (deUint32 i = 0u; i < m_data.m_numLayers; i++) { const VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask 0u, // uint32_t baseMipLevel 1u, // uint32_t levelCount i, // uint32_t baseArrayLayer 1u, // uint32_t layerCount }; const VkImageViewCreateInfo imageViewCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType DE_NULL, // const void* pNext 0u, // VkImageViewCreateFlags flags *colorTargetImage, // VkImage image VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType colorAttachmentFormat, // VkFormat format ComponentMapping(), // VkComponentMapping components subresourceRange // VkImageSubresourceRange subresourceRange }; imageViews.push_back(createImageView(vk, device, &imageViewCreateInfo)); colorAttachments.push_back(*imageViews.back()); renderPassCreateInfo.addAttachment(AttachmentDescription(colorAttachmentFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); const VkAttachmentReference colorAttachmentReference = { i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, DE_NULL, 1u, &colorAttachmentReference, DE_NULL, AttachmentReference(), 0, DE_NULL)); } Unique renderPass (createRenderPass(vk, device, &renderPassCreateInfo)); const FramebufferCreateInfo framebufferCreateInfo (*renderPass, colorAttachments, WIDTH, HEIGHT, 1); Unique framebuffer (createFramebuffer(vk, device, &framebufferCreateInfo)); const VkVertexInputBindingDescription vertexInputBindingDescription = { 0, // uint32_t binding (deUint32)sizeof(tcu::Vec4) * 2, // uint32_t stride VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate }; const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = { { 0u, // uint32_t location 0u, // uint32_t binding VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format 0u // uint32_t offset }, { 1u, // uint32_t location 0u, // uint32_t binding VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format (deUint32)(sizeof(float)* 4), // uint32_t offset } }; PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions); const VkDeviceSize dataSize = m_data.m_vertices.size() * sizeof(PositionColorVertex); de::SharedPtr vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible); deUint8* ptr = reinterpret_cast(vertexBuffer->getBoundMemory().getHostPtr()); deMemcpy(ptr, &(m_data.m_vertices[0]), static_cast(dataSize)); flushAlloc(vk, device, vertexBuffer->getBoundMemory()); const CmdPoolCreateInfo cmdPoolCreateInfo (queueFamilyIndex); const Unique cmdPool (createCommandPool(vk, device, &cmdPoolCreateInfo)); const Unique cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); const Unique vs (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0)); const Unique fs (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0)); VkViewport viewport = makeViewport(WIDTH, HEIGHT); VkRect2D scissor = makeRect2D(WIDTH, HEIGHT); vector> pipelines; PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0); pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT)); pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT)); pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState)); pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)); PipelineCreateInfo::ColorBlendState::Attachment attachment; pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1u, &attachment)); pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, vector(1, viewport), vector(1, scissor))); pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState()); pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState()); pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState()); for (deUint32 i = 0; i < m_data.m_numLayers; i++) { pipelineCreateInfo.subpass = i; pipelines.push_back(createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo)); } beginCommandBuffer(vk, *cmdBuffer, 0u); const VkImageMemoryBarrier initialTransition = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType DE_NULL, // const void* pNext 0u, // VkAccessFlags srcAccessMask VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex *colorTargetImage, // VkImage image makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, m_data.m_numLayers) // VkImageSubresourceRange subresourceRange }; vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &initialTransition); const VkRect2D renderArea = makeRect2D(WIDTH, HEIGHT); vector clearColors (m_data.m_numLayers, makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f)); const VkRenderPassBeginInfo renderPassBeginInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType DE_NULL, // const void* pNext *renderPass, // VkRenderPass renderPass *framebuffer, // VkFramebuffer framebuffer renderArea, // VkRect2D renderArea (deUint32)clearColors.size(), // deUint32 clearValueCount clearColors.data(), // const VkClearValue* pClearValues }; vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); const VkDeviceSize vertexBufferOffset = 0; const VkBuffer vertexBufferObj = vertexBuffer->object(); vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBufferObj, &vertexBufferOffset); for (deUint32 i = 0; i < m_data.m_numLayers; i++) { if (i != 0) vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelines[i]); vk.cmdDraw(*cmdBuffer, 9u, 1u, i * 9u, 0u); } endRenderPass(vk, *cmdBuffer); const VkImageMemoryBarrier imageBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType DE_NULL, // const void* pNext VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex *colorTargetImage, // VkImage image makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, m_data.m_numLayers) // VkImageSubresourceRange subresourceRange; }; vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier); for (deUint32 i = 0; i < m_data.m_numLayers; i++) { const VkImageSubresourceLayers subresource = { VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask 0u, // deUint32 mipLevel i, // deUint32 baseArrayLayer 1u // deUint32 layerCount }; const VkBufferImageCopy region = { 0ull, // VkDeviceSize bufferOffset 0u, // deUint32 bufferRowLength 0u, // deUint32 bufferImageHeight subresource, // VkImageSubresourceLayers imageSubresource makeOffset3D(0, 0, 0), // VkOffset3D imageOffset makeExtent3D(WIDTH, HEIGHT, 1u) // VkExtent3D imageExtent }; vk.cmdCopyImageToBuffer(*cmdBuffer, *colorTargetImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *resultBuffers[i], 1u, ®ion); const VkBufferMemoryBarrier bufferBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType DE_NULL, // const void* pNext VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex *resultBuffers[i], // VkBuffer buffer 0ull, // VkDeviceSize offset VK_WHOLE_SIZE // VkDeviceSize size }; vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL); } endCommandBuffer(vk, *cmdBuffer); submitCommandsAndWait(vk, device, queue, cmdBuffer.get()); qpTestResult res = QP_TEST_RESULT_PASS; for (deUint32 i = 0; i < m_data.m_numLayers; i++) { invalidateMappedMemoryRange(vk, m_context.getDevice(), resultBufferAllocations[i]->getMemory(), resultBufferAllocations[i]->getOffset(), VK_WHOLE_SIZE); tcu::TextureLevel refImage(mapVkFormat(colorAttachmentFormat), WIDTH, HEIGHT); tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); vector vertices; vector colors; for (int v = 0; v < 9; v++) { int idx = i * 9 + v; vertices.push_back(m_data.m_vertices[idx].position); colors.push_back(m_data.m_vertices[idx].color); } generateRefImage(refImage.getAccess(), vertices, colors); const tcu::TextureFormat format (mapVkFormat(colorAttachmentFormat)); const void *const ptrResult (resultBufferAllocations[i]->getHostPtr()); const tcu::ConstPixelBufferAccess renderedFrame (format, WIDTH, HEIGHT, 1, ptrResult); if (!tcu::fuzzyCompare(log, "Result", "Image comparison result", refImage.getAccess(), renderedFrame, 0.053f, tcu::COMPARE_LOG_RESULT)) res = QP_TEST_RESULT_FAIL; } return tcu::TestStatus(res, qpGetTestResultName(res)); } void createAhbDrawTests (tcu::TestCaseGroup* testGroup) { testGroup->addChild(new AhbTestCase(testGroup->getTestContext(), "triangle_list", "Draw triangle list to a single layer color buffer", DrawParams(9u, 1u))); testGroup->addChild(new AhbTestCase(testGroup->getTestContext(), "triangle_list_layers_3", "Draw triangle list to a color buffer with three layers", DrawParams(9u * 3u, 3u))); testGroup->addChild(new AhbTestCase(testGroup->getTestContext(), "triangle_list_layers_5", "Draw triangle list to a color buffer with five layers", DrawParams(9u * 5u, 5u))); testGroup->addChild(new AhbTestCase(testGroup->getTestContext(), "triangle_list_layers_8", "Draw triangle list to a color buffer with eight layers", DrawParams(9u * 8u, 8u))); } } // anonymous tcu::TestCaseGroup* createAhbTests (tcu::TestContext& testCtx) { return createTestGroup(testCtx, "ahb", "Draw tests using Android Hardware Buffer", createAhbDrawTests); } } // DrawTests } // vkt