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 deBool useDynamicRendering;
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 VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
351 vk::VkPipelineRenderingCreateInfoKHR renderingCreateInfo
352 {
353 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
354 &discardRectangleStateCreateInfo,
355 0u,
356 1u,
357 &colorAttachmentFormat,
358 VK_FORMAT_UNDEFINED,
359 VK_FORMAT_UNDEFINED
360 };
361
362 // when pipeline is created without render pass we are using dynamic rendering
363 if (renderPass == DE_NULL)
364 graphicsPipelineInfo.pNext = &renderingCreateInfo;
365
366 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
367 }
368
generateDiscardRectangles(const UVec2 & renderSize,deUint32 numRect,std::vector<VkRect2D> & rectangles)369 void generateDiscardRectangles(const UVec2& renderSize, deUint32 numRect, std::vector<VkRect2D>& rectangles)
370 {
371 deUint32 cellHight = renderSize.y() - 10;
372 deUint32 cellWidth = (renderSize.x() - 10) / (2 * numRect - 1);
373
374 DE_ASSERT(rectangles.size() == 0);
375
376 for (deUint32 i = 0; i < numRect; i++)
377 {
378 VkRect2D rect;
379 rect.extent.height = cellHight;
380 rect.extent.width = cellWidth;
381 rect.offset.x = 5u + i * 2 * cellWidth;
382 rect.offset.y = 5u;
383 rectangles.push_back(rect);
384 }
385 }
386
387 //! 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)388 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format,
389 const UVec2& renderSize,
390 const TestMode testMode,
391 const Vec4& color,
392 const deUint32 numRectangles,
393 const std::vector<VkRect2D> rectangles,
394 const deBool enableScissor,
395 const VkRect2D scissor)
396 {
397 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
398 const Vec4 rectColor = testMode == TEST_MODE_INCLUSIVE ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : color;
399 const Vec4 clearColor = testMode == TEST_MODE_INCLUSIVE ? color : Vec4(0.0f, 1.0f, 0.0f, 1.0f);
400
401 if (!enableScissor)
402 {
403 // Clear the image with clearColor
404 tcu::clear(image.getAccess(), clearColor);
405
406 // Now draw the discard rectangles taking into account the selected mode.
407 for (deUint32 i = 0; i < numRectangles; i++)
408 {
409 tcu::clear(tcu::getSubregion(image.getAccess(), rectangles[i].offset.x, rectangles[i].offset.y,
410 rectangles[i].extent.width, rectangles[i].extent.height),
411 rectColor);
412 }
413 }
414 else
415 {
416 // Clear the image with the original clear color
417 tcu::clear(image.getAccess(), color);
418 // Clear the scissor are with the clearColor which depends on the selected mode
419 tcu::clear(tcu::getSubregion(image.getAccess(), scissor.offset.x, scissor.offset.y,
420 scissor.extent.width, scissor.extent.height),
421 clearColor);
422
423 // Now draw the discard rectangles taking into account both the scissor area and
424 // the selected mode.
425 for (deUint32 rect = 0; rect < numRectangles; rect++)
426 {
427 for (deUint32 x = rectangles[rect].offset.x; x < (rectangles[rect].offset.x + rectangles[rect].extent.width); x++)
428 {
429 for(deUint32 y = rectangles[rect].offset.y; y < (rectangles[rect].offset.y + rectangles[rect].extent.height); y++)
430 {
431 if ((x >= (deUint32)scissor.offset.x) && (x < (scissor.offset.x + scissor.extent.width)) &&
432 (y >= (deUint32)scissor.offset.y) && (y < (scissor.offset.y + scissor.extent.height)))
433 {
434 image.getAccess().setPixel(rectColor, x, y);
435 }
436 }
437 }
438 }
439 }
440 return image;
441 }
442
443 class DiscardRectanglesTestInstance : public TestInstance
444 {
445 public:
446 DiscardRectanglesTestInstance (Context& context,
447 TestParams params);
~DiscardRectanglesTestInstance(void)448 virtual ~DiscardRectanglesTestInstance (void) {}
449 virtual tcu::TestStatus iterate (void);
450
451 private:
452 const TestParams m_params;
453 const Vec4 m_clearColor;
454 const UVec2 m_renderSize;
455 std::vector<Vec4> m_vertices;
456 std::vector<VkRect2D> m_rectangles;
457
458 Move<VkImage> m_colorImage;
459 MovePtr<Allocation> m_colorImageAlloc;
460 Move<VkImageView> m_colorAttachment;
461 SharedPtr<Buffer> m_colorBuffer;
462 SharedPtr<Buffer> m_vertexBuffer;
463 Move<VkShaderModule> m_vertexModule;
464 Move<VkShaderModule> m_fragmentModule;
465 Move<VkRenderPass> m_renderPass;
466 Move<VkFramebuffer> m_framebuffer;
467 Move<VkPipelineLayout> m_pipelineLayout;
468 Move<VkPipeline> m_pipeline;
469 Move<VkCommandPool> m_cmdPool;
470 Move<VkCommandBuffer> m_cmdBuffer;
471 };
472
DiscardRectanglesTestInstance(Context & context,TestParams params)473 DiscardRectanglesTestInstance::DiscardRectanglesTestInstance (Context& context,
474 TestParams params)
475 : TestInstance (context)
476 , m_params (params)
477 , m_clearColor (Vec4(1.0f, 0.0f, 0.0f, 1.0f))
478 , m_renderSize (UVec2(340, 100))
479 {
480 }
481
iterate(void)482 tcu::TestStatus DiscardRectanglesTestInstance::iterate (void)
483 {
484 const DeviceInterface& vk = m_context.getDeviceInterface();
485 const InstanceInterface& vki = m_context.getInstanceInterface();
486 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
487 const VkDevice device = m_context.getDevice();
488 const VkQueue queue = m_context.getUniversalQueue();
489 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
490 Allocator& allocator = m_context.getDefaultAllocator();
491 const VkDiscardRectangleModeEXT discardRectangleMode = m_params.testMode == TEST_MODE_EXCLUSIVE ? VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT : VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT;
492 const VkRect2D rectScissor = { { 90, 25 }, { 160, 50} };
493 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
494 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
495 const VkDeviceSize colorBufferSize = m_renderSize.x() * m_renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
496
497 // Check for VK_EXT_discard_rectangles support and maximum number of active discard rectangles
498 {
499 VkPhysicalDeviceDiscardRectanglePropertiesEXT discardRectangleProperties;
500 deMemset(&discardRectangleProperties, 0, sizeof(VkPhysicalDeviceDiscardRectanglePropertiesEXT));
501 discardRectangleProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT;
502
503 VkPhysicalDeviceProperties2 physicalDeviceProperties;
504 physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
505 physicalDeviceProperties.pNext = &discardRectangleProperties;
506
507 vki.getPhysicalDeviceProperties2(physicalDevice, &physicalDeviceProperties);
508
509 if (discardRectangleProperties.maxDiscardRectangles == 0)
510 {
511 throw tcu::NotSupportedError("Implementation doesn't support discard rectangles");
512 }
513
514 if (discardRectangleProperties.maxDiscardRectangles < 4)
515 {
516 std::ostringstream message;
517 message << "Implementation doesn't support the minimum value for maxDiscardRectangles: " << discardRectangleProperties.maxDiscardRectangles << " < 4";
518 return tcu::TestStatus::fail(message.str());
519 }
520
521 if (discardRectangleProperties.maxDiscardRectangles < m_params.numRectangles)
522 {
523 std::ostringstream message;
524 message << "Implementation doesn't support the required number of discard rectangles: " << discardRectangleProperties.maxDiscardRectangles << " < " << m_params.numRectangles;
525 throw tcu::NotSupportedError(message.str());
526 }
527 }
528
529 // Color attachment
530 {
531 m_colorImage = makeImage(vk, device, makeImageCreateInfo(colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
532 m_colorImageAlloc = bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
533 m_colorBuffer = Buffer::createAndAlloc(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), allocator, MemoryRequirement::HostVisible);
534 m_colorAttachment = makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
535
536 // Zero colorBuffer.
537 const Allocation alloc = m_colorBuffer->getBoundMemory();
538 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
539 flushAlloc(vk, device, alloc);
540 }
541
542 // Initialize the pipeline and other variables
543 {
544 // Draw a quad covering the whole framebuffer
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 m_vertices.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
549 VkDeviceSize vertexBufferSize = sizeInBytes(m_vertices);
550 m_vertexBuffer = Buffer::createAndAlloc (vk, device, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), allocator, MemoryRequirement::HostVisible);
551
552
553 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), m_vertices.data(), static_cast<std::size_t>(vertexBufferSize));
554 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
555
556 m_vertexModule = createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u);
557 m_fragmentModule = createShaderModule (vk, device, m_context.getBinaryCollection().get("frag"), 0u);
558
559 if (!m_params.useDynamicRendering)
560 {
561 m_renderPass = makeRenderPass (vk, device, colorFormat);
562 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, m_colorAttachment.get(),
563 static_cast<deUint32>(m_renderSize.x()),
564 static_cast<deUint32>(m_renderSize.y()));
565 }
566
567 m_pipelineLayout = makePipelineLayout (vk, device);
568
569 generateDiscardRectangles(m_renderSize, m_params.numRectangles, m_rectangles);
570 m_pipeline = makeGraphicsPipeline (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_fragmentModule, m_renderSize,
571 m_params.dynamicDiscardRectangles, discardRectangleMode, m_params.numRectangles,
572 m_rectangles.data(), m_params.scissorMode, rectScissor);
573 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
574 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
575 }
576
577 // Write command buffer and submit it
578 {
579 beginCommandBuffer(vk, *m_cmdBuffer);
580
581 const VkClearValue clearValue = makeClearValueColor(m_clearColor);
582 const VkRect2D renderArea =
583 {
584 makeOffset2D(0, 0),
585 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
586 };
587
588 if (m_params.useDynamicRendering)
589 {
590 initialTransitionColor2DImage(vk, *m_cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
591 VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
592 beginRendering(vk, *m_cmdBuffer, *m_colorAttachment, renderArea, clearValue, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
593 }
594 else
595 {
596 const VkRenderPassBeginInfo renderPassBeginInfo =
597 {
598 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
599 DE_NULL, // const void* pNext;
600 *m_renderPass, // VkRenderPass renderPass;
601 *m_framebuffer, // VkFramebuffer framebuffer;
602 renderArea, // VkRect2D renderArea;
603 1u, // uint32_t clearValueCount;
604 &clearValue, // const VkClearValue* pClearValues;
605 };
606 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
607 }
608
609 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
610 {
611 const VkBuffer vertexBuffer = m_vertexBuffer->object();
612 const VkDeviceSize vertexBufferOffset = 0ull;
613 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
614 }
615 if (m_params.dynamicDiscardRectangles)
616 {
617 vk.cmdSetDiscardRectangleEXT(*m_cmdBuffer, 0u, m_params.numRectangles, m_rectangles.data());
618 }
619 if (m_params.scissorMode == TEST_SCISSOR_MODE_DYNAMIC)
620 {
621 vk.cmdSetScissor(*m_cmdBuffer, 0u, 1u, &rectScissor);
622 }
623 vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_vertices.size()), 1u, 0u, 0u); // two triangles
624
625 if (m_params.useDynamicRendering)
626 vk.cmdEndRenderingKHR(*m_cmdBuffer);
627 else
628 vk.cmdEndRenderPass(*m_cmdBuffer);
629
630 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);
631
632 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
633 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
634 }
635
636 // Verify results
637 {
638 const Allocation alloc = m_colorBuffer->getBoundMemory();
639 invalidateAlloc(vk, device, alloc);
640
641 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), m_renderSize.x(), m_renderSize.y(), 1u, alloc.getHostPtr());
642 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), m_renderSize, m_params.testMode, m_clearColor,
643 m_params.numRectangles, m_rectangles, m_params.scissorMode != TEST_SCISSOR_MODE_NONE, rectScissor);
644 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
645 TCU_FAIL("Rendered image is not correct");
646 }
647 return tcu::TestStatus::pass("OK");
648 }
649
650 class DiscardRectanglesTestCase : public TestCase
651 {
652 public:
653 DiscardRectanglesTestCase (tcu::TestContext &context,
654 const char *name,
655 const char *description,
656 TestParams params);
~DiscardRectanglesTestCase(void)657 virtual ~DiscardRectanglesTestCase (void) {}
658
659 virtual TestInstance* createInstance (Context& context) const;
660 virtual void initPrograms (SourceCollections& programCollection) const;
661 virtual void checkSupport (Context& context) const;
662
663 private:
664 const TestParams m_params;
665 };
666
DiscardRectanglesTestCase(tcu::TestContext & context,const char * name,const char * description,TestParams params)667 DiscardRectanglesTestCase::DiscardRectanglesTestCase (tcu::TestContext &context,
668 const char *name,
669 const char *description,
670 TestParams params)
671 : TestCase (context, name, description)
672 , m_params (params)
673 {
674 }
675
initPrograms(SourceCollections & programCollection) const676 void DiscardRectanglesTestCase::initPrograms(SourceCollections& programCollection) const
677 {
678 // Vertex
679 {
680 std::ostringstream src;
681 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
682 << "\n"
683 << "layout(location = 0) in highp vec4 position;\n"
684 << "layout(location = 0) out highp vec4 vsColor;\n"
685 << "\n"
686 << "out gl_PerVertex {\n"
687 << " vec4 gl_Position;\n"
688 << "};\n"
689 << "\n"
690 << "void main (void)\n"
691 << "{\n"
692 << " gl_Position = position;\n"
693 << " vsColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
694 << "}\n";
695 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
696 }
697
698 // Fragment
699 {
700 std::ostringstream src;
701 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
702 << "\n"
703 << "layout(location = 0) in highp vec4 vsColor;\n"
704 << "layout(location = 0) out highp vec4 fsColor;\n"
705 << "\n"
706 << "void main (void)\n"
707 << "{\n"
708 << " fsColor = vsColor;\n"
709 << "}\n";
710 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
711 }
712 }
713
checkSupport(Context & context) const714 void DiscardRectanglesTestCase::checkSupport (Context& context) const
715 {
716 context.requireDeviceFunctionality("VK_EXT_discard_rectangles");
717 if (m_params.useDynamicRendering)
718 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
719 }
720
createInstance(Context & context) const721 TestInstance* DiscardRectanglesTestCase::createInstance (Context& context) const
722 {
723 return new DiscardRectanglesTestInstance(context, m_params);
724 }
725
createTests(tcu::TestCaseGroup * testGroup,bool useDynamicRendering)726 void createTests (tcu::TestCaseGroup* testGroup, bool useDynamicRendering)
727 {
728 tcu::TestContext& testCtx = testGroup->getTestContext();
729 deUint32 numRect [NUM_RECT_TESTS] = { 1, 2, 3, 4, 8, 16};
730 std::string modeName [TEST_MODE_COUNT] = { "inclusive_", "exclusive_" };
731 std::string scissorName [TEST_SCISSOR_MODE_COUNT] = { "", "scissor_", "dynamic_scissor_" };
732 std::string dynamicName [NUM_DYNAMIC_DISCARD_TYPE_TESTS] = { "", "dynamic_discard_" };
733
734 for (deUint32 dynamic = 0 ; dynamic < NUM_DYNAMIC_DISCARD_TYPE_TESTS; dynamic++)
735 {
736 for (deUint32 scissor = 0 ; scissor < TEST_SCISSOR_MODE_COUNT; scissor++)
737 {
738 for (deUint32 mode = 0; mode < TEST_MODE_COUNT; mode++)
739 {
740 for (deUint32 rect = 0; rect < NUM_RECT_TESTS; rect++)
741 {
742 std::ostringstream name;
743 TestParams params;
744
745 params.testMode = (TestMode) mode;
746 params.dynamicDiscardRectangles = dynamic ? DE_TRUE : DE_FALSE;
747 params.scissorMode = (TestScissorMode) scissor;
748 params.numRectangles = numRect[rect];
749 params.useDynamicRendering = useDynamicRendering;
750 name << dynamicName[dynamic] << scissorName[scissor] << modeName[mode] << "rect_" << numRect[rect];
751
752 testGroup->addChild(new DiscardRectanglesTestCase(testCtx, name.str().c_str(), "", params));
753 }
754 }
755 }
756 }
757 }
758 } // Anonymous
759
createDiscardRectanglesTests(tcu::TestContext & testCtx,bool useDynamicRendering)760 tcu::TestCaseGroup* createDiscardRectanglesTests (tcu::TestContext& testCtx, bool useDynamicRendering)
761 {
762 return createTestGroup(testCtx, "discard_rectangles", "Discard Rectangles tests", createTests, useDynamicRendering);
763 }
764
765 } // Draw
766 } //vkt
767