1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2023 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief glPointSize clamp test
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktDrawPointClampTests.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27
28 #include "vkPrograms.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkImageUtil.hpp"
36
37 #include "tcuTestLog.hpp"
38 #include "tcuFormatUtil.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuImageCompare.hpp"
41
42 #include "deUniquePtr.hpp"
43 #include "deMath.h"
44
45 namespace vkt
46 {
47 namespace Draw
48 {
49
50 using namespace vk;
51 using namespace de;
52
53 struct Vertex
54 {
55 tcu::Vec4 pos;
56 tcu::Vec4 color;
57 };
58
createPointSizeClampProgs(SourceCollections & dst)59 void createPointSizeClampProgs(SourceCollections &dst)
60 {
61 std::stringstream vertShader;
62 vertShader << "#version 450\n"
63 << "layout(location = 0) in vec4 in_position;\n"
64 << "layout(location = 1) in vec4 in_color;\n"
65 << "layout(push_constant) uniform pointSizeBlk {\n"
66 << " float psize;\n"
67 << "} in_pointSize;\n"
68 << "layout(location = 0) out vec4 out_color;\n"
69
70 << "out gl_PerVertex {\n"
71 << " vec4 gl_Position;\n"
72 << " float gl_PointSize;\n"
73 << "};\n"
74 << "void main() {\n"
75 << " gl_PointSize = in_pointSize.psize;\n"
76 << " gl_Position = in_position;\n"
77 << " out_color = in_color;\n"
78 << "}\n";
79
80 std::stringstream fragShader;
81 fragShader << "#version 450\n"
82 << "layout(location = 0) flat in vec4 in_color;\n"
83 << "layout(location = 0) out vec4 out_color;\n"
84 << "void main()\n"
85 << "{\n"
86 << " out_color = in_color;\n"
87 << "}\n";
88
89 dst.glslSources.add("vert") << glu::VertexSource(vertShader.str());
90 dst.glslSources.add("frag") << glu::FragmentSource(fragShader.str());
91 }
92
renderPointSizeClampTest(Context & context)93 tcu::TestStatus renderPointSizeClampTest(Context &context)
94 {
95 const VkDevice vkDevice = context.getDevice();
96 const DeviceInterface &vk = context.getDeviceInterface();
97 const VkQueue queue = context.getUniversalQueue();
98 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
99 const VkPhysicalDevice phyDevice = context.getPhysicalDevice();
100 SimpleAllocator memAlloc(vk, vkDevice,
101 getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), phyDevice));
102 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
103 const tcu::Vec4 clearColor(0.0f, 1.0f, 0.0f, 1.0f);
104 const tcu::Vec4 pointColor(0.0f, 0.0f, 0.0f, 0.0f);
105
106 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(context.getInstanceInterface(), phyDevice);
107 if (!features.largePoints)
108 throw tcu::NotSupportedError("Large points not supported");
109
110 VkPhysicalDeviceProperties phyDevProps;
111 context.getInstanceInterface().getPhysicalDeviceProperties(phyDevice, &phyDevProps);
112
113 //float minPointSizeRange = phyDevProps.limits.pointSizeRange[0];
114 float maxPointSizeRange = phyDevProps.limits.pointSizeRange[1];
115
116 uint32_t fbWidthSize = deCeilFloatToInt32(maxPointSizeRange * 0.5f) + 1;
117
118 const tcu::IVec2 renderSize(fbWidthSize, 1);
119
120 const float testPointSize = deFloatFloor(maxPointSizeRange * 2.0f);
121
122 VkPushConstantRange pcPointSize;
123 pcPointSize.offset = 0;
124 pcPointSize.size = sizeof(float);
125 pcPointSize.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
126
127 float pxCenter = (float)fbWidthSize - 0.25f;
128
129 float testPointXCoord = ((2.0f * pxCenter) / (float)fbWidthSize) - 1.0f;
130
131 const struct Vertex vertices[] = {{tcu::Vec4(testPointXCoord, 0.0f, 0.0f, 1.0f), pointColor}};
132
133 const VkBufferCreateInfo vertexBufferParams = {
134 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
135 DE_NULL, // pNext
136 0u, // flags
137 (VkDeviceSize)sizeof(vertices), // size
138 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // usage
139 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
140 1u, // queueFamilyIndexCount
141 &queueFamilyIndex, // pQueueFamilyIndices
142 };
143 const Unique<VkBuffer> vertexBuffer(createBuffer(vk, vkDevice, &vertexBufferParams));
144 const UniquePtr<Allocation> vertexBufferMemory(
145 memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible));
146
147 VK_CHECK(
148 vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
149
150 const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(uint32_t) * renderSize.x() * renderSize.y());
151 const VkBufferCreateInfo readImageBufferParams = {
152 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
153 DE_NULL, // pNext
154 (VkBufferCreateFlags)0u, // flags
155 imageSizeBytes, // size
156 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
157 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
158 1u, // queueFamilyIndexCount
159 &queueFamilyIndex, // pQueueFamilyIndices
160 };
161 const Unique<VkBuffer> readImageBuffer(createBuffer(vk, vkDevice, &readImageBufferParams));
162 const UniquePtr<Allocation> readImageBufferMemory(
163 memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
164
165 VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(),
166 readImageBufferMemory->getOffset()));
167
168 const VkImageCreateInfo imageParams = {
169 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
170 DE_NULL, // pNext
171 0u, // flags
172 VK_IMAGE_TYPE_2D, // imageType
173 colorFormat, // format
174 {(uint32_t)renderSize.x(), (uint32_t)renderSize.y(), 1}, // extent
175 1u, // mipLevels
176 1u, // arraySize
177 VK_SAMPLE_COUNT_1_BIT, // samples
178 VK_IMAGE_TILING_OPTIMAL, // tiling
179 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // usage
180 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
181 1u, // queueFamilyIndexCount
182 &queueFamilyIndex, // pQueueFamilyIndices
183 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
184 };
185
186 const Unique<VkImage> image(createImage(vk, vkDevice, &imageParams));
187 const UniquePtr<Allocation> imageMemory(
188 memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any));
189
190 VK_CHECK(vk.bindImageMemory(vkDevice, *image, imageMemory->getMemory(), imageMemory->getOffset()));
191
192 const Unique<VkRenderPass> renderPass(makeRenderPass(vk, vkDevice, colorFormat));
193
194 const VkImageViewCreateInfo colorAttViewParams = {
195 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
196 DE_NULL, // pNext
197 0u, // flags
198 *image, // image
199 VK_IMAGE_VIEW_TYPE_2D, // viewType
200 colorFormat, // format
201 {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}, // components
202 {
203 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
204 0u, // baseMipLevel
205 1u, // levelCount
206 0u, // baseArrayLayer
207 1u, // layerCount
208 }, // subresourceRange
209 };
210 const Unique<VkImageView> colorAttView(createImageView(vk, vkDevice, &colorAttViewParams));
211
212 // Pipeline layout
213 const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
214 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
215 DE_NULL, // pNext
216 (vk::VkPipelineLayoutCreateFlags)0,
217 0u, // setLayoutCount
218 DE_NULL, // pSetLayouts
219 1u, // pushConstantRangeCount
220 &pcPointSize, // pPushConstantRanges
221 };
222 const Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(vk, vkDevice, &pipelineLayoutParams));
223
224 // Shaders
225 const Unique<VkShaderModule> vertShaderModule(
226 createShaderModule(vk, vkDevice, context.getBinaryCollection().get("vert"), 0));
227 const Unique<VkShaderModule> fragShaderModule(
228 createShaderModule(vk, vkDevice, context.getBinaryCollection().get("frag"), 0));
229
230 // Pipeline
231 const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
232 const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
233
234 const VkVertexInputBindingDescription vertexInputBindingDescription = {
235 0u, // uint32_t binding
236 sizeof(Vertex), // uint32_t stride
237 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate
238 };
239
240 const VkVertexInputAttributeDescription vertexInputAttributeDescriptionPos = {
241 0u, // uint32_t location
242 0u, // uint32_t binding
243 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format
244 offsetof(Vertex, pos) // uint32_t offset
245 };
246
247 const VkVertexInputAttributeDescription vertexInputAttributeDescriptionColor = {
248 1u, // uint32_t location
249 0u, // uint32_t binding
250 colorFormat, // VkFormat format
251 offsetof(Vertex, color) // uint32_t offset
252 };
253
254 std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions;
255 vertexInputAttributeDescriptions.resize(2);
256 vertexInputAttributeDescriptions[0] = vertexInputAttributeDescriptionPos;
257 vertexInputAttributeDescriptions[1] = vertexInputAttributeDescriptionColor;
258
259 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
260 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
261 DE_NULL, // const void* pNext
262 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags
263 1u, // uint32_t vertexBindingDescriptionCount
264 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
265 (uint32_t)vertexInputAttributeDescriptions
266 .size(), // uint32_t vertexAttributeDescriptionCount
267 &vertexInputAttributeDescriptions[0] // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
268 };
269
270 const Unique<VkPipeline> pipeline(makeGraphicsPipeline(
271 vk, // const DeviceInterface& vk
272 vkDevice, // const VkDevice device
273 *pipelineLayout, // const VkPipelineLayout pipelineLayout
274 *vertShaderModule, // const VkShaderModule vertexShaderModule
275 DE_NULL, // const VkShaderModule tessellationControlModule
276 DE_NULL, // const VkShaderModule tessellationEvalModule
277 DE_NULL, // const VkShaderModule geometryShaderModule
278 *fragShaderModule, // const VkShaderModule fragmentShaderModule
279 *renderPass, // const VkRenderPass renderPass
280 viewports, // const std::vector<VkViewport>& viewports
281 scissors, // const std::vector<VkRect2D>& scissors
282 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // const VkPrimitiveTopology topology
283 0u, // const uint32_t subpass
284 0u, // const uint32_t patchControlPoints
285 &vertexInputStateCreateInfo)); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
286
287 // Framebuffer
288 const VkFramebufferCreateInfo framebufferParams = {
289 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
290 DE_NULL, // pNext
291 0u, // flags
292 *renderPass, // renderPass
293 1u, // attachmentCount
294 &*colorAttView, // pAttachments
295 (uint32_t)renderSize.x(), // width
296 (uint32_t)renderSize.y(), // height
297 1u, // layers
298 };
299 const Unique<VkFramebuffer> framebuffer(createFramebuffer(vk, vkDevice, &framebufferParams));
300
301 const VkCommandPoolCreateInfo cmdPoolParams = {
302 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
303 DE_NULL, // pNext
304 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
305 queueFamilyIndex, // queueFamilyIndex
306 };
307 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
308
309 // Command buffer
310 const VkCommandBufferAllocateInfo cmdBufParams = {
311 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
312 DE_NULL, // pNext
313 *cmdPool, // pool
314 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
315 1u, // bufferCount
316 };
317 const Unique<VkCommandBuffer> cmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
318
319 // Record commands
320 beginCommandBuffer(vk, *cmdBuf);
321
322 {
323 const VkMemoryBarrier vertFlushBarrier = {
324 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
325 DE_NULL, // pNext
326 VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask
327 VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // dstAccessMask
328 };
329 const VkImageMemoryBarrier colorAttBarrier = {
330 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
331 DE_NULL, // pNext
332 0u, // srcAccessMask
333 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), // dstAccessMask
334 VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
335 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
336 queueFamilyIndex, // srcQueueFamilyIndex
337 queueFamilyIndex, // dstQueueFamilyIndex
338 *image, // image
339 {
340 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
341 0u, // baseMipLevel
342 1u, // levelCount
343 0u, // baseArrayLayer
344 1u, // layerCount
345 } // subresourceRange
346 };
347 vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
348 (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier *)DE_NULL, 1,
349 &colorAttBarrier);
350 }
351
352 beginRenderPass(vk, *cmdBuf, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()),
353 clearColor);
354
355 vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
356 {
357 const VkDeviceSize bindingOffset = 0;
358 vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
359 }
360 vk.cmdPushConstants(*cmdBuf, *pipelineLayout, pcPointSize.stageFlags, pcPointSize.offset, pcPointSize.size,
361 &testPointSize);
362 vk.cmdDraw(*cmdBuf, 1u, 1u, 0u, 0u);
363 endRenderPass(vk, *cmdBuf);
364 copyImageToBuffer(vk, *cmdBuf, *image, *readImageBuffer, renderSize);
365 endCommandBuffer(vk, *cmdBuf);
366
367 // Upload vertex data
368 deMemcpy(vertexBufferMemory->getHostPtr(), &vertices[0], sizeof(vertices));
369 flushAlloc(vk, vkDevice, *vertexBufferMemory);
370
371 // Submit & wait for completion
372 submitCommandsAndWait(vk, vkDevice, queue, cmdBuf.get());
373
374 {
375 invalidateAlloc(vk, vkDevice, *readImageBufferMemory);
376 const tcu::TextureFormat tcuFormat = vk::mapVkFormat(colorFormat);
377 const tcu::ConstPixelBufferAccess resultAccess(tcuFormat, renderSize.x(), renderSize.y(), 1,
378 readImageBufferMemory->getHostPtr());
379
380 tcu::TextureLevel referenceLevel(tcuFormat, renderSize.x(), renderSize.y());
381 auto referenceAccess = referenceLevel.getAccess();
382 tcu::clear(referenceAccess, pointColor);
383 referenceAccess.setPixel(clearColor, 0, 0);
384
385 auto &log = context.getTestContext().getLog();
386 const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f);
387
388 if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, threshold,
389 tcu::COMPARE_LOG_ON_ERROR))
390 return tcu::TestStatus::fail("Unexpected color in result buffer; check log for details");
391 }
392 return tcu::TestStatus::pass("Rendering succeeded");
393 }
394
createDrawPointClampTests(tcu::TestContext & testCtx)395 tcu::TestCaseGroup *createDrawPointClampTests(tcu::TestContext &testCtx)
396 {
397 de::MovePtr<tcu::TestCaseGroup> pointClampTests(new tcu::TestCaseGroup(testCtx, "point_size_clamp"));
398
399 addFunctionCaseWithPrograms(pointClampTests.get(), "point_size_clamp_max", createPointSizeClampProgs,
400 renderPointSizeClampTest);
401
402 return pointClampTests.release();
403 }
404 } // namespace Draw
405 } // namespace vkt
406