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