1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * -----------------------------
4 *
5 * Copyright (c) 2020 Google Inc.
6 * Copyright (c) 2020 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 Tests for multiple color or depth clears within a render pass
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawMultipleClearsWithinRenderPass.hpp"
26
27 #include "vktTestGroupUtil.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vktDrawCreateInfoUtil.hpp"
30 #include "vktDrawBufferObjectUtil.hpp"
31 #include "vktDrawImageObjectUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkCmdUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "vktDrawTestCaseUtil.hpp"
41
42 #include "deStringUtil.hpp"
43
44 #include <cmath>
45 #include <vector>
46 #include <string>
47 #include <sstream>
48
49 namespace vkt
50 {
51 namespace Draw
52 {
53 namespace
54 {
55 using namespace vk;
56 using tcu::Vec4;
57 using de::SharedPtr;
58 using std::string;
59 using std::abs;
60 using std::vector;
61 using std::ostringstream;
62
63 const deUint32 WIDTH = 400;
64 const deUint32 HEIGHT = 300;
65
66 enum struct Topology
67 {
68 TRIANGLE_STRIP = 0,
69 TRIANGLES,
70 TRIANGLE
71 };
72
73 const Topology topologiesToTest[] =
74 {
75 Topology::TRIANGLE_STRIP,
76 Topology::TRIANGLES,
77 Topology::TRIANGLE
78 };
79
80 struct FormatPair
81 {
82 VkFormat colorFormat;
83 VkFormat depthFormat;
84 };
85
86 const FormatPair formatsToTest[] =
87 {
88 { VK_FORMAT_R8G8B8A8_UNORM , VK_FORMAT_UNDEFINED },
89 { VK_FORMAT_R8G8B8A8_SNORM , VK_FORMAT_UNDEFINED },
90 { VK_FORMAT_UNDEFINED , VK_FORMAT_D32_SFLOAT },
91 { VK_FORMAT_UNDEFINED , VK_FORMAT_D16_UNORM },
92 { VK_FORMAT_R8G8B8A8_UNORM , VK_FORMAT_D32_SFLOAT },
93 { VK_FORMAT_R8G8B8A8_UNORM , VK_FORMAT_D16_UNORM },
94 { VK_FORMAT_R8G8B8A8_SNORM , VK_FORMAT_D32_SFLOAT },
95 { VK_FORMAT_R8G8B8A8_SNORM , VK_FORMAT_D16_UNORM },
96 };
97
98 const Vec4 verticesTriangleStrip[] =
99 {
100 Vec4(-1.0f, -1.0f, 0.0f, 1.0f), // 0 -- 2
101 Vec4(-1.0f, 1.0f, 0.0f, 1.0f), // | / |
102 Vec4( 1.0f, -1.0f, 0.0f, 1.0f), // | / |
103 Vec4( 1.0f, 1.0f, 0.0f, 1.0f) // 1 -- 3
104 };
105 const Vec4 verticesTriangles[] =
106 {
107 Vec4(-1.0f, -1.0f, 0.0f, 1.0f), // 0 - 1
108 Vec4(-1.0f, 1.0f, 0.0f, 1.0f), // | /
109 Vec4( 1.0f, -1.0f, 0.0f, 1.0f), // 2
110 Vec4( 1.0f, -1.0f, 0.0f, 1.0f), // 4
111 Vec4(-1.0f, 1.0f, 0.0f, 1.0f), // / |
112 Vec4( 1.0f, 1.0f, 0.0f, 1.0f) // 3 - 5
113 };
114 const Vec4 verticesBigTriangle[] =
115 {
116 Vec4(-1.0f, -1.0f, 0.0f, 1.0f), // 0 - 2
117 Vec4(-1.0f, 3.0f, 0.0f, 1.0f), // | /
118 Vec4( 3.0f, -1.0f, 0.0f, 1.0f), // 1
119 };
120
121 const deUint32 TOPOLOGY_MAX_VERTICES_COUNT = 6;
122 const deUint32 TEST_MAX_STEPS_COUNT = 3;
123
124 struct Vertices
125 {
126 const char* testNameSuffix;
127 VkPrimitiveTopology topology;
128 deUint32 verticesCount;
129 const Vec4* vertices;
130 };
131
132 const Vertices verticesByTopology[] =
133 {
134 {
135 "_triangle_strip",
136 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
137 DE_LENGTH_OF_ARRAY(verticesTriangleStrip),
138 verticesTriangleStrip
139 },
140 {
141 "_triangles",
142 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
143 DE_LENGTH_OF_ARRAY(verticesTriangles),
144 verticesTriangles
145 },
146 {
147 "_big_triangle",
148 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
149 DE_LENGTH_OF_ARRAY(verticesBigTriangle),
150 verticesBigTriangle
151 }
152 };
153
154 enum struct ClearOp
155 {
156 LOAD = 0,
157 DRAW,
158 CLEAR
159 };
160
161 struct ClearStep
162 {
163 ClearOp clearOp;
164 Vec4 color;
165 float depth;
166 };
167
168 struct TestParams
169 {
170 VkFormat colorFormat;
171 VkFormat depthFormat;
172 Topology topology;
173 Vec4 expectedColor;
174 float colorEpsilon;
175 float expectedDepth;
176 float depthEpsilon;
177 deUint32 repeatCount;
178 bool enableBlend;
179 bool useDynamicRendering;
180 vector<ClearStep> steps;
181 };
182
183 class MultipleClearsTest : public TestInstance
184 {
185 public:
186 MultipleClearsTest (Context& context, const TestParams& params);
187 virtual tcu::TestStatus iterate (void);
188 private:
189 void clearAttachments (const DeviceInterface& vk, VkCommandBuffer cmdBuffer, const ClearOp clearOp, const size_t stepIndex);
190
191 SharedPtr<Image> m_colorTargetImage;
192 SharedPtr<Image> m_depthTargetImage;
193 Move<VkImageView> m_colorTargetView;
194 Move<VkImageView> m_depthTargetView;
195 SharedPtr<Buffer> m_vertexBuffer;
196 Move<VkRenderPass> m_renderPass;
197 Move<VkFramebuffer> m_framebuffer;
198 Move<VkPipelineLayout> m_pipelineLayout;
199 Move<VkPipeline> m_pipeline;
200
201 const TestParams m_params;
202 Vec4 m_vertices[TOPOLOGY_MAX_VERTICES_COUNT * TEST_MAX_STEPS_COUNT];
203 };
204
MultipleClearsTest(Context & context,const TestParams & params)205 MultipleClearsTest::MultipleClearsTest (Context &context, const TestParams& params)
206 : TestInstance(context)
207 , m_params(params)
208 {
209 const DeviceInterface& vk = m_context.getDeviceInterface();
210 const VkDevice device = m_context.getDevice();
211 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
212 const bool hasColor = m_params.colorFormat != VK_FORMAT_UNDEFINED;
213 const bool hasDepth = m_params.depthFormat != VK_FORMAT_UNDEFINED;
214
215 DescriptorSetLayoutBuilder descriptorSetLayoutBuilder;
216 // Vertex data
217 const auto& vertexData = verticesByTopology[(size_t)m_params.topology];
218 {
219 DE_ASSERT(vertexData.verticesCount <= TOPOLOGY_MAX_VERTICES_COUNT);
220 const size_t verticesCount = vertexData.verticesCount;
221 const VkDeviceSize dataSize = verticesCount * sizeof(Vec4);
222 const VkDeviceSize totalDataSize = m_params.steps.size() * dataSize;
223 DE_ASSERT(totalDataSize <= sizeof(m_vertices));
224
225 for(size_t i = 0; i < m_params.steps.size(); ++i)
226 {
227 const size_t start = i * verticesCount;
228 deMemcpy(&m_vertices[start], vertexData.vertices, static_cast<size_t>(dataSize));
229 for(size_t j = 0; j < verticesCount; ++j)
230 m_vertices[start + j][2] = m_params.steps[i].depth;
231 }
232 m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(totalDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
233 m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
234 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), m_vertices, static_cast<std::size_t>(totalDataSize));
235 flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
236 }
237
238 if (hasColor)
239 {
240 const VkImageUsageFlags targetImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
241 const ImageCreateInfo targetImageCreateInfo (VK_IMAGE_TYPE_2D, m_params.colorFormat, { WIDTH, HEIGHT, 1u }, 1u, 1u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, targetImageUsageFlags);
242 m_colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), queueFamilyIndex);
243 const ImageViewCreateInfo colorTargetViewInfo (m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_params.colorFormat);
244 m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
245 }
246
247 if (hasDepth)
248 {
249 const VkImageUsageFlags depthImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
250 const ImageCreateInfo depthImageCreateInfo (VK_IMAGE_TYPE_2D, m_params.depthFormat, { WIDTH, HEIGHT, 1u }, 1u, 1u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, depthImageUsageFlags);
251 m_depthTargetImage = Image::createAndAlloc(vk, device, depthImageCreateInfo, m_context.getDefaultAllocator(), queueFamilyIndex);
252 const ImageViewCreateInfo depthTargetViewInfo (m_depthTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_params.depthFormat);
253 m_depthTargetView = createImageView(vk, device, &depthTargetViewInfo);
254 }
255
256 // Render pass
257 if (!m_params.useDynamicRendering)
258 {
259 RenderPassCreateInfo renderPassCreateInfo;
260 if (hasColor)
261 {
262 renderPassCreateInfo.addAttachment(AttachmentDescription(
263 m_params.colorFormat, // format
264 VK_SAMPLE_COUNT_1_BIT, // samples
265 VK_ATTACHMENT_LOAD_OP_LOAD, // loadOp
266 VK_ATTACHMENT_STORE_OP_STORE, // storeOp
267 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
268 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
269 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // initialLayout
270 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); // finalLayout
271 }
272 if (hasDepth)
273 {
274 renderPassCreateInfo.addAttachment(AttachmentDescription(
275 m_params.depthFormat, // format
276 VK_SAMPLE_COUNT_1_BIT, // samples
277 VK_ATTACHMENT_LOAD_OP_LOAD, // loadOp
278 VK_ATTACHMENT_STORE_OP_STORE, // storeOp
279 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
280 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
281 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // initialLayout
282 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); // finalLayout
283 }
284 const VkAttachmentReference colorAttachmentReference = hasColor ? makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) : AttachmentReference();
285 const VkAttachmentReference depthAttachmentReference = hasDepth ? makeAttachmentReference(hasColor ? 1u : 0u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) : AttachmentReference();
286 renderPassCreateInfo.addSubpass(SubpassDescription(
287 VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
288 (VkSubpassDescriptionFlags)0, // flags
289 0u, // inputAttachmentCount
290 DE_NULL, // inputAttachments
291 hasColor ? 1 : 0, // colorAttachmentCount
292 hasColor ? &colorAttachmentReference : DE_NULL, // colorAttachments
293 DE_NULL, // resolveAttachments
294 depthAttachmentReference, // depthStencilAttachment
295 0u, // preserveAttachmentCount
296 DE_NULL)); // preserveAttachments
297 m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
298
299 std::vector<VkImageView> attachments;
300 if (hasColor)
301 attachments.push_back(*m_colorTargetView);
302 if (hasDepth)
303 attachments.push_back(*m_depthTargetView);
304 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1);
305 m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
306 }
307
308 // Vertex input
309 const VkVertexInputBindingDescription vertexInputBindingDescription =
310 {
311 0u, // uint32_t binding;
312 sizeof(Vec4), // uint32_t stride;
313 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
314 };
315
316 const VkVertexInputAttributeDescription vertexInputAttributeDescription =
317 {
318 0u, // uint32_t location;
319 0u, // uint32_t binding;
320 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
321 0u // uint32_t offset;
322 };
323
324 const PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription,
325 1, &vertexInputAttributeDescription);
326
327 // Graphics pipeline
328 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
329 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, m_context.getBinaryCollection().get(hasColor ? "frag" : "frag_depthonly"), 0));
330
331 const VkPushConstantRange pcRange = vk::VkPushConstantRange { VkShaderStageFlagBits::VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ClearStep::color) };
332 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo (0u, DE_NULL, 1u, &pcRange);
333 m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
334
335 const VkRect2D scissor = makeRect2D(WIDTH, HEIGHT);
336 const VkViewport viewport = makeViewport(WIDTH, HEIGHT);
337
338 const auto vkCbAttachmentState = makePipelineColorBlendAttachmentState(
339 m_params.enableBlend ? VK_TRUE : VK_FALSE, // VkBool32 blendEnable
340 VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor
341 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstColorBlendFactor
342 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
343 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
344 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor
345 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
346 VK_COLOR_COMPONENT_R_BIT | // VkColorComponentFlags colorWriteMask
347 VK_COLOR_COMPONENT_G_BIT |
348 VK_COLOR_COMPONENT_B_BIT |
349 VK_COLOR_COMPONENT_A_BIT);
350 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
351 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vertexModule, "main", VK_SHADER_STAGE_VERTEX_BIT));
352 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
353 pipelineCreateInfo.addState (PipelineCreateInfo::VertexInputState (vertexInputState));
354 pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(vertexData.topology));
355 pipelineCreateInfo.addState (PipelineCreateInfo::ColorBlendState (1, &vkCbAttachmentState));
356 pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState (1, std::vector<VkViewport>(1, viewport), std::vector<VkRect2D>(1, scissor)));
357 pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState (hasDepth, hasDepth, VK_COMPARE_OP_ALWAYS, VK_FALSE, VK_FALSE));
358 pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState ());
359 pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState ());
360
361 vk::VkPipelineRenderingCreateInfoKHR renderingCreateInfo
362 {
363 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
364 DE_NULL,
365 0u,
366 hasColor,
367 (hasColor ? &m_params.colorFormat : DE_NULL),
368 (hasDepth ? m_params.depthFormat : VK_FORMAT_UNDEFINED),
369 (hasDepth ? m_params.depthFormat : VK_FORMAT_UNDEFINED)
370 };
371
372 if (m_params.useDynamicRendering)
373 pipelineCreateInfo.pNext = &renderingCreateInfo;
374
375 m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
376 }
377
clearAttachments(const DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,const ClearOp clearOp,const size_t stepIndex)378 void MultipleClearsTest::clearAttachments (const DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, const ClearOp clearOp, const size_t stepIndex)
379 {
380 const Vec4& color = m_params.steps[stepIndex].color;
381 const float depth = m_params.steps[stepIndex].depth;
382 switch(clearOp) {
383 case ClearOp::LOAD:
384 break;
385 case ClearOp::DRAW:
386 {
387 const auto& vertexData = verticesByTopology[(size_t)m_params.topology];
388 const deUint32 verticesCount = vertexData.verticesCount;
389 vk.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(color), color.getPtr());
390 vk.cmdDraw(cmdBuffer, verticesCount, 1, static_cast<deUint32>(verticesCount * stepIndex), 0);
391 }
392 break;
393 case ClearOp::CLEAR:
394 {
395 vector<VkClearAttachment> clearAttachments;
396 if (m_params.colorFormat != VK_FORMAT_UNDEFINED)
397 {
398 const VkClearAttachment clearAttachment =
399 {
400 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
401 static_cast<deUint32>(clearAttachments.size()), // uint32_t colorAttachment
402 makeClearValueColor(color) // VkClearValue clearValue
403 };
404 clearAttachments.push_back(clearAttachment);
405 }
406 if (m_params.depthFormat != VK_FORMAT_UNDEFINED)
407 {
408 const VkClearAttachment clearAttachment =
409 {
410 VK_IMAGE_ASPECT_DEPTH_BIT, // VkImageAspectFlags aspectMask
411 static_cast<deUint32>(clearAttachments.size()), // uint32_t colorAttachment
412 makeClearValueDepthStencil(depth, 0) // VkClearValue clearValue
413 };
414 clearAttachments.push_back(clearAttachment);
415 }
416 const VkClearRect clearRect =
417 {
418 makeRect2D(WIDTH, HEIGHT), // VkRect2D rect
419 0, // uint32_t baseArrayLayer
420 1 // uint32_t layerCount
421 };
422 vk.cmdClearAttachments(cmdBuffer, static_cast<deUint32>(clearAttachments.size()), clearAttachments.data(), 1, &clearRect);
423 }
424 break;
425 default:
426 break;
427 }
428 }
429
iterate(void)430 tcu::TestStatus MultipleClearsTest::iterate (void)
431 {
432 const DeviceInterface& vk = m_context.getDeviceInterface();
433 const VkDevice device = m_context.getDevice();
434 const VkQueue queue = m_context.getUniversalQueue();
435 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
436
437 const CmdPoolCreateInfo cmdPoolCreateInfo (queueFamilyIndex);
438 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, &cmdPoolCreateInfo));
439 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
440
441 const bool hasColor = m_params.colorFormat != VK_FORMAT_UNDEFINED;
442 const bool hasDepth = m_params.depthFormat != VK_FORMAT_UNDEFINED;
443
444 beginCommandBuffer(vk, *cmdBuffer);
445 if (hasColor)
446 initialTransitionColor2DImage(vk, *cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
447 if (hasDepth)
448 initialTransitionDepth2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
449
450 const VkRect2D renderArea = makeRect2D(0, 0, WIDTH, HEIGHT);
451 if (m_params.useDynamicRendering)
452 {
453 VkClearValue clearColorValue = makeClearValueColor(tcu::Vec4(0.0f));
454 VkClearValue clearDepthValue = makeClearValueDepthStencil(0.0f, 0u);
455 if (!m_params.steps.empty() && m_params.steps[0].clearOp == ClearOp::LOAD)
456 {
457 clearColorValue = makeClearValueColor(m_params.steps[0].color);
458 clearDepthValue = makeClearValueDepthStencil(m_params.steps[0].depth, 0u);
459 }
460
461 vk::VkRenderingAttachmentInfoKHR colorAttachment
462 {
463 vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
464 DE_NULL, // const void* pNext;
465 *m_colorTargetView, // VkImageView imageView;
466 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
467 vk::VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
468 DE_NULL, // VkImageView resolveImageView;
469 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
470 vk::VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
471 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
472 clearColorValue // VkClearValue clearValue;
473 };
474
475 vk::VkRenderingAttachmentInfoKHR depthAttachment
476 {
477 vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
478 DE_NULL, // const void* pNext;
479 *m_depthTargetView, // VkImageView imageView;
480 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
481 vk::VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
482 DE_NULL, // VkImageView resolveImageView;
483 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
484 vk::VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
485 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
486 clearDepthValue // VkClearValue clearValue;
487 };
488
489 vk::VkRenderingInfoKHR renderingInfo
490 {
491 vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
492 DE_NULL,
493 0u, // VkRenderingFlagsKHR flags;
494 renderArea, // VkRect2D renderArea;
495 1u, // deUint32 layerCount;
496 0u, // deUint32 viewMask;
497 hasColor, // deUint32 colorAttachmentCount;
498 (hasColor ? &colorAttachment : DE_NULL), // const VkRenderingAttachmentInfoKHR* pColorAttachments;
499 (hasDepth ? &depthAttachment : DE_NULL), // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
500 DE_NULL, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
501 };
502
503 vk.cmdBeginRenderingKHR(*cmdBuffer, &renderingInfo);
504 }
505 else
506 {
507 if (!m_params.steps.empty() && m_params.steps[0].clearOp == ClearOp::LOAD)
508 beginRenderPass(vk, *cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, m_params.steps[0].color, m_params.steps[0].depth, 0);
509 else
510 beginRenderPass(vk, *cmdBuffer, *m_renderPass, *m_framebuffer, renderArea);
511 }
512
513 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
514 {
515 const VkDeviceSize offset = 0;
516 const VkBuffer buffer = m_vertexBuffer->object();
517 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &offset);
518 }
519 for(deUint32 i = 0; i < m_params.repeatCount; ++i)
520 for(size_t j = 0; j < m_params.steps.size(); ++j)
521 {
522 const auto& step = m_params.steps[j];
523 // ClearOp::LOAD only supported for first step
524 DE_ASSERT(j == 0 || step.clearOp != ClearOp::LOAD);
525 clearAttachments(vk, *cmdBuffer, step.clearOp, j);
526 }
527
528 if (m_params.useDynamicRendering)
529 endRendering(vk, *cmdBuffer);
530 else
531 endRenderPass(vk, *cmdBuffer);
532
533 if (hasDepth)
534 {
535 const VkMemoryBarrier memBarrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT };
536 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
537 }
538 if (hasColor)
539 {
540 const VkMemoryBarrier memBarrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT };
541 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
542 }
543
544 if (hasColor)
545 transition2DImage(vk, *cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_ASPECT_COLOR_BIT,
546 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
547 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
548 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_HOST_BIT);
549 if (hasDepth)
550 transition2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_ASPECT_DEPTH_BIT,
551 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
552 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
553 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_HOST_BIT);
554
555 endCommandBuffer(vk, *cmdBuffer);
556 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
557
558 VK_CHECK(vk.queueWaitIdle(queue));
559
560 if (hasColor)
561 {
562 const auto resultImage = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, { 0, 0, 0 }, WIDTH, HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT);
563
564 for(int z = 0; z < resultImage.getDepth(); ++z)
565 for(int y = 0; y < resultImage.getHeight(); ++y)
566 for(int x = 0; x < resultImage.getWidth(); ++x)
567 {
568 const Vec4 difference = m_params.expectedColor - resultImage.getPixel(x,y,z);
569 if (abs(difference.x()) >= m_params.colorEpsilon || abs(difference.y()) >= m_params.colorEpsilon || abs(difference.z()) >= m_params.colorEpsilon)
570 {
571 ostringstream msg;
572 msg << "Color value mismatch, expected: " << m_params.expectedColor << ", got: " << resultImage.getPixel(x,y,z) << " at " << "(" << x << ", " << y << ", " << z << ")";
573 return tcu::TestStatus::fail(msg.str());
574 }
575 }
576 }
577 if (hasDepth)
578 {
579 const auto resultImage = m_depthTargetImage->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, { 0, 0, 0 }, WIDTH, HEIGHT, VK_IMAGE_ASPECT_DEPTH_BIT);
580
581 for(int z = 0; z < resultImage.getDepth(); ++z)
582 for(int y = 0; y < resultImage.getHeight(); ++y)
583 for(int x = 0; x < resultImage.getWidth(); ++x)
584 {
585 const float difference = m_params.expectedDepth - resultImage.getPixDepth(x,y,z);
586 if (abs(difference) >= m_params.depthEpsilon)
587 {
588 ostringstream msg;
589 msg << "Depth value mismatch, expected: " << m_params.expectedDepth << ", got: " << resultImage.getPixDepth(x,y,z) << " at " << "(" << x << ", " << y << ", " << z << ")";
590 return tcu::TestStatus::fail(msg.str());
591 }
592 }
593 }
594 return tcu::TestStatus::pass("Pass");
595 }
596
597 class MultipleClearsWithinRenderPassTest : public TestCase
598 {
599 public:
MultipleClearsWithinRenderPassTest(tcu::TestContext & testCtx,const string & name,const string & description,const TestParams & params)600 MultipleClearsWithinRenderPassTest (tcu::TestContext& testCtx, const string& name, const string& description, const TestParams& params)
601 : TestCase(testCtx, name, description)
602 , m_params(params)
603 {
604 DE_ASSERT(m_params.steps.size() <= static_cast<size_t>(TEST_MAX_STEPS_COUNT));
605 }
606
initPrograms(SourceCollections & programCollection) const607 virtual void initPrograms (SourceCollections& programCollection) const
608 {
609 {
610 ostringstream src;
611 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
612 << "\n"
613 << "layout(location = 0) in vec4 in_position;\n"
614 << "\n"
615 << "out gl_PerVertex {\n"
616 << " vec4 gl_Position;\n"
617 << "};\n"
618 << "\n"
619 << "void main(void)\n"
620 << "{\n"
621 << " gl_Position = in_position;\n"
622 << "}\n";
623 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
624 }
625 {
626 ostringstream src;
627 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
628 << "\n"
629 << "layout(push_constant) uniform Color { vec4 color; } u_color;\n"
630 << "layout(location = 0) out vec4 out_color;\n"
631 << "\n"
632 << "void main(void)\n"
633 << "{\n"
634 << " out_color = u_color.color;\n"
635 << "}\n";
636 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
637 }
638 {
639 ostringstream src;
640 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
641 << "\n"
642 << "layout(push_constant) uniform Color { vec4 color; } u_color;\n"
643 << "\n"
644 << "void main(void)\n"
645 << "{\n"
646 << "}\n";
647 programCollection.glslSources.add("frag_depthonly") << glu::FragmentSource(src.str());
648 }
649 }
650
checkSupport(Context & context) const651 virtual void checkSupport (Context& context) const
652 {
653 VkImageFormatProperties imageFormatProperties;
654 const auto& vki = context.getInstanceInterface();
655 const auto& vkd = context.getPhysicalDevice();
656 if (m_params.colorFormat != VK_FORMAT_UNDEFINED)
657 {
658 const auto colorUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
659 if (vki.getPhysicalDeviceImageFormatProperties(vkd, m_params.colorFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, colorUsage, 0u, &imageFormatProperties) != VK_SUCCESS)
660 TCU_THROW(NotSupportedError, "Color format not supported");
661 }
662 if (m_params.depthFormat != VK_FORMAT_UNDEFINED)
663 {
664 const auto depthUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
665 if (vki.getPhysicalDeviceImageFormatProperties(vkd, m_params.depthFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, depthUsage, 0u, &imageFormatProperties) != VK_SUCCESS)
666 TCU_THROW(NotSupportedError, "Depth format not supported");
667 }
668
669 if (m_params.useDynamicRendering)
670 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
671 }
672
createInstance(Context & context) const673 virtual TestInstance* createInstance (Context& context) const
674 {
675 return new MultipleClearsTest(context, m_params);
676 }
677
678 private:
679 const TestParams m_params;
680 };
681
682 } // anonymous
683
MultipleClearsWithinRenderPassTests(tcu::TestContext & testCtx,bool useDynamicRendering)684 MultipleClearsWithinRenderPassTests::MultipleClearsWithinRenderPassTests (tcu::TestContext &testCtx, bool useDynamicRendering)
685 : TestCaseGroup (testCtx, "multiple_clears_within_render_pass", "Tests for multiple clears within render pass")
686 , m_useDynamicRendering(useDynamicRendering)
687 {
688 }
689
~MultipleClearsWithinRenderPassTests()690 MultipleClearsWithinRenderPassTests::~MultipleClearsWithinRenderPassTests ()
691 {
692 }
693
init()694 void MultipleClearsWithinRenderPassTests::init ()
695 {
696 for(const auto &formatPair : formatsToTest)
697 {
698 ostringstream formatSuffix;
699 if (formatPair.colorFormat != VK_FORMAT_UNDEFINED)
700 formatSuffix << "_c" << de::toLower(string(getFormatName(formatPair.colorFormat)).substr(9));
701 if (formatPair.depthFormat != VK_FORMAT_UNDEFINED)
702 formatSuffix << "_d" << de::toLower(string(getFormatName(formatPair.depthFormat)).substr(9));
703 for(const auto &topology : topologiesToTest)
704 {
705 const string testNameSuffix = formatSuffix.str() + verticesByTopology[(deUint32)topology].testNameSuffix;
706 {
707 const TestParams params =
708 {
709 formatPair.colorFormat, // VkFormat colorFormat;
710 formatPair.depthFormat, // VkFormat depthFormat;
711 topology, // Topology topology;
712 Vec4(0.0f, 0.5f, 0.5f, 1.0f), // Vec4 expectedColor;
713 0.01f, // float colorEpsilon;
714 0.9f, // float expectedDepth;
715 0.01f, // float depthEpsilon;
716 1u, // deUint32 repeatCount;
717 true, // bool enableBlend;
718 m_useDynamicRendering, // bool useDynamicRendering;
719 { // vector<ClearStep> steps;
720 { ClearOp::LOAD , Vec4(1.0f, 0.0f, 0.0f, 1.0f) , 0.7f },
721 { ClearOp::CLEAR , Vec4(0.0f, 1.0f, 0.0f, 1.0f) , 0.3f },
722 { ClearOp::DRAW , Vec4(0.0f, 0.0f, 1.0f, 0.5f) , 0.9f }
723 }
724 };
725 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "load_clear_draw" + testNameSuffix, "Multiple clears within same render pass, methods: load, clear, draw", params));
726 }
727 {
728 const TestParams params =
729 {
730 formatPair.colorFormat, // VkFormat format;
731 formatPair.depthFormat, // VkFormat depthFormat;
732 topology, // Topology topology;
733 Vec4(0.0f, 0.5f, 0.5f, 1.0f), // Vec4 expectedColor;
734 0.01f, // float colorEpsilon;
735 0.9f, // float expectedDepth;
736 0.01f, // float depthEpsilon;
737 1u, // deUint32 repeatCount;
738 true, // bool enableBlend;
739 m_useDynamicRendering, // bool useDynamicRendering;
740 { // vector<ClearStep> steps;
741 { ClearOp::DRAW , Vec4(1.0f, 0.0f, 0.0f, 1.0f) , 0.7f },
742 { ClearOp::CLEAR , Vec4(0.0f, 1.0f, 0.0f, 1.0f) , 0.3f },
743 { ClearOp::DRAW , Vec4(0.0f, 0.0f, 1.0f, 0.5f) , 0.9f }
744 }
745 };
746 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "draw_clear_draw" + testNameSuffix, "Multiple clears within same render pass, methods: draw, clear, draw", params));
747 }
748 {
749 const TestParams params =
750 {
751 formatPair.colorFormat, // VkFormat format;
752 formatPair.depthFormat, // VkFormat depthFormat;
753 topology, // Topology topology;
754 Vec4(0.0f, 0.5f, 0.5f, 1.0f), // Vec4 expectedColor;
755 0.01f, // float colorEpsilon;
756 0.9f, // float expectedDepth;
757 0.01f, // float depthEpsilon;
758 1u, // deUint32 repeatCount;
759 true, // bool enableBlend;
760 m_useDynamicRendering, // bool useDynamicRendering;
761 { // vector<ClearStep> steps;
762 { ClearOp::CLEAR , Vec4(1.0f, 0.0f, 0.0f, 1.0f) , 0.7f },
763 { ClearOp::CLEAR , Vec4(0.0f, 1.0f, 0.0f, 1.0f) , 0.3f },
764 { ClearOp::DRAW , Vec4(0.0f, 0.0f, 1.0f, 0.5f) , 0.9f }
765 }
766 };
767 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "clear_clear_draw" + testNameSuffix, "Multiple clears within same render pass, methods: clear, clear, draw", params));
768 }
769 {
770 const TestParams params =
771 {
772 formatPair.colorFormat, // VkFormat format;
773 formatPair.depthFormat, // VkFormat depthFormat;
774 topology, // Topology topology;
775 Vec4(0.0f, 1.0f, 0.0f, 1.0f), // Vec4 expectedColor;
776 0.01f, // float colorEpsilon;
777 0.9f, // float expectedDepth;
778 0.01f, // float depthEpsilon;
779 1u, // deUint32 repeatCount;
780 false, // bool enableBlend;
781 m_useDynamicRendering, // bool useDynamicRendering;
782 { // vector<ClearStep> steps;
783 { ClearOp::LOAD , Vec4(1.0f, 0.0f, 0.0f, 1.0f) , 0.3f },
784 { ClearOp::CLEAR , Vec4(0.0f, 1.0f, 0.0f, 1.0f) , 0.9f }
785 }
786 };
787 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "load_clear" + testNameSuffix, "Multiple clears within same render pass, methods: load, clear", params));
788 }
789 {
790 const TestParams params =
791 {
792 formatPair.colorFormat, // VkFormat format;
793 formatPair.depthFormat, // VkFormat depthFormat;
794 topology, // Topology topology;
795 Vec4(0.0f, 1.0f, 0.0f, 1.0f), // Vec4 expectedColor;
796 0.01f, // float colorEpsilon;
797 0.9f, // float expectedDepth;
798 0.01f, // float depthEpsilon;
799 1u, // deUint32 repeatCount;
800 false, // bool enableBlend;
801 m_useDynamicRendering, // bool useDynamicRendering;
802 { // vector<ClearStep> steps;
803 { ClearOp::DRAW , Vec4(1.0f, 0.0f, 0.0f, 1.0f) , 0.3f },
804 { ClearOp::CLEAR , Vec4(0.0f, 1.0f, 0.0f, 1.0f) , 0.9f }
805 }
806 };
807 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "draw_clear" + testNameSuffix, "Multiple clears within same render pass, methods: draw, clear", params));
808 }
809 {
810 const TestParams params =
811 {
812 formatPair.colorFormat, // VkFormat format;
813 formatPair.depthFormat, // VkFormat depthFormat;
814 topology, // Topology topology;
815 Vec4(0.0f, 1.0f, 0.0f, 1.0f), // Vec4 expectedColor;
816 0.01f, // float colorEpsilon;
817 0.9f, // float expectedDepth;
818 0.01f, // float depthEpsilon;
819 1u, // deUint32 repeatCount;
820 false, // bool enableBlend;
821 m_useDynamicRendering, // bool useDynamicRendering;
822 { // vector<ClearStep> steps;
823 { ClearOp::CLEAR , Vec4(1.0f, 0.0f, 0.0f, 1.0f) , 0.3f },
824 { ClearOp::CLEAR , Vec4(0.0f, 1.0f, 0.0f, 1.0f) , 0.9f }
825 }
826 };
827 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "clear_clear" + testNameSuffix, "Multiple clears within same render pass, methods: clear, clear", params));
828 }
829 }
830 }
831 }
832 } // Draw
833 } // vkt
834