/*------------------------------------------------------------------------ * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2016 The Khronos Group Inc. * Copyright (c) 2016 The Android Open Source Project * * 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 Geometry Basic Class *//*--------------------------------------------------------------------*/ #include "vktGeometryBasicClass.hpp" #include "vkDefs.hpp" #include "vktTestCase.hpp" #include "vktTestCaseUtil.hpp" #include "vkBarrierUtil.hpp" #include "vkImageUtil.hpp" #include "vkPrograms.hpp" #include "vkBuilderUtil.hpp" #include "vkRefUtil.hpp" #include "vkQueryUtil.hpp" #include "vkMemUtil.hpp" #include "vkCmdUtil.hpp" #include "vkObjUtil.hpp" #include "vkBufferWithMemory.hpp" #include "vkImageWithMemory.hpp" #include namespace vkt { namespace geometry { using namespace vk; using tcu::IVec2; using tcu::Vec4; using tcu::TestStatus; using tcu::TestContext; using tcu::TestCaseGroup; using de::MovePtr; using std::string; using std::vector; using std::size_t; static const int TEST_CANVAS_SIZE = 256; GeometryExpanderRenderTestInstance::GeometryExpanderRenderTestInstance (Context& context, const VkPrimitiveTopology primitiveType, const char* name) : TestInstance (context) , m_primitiveType (primitiveType) , m_name (name) , m_numDrawVertices (0) { } tcu::TestStatus GeometryExpanderRenderTestInstance::iterate (void) { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); const VkQueue queue = m_context.getUniversalQueue(); Allocator& memAlloc = m_context.getDefaultAllocator(); const IVec2 resolution = IVec2(TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; const ImageWithMemory colorAttachmentImage ( vk, device, memAlloc, makeImageCreateInfo(resolution, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::Any ); const Unique renderPass (makeRenderPass(vk, device, colorFormat)); const Move pipelineLayout (createPipelineLayout(vk, device)); const VkImageSubresourceRange colorSubRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); const Unique colorAttachmentView (makeImageView(vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubRange)); const Unique framebuffer (makeFramebuffer(vk, device, *renderPass, *colorAttachmentView, resolution.x(), resolution.y(), 1u)); const Unique cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); const Unique cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); const VkDeviceSize vertexDataSizeBytes = sizeInBytes(m_vertexPosData) + sizeInBytes(m_vertexAttrData); const deUint32 vertexPositionsOffset = 0u; const deUint32 vertexAtrrOffset = static_cast(sizeof(Vec4)); const string geometryShaderName = (m_context.getBinaryCollection().contains("geometry_pointsize") && checkPointSize (m_context.getInstanceInterface(), m_context.getPhysicalDevice()))? "geometry_pointsize" : "geometry"; const Unique pipeline (GraphicsPipelineBuilder() .setRenderSize (resolution) .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vertex"), DE_NULL) .setShader (vk, device, VK_SHADER_STAGE_GEOMETRY_BIT, m_context.getBinaryCollection().get(geometryShaderName), DE_NULL) .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("fragment"), DE_NULL) .addVertexBinding (makeVertexInputBindingDescription(0u, 2u*vertexAtrrOffset, VK_VERTEX_INPUT_RATE_VERTEX)) .addVertexAttribute (makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertexPositionsOffset)) .addVertexAttribute (makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertexAtrrOffset)) .setPrimitiveTopology (m_primitiveType) .build (vk, device, *pipelineLayout, *renderPass)); const VkDeviceSize colorBufferSizeBytes = resolution.x()*resolution.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); const BufferWithMemory colorBuffer (vk, device, memAlloc, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible); const BufferWithMemory vertexBuffer (vk, device, memAlloc, makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ), MemoryRequirement::HostVisible); { const Allocation& alloc = vertexBuffer.getAllocation(); struct DataVec4 { Vec4 pos; Vec4 color; }; DataVec4* const pData = static_cast(alloc.getHostPtr()); for(int ndx = 0; ndx < m_numDrawVertices; ++ndx) { pData[ndx].pos = m_vertexPosData[ndx]; pData[ndx].color = m_vertexAttrData[ndx]; } flushAlloc(vk, device, alloc); // No barrier needed, flushed memory is automatically visible } // Draw commands beginCommandBuffer(vk, *cmdBuffer); // Change color attachment image layout { const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier( (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorAttachmentImage, colorSubRange); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier); } // Begin render pass { const VkRect2D renderArea = { makeOffset2D(0, 0), makeExtent2D(resolution.x(), resolution.y()), }; const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f); beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor); } vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); { const VkBuffer buffers[] = { vertexBuffer.get()}; const VkDeviceSize offsets[] = { vertexPositionsOffset }; vk.cmdBindVertexBuffers(*cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(buffers), buffers, offsets); } bindDescriptorSets(vk, device, memAlloc, *cmdBuffer, *pipelineLayout); drawCommand (*cmdBuffer); endRenderPass(vk, *cmdBuffer); // Copy render result to a host-visible buffer copyImageToBuffer(vk, *cmdBuffer, *colorAttachmentImage, *colorBuffer, resolution); endCommandBuffer(vk, *cmdBuffer); submitCommandsAndWait(vk, device, queue, *cmdBuffer); { // Log the result image. const Allocation& colorBufferAlloc = colorBuffer.getAllocation(); invalidateAlloc(vk, device, colorBufferAlloc); const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), resolution.x(), resolution.y(), 1, colorBufferAlloc.getHostPtr()); if (!compareWithFileImage(m_context, imagePixelAccess, m_name)) return TestStatus::fail("Fail"); } return TestStatus::pass("Pass"); } Move GeometryExpanderRenderTestInstance::createPipelineLayout (const DeviceInterface& vk, const VkDevice device) { return makePipelineLayout(vk, device); } void GeometryExpanderRenderTestInstance::drawCommand (const VkCommandBuffer& cmdBuffer) { const DeviceInterface& vk = m_context.getDeviceInterface(); vk.cmdDraw(cmdBuffer, static_cast(m_numDrawVertices), 1u, 0u, 0u); } } // geometry } // vkt