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 "vkBarrierUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkBuilderUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 #include "vkObjUtil.hpp"
39
40 #include <string>
41
42 namespace vkt
43 {
44 namespace geometry
45 {
46 using namespace vk;
47 using tcu::IVec2;
48 using tcu::Vec4;
49 using tcu::TestStatus;
50 using tcu::TestContext;
51 using tcu::TestCaseGroup;
52 using de::MovePtr;
53 using std::string;
54 using std::vector;
55 using std::size_t;
56
57 static const int TEST_CANVAS_SIZE = 256;
58
GeometryExpanderRenderTestInstance(Context & context,const VkPrimitiveTopology primitiveType,const char * name)59 GeometryExpanderRenderTestInstance::GeometryExpanderRenderTestInstance (Context& context,
60 const VkPrimitiveTopology primitiveType,
61 const char* name)
62 : TestInstance (context)
63 , m_primitiveType (primitiveType)
64 , m_name (name)
65 {
66 checkGeometryShaderSupport(context.getInstanceInterface(), context.getPhysicalDevice());
67 }
68
iterate(void)69 tcu::TestStatus GeometryExpanderRenderTestInstance::iterate (void)
70 {
71 const DeviceInterface& vk = m_context.getDeviceInterface();
72 const VkDevice device = m_context.getDevice();
73 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
74 const VkQueue queue = m_context.getUniversalQueue();
75 Allocator& memAlloc = m_context.getDefaultAllocator();
76 const IVec2 resolution = IVec2(TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
77 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
78 const Image colorAttachmentImage (
79 vk,
80 device,
81 memAlloc,
82 makeImageCreateInfo(resolution, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
83 MemoryRequirement::Any
84 );
85 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat));
86
87 const Move<VkPipelineLayout> pipelineLayout (createPipelineLayout(vk, device));
88 const VkImageSubresourceRange colorSubRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
89 const Unique<VkImageView> colorAttachmentView (makeImageView(vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubRange));
90 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, *colorAttachmentView, resolution.x(), resolution.y(), 1u));
91 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
92 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
93
94 const VkDeviceSize vertexDataSizeBytes = sizeInBytes(m_vertexPosData) + sizeInBytes(m_vertexAttrData);
95 const deUint32 vertexPositionsOffset = 0u;
96 const deUint32 vertexAtrrOffset = static_cast<deUint32>(sizeof(Vec4));
97 const string geometryShaderName = (m_context.getBinaryCollection().contains("geometry_pointsize") && checkPointSize (m_context.getInstanceInterface(), m_context.getPhysicalDevice()))?
98 "geometry_pointsize" : "geometry";
99
100 const Unique<VkPipeline> pipeline (GraphicsPipelineBuilder()
101 .setRenderSize (resolution)
102 .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vertex"), DE_NULL)
103 .setShader (vk, device, VK_SHADER_STAGE_GEOMETRY_BIT, m_context.getBinaryCollection().get(geometryShaderName), DE_NULL)
104 .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("fragment"), DE_NULL)
105 .addVertexBinding (makeVertexInputBindingDescription(0u, 2u*vertexAtrrOffset, VK_VERTEX_INPUT_RATE_VERTEX))
106 .addVertexAttribute (makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertexPositionsOffset))
107 .addVertexAttribute (makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertexAtrrOffset))
108 .setPrimitiveTopology (m_primitiveType)
109 .build (vk, device, *pipelineLayout, *renderPass));
110
111 const VkDeviceSize colorBufferSizeBytes = resolution.x()*resolution.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
112 const Buffer colorBuffer (vk, device, memAlloc, makeBufferCreateInfo(colorBufferSizeBytes,
113 VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible);
114 const Buffer vertexBuffer (vk, device, memAlloc, makeBufferCreateInfo(vertexDataSizeBytes,
115 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ), MemoryRequirement::HostVisible);
116 {
117 const Allocation& alloc = vertexBuffer.getAllocation();
118 struct DataVec4
119 {
120 Vec4 pos;
121 Vec4 color;
122 };
123
124 DataVec4* const pData = static_cast<DataVec4*>(alloc.getHostPtr());
125 for(int ndx = 0; ndx < m_numDrawVertices; ++ndx)
126 {
127 pData[ndx].pos = m_vertexPosData[ndx];
128 pData[ndx].color = m_vertexAttrData[ndx];
129 }
130 flushAlloc(vk, device, alloc);
131 // No barrier needed, flushed memory is automatically visible
132 }
133
134 // Draw commands
135 beginCommandBuffer(vk, *cmdBuffer);
136
137 // Change color attachment image layout
138 {
139 const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
140 (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
141 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
142 *colorAttachmentImage, colorSubRange);
143
144 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
145 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
146 }
147
148 // Begin render pass
149 {
150 const VkRect2D renderArea = {
151 makeOffset2D(0, 0),
152 makeExtent2D(resolution.x(), resolution.y()),
153 };
154 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
155 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
156 }
157
158 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
159 {
160 const VkBuffer buffers[] = { vertexBuffer.get()};
161 const VkDeviceSize offsets[] = { vertexPositionsOffset };
162 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(buffers), buffers, offsets);
163 }
164
165 bindDescriptorSets(vk, device, memAlloc, *cmdBuffer, *pipelineLayout);
166
167 drawCommand (*cmdBuffer);
168 endRenderPass(vk, *cmdBuffer);
169
170 // Copy render result to a host-visible buffer
171 copyImageToBuffer(vk, *cmdBuffer, *colorAttachmentImage, *colorBuffer, resolution);
172
173 endCommandBuffer(vk, *cmdBuffer);
174 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
175
176 {
177 // Log the result image.
178 const Allocation& colorBufferAlloc = colorBuffer.getAllocation();
179 invalidateMappedMemoryRange(vk, device, colorBufferAlloc.getMemory(), colorBufferAlloc.getOffset(), colorBufferSizeBytes);
180 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), resolution.x(), resolution.y(), 1, colorBufferAlloc.getHostPtr());
181
182 if (!compareWithFileImage(m_context, imagePixelAccess, m_name))
183 return TestStatus::fail("Fail");
184 }
185
186 return TestStatus::pass("Pass");
187 }
188
createPipelineLayout(const DeviceInterface & vk,const VkDevice device)189 Move<VkPipelineLayout> GeometryExpanderRenderTestInstance::createPipelineLayout (const DeviceInterface& vk, const VkDevice device)
190 {
191 return makePipelineLayout(vk, device);
192 }
193
drawCommand(const VkCommandBuffer & cmdBuffer)194 void GeometryExpanderRenderTestInstance::drawCommand (const VkCommandBuffer& cmdBuffer)
195 {
196 const DeviceInterface& vk = m_context.getDeviceInterface();
197 vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_numDrawVertices), 1u, 0u, 0u);
198 }
199
200 } // geometry
201 } // vkt
202