1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2019 Valve Corporation.
6 * Copyright (c) 2019 The Khronos Group Inc.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief EXT_discard_rectangles tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktDrawDiscardRectanglesTests.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"
41 #include "tcuTestCase.hpp"
42 #include "tcuVector.hpp"
43 #include "tcuTextureUtil.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuImageCompare.hpp"
47 #include "deUniquePtr.hpp"
48 #include "deSharedPtr.hpp"
68 TEST_MODE_INCLUSIVE = 0,
75 TEST_SCISSOR_MODE_NONE = 0,
76 TEST_SCISSOR_MODE_STATIC,
77 TEST_SCISSOR_MODE_DYNAMIC,
78 TEST_SCISSOR_MODE_COUNT
81 #define NUM_RECT_TESTS 6
82 #define NUM_DYNAMIC_DISCARD_TYPE_TESTS 2
87 deUint32 numRectangles;
88 deBool dynamicDiscardRectangles;
89 TestScissorMode scissorMode;
90 const SharedGroupParams groupParams;
94 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
96 return vec.size() * sizeof(vec[0]);
99 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, VkImageUsageFlags usage)
101 const VkImageCreateInfo imageParams =
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;
122 VkPipelineDiscardRectangleStateCreateInfoEXT makeDiscardRectangleStateCreateInfo (const deBool dynamicDiscardRectangle,
123 const VkDiscardRectangleModeEXT discardRectangleMode,
124 const deUint32 discardRectangleCount,
125 const VkRect2D *pDiscardRectangles)
127 const VkPipelineDiscardRectangleStateCreateInfoEXT discardRectanglesCreateInfo =
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;
136 return discardRectanglesCreateInfo;
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)
153 const VkVertexInputBindingDescription vertexInputBindingDescription =
155 0u, // uint32_t binding;
156 sizeof(Vec4), // uint32_t stride;
157 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
160 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
163 0u, // uint32_t location;
164 0u, // uint32_t binding;
165 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
166 0u, // uint32_t offset;
170 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
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;
181 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
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;
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() } };
194 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
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;
205 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
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;
222 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
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;
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
244 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
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;
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 =
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;
273 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
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];
285 const VkPipelineShaderStageCreateInfo pShaderStages[] =
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;
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;
307 const VkPipelineDiscardRectangleStateCreateInfoEXT discardRectangleStateCreateInfo = makeDiscardRectangleStateCreateInfo(dynamicDiscardRectangle, discardRectangleMode, discardRectangleCount, pDiscardRectangles);
309 const VkDynamicState dynamicStateDiscardRectangles = VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT;
310 const VkDynamicState dynamicStateScissor = VK_DYNAMIC_STATE_SCISSOR;
311 std::vector<VkDynamicState> dynamicStates;
313 if (dynamicDiscardRectangle)
314 dynamicStates.push_back(dynamicStateDiscardRectangles);
315 if (scissorMode == TEST_SCISSOR_MODE_DYNAMIC)
316 dynamicStates.push_back(dynamicStateScissor);
318 const VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo =
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;
327 VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
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;
350 #ifndef CTS_USES_VULKANSC
351 VkFormat colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
352 vk::VkPipelineRenderingCreateInfoKHR renderingCreateInfo
354 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
355 &discardRectangleStateCreateInfo,
358 &colorAttachmentFormat,
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
368 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
371 void generateDiscardRectangles(const UVec2& renderSize, deUint32 numRect, std::vector<VkRect2D>& rectangles)
373 deUint32 cellHight = renderSize.y() - 10;
374 deUint32 cellWidth = (renderSize.x() - 10) / (2 * numRect - 1);
376 DE_ASSERT(rectangles.size() == 0);
378 for (deUint32 i = 0; i < numRect; i++)
381 rect.extent.height = cellHight;
382 rect.extent.width = cellWidth;
383 rect.offset.x = 5u + i * 2 * cellWidth;
385 rectangles.push_back(rect);
389 //! Renders a colorful grid of rectangles.
390 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format,
391 const UVec2& renderSize,
392 const TestMode testMode,
394 const deUint32 numRectangles,
395 const std::vector<VkRect2D> rectangles,
396 const deBool enableScissor,
397 const VkRect2D scissor)
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);
405 // Clear the image with clearColor
406 tcu::clear(image.getAccess(), clearColor);
408 // Now draw the discard rectangles taking into account the selected mode.
409 for (deUint32 i = 0; i < numRectangles; i++)
411 tcu::clear(tcu::getSubregion(image.getAccess(), rectangles[i].offset.x, rectangles[i].offset.y,
412 rectangles[i].extent.width, rectangles[i].extent.height),
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),
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++)
429 for (deUint32 x = rectangles[rect].offset.x; x < (rectangles[rect].offset.x + rectangles[rect].extent.width); x++)
431 for(deUint32 y = rectangles[rect].offset.y; y < (rectangles[rect].offset.y + rectangles[rect].extent.height); y++)
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)))
436 image.getAccess().setPixel(rectColor, x, y);
445 class DiscardRectanglesTestInstance : public TestInstance
448 DiscardRectanglesTestInstance (Context& context,
450 virtual ~DiscardRectanglesTestInstance (void) {}
451 virtual tcu::TestStatus iterate (void);
455 void preRenderCommands (VkCommandBuffer cmdBuffer) const;
456 void drawCommands (VkCommandBuffer cmdBuffer, const VkRect2D& rectScissor) const;
458 #ifndef CTS_USES_VULKANSC
459 void beginSecondaryCmdBuffer (VkCommandBuffer cmdBuffer, VkFormat colorFormat, VkRenderingFlagsKHR renderingFlags = 0u) const;
460 #endif // CTS_USES_VULKANSC
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;
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;
485 DiscardRectanglesTestInstance::DiscardRectanglesTestInstance (Context& context,
487 : TestInstance (context)
489 , m_clearColor (Vec4(1.0f, 0.0f, 0.0f, 1.0f))
490 , m_renderSize (UVec2(340, 100))
494 tcu::TestStatus DiscardRectanglesTestInstance::iterate (void)
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));
509 // Check for VK_EXT_discard_rectangles support and maximum number of active discard rectangles
511 VkPhysicalDeviceDiscardRectanglePropertiesEXT discardRectangleProperties;
512 deMemset(&discardRectangleProperties, 0, sizeof(VkPhysicalDeviceDiscardRectanglePropertiesEXT));
513 discardRectangleProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT;
515 VkPhysicalDeviceProperties2 physicalDeviceProperties;
516 physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
517 physicalDeviceProperties.pNext = &discardRectangleProperties;
519 vki.getPhysicalDeviceProperties2(physicalDevice, &physicalDeviceProperties);
521 if (discardRectangleProperties.maxDiscardRectangles == 0)
523 throw tcu::NotSupportedError("Implementation doesn't support discard rectangles");
526 if (discardRectangleProperties.maxDiscardRectangles < 4)
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());
533 if (discardRectangleProperties.maxDiscardRectangles < m_params.numRectangles)
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());
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);
549 const Allocation alloc = m_colorBuffer->getBoundMemory();
550 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
551 flushAlloc(vk, device, alloc);
554 // Initialize the pipeline and other variables
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);
565 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), m_vertices.data(), static_cast<std::size_t>(vertexBufferSize));
566 flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
568 m_vertexModule = createShaderModule (vk, device, m_context.getBinaryCollection().get("vert"), 0u);
569 m_fragmentModule = createShaderModule (vk, device, m_context.getBinaryCollection().get("frag"), 0u);
571 if (!m_params.groupParams->useDynamicRendering)
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()));
579 m_pipelineLayout = makePipelineLayout (vk, device);
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);
589 const VkClearValue clearValue = makeClearValueColor(m_clearColor);
590 const VkRect2D renderArea
593 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
596 // Write command buffers and submit it
598 #ifndef CTS_USES_VULKANSC
599 if (m_params.groupParams->useSecondaryCmdBuffer)
601 m_secCmdBuffer = allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
603 // record secondary command buffer
604 if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
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);
611 beginSecondaryCmdBuffer(*m_secCmdBuffer, colorFormat);
613 drawCommands(*m_secCmdBuffer, rectScissor);
615 if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
616 vk.cmdEndRendering(*m_secCmdBuffer);
618 endCommandBuffer(vk, *m_secCmdBuffer);
620 // record primary command buffer
621 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
622 preRenderCommands(*m_cmdBuffer);
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);
628 vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
630 if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
631 vk.cmdEndRendering(*m_cmdBuffer);
633 else if (m_params.groupParams->useDynamicRendering)
635 beginCommandBuffer(vk, *m_cmdBuffer);
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);
643 #endif // CTS_USES_VULKANSC
645 if (!m_params.groupParams->useDynamicRendering)
647 const VkRenderPassBeginInfo renderPassBeginInfo
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;
658 beginCommandBuffer(vk, *m_cmdBuffer);
660 preRenderCommands(*m_cmdBuffer);
661 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
662 drawCommands(*m_cmdBuffer, rectScissor);
663 vk.cmdEndRenderPass(*m_cmdBuffer);
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));
669 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
673 const Allocation alloc = m_colorBuffer->getBoundMemory();
674 invalidateAlloc(vk, device, alloc);
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");
682 return tcu::TestStatus::pass("OK");
685 void DiscardRectanglesTestInstance::preRenderCommands(vk::VkCommandBuffer cmdBuffer) const
687 if (!m_params.groupParams->useDynamicRendering)
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);
695 void DiscardRectanglesTestInstance::drawCommands(vk::VkCommandBuffer cmdBuffer, const VkRect2D& rectScissor) const
697 const DeviceInterface& vk = m_context.getDeviceInterface();
698 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
700 const VkBuffer vertexBuffer = m_vertexBuffer->object();
701 const VkDeviceSize vertexBufferOffset = 0ull;
702 vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
704 if (m_params.dynamicDiscardRectangles)
706 vk.cmdSetDiscardRectangleEXT(cmdBuffer, 0u, m_params.numRectangles, m_rectangles.data());
708 if (m_params.scissorMode == TEST_SCISSOR_MODE_DYNAMIC)
710 vk.cmdSetScissor(cmdBuffer, 0u, 1u, &rectScissor);
712 vk.cmdDraw(cmdBuffer, static_cast<deUint32>(m_vertices.size()), 1u, 0u, 0u); // two triangles
715 #ifndef CTS_USES_VULKANSC
716 void DiscardRectanglesTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat colorFormat, VkRenderingFlagsKHR renderingFlags) const
718 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
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;
730 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
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;
736 const VkCommandBufferBeginInfo commandBufBeginParams
738 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
739 DE_NULL, // const void* pNext;
740 usageFlags, // VkCommandBufferUsageFlags flags;
741 &bufferInheritanceInfo
744 const DeviceInterface& vk = m_context.getDeviceInterface();
745 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
747 #endif // CTS_USES_VULKANSC
749 class DiscardRectanglesTestCase : public TestCase
752 DiscardRectanglesTestCase (tcu::TestContext &context,
754 const char *description,
756 virtual ~DiscardRectanglesTestCase (void) {}
758 virtual TestInstance* createInstance (Context& context) const;
759 virtual void initPrograms (SourceCollections& programCollection) const;
760 virtual void checkSupport (Context& context) const;
763 const TestParams m_params;
766 DiscardRectanglesTestCase::DiscardRectanglesTestCase (tcu::TestContext &context,
768 const char *description,
770 : TestCase (context, name, description)
775 void DiscardRectanglesTestCase::initPrograms(SourceCollections& programCollection) const
779 std::ostringstream src;
780 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
782 << "layout(location = 0) in highp vec4 position;\n"
783 << "layout(location = 0) out highp vec4 vsColor;\n"
785 << "out gl_PerVertex {\n"
786 << " vec4 gl_Position;\n"
789 << "void main (void)\n"
791 << " gl_Position = position;\n"
792 << " vsColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
794 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
799 std::ostringstream src;
800 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
802 << "layout(location = 0) in highp vec4 vsColor;\n"
803 << "layout(location = 0) out highp vec4 fsColor;\n"
805 << "void main (void)\n"
807 << " fsColor = vsColor;\n"
809 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
813 void DiscardRectanglesTestCase::checkSupport (Context& context) const
815 context.requireDeviceFunctionality("VK_EXT_discard_rectangles");
816 if (m_params.groupParams->useDynamicRendering)
817 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
820 TestInstance* DiscardRectanglesTestCase::createInstance (Context& context) const
822 return new DiscardRectanglesTestInstance(context, m_params);
825 void createTests (tcu::TestCaseGroup* testGroup, const SharedGroupParams groupParams)
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_" };
833 for (deUint32 dynamic = 0 ; dynamic < NUM_DYNAMIC_DISCARD_TYPE_TESTS; dynamic++)
835 for (deUint32 scissor = 0 ; scissor < TEST_SCISSOR_MODE_COUNT; scissor++)
837 for (deUint32 mode = 0; mode < TEST_MODE_COUNT; mode++)
839 for (deUint32 rect = 0; rect < NUM_RECT_TESTS; rect++)
841 std::ostringstream name;
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;
851 name << dynamicName[dynamic] << scissorName[scissor] << modeName[mode] << "rect_" << numRect[rect];
853 testGroup->addChild(new DiscardRectanglesTestCase(testCtx, name.str().c_str(), "", params));
861 tcu::TestCaseGroup* createDiscardRectanglesTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
863 return createTestGroup(testCtx, "discard_rectangles", "Discard Rectangles tests", createTests, groupParams);