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