1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2014 The Android Open Source Project
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 Scissor multi viewport tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktFragmentOperationsScissorMultiViewportTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktFragmentOperationsMakeUtil.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkQueryUtil.hpp"
37 #include "tcuTestLog.hpp"
38 #include "tcuVector.hpp"
39 #include "tcuImageCompare.hpp"
40 #include "tcuTextureUtil.hpp"
42 #include "deUniquePtr.hpp"
47 namespace FragmentOperations
62 MIN_MAX_VIEWPORTS = 16, //!< Minimum number of viewports for an implementation supporting multiViewport.
66 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
68 return vec.size() * sizeof(vec[0]);
71 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const IVec2& size, VkImageUsageFlags usage)
73 const VkImageCreateInfo imageParams =
75 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
76 DE_NULL, // const void* pNext;
77 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
78 VK_IMAGE_TYPE_2D, // VkImageType imageType;
79 format, // VkFormat format;
80 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
81 1u, // deUint32 mipLevels;
82 1u, // deUint32 arrayLayers;
83 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
84 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
85 usage, // VkImageUsageFlags usage;
86 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
87 0u, // deUint32 queueFamilyIndexCount;
88 DE_NULL, // const deUint32* pQueueFamilyIndices;
89 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
94 //! A single-attachment, single-subpass render pass.
95 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
96 const VkDevice device,
97 const VkFormat colorFormat)
99 const VkAttachmentDescription colorAttachmentDescription =
101 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
102 colorFormat, // VkFormat format;
103 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
104 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
105 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
106 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
107 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
108 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
109 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
112 const VkAttachmentReference colorAttachmentRef =
114 0u, // deUint32 attachment;
115 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
118 const VkSubpassDescription subpassDescription =
120 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
121 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
122 0u, // deUint32 inputAttachmentCount;
123 DE_NULL, // const VkAttachmentReference* pInputAttachments;
124 1u, // deUint32 colorAttachmentCount;
125 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments;
126 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
127 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
128 0u, // deUint32 preserveAttachmentCount;
129 DE_NULL // const deUint32* pPreserveAttachments;
132 const VkRenderPassCreateInfo renderPassInfo =
134 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
135 DE_NULL, // const void* pNext;
136 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
137 1u, // deUint32 attachmentCount;
138 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
139 1u, // deUint32 subpassCount;
140 &subpassDescription, // const VkSubpassDescription* pSubpasses;
141 0u, // deUint32 dependencyCount;
142 DE_NULL // const VkSubpassDependency* pDependencies;
145 return createRenderPass(vk, device, &renderPassInfo);
148 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
149 const VkDevice device,
150 const VkPipelineLayout pipelineLayout,
151 const VkRenderPass renderPass,
152 const VkShaderModule vertexModule,
153 const VkShaderModule geometryModule,
154 const VkShaderModule fragmentModule,
155 const IVec2 renderSize,
156 const int numViewports,
157 const std::vector<IVec4> scissors)
159 const VkVertexInputBindingDescription vertexInputBindingDescription =
161 0u, // uint32_t binding;
162 sizeof(Vec4), // uint32_t stride;
163 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
166 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
169 0u, // uint32_t location;
170 0u, // uint32_t binding;
171 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
172 0u, // uint32_t offset;
176 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
178 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
179 DE_NULL, // const void* pNext;
180 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
181 1u, // uint32_t vertexBindingDescriptionCount;
182 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
183 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
184 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
187 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
189 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
190 DE_NULL, // const void* pNext;
191 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
192 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // VkPrimitiveTopology topology;
193 VK_FALSE, // VkBool32 primitiveRestartEnable;
196 const VkViewport defaultViewport = makeViewport(
198 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
200 const std::vector<VkViewport> viewports(numViewports, defaultViewport);
202 DE_ASSERT(numViewports == static_cast<int>(scissors.size()));
204 std::vector<VkRect2D> rectScissors;
205 rectScissors.reserve(numViewports);
207 for (std::vector<IVec4>::const_iterator it = scissors.begin(); it != scissors.end(); ++it)
209 const VkRect2D rect =
211 makeOffset2D(it->x(), it->y()),
212 makeExtent2D(static_cast<deUint32>(it->z()), static_cast<deUint32>(it->w())),
214 rectScissors.push_back(rect);
217 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
219 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
220 DE_NULL, // const void* pNext;
221 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
222 static_cast<deUint32>(numViewports), // uint32_t viewportCount;
223 &viewports[0], // const VkViewport* pViewports;
224 static_cast<deUint32>(numViewports), // uint32_t scissorCount;
225 &rectScissors[0], // const VkRect2D* pScissors;
228 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
230 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
231 DE_NULL, // const void* pNext;
232 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
233 VK_FALSE, // VkBool32 depthClampEnable;
234 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
235 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
236 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
237 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
238 VK_FALSE, // VkBool32 depthBiasEnable;
239 0.0f, // float depthBiasConstantFactor;
240 0.0f, // float depthBiasClamp;
241 0.0f, // float depthBiasSlopeFactor;
242 1.0f, // float lineWidth;
245 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
247 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
248 DE_NULL, // const void* pNext;
249 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
250 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
251 VK_FALSE, // VkBool32 sampleShadingEnable;
252 0.0f, // float minSampleShading;
253 DE_NULL, // const VkSampleMask* pSampleMask;
254 VK_FALSE, // VkBool32 alphaToCoverageEnable;
255 VK_FALSE // VkBool32 alphaToOneEnable;
258 const VkStencilOpState stencilOpState = makeStencilOpState(
259 VK_STENCIL_OP_KEEP, // stencil fail
260 VK_STENCIL_OP_KEEP, // depth & stencil pass
261 VK_STENCIL_OP_KEEP, // depth only fail
262 VK_COMPARE_OP_ALWAYS, // compare op
267 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
269 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
270 DE_NULL, // const void* pNext;
271 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
272 VK_FALSE, // VkBool32 depthTestEnable;
273 VK_FALSE, // VkBool32 depthWriteEnable;
274 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
275 VK_FALSE, // VkBool32 depthBoundsTestEnable;
276 VK_FALSE, // VkBool32 stencilTestEnable;
277 stencilOpState, // VkStencilOpState front;
278 stencilOpState, // VkStencilOpState back;
279 0.0f, // float minDepthBounds;
280 1.0f, // float maxDepthBounds;
283 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
284 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
286 VK_FALSE, // VkBool32 blendEnable;
287 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
288 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
289 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
290 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
291 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
292 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
293 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
296 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
298 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
299 DE_NULL, // const void* pNext;
300 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
301 VK_FALSE, // VkBool32 logicOpEnable;
302 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
303 1u, // deUint32 attachmentCount;
304 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
305 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
308 const VkPipelineShaderStageCreateInfo pShaderStages[] =
311 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
312 DE_NULL, // const void* pNext;
313 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
314 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
315 vertexModule, // VkShaderModule module;
316 "main", // const char* pName;
317 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
320 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
321 DE_NULL, // const void* pNext;
322 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
323 VK_SHADER_STAGE_GEOMETRY_BIT, // VkShaderStageFlagBits stage;
324 geometryModule, // VkShaderModule module;
325 "main", // const char* pName;
326 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
329 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
330 DE_NULL, // const void* pNext;
331 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
332 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
333 fragmentModule, // VkShaderModule module;
334 "main", // const char* pName;
335 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
339 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
341 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
342 DE_NULL, // const void* pNext;
343 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
344 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
345 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
346 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
347 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
348 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
349 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
350 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
351 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
352 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
353 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
354 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
355 pipelineLayout, // VkPipelineLayout layout;
356 renderPass, // VkRenderPass renderPass;
357 0u, // deUint32 subpass;
358 DE_NULL, // VkPipeline basePipelineHandle;
359 0, // deInt32 basePipelineIndex;
362 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
365 void zeroBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize size)
367 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(size));
368 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), size);
371 void requireFeatureMultiViewport (const InstanceInterface& vki, const VkPhysicalDevice physDevice)
373 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
374 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits;
376 if (!features.geometryShader)
377 TCU_THROW(NotSupportedError, "Required feature is not supported: geometryShader");
379 if (!features.multiViewport)
380 TCU_THROW(NotSupportedError, "Required feature is not supported: multiViewport");
382 if (limits.maxViewports < MIN_MAX_VIEWPORTS)
383 TCU_THROW(NotSupportedError, "Implementation doesn't support minimum required number of viewports");
386 std::vector<IVec4> generateScissors (const int numScissors, const IVec2& renderSize)
388 // Scissor rects will be arranged in a grid-like fashion.
390 const int numCols = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(numScissors)));
391 const int numRows = deCeilFloatToInt32(static_cast<float>(numScissors) / static_cast<float>(numCols));
392 const int rectWidth = renderSize.x() / numCols;
393 const int rectHeight = renderSize.y() / numRows;
395 std::vector<IVec4> scissors;
396 scissors.reserve(numScissors);
401 for (int scissorNdx = 0; scissorNdx < numScissors; ++scissorNdx)
403 const bool nextRow = (scissorNdx != 0) && (scissorNdx % numCols == 0);
410 scissors.push_back(IVec4(x, y, rectWidth, rectHeight));
418 std::vector<Vec4> generateColors (const int numColors)
420 const Vec4 colors[] =
422 Vec4(0.18f, 0.42f, 0.17f, 1.0f),
423 Vec4(0.29f, 0.62f, 0.28f, 1.0f),
424 Vec4(0.59f, 0.84f, 0.44f, 1.0f),
425 Vec4(0.96f, 0.95f, 0.72f, 1.0f),
426 Vec4(0.94f, 0.55f, 0.39f, 1.0f),
427 Vec4(0.82f, 0.19f, 0.12f, 1.0f),
428 Vec4(0.46f, 0.15f, 0.26f, 1.0f),
429 Vec4(0.24f, 0.14f, 0.24f, 1.0f),
430 Vec4(0.49f, 0.31f, 0.26f, 1.0f),
431 Vec4(0.78f, 0.52f, 0.33f, 1.0f),
432 Vec4(0.94f, 0.82f, 0.31f, 1.0f),
433 Vec4(0.98f, 0.65f, 0.30f, 1.0f),
434 Vec4(0.22f, 0.65f, 0.53f, 1.0f),
435 Vec4(0.67f, 0.81f, 0.91f, 1.0f),
436 Vec4(0.43f, 0.44f, 0.75f, 1.0f),
437 Vec4(0.26f, 0.24f, 0.48f, 1.0f),
440 DE_ASSERT(numColors <= DE_LENGTH_OF_ARRAY(colors));
442 return std::vector<Vec4>(colors, colors + numColors);
445 //! Renders a colorful grid of rectangles.
446 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format,
447 const IVec2& renderSize,
448 const Vec4& clearColor,
449 const std::vector<IVec4>& scissors,
450 const std::vector<Vec4>& scissorColors)
452 DE_ASSERT(scissors.size() == scissorColors.size());
454 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
455 tcu::clear(image.getAccess(), clearColor);
457 for (std::size_t i = 0; i < scissors.size(); ++i)
460 tcu::getSubregion(image.getAccess(), scissors[i].x(), scissors[i].y(), scissors[i].z(), scissors[i].w()),
467 void initPrograms (SourceCollections& programCollection, const int numViewports)
469 DE_UNREF(numViewports);
473 std::ostringstream src;
474 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
476 << "layout(location = 0) in vec4 in_color;\n"
477 << "layout(location = 0) out vec4 out_color;\n"
479 << "void main(void)\n"
481 << " out_color = in_color;\n"
484 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
489 // Each input point generates a fullscreen quad.
491 std::ostringstream src;
492 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
494 << "layout(points) in;\n"
495 << "layout(triangle_strip, max_vertices=4) out;\n"
497 << "out gl_PerVertex {\n"
498 << " vec4 gl_Position;\n"
501 << "layout(location = 0) in vec4 in_color[];\n"
502 << "layout(location = 0) out vec4 out_color;\n"
504 << "void main(void)\n"
506 << " gl_ViewportIndex = gl_PrimitiveIDIn;\n"
507 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
508 << " out_color = in_color[0];\n"
511 << " gl_ViewportIndex = gl_PrimitiveIDIn;\n"
512 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
513 << " out_color = in_color[0];\n"
516 << " gl_ViewportIndex = gl_PrimitiveIDIn;\n"
517 << " gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n"
518 << " out_color = in_color[0];\n"
521 << " gl_ViewportIndex = gl_PrimitiveIDIn;\n"
522 << " gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n"
523 << " out_color = in_color[0];\n"
527 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
532 std::ostringstream src;
533 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
535 << "layout(location = 0) in vec4 in_color;\n"
536 << "layout(location = 0) out vec4 out_color;\n"
538 << "void main(void)\n"
540 << " out_color = in_color;\n"
543 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
547 class ScissorRenderer
550 ScissorRenderer (Context& context,
551 const IVec2& renderSize,
552 const int numViewports,
553 const std::vector<IVec4>& scissors,
554 const VkFormat colorFormat,
555 const Vec4& clearColor,
556 const std::vector<Vec4>& vertices)
557 : m_renderSize (renderSize)
558 , m_colorFormat (colorFormat)
559 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
560 , m_clearColor (clearColor)
561 , m_numViewports (numViewports)
562 , m_vertexBufferSize (sizeInBytes(vertices))
564 const DeviceInterface& vk = context.getDeviceInterface();
565 const VkDevice device = context.getDevice();
566 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
567 Allocator& allocator = context.getDefaultAllocator();
569 m_colorImage = makeImage (vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
570 m_colorImageAlloc = bindImage (vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
571 m_colorAttachment = makeImageView (vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
573 m_vertexBuffer = makeBuffer (vk, device, makeBufferCreateInfo(m_vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
574 m_vertexBufferAlloc = bindBuffer (vk, device, allocator, *m_vertexBuffer, MemoryRequirement::HostVisible);
577 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(m_vertexBufferSize));
578 flushMappedMemoryRange(vk, device, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), m_vertexBufferSize);
581 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u);
582 m_geometryModule = createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u);
583 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u);
584 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
585 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, 1u, &m_colorAttachment.get(),
586 static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y()));
587 m_pipelineLayout = makePipelineLayout (vk, device);
588 m_pipeline = makeGraphicsPipeline (vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_geometryModule, *m_fragmentModule,
589 m_renderSize, m_numViewports, scissors);
590 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
591 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
594 void draw (Context& context, const VkBuffer colorBuffer) const
596 const DeviceInterface& vk = context.getDeviceInterface();
597 const VkDevice device = context.getDevice();
598 const VkQueue queue = context.getUniversalQueue();
600 beginCommandBuffer(vk, *m_cmdBuffer);
602 const VkClearValue clearValue = makeClearValueColor(m_clearColor);
603 const VkRect2D renderArea =
606 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
608 const VkRenderPassBeginInfo renderPassBeginInfo =
610 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
611 DE_NULL, // const void* pNext;
612 *m_renderPass, // VkRenderPass renderPass;
613 *m_framebuffer, // VkFramebuffer framebuffer;
614 renderArea, // VkRect2D renderArea;
615 1u, // uint32_t clearValueCount;
616 &clearValue, // const VkClearValue* pClearValues;
618 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
620 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
622 const VkDeviceSize vertexBufferOffset = 0ull;
623 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
625 vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_numViewports), 1u, 0u, 0u); // one vertex per viewport
626 vk.cmdEndRenderPass(*m_cmdBuffer);
628 // Prepare color image for copy
630 const VkImageMemoryBarrier barriers[] =
633 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
634 DE_NULL, // const void* pNext;
635 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
636 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
637 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
638 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
639 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
640 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
641 *m_colorImage, // VkImage image;
642 m_colorSubresourceRange, // VkImageSubresourceRange subresourceRange;
646 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
647 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
649 // Color image -> host buffer
651 const VkBufferImageCopy region =
653 0ull, // VkDeviceSize bufferOffset;
654 0u, // uint32_t bufferRowLength;
655 0u, // uint32_t bufferImageHeight;
656 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource;
657 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
658 makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u), // VkExtent3D imageExtent;
661 vk.cmdCopyImageToBuffer(*m_cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer, 1u, ®ion);
663 // Buffer write barrier
665 const VkBufferMemoryBarrier barriers[] =
668 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
669 DE_NULL, // const void* pNext;
670 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
671 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
672 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
673 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
674 colorBuffer, // VkBuffer buffer;
675 0ull, // VkDeviceSize offset;
676 VK_WHOLE_SIZE, // VkDeviceSize size;
680 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
681 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
684 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
685 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
689 const IVec2 m_renderSize;
690 const VkFormat m_colorFormat;
691 const VkImageSubresourceRange m_colorSubresourceRange;
692 const Vec4 m_clearColor;
693 const int m_numViewports;
694 const VkDeviceSize m_vertexBufferSize;
696 Move<VkImage> m_colorImage;
697 MovePtr<Allocation> m_colorImageAlloc;
698 Move<VkImageView> m_colorAttachment;
699 Move<VkBuffer> m_vertexBuffer;
700 MovePtr<Allocation> m_vertexBufferAlloc;
701 Move<VkShaderModule> m_vertexModule;
702 Move<VkShaderModule> m_geometryModule;
703 Move<VkShaderModule> m_fragmentModule;
704 Move<VkRenderPass> m_renderPass;
705 Move<VkFramebuffer> m_framebuffer;
706 Move<VkPipelineLayout> m_pipelineLayout;
707 Move<VkPipeline> m_pipeline;
708 Move<VkCommandPool> m_cmdPool;
709 Move<VkCommandBuffer> m_cmdBuffer;
712 ScissorRenderer (const ScissorRenderer&);
713 ScissorRenderer& operator= (const ScissorRenderer&);
716 tcu::TestStatus test (Context& context, const int numViewports)
718 requireFeatureMultiViewport(context.getInstanceInterface(), context.getPhysicalDevice());
720 const DeviceInterface& vk = context.getDeviceInterface();
721 const VkDevice device = context.getDevice();
722 Allocator& allocator = context.getDefaultAllocator();
724 const IVec2 renderSize (128, 128);
725 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
726 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
727 const std::vector<Vec4> vertexColors = generateColors(numViewports);
728 const std::vector<IVec4> scissors = generateScissors(numViewports, renderSize);
730 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
731 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
732 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
734 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
737 context.getTestContext().getLog()
738 << tcu::TestLog::Message << "Rendering a colorful grid of " << numViewports << " rectangle(s)." << tcu::TestLog::EndMessage
739 << tcu::TestLog::Message << "Not covered area will be filled with a gray color." << tcu::TestLog::EndMessage;
744 const ScissorRenderer renderer (context, renderSize, numViewports, scissors, colorFormat, clearColor, vertexColors);
745 renderer.draw(context, *colorBuffer);
750 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), 0ull, colorBufferSize);
752 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferAlloc->getHostPtr());
753 const tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, clearColor, scissors, vertexColors);
755 // Images should now match.
756 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
757 return tcu::TestStatus::fail("Rendered image is not correct");
760 return tcu::TestStatus::pass("OK");
765 tcu::TestCaseGroup* createScissorMultiViewportTests (tcu::TestContext& testCtx)
767 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "multi_viewport", ""));
769 for (int numViewports = 1; numViewports <= MIN_MAX_VIEWPORTS; ++numViewports)
770 addFunctionCaseWithPrograms(group.get(), "scissor_" + de::toString(numViewports), "", initPrograms, test, numViewports);
772 return group.release();
775 } // FragmentOperations