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