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