1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group Inc. 6 * Copyright (c) 2016 The Android Open Source Project 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 *//*! 21 * \file 22 * \brief Geometry Basic Class 23 *//*--------------------------------------------------------------------*/ 24 25#include "vktGeometryBasicClass.hpp" 26 27#include "vkDefs.hpp" 28#include "vktTestCase.hpp" 29#include "vktTestCaseUtil.hpp" 30#include "vkImageUtil.hpp" 31#include "vkPrograms.hpp" 32#include "vkBuilderUtil.hpp" 33#include "vkRefUtil.hpp" 34#include "vkQueryUtil.hpp" 35#include "vkMemUtil.hpp" 36 37#include <string> 38 39namespace vkt 40{ 41namespace geometry 42{ 43using namespace vk; 44using tcu::IVec2; 45using tcu::Vec4; 46using tcu::TestStatus; 47using tcu::TestContext; 48using tcu::TestCaseGroup; 49using de::MovePtr; 50using std::string; 51using std::vector; 52using std::size_t; 53 54static const int TEST_CANVAS_SIZE = 256; 55 56GeometryExpanderRenderTestInstance::GeometryExpanderRenderTestInstance (Context& context, 57 const VkPrimitiveTopology primitiveType, 58 const char* name) 59 : TestInstance (context) 60 , m_primitiveType (primitiveType) 61 , m_name (name) 62{ 63 checkGeometryShaderSupport(context.getInstanceInterface(), context.getPhysicalDevice()); 64} 65 66tcu::TestStatus GeometryExpanderRenderTestInstance::iterate (void) 67{ 68 const DeviceInterface& vk = m_context.getDeviceInterface(); 69 const VkDevice device = m_context.getDevice(); 70 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 71 const VkQueue queue = m_context.getUniversalQueue(); 72 Allocator& memAlloc = m_context.getDefaultAllocator(); 73 const IVec2 resolution = IVec2(TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 74 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 75 const Image colorAttachmentImage ( 76 vk, 77 device, 78 memAlloc, 79 makeImageCreateInfo(resolution, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT), 80 MemoryRequirement::Any 81 ); 82 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat)); 83 84 const Move<VkPipelineLayout> pipelineLayout (createPipelineLayout(vk, device)); 85 const VkImageSubresourceRange colorSubRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 86 const Unique<VkImageView> colorAttachmentView (makeImageView(vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubRange)); 87 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, *colorAttachmentView, resolution.x(), resolution.y(), 1u)); 88 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 89 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 90 91 const VkDeviceSize vertexDataSizeBytes = sizeInBytes(m_vertexPosData) + sizeInBytes(m_vertexAttrData); 92 const deUint32 vertexPositionsOffset = 0u; 93 const deUint32 vertexAtrrOffset = static_cast<deUint32>(sizeof(Vec4)); 94 const string geometryShaderName = (m_context.getBinaryCollection().contains("geometry_pointsize") && checkPointSize (m_context.getInstanceInterface(), m_context.getPhysicalDevice()))? 95 "geometry_pointsize" : "geometry"; 96 97 const Unique<VkPipeline> pipeline (GraphicsPipelineBuilder() 98 .setRenderSize (resolution) 99 .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vertex"), DE_NULL) 100 .setShader (vk, device, VK_SHADER_STAGE_GEOMETRY_BIT, m_context.getBinaryCollection().get(geometryShaderName), DE_NULL) 101 .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("fragment"), DE_NULL) 102 .addVertexBinding (makeVertexInputBindingDescription(0u, 2u*vertexAtrrOffset, VK_VERTEX_INPUT_RATE_VERTEX)) 103 .addVertexAttribute (makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertexPositionsOffset)) 104 .addVertexAttribute (makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertexAtrrOffset)) 105 .setPrimitiveTopology (m_primitiveType) 106 .build (vk, device, *pipelineLayout, *renderPass)); 107 108 const VkDeviceSize colorBufferSizeBytes = resolution.x()*resolution.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); 109 const Buffer colorBuffer (vk, device, memAlloc, makeBufferCreateInfo(colorBufferSizeBytes, 110 VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible); 111 const Buffer vertexBuffer (vk, device, memAlloc, makeBufferCreateInfo(vertexDataSizeBytes, 112 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ), MemoryRequirement::HostVisible); 113 { 114 const Allocation& alloc = vertexBuffer.getAllocation(); 115 struct DataVec4 116 { 117 Vec4 pos; 118 Vec4 color; 119 }; 120 121 DataVec4* const pData = static_cast<DataVec4*>(alloc.getHostPtr()); 122 for(int ndx = 0; ndx < m_numDrawVertices; ++ndx) 123 { 124 pData[ndx].pos = m_vertexPosData[ndx]; 125 pData[ndx].color = m_vertexAttrData[ndx]; 126 } 127 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), vertexDataSizeBytes); 128 // No barrier needed, flushed memory is automatically visible 129 } 130 131 // Draw commands 132 beginCommandBuffer(vk, *cmdBuffer); 133 134 // Change color attachment image layout 135 { 136 const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier( 137 (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 138 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 139 *colorAttachmentImage, colorSubRange); 140 141 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 142 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier); 143 } 144 145 // Begin render pass 146 { 147 const VkRect2D renderArea = { 148 makeOffset2D(0, 0), 149 makeExtent2D(resolution.x(), resolution.y()), 150 }; 151 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f); 152 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor); 153 } 154 155 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); 156 { 157 const VkBuffer buffers[] = { vertexBuffer.get()}; 158 const VkDeviceSize offsets[] = { vertexPositionsOffset }; 159 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(buffers), buffers, offsets); 160 } 161 162 bindDescriptorSets(vk, device, memAlloc, *cmdBuffer, *pipelineLayout); 163 164 drawCommand (*cmdBuffer); 165 endRenderPass(vk, *cmdBuffer); 166 167 // Copy render result to a host-visible buffer 168 { 169 const VkImageMemoryBarrier colorAttachmentPreCopyBarrier = makeImageMemoryBarrier( 170 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, 171 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 172 *colorAttachmentImage, colorSubRange); 173 174 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 175 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentPreCopyBarrier); 176 } 177 { 178 const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(resolution.x(), resolution.y(), 1), makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u)); 179 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorAttachmentImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ©Region); 180 } 181 182 { 183 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes); 184 185 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 186 0u, DE_NULL, 1u, &postCopyBarrier, 0u, DE_NULL); 187 } 188 189 endCommandBuffer(vk, *cmdBuffer); 190 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 191 192 { 193 // Log the result image. 194 const Allocation& colorBufferAlloc = colorBuffer.getAllocation(); 195 invalidateMappedMemoryRange(vk, device, colorBufferAlloc.getMemory(), colorBufferAlloc.getOffset(), colorBufferSizeBytes); 196 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), resolution.x(), resolution.y(), 1, colorBufferAlloc.getHostPtr()); 197 198 if (!compareWithFileImage(m_context, imagePixelAccess, m_name)) 199 return TestStatus::fail("Fail"); 200 } 201 202 return TestStatus::pass("Pass"); 203} 204 205Move<VkPipelineLayout> GeometryExpanderRenderTestInstance::createPipelineLayout (const DeviceInterface& vk, const VkDevice device) 206{ 207 return makePipelineLayout(vk, device); 208} 209 210void GeometryExpanderRenderTestInstance::drawCommand (const VkCommandBuffer& cmdBuffer) 211{ 212 const DeviceInterface& vk = m_context.getDeviceInterface(); 213 vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numDrawVertices), 1u, 0u, 0u); 214} 215 216} // geometry 217} // vkt 218