1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 Valve Corporation.
6 * Copyright (c) 2019 The Khronos Group Inc.
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 EXT_discard_rectangles tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawDiscardRectanglesTests.hpp"
26
27 #include "vkDefs.hpp"
28 #include "vkRef.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vktTestGroupUtil.hpp"
37 #include "vktTestCase.hpp"
38 #include "vktDrawBufferObjectUtil.hpp"
39 #include "vktDrawImageObjectUtil.hpp"
40
41 #include "tcuTestCase.hpp"
42 #include "tcuVector.hpp"
43 #include "tcuTextureUtil.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuImageCompare.hpp"
46
47 #include "deUniquePtr.hpp"
48 #include "deSharedPtr.hpp"
49
50 namespace vkt
51 {
52 namespace Draw
53 {
54
55 namespace
56 {
57 using namespace vk;
58 using de::MovePtr;
59 using de::SharedPtr;
60 using de::UniquePtr;
61 using tcu::UVec2;
62 using tcu::UVec4;
63 using tcu::Vec2;
64 using tcu::Vec4;
65
66 enum TestMode
67 {
68 TEST_MODE_INCLUSIVE = 0,
69 TEST_MODE_EXCLUSIVE,
70 TEST_MODE_COUNT
71 };
72
73 enum TestScissorMode
74 {
75 TEST_SCISSOR_MODE_NONE = 0,
76 TEST_SCISSOR_MODE_STATIC,
77 TEST_SCISSOR_MODE_DYNAMIC,
78 TEST_SCISSOR_MODE_COUNT
79 };
80
81 #define NUM_RECT_TESTS 6
82 #define NUM_DYNAMIC_DISCARD_TYPE_TESTS 2
83
84 struct TestParams
85 {
86 TestMode testMode;
87 uint32_t numRectangles;
88 bool dynamicDiscardRectangles;
89 TestScissorMode scissorMode;
90 const SharedGroupParams groupParams;
91 };
92
93 template <typename T>
sizeInBytes(const std::vector<T> & vec)94 inline VkDeviceSize sizeInBytes(const std::vector<T> &vec)
95 {
96 return vec.size() * sizeof(vec[0]);
97 }
98
makeImageCreateInfo(const VkFormat format,const UVec2 & size,VkImageUsageFlags usage)99 VkImageCreateInfo makeImageCreateInfo(const VkFormat format, const UVec2 &size, VkImageUsageFlags usage)
100 {
101 const VkImageCreateInfo imageParams = {
102 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
103 DE_NULL, // const void* pNext;
104 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
105 VK_IMAGE_TYPE_2D, // VkImageType imageType;
106 format, // VkFormat format;
107 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
108 1u, // uint32_t mipLevels;
109 1u, // uint32_t arrayLayers;
110 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
111 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
112 usage, // VkImageUsageFlags usage;
113 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
114 0u, // uint32_t queueFamilyIndexCount;
115 DE_NULL, // const uint32_t* pQueueFamilyIndices;
116 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
117 };
118 return imageParams;
119 }
120
makeDiscardRectangleStateCreateInfo(const bool dynamicDiscardRectangle,const VkDiscardRectangleModeEXT discardRectangleMode,const uint32_t discardRectangleCount,const VkRect2D * pDiscardRectangles)121 VkPipelineDiscardRectangleStateCreateInfoEXT makeDiscardRectangleStateCreateInfo(
122 const bool dynamicDiscardRectangle, const VkDiscardRectangleModeEXT discardRectangleMode,
123 const uint32_t discardRectangleCount, const VkRect2D *pDiscardRectangles)
124 {
125 const VkPipelineDiscardRectangleStateCreateInfoEXT discardRectanglesCreateInfo = {
126 VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT, // VkStructureType sType;
127 DE_NULL, // const void* pNext;
128 0u, // VkPipelineDiscardRectangleStateCreateFlagsEXT flags;
129 discardRectangleMode, // VkDiscardRectangleModeEXT discardRectangleMode;
130 discardRectangleCount, // uint32_t discardRectangleCount;
131 dynamicDiscardRectangle ? DE_NULL : pDiscardRectangles // const VkRect2D* pDiscardRectangles;
132 };
133 return discardRectanglesCreateInfo;
134 }
135
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const UVec2 renderSize,const bool dynamicDiscardRectangle,const VkDiscardRectangleModeEXT discardRectangleMode,const uint32_t discardRectangleCount,const VkRect2D * pDiscardRectangles,const TestScissorMode scissorMode,const VkRect2D rectScissor)136 Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, const VkDevice device,
137 const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass,
138 const VkShaderModule vertexModule, const VkShaderModule fragmentModule,
139 const UVec2 renderSize, const bool dynamicDiscardRectangle,
140 const VkDiscardRectangleModeEXT discardRectangleMode,
141 const uint32_t discardRectangleCount, const VkRect2D *pDiscardRectangles,
142 const TestScissorMode scissorMode, const VkRect2D rectScissor)
143 {
144 const VkVertexInputBindingDescription vertexInputBindingDescription = {
145 0u, // uint32_t binding;
146 sizeof(Vec4), // uint32_t stride;
147 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
148 };
149
150 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
151 {
152 0u, // uint32_t location;
153 0u, // uint32_t binding;
154 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
155 0u, // uint32_t offset;
156 },
157 };
158
159 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = {
160 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
161 DE_NULL, // const void* pNext;
162 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
163 1u, // uint32_t vertexBindingDescriptionCount;
164 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
165 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
166 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
167 };
168
169 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = {
170 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
171 DE_NULL, // const void* pNext;
172 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
173 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology;
174 VK_FALSE, // VkBool32 primitiveRestartEnable;
175 };
176
177 VkViewport viewport =
178 makeViewport(0.0f, 0.0f, static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 0.0f, 1.0f);
179 const VkRect2D rectScissorRenderSize = {{0, 0}, {renderSize.x(), renderSize.y()}};
180
181 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = {
182 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
183 DE_NULL, // const void* pNext;
184 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
185 1u, // uint32_t viewportCount;
186 &viewport, // const VkViewport* pViewports;
187 1u, // uint32_t scissorCount;
188 scissorMode != TEST_SCISSOR_MODE_NONE ? &rectScissor : &rectScissorRenderSize, // const VkRect2D* pScissors;
189 };
190
191 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = {
192 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
193 DE_NULL, // const void* pNext;
194 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
195 VK_FALSE, // VkBool32 depthClampEnable;
196 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
197 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
198 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
199 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
200 VK_FALSE, // VkBool32 depthBiasEnable;
201 0.0f, // float depthBiasConstantFactor;
202 0.0f, // float depthBiasClamp;
203 0.0f, // float depthBiasSlopeFactor;
204 1.0f, // float lineWidth;
205 };
206
207 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = {
208 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
209 DE_NULL, // const void* pNext;
210 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
211 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
212 VK_FALSE, // VkBool32 sampleShadingEnable;
213 0.0f, // float minSampleShading;
214 DE_NULL, // const VkSampleMask* pSampleMask;
215 VK_FALSE, // VkBool32 alphaToCoverageEnable;
216 VK_FALSE // VkBool32 alphaToOneEnable;
217 };
218
219 const VkStencilOpState stencilOpState = makeStencilOpState(VK_STENCIL_OP_KEEP, // stencil fail
220 VK_STENCIL_OP_KEEP, // depth & stencil pass
221 VK_STENCIL_OP_KEEP, // depth only fail
222 VK_COMPARE_OP_ALWAYS, // compare op
223 0u, // compare mask
224 0u, // write mask
225 0u); // reference
226
227 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = {
228 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
229 DE_NULL, // const void* pNext;
230 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
231 VK_FALSE, // VkBool32 depthTestEnable;
232 VK_FALSE, // VkBool32 depthWriteEnable;
233 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
234 VK_FALSE, // VkBool32 depthBoundsTestEnable;
235 VK_FALSE, // VkBool32 stencilTestEnable;
236 stencilOpState, // VkStencilOpState front;
237 stencilOpState, // VkStencilOpState back;
238 0.0f, // float minDepthBounds;
239 1.0f, // float maxDepthBounds;
240 };
241
242 const VkColorComponentFlags colorComponentsAll =
243 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
244 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {
245 VK_FALSE, // VkBool32 blendEnable;
246 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
247 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
248 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
249 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
250 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
251 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
252 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
253 };
254
255 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = {
256 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
257 DE_NULL, // const void* pNext;
258 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
259 VK_FALSE, // VkBool32 logicOpEnable;
260 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
261 1u, // uint32_t attachmentCount;
262 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
263 {0.0f, 0.0f, 0.0f, 0.0f}, // float blendConstants[4];
264 };
265
266 const VkPipelineShaderStageCreateInfo pShaderStages[] = {
267 {
268 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
269 DE_NULL, // const void* pNext;
270 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
271 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
272 vertexModule, // VkShaderModule module;
273 "main", // const char* pName;
274 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
275 },
276 {
277 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
278 DE_NULL, // const void* pNext;
279 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
280 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
281 fragmentModule, // VkShaderModule module;
282 "main", // const char* pName;
283 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
284 },
285 };
286
287 const VkPipelineDiscardRectangleStateCreateInfoEXT discardRectangleStateCreateInfo =
288 makeDiscardRectangleStateCreateInfo(dynamicDiscardRectangle, discardRectangleMode, discardRectangleCount,
289 pDiscardRectangles);
290
291 const VkDynamicState dynamicStateDiscardRectangles = VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT;
292 const VkDynamicState dynamicStateScissor = VK_DYNAMIC_STATE_SCISSOR;
293 std::vector<VkDynamicState> dynamicStates;
294
295 if (dynamicDiscardRectangle)
296 dynamicStates.push_back(dynamicStateDiscardRectangles);
297 if (scissorMode == TEST_SCISSOR_MODE_DYNAMIC)
298 dynamicStates.push_back(dynamicStateScissor);
299
300 const VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {
301 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
302 DE_NULL, // const void* pNext;
303 0u, // VkPipelineDynamicStateCreateFlags flags;
304 (uint32_t)dynamicStates.size(), // uint32_t dynamicStateCount;
305 dynamicStates.data() // const VkDynamicState* pDynamicStates;
306 };
307
308 VkGraphicsPipelineCreateInfo graphicsPipelineInfo = {
309 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
310 &discardRectangleStateCreateInfo, // const void* pNext;
311 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
312 2u, // uint32_t stageCount;
313 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
314 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
315 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
316 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
317 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
318 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
319 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
320 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
321 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
322 &pipelineDynamicStateCreateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
323 pipelineLayout, // VkPipelineLayout layout;
324 renderPass, // VkRenderPass renderPass;
325 0u, // uint32_t subpass;
326 DE_NULL, // VkPipeline basePipelineHandle;
327 0, // int32_t basePipelineIndex;
328 };
329
330 #ifndef CTS_USES_VULKANSC
331 VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
332 vk::VkPipelineRenderingCreateInfoKHR renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
333 &discardRectangleStateCreateInfo,
334 0u,
335 1u,
336 &colorAttachmentFormat,
337 VK_FORMAT_UNDEFINED,
338 VK_FORMAT_UNDEFINED};
339
340 // when pipeline is created without render pass we are using dynamic rendering
341 if (renderPass == DE_NULL)
342 graphicsPipelineInfo.pNext = &renderingCreateInfo;
343 #endif // CTS_USES_VULKANSC
344
345 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
346 }
347
generateDiscardRectangles(const UVec2 & renderSize,uint32_t numRect,std::vector<VkRect2D> & rectangles)348 void generateDiscardRectangles(const UVec2 &renderSize, uint32_t numRect, std::vector<VkRect2D> &rectangles)
349 {
350 uint32_t cellHight = renderSize.y() - 10;
351 uint32_t cellWidth = (renderSize.x() - 10) / (2 * numRect - 1);
352
353 DE_ASSERT(rectangles.size() == 0);
354
355 for (uint32_t i = 0; i < numRect; i++)
356 {
357 VkRect2D rect;
358 rect.extent.height = cellHight;
359 rect.extent.width = cellWidth;
360 rect.offset.x = 5u + i * 2 * cellWidth;
361 rect.offset.y = 5u;
362 rectangles.push_back(rect);
363 }
364 }
365
366 //! Renders a colorful grid of rectangles.
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const TestMode testMode,const Vec4 & color,const uint32_t numRectangles,const std::vector<VkRect2D> rectangles,const bool enableScissor,const VkRect2D scissor)367 tcu::TextureLevel generateReferenceImage(const tcu::TextureFormat format, const UVec2 &renderSize,
368 const TestMode testMode, const Vec4 &color, const uint32_t numRectangles,
369 const std::vector<VkRect2D> rectangles, const bool enableScissor,
370 const VkRect2D scissor)
371 {
372 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
373 const Vec4 rectColor = testMode == TEST_MODE_INCLUSIVE ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : color;
374 const Vec4 clearColor = testMode == TEST_MODE_INCLUSIVE ? color : Vec4(0.0f, 1.0f, 0.0f, 1.0f);
375
376 if (!enableScissor)
377 {
378 // Clear the image with clearColor
379 tcu::clear(image.getAccess(), clearColor);
380
381 // Now draw the discard rectangles taking into account the selected mode.
382 for (uint32_t i = 0; i < numRectangles; i++)
383 {
384 tcu::clear(tcu::getSubregion(image.getAccess(), rectangles[i].offset.x, rectangles[i].offset.y,
385 rectangles[i].extent.width, rectangles[i].extent.height),
386 rectColor);
387 }
388 }
389 else
390 {
391 // Clear the image with the original clear color
392 tcu::clear(image.getAccess(), color);
393 // Clear the scissor are with the clearColor which depends on the selected mode
394 tcu::clear(tcu::getSubregion(image.getAccess(), scissor.offset.x, scissor.offset.y, scissor.extent.width,
395 scissor.extent.height),
396 clearColor);
397
398 // Now draw the discard rectangles taking into account both the scissor area and
399 // the selected mode.
400 for (uint32_t rect = 0; rect < numRectangles; rect++)
401 {
402 for (uint32_t x = rectangles[rect].offset.x;
403 x < (rectangles[rect].offset.x + rectangles[rect].extent.width); x++)
404 {
405 for (uint32_t y = rectangles[rect].offset.y;
406 y < (rectangles[rect].offset.y + rectangles[rect].extent.height); y++)
407 {
408 if ((x >= (uint32_t)scissor.offset.x) && (x < (scissor.offset.x + scissor.extent.width)) &&
409 (y >= (uint32_t)scissor.offset.y) && (y < (scissor.offset.y + scissor.extent.height)))
410 {
411 image.getAccess().setPixel(rectColor, x, y);
412 }
413 }
414 }
415 }
416 }
417 return image;
418 }
419
420 class DiscardRectanglesTestInstance : public TestInstance
421 {
422 public:
423 DiscardRectanglesTestInstance(Context &context, TestParams params);
~DiscardRectanglesTestInstance(void)424 virtual ~DiscardRectanglesTestInstance(void)
425 {
426 }
427 virtual tcu::TestStatus iterate(void);
428
429 protected:
430 void preRenderCommands(VkCommandBuffer cmdBuffer) const;
431 void drawCommands(VkCommandBuffer cmdBuffer, const VkRect2D &rectScissor) const;
432
433 #ifndef CTS_USES_VULKANSC
434 void beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat colorFormat,
435 VkRenderingFlagsKHR renderingFlags = 0u) const;
436 #endif // CTS_USES_VULKANSC
437
438 private:
439 const TestParams m_params;
440 const Vec4 m_clearColor;
441 const UVec2 m_renderSize;
442 std::vector<Vec4> m_vertices;
443 std::vector<VkRect2D> m_rectangles;
444
445 Move<VkImage> m_colorImage;
446 MovePtr<Allocation> m_colorImageAlloc;
447 Move<VkImageView> m_colorAttachment;
448 SharedPtr<Buffer> m_colorBuffer;
449 SharedPtr<Buffer> m_vertexBuffer;
450 Move<VkShaderModule> m_vertexModule;
451 Move<VkShaderModule> m_fragmentModule;
452 Move<VkRenderPass> m_renderPass;
453 Move<VkFramebuffer> m_framebuffer;
454 Move<VkPipelineLayout> m_pipelineLayout;
455 Move<VkPipeline> m_pipeline;
456 Move<VkCommandPool> m_cmdPool;
457 Move<VkCommandBuffer> m_cmdBuffer;
458 Move<VkCommandBuffer> m_secCmdBuffer;
459 };
460
DiscardRectanglesTestInstance(Context & context,TestParams params)461 DiscardRectanglesTestInstance::DiscardRectanglesTestInstance(Context &context, TestParams params)
462 : TestInstance(context)
463 , m_params(params)
464 , m_clearColor(Vec4(1.0f, 0.0f, 0.0f, 1.0f))
465 , m_renderSize(UVec2(340, 100))
466 {
467 }
468
iterate(void)469 tcu::TestStatus DiscardRectanglesTestInstance::iterate(void)
470 {
471 const DeviceInterface &vk = m_context.getDeviceInterface();
472 const InstanceInterface &vki = m_context.getInstanceInterface();
473 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
474 const VkDevice device = m_context.getDevice();
475 const VkQueue queue = m_context.getUniversalQueue();
476 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
477 Allocator &allocator = m_context.getDefaultAllocator();
478 const VkDiscardRectangleModeEXT discardRectangleMode = m_params.testMode == TEST_MODE_EXCLUSIVE ?
479 VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT :
480 VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT;
481 const VkRect2D rectScissor = {{90, 25}, {160, 50}};
482 const VkImageSubresourceRange colorSubresourceRange =
483 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
484 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
485 const VkDeviceSize colorBufferSize =
486 m_renderSize.x() * m_renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
487
488 // Check for VK_EXT_discard_rectangles support and maximum number of active discard rectangles
489 {
490 VkPhysicalDeviceDiscardRectanglePropertiesEXT discardRectangleProperties;
491 deMemset(&discardRectangleProperties, 0, sizeof(VkPhysicalDeviceDiscardRectanglePropertiesEXT));
492 discardRectangleProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT;
493
494 VkPhysicalDeviceProperties2 physicalDeviceProperties;
495 physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
496 physicalDeviceProperties.pNext = &discardRectangleProperties;
497
498 vki.getPhysicalDeviceProperties2(physicalDevice, &physicalDeviceProperties);
499
500 if (discardRectangleProperties.maxDiscardRectangles == 0)
501 {
502 throw tcu::NotSupportedError("Implementation doesn't support discard rectangles");
503 }
504
505 if (discardRectangleProperties.maxDiscardRectangles < 4)
506 {
507 std::ostringstream message;
508 message << "Implementation doesn't support the minimum value for maxDiscardRectangles: "
509 << discardRectangleProperties.maxDiscardRectangles << " < 4";
510 return tcu::TestStatus::fail(message.str());
511 }
512
513 if (discardRectangleProperties.maxDiscardRectangles < m_params.numRectangles)
514 {
515 std::ostringstream message;
516 message << "Implementation doesn't support the required number of discard rectangles: "
517 << discardRectangleProperties.maxDiscardRectangles << " < " << m_params.numRectangles;
518 throw tcu::NotSupportedError(message.str());
519 }
520 }
521
522 // Color attachment
523 {
524 m_colorImage =
525 makeImage(vk, device,
526 makeImageCreateInfo(colorFormat, m_renderSize,
527 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
528 m_colorImageAlloc = bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
529 m_colorBuffer =
530 Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT),
531 allocator, MemoryRequirement::HostVisible);
532 m_colorAttachment =
533 makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
534
535 // Zero colorBuffer.
536 const Allocation alloc = m_colorBuffer->getBoundMemory();
537 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
538 flushAlloc(vk, device, alloc);
539 }
540
541 // Initialize the pipeline and other variables
542 {
543 // Draw a quad covering the whole framebuffer
544 m_vertices.push_back(Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
545 m_vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
546 m_vertices.push_back(Vec4(1.0f, 1.0f, 0.0f, 1.0f));
547 m_vertices.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f));
548 VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices);
549 m_vertexBuffer = Buffer::createAndAlloc(
550 vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator,
551 MemoryRequirement::HostVisible);
552
553 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), m_vertices.data(),
554 static_cast<std::size_t>(vertexBufferSize));
555 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
556
557 m_vertexModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u);
558 m_fragmentModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
559
560 if (!m_params.groupParams->useDynamicRendering)
561 {
562 m_renderPass = makeRenderPass(vk, device, colorFormat);
563 m_framebuffer =
564 makeFramebuffer(vk, device, *m_renderPass, m_colorAttachment.get(),
565 static_cast<uint32_t>(m_renderSize.x()), static_cast<uint32_t>(m_renderSize.y()));
566 }
567
568 m_pipelineLayout = makePipelineLayout(vk, device);
569
570 generateDiscardRectangles(m_renderSize, m_params.numRectangles, m_rectangles);
571 m_pipeline =
572 makeGraphicsPipeline(vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_fragmentModule,
573 m_renderSize, m_params.dynamicDiscardRectangles, discardRectangleMode,
574 m_params.numRectangles, m_rectangles.data(), m_params.scissorMode, rectScissor);
575 m_cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
576 m_cmdBuffer = allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
577 }
578
579 const VkClearValue clearValue = makeClearValueColor(m_clearColor);
580 const VkRect2D renderArea{
581 makeOffset2D(0, 0),
582 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
583 };
584
585 // Write command buffers and submit it
586
587 #ifndef CTS_USES_VULKANSC
588 if (m_params.groupParams->useSecondaryCmdBuffer)
589 {
590 m_secCmdBuffer = allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
591
592 // record secondary command buffer
593 if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
594 {
595 beginSecondaryCmdBuffer(*m_secCmdBuffer, colorFormat, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
596 beginRendering(vk, *m_secCmdBuffer, *m_colorAttachment, renderArea, clearValue,
597 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
598 }
599 else
600 beginSecondaryCmdBuffer(*m_secCmdBuffer, colorFormat);
601
602 drawCommands(*m_secCmdBuffer, rectScissor);
603
604 if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
605 vk.cmdEndRendering(*m_secCmdBuffer);
606
607 endCommandBuffer(vk, *m_secCmdBuffer);
608
609 // record primary command buffer
610 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
611 preRenderCommands(*m_cmdBuffer);
612
613 if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
614 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue,
615 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR,
616 VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
617
618 vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
619
620 if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
621 vk.cmdEndRendering(*m_cmdBuffer);
622 }
623 else if (m_params.groupParams->useDynamicRendering)
624 {
625 beginCommandBuffer(vk, *m_cmdBuffer);
626
627 preRenderCommands(*m_cmdBuffer);
628 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue,
629 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
630 drawCommands(*m_cmdBuffer, rectScissor);
631 vk.cmdEndRendering(*m_cmdBuffer);
632 }
633 #endif // CTS_USES_VULKANSC
634
635 if (!m_params.groupParams->useDynamicRendering)
636 {
637 const VkRenderPassBeginInfo renderPassBeginInfo{
638 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
639 DE_NULL, // const void* pNext;
640 *m_renderPass, // VkRenderPass renderPass;
641 *m_framebuffer, // VkFramebuffer framebuffer;
642 renderArea, // VkRect2D renderArea;
643 1u, // uint32_t clearValueCount;
644 &clearValue, // const VkClearValue* pClearValues;
645 };
646
647 beginCommandBuffer(vk, *m_cmdBuffer);
648
649 preRenderCommands(*m_cmdBuffer);
650 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
651 drawCommands(*m_cmdBuffer, rectScissor);
652 vk.cmdEndRenderPass(*m_cmdBuffer);
653 }
654
655 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, m_colorBuffer->object(),
656 tcu::IVec2(m_renderSize.x(), m_renderSize.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
657 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, colorSubresourceRange.layerCount);
658 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
659
660 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
661
662 // Verify results
663 {
664 const Allocation alloc = m_colorBuffer->getBoundMemory();
665 invalidateAlloc(vk, device, alloc);
666
667 const tcu::ConstPixelBufferAccess resultImage(mapVkFormat(colorFormat), m_renderSize.x(), m_renderSize.y(), 1u,
668 alloc.getHostPtr());
669 const tcu::TextureLevel referenceImage = generateReferenceImage(
670 mapVkFormat(colorFormat), m_renderSize, m_params.testMode, m_clearColor, m_params.numRectangles,
671 m_rectangles, m_params.scissorMode != TEST_SCISSOR_MODE_NONE, rectScissor);
672 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
673 referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
674 TCU_FAIL("Rendered image is not correct");
675 }
676 return tcu::TestStatus::pass("OK");
677 }
678
preRenderCommands(vk::VkCommandBuffer cmdBuffer) const679 void DiscardRectanglesTestInstance::preRenderCommands(vk::VkCommandBuffer cmdBuffer) const
680 {
681 if (!m_params.groupParams->useDynamicRendering)
682 return;
683
684 const DeviceInterface &vk = m_context.getDeviceInterface();
685 initialTransitionColor2DImage(vk, cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
686 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
687 }
688
drawCommands(vk::VkCommandBuffer cmdBuffer,const VkRect2D & rectScissor) const689 void DiscardRectanglesTestInstance::drawCommands(vk::VkCommandBuffer cmdBuffer, const VkRect2D &rectScissor) const
690 {
691 const DeviceInterface &vk = m_context.getDeviceInterface();
692 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
693 {
694 const VkBuffer vertexBuffer = m_vertexBuffer->object();
695 const VkDeviceSize vertexBufferOffset = 0ull;
696 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
697 }
698 if (m_params.dynamicDiscardRectangles)
699 {
700 vk.cmdSetDiscardRectangleEXT(cmdBuffer, 0u, m_params.numRectangles, m_rectangles.data());
701 }
702 if (m_params.scissorMode == TEST_SCISSOR_MODE_DYNAMIC)
703 {
704 vk.cmdSetScissor(cmdBuffer, 0u, 1u, &rectScissor);
705 }
706 vk.cmdDraw(cmdBuffer, static_cast<uint32_t>(m_vertices.size()), 1u, 0u, 0u); // two triangles
707 }
708
709 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkFormat colorFormat,VkRenderingFlagsKHR renderingFlags) const710 void DiscardRectanglesTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat colorFormat,
711 VkRenderingFlagsKHR renderingFlags) const
712 {
713 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
714 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
715 DE_NULL, // const void* pNext;
716 renderingFlags, // VkRenderingFlagsKHR flags;
717 0u, // uint32_t viewMask;
718 1u, // uint32_t colorAttachmentCount;
719 &colorFormat, // const VkFormat* pColorAttachmentFormats;
720 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
721 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
722 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
723 };
724 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
725
726 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
727 if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
728 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
729
730 const VkCommandBufferBeginInfo commandBufBeginParams{
731 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
732 DE_NULL, // const void* pNext;
733 usageFlags, // VkCommandBufferUsageFlags flags;
734 &bufferInheritanceInfo};
735
736 const DeviceInterface &vk = m_context.getDeviceInterface();
737 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
738 }
739 #endif // CTS_USES_VULKANSC
740
741 class DiscardRectanglesTestCase : public TestCase
742 {
743 public:
744 DiscardRectanglesTestCase(tcu::TestContext &context, const char *name, TestParams params);
~DiscardRectanglesTestCase(void)745 virtual ~DiscardRectanglesTestCase(void)
746 {
747 }
748
749 virtual TestInstance *createInstance(Context &context) const;
750 virtual void initPrograms(SourceCollections &programCollection) const;
751 virtual void checkSupport(Context &context) const;
752
753 private:
754 const TestParams m_params;
755 };
756
DiscardRectanglesTestCase(tcu::TestContext & context,const char * name,TestParams params)757 DiscardRectanglesTestCase::DiscardRectanglesTestCase(tcu::TestContext &context, const char *name, TestParams params)
758 : TestCase(context, name)
759 , m_params(params)
760 {
761 }
762
initPrograms(SourceCollections & programCollection) const763 void DiscardRectanglesTestCase::initPrograms(SourceCollections &programCollection) const
764 {
765 // Vertex
766 {
767 std::ostringstream src;
768 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
769 << "\n"
770 << "layout(location = 0) in highp vec4 position;\n"
771 << "layout(location = 0) out highp vec4 vsColor;\n"
772 << "\n"
773 << "out gl_PerVertex {\n"
774 << " vec4 gl_Position;\n"
775 << "};\n"
776 << "\n"
777 << "void main (void)\n"
778 << "{\n"
779 << " gl_Position = position;\n"
780 << " vsColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
781 << "}\n";
782 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
783 }
784
785 // Fragment
786 {
787 std::ostringstream src;
788 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
789 << "\n"
790 << "layout(location = 0) in highp vec4 vsColor;\n"
791 << "layout(location = 0) out highp vec4 fsColor;\n"
792 << "\n"
793 << "void main (void)\n"
794 << "{\n"
795 << " fsColor = vsColor;\n"
796 << "}\n";
797 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
798 }
799 }
800
checkSupport(Context & context) const801 void DiscardRectanglesTestCase::checkSupport(Context &context) const
802 {
803 context.requireDeviceFunctionality("VK_EXT_discard_rectangles");
804 if (m_params.groupParams->useDynamicRendering)
805 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
806 }
807
createInstance(Context & context) const808 TestInstance *DiscardRectanglesTestCase::createInstance(Context &context) const
809 {
810 return new DiscardRectanglesTestInstance(context, m_params);
811 }
812
createTests(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)813 void createTests(tcu::TestCaseGroup *testGroup, const SharedGroupParams groupParams)
814 {
815 tcu::TestContext &testCtx = testGroup->getTestContext();
816 uint32_t numRect[NUM_RECT_TESTS] = {1, 2, 3, 4, 8, 16};
817 std::string modeName[TEST_MODE_COUNT] = {"inclusive_", "exclusive_"};
818 std::string scissorName[TEST_SCISSOR_MODE_COUNT] = {"", "scissor_", "dynamic_scissor_"};
819 std::string dynamicName[NUM_DYNAMIC_DISCARD_TYPE_TESTS] = {"", "dynamic_discard_"};
820
821 for (uint32_t dynamic = 0; dynamic < NUM_DYNAMIC_DISCARD_TYPE_TESTS; dynamic++)
822 {
823 for (uint32_t scissor = 0; scissor < TEST_SCISSOR_MODE_COUNT; scissor++)
824 {
825 for (uint32_t mode = 0; mode < TEST_MODE_COUNT; mode++)
826 {
827 for (uint32_t rect = 0; rect < NUM_RECT_TESTS; rect++)
828 {
829 std::ostringstream name;
830 TestParams params{
831 (TestMode)mode, // TestMode testMode;
832 numRect[rect], // uint32_t numRectangles;
833 dynamic ? true : false, // bool dynamicDiscardRectangles;
834 (TestScissorMode)scissor, // TestScissorMode scissorMode;
835 groupParams, // const SharedGroupParams groupParams;
836 };
837
838 name << dynamicName[dynamic] << scissorName[scissor] << modeName[mode] << "rect_" << numRect[rect];
839
840 testGroup->addChild(new DiscardRectanglesTestCase(testCtx, name.str().c_str(), params));
841 }
842 }
843 }
844 }
845 }
846 } // namespace
847
createDiscardRectanglesTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)848 tcu::TestCaseGroup *createDiscardRectanglesTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
849 {
850 return createTestGroup(testCtx, "discard_rectangles", createTests, groupParams);
851 }
852
853 } // namespace Draw
854 } // namespace vkt
855