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 vector<ClearStep> steps;
180 };
181
182 class MultipleClearsTest : public TestInstance
183 {
184 public:
185 MultipleClearsTest (Context& context, const TestParams& params);
186 virtual tcu::TestStatus iterate (void);
187 private:
188 void clearAttachments (const DeviceInterface& vk, VkCommandBuffer cmdBuffer, const ClearOp clearOp, const size_t stepIndex);
189
190 SharedPtr<Image> m_colorTargetImage;
191 SharedPtr<Image> m_depthTargetImage;
192 Move<VkImageView> m_colorTargetView;
193 Move<VkImageView> m_depthTargetView;
194 SharedPtr<Buffer> m_vertexBuffer;
195 Move<VkRenderPass> m_renderPass;
196 Move<VkFramebuffer> m_framebuffer;
197 Move<VkPipelineLayout> m_pipelineLayout;
198 Move<VkPipeline> m_pipeline;
199
200 const TestParams m_params;
201 Vec4 m_vertices[TOPOLOGY_MAX_VERTICES_COUNT * TEST_MAX_STEPS_COUNT];
202 };
203
MultipleClearsTest(Context & context,const TestParams & params)204 MultipleClearsTest::MultipleClearsTest (Context &context, const TestParams& params)
205 : TestInstance(context)
206 , m_params(params)
207 {
208 const DeviceInterface& vk = m_context.getDeviceInterface();
209 const VkDevice device = m_context.getDevice();
210 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
211 const bool hasColor = m_params.colorFormat != VK_FORMAT_UNDEFINED;
212 const bool hasDepth = m_params.depthFormat != VK_FORMAT_UNDEFINED;
213
214 DescriptorSetLayoutBuilder descriptorSetLayoutBuilder;
215 // Vertex data
216 const auto& vertexData = verticesByTopology[(size_t)m_params.topology];
217 {
218 DE_ASSERT(vertexData.verticesCount <= TOPOLOGY_MAX_VERTICES_COUNT);
219 const size_t verticesCount = vertexData.verticesCount;
220 const VkDeviceSize dataSize = verticesCount * sizeof(Vec4);
221 const VkDeviceSize totalDataSize = m_params.steps.size() * dataSize;
222 DE_ASSERT(totalDataSize <= sizeof(m_vertices));
223
224 for(size_t i = 0; i < m_params.steps.size(); ++i)
225 {
226 const size_t start = i * verticesCount;
227 deMemcpy(&m_vertices[start], vertexData.vertices, static_cast<size_t>(dataSize));
228 for(size_t j = 0; j < verticesCount; ++j)
229 m_vertices[start + j][2] = m_params.steps[i].depth;
230 }
231 m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(totalDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
232 m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
233 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), m_vertices, static_cast<std::size_t>(totalDataSize));
234 flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
235 }
236 // Render pass
237 std::vector<VkImageView> attachments;
238 {
239 RenderPassCreateInfo renderPassCreateInfo;
240 if (hasColor)
241 {
242 const VkImageUsageFlags targetImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
243 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);
244 m_colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), queueFamilyIndex);
245
246 renderPassCreateInfo.addAttachment(AttachmentDescription(
247 m_params.colorFormat, // format
248 VK_SAMPLE_COUNT_1_BIT, // samples
249 VK_ATTACHMENT_LOAD_OP_LOAD, // loadOp
250 VK_ATTACHMENT_STORE_OP_STORE, // storeOp
251 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
252 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
253 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // initialLayout
254 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); // finalLayout
255
256 const ImageViewCreateInfo colorTargetViewInfo (m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_params.colorFormat);
257 m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
258 attachments.push_back(*m_colorTargetView);
259 }
260 if (hasDepth)
261 {
262 const VkImageUsageFlags depthImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
263 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);
264 m_depthTargetImage = Image::createAndAlloc(vk, device, depthImageCreateInfo, m_context.getDefaultAllocator(), queueFamilyIndex);
265
266 renderPassCreateInfo.addAttachment(AttachmentDescription(
267 m_params.depthFormat, // format
268 VK_SAMPLE_COUNT_1_BIT, // samples
269 VK_ATTACHMENT_LOAD_OP_LOAD, // loadOp
270 VK_ATTACHMENT_STORE_OP_STORE, // storeOp
271 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
272 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
273 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // initialLayout
274 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); // finalLayout
275
276 const ImageViewCreateInfo depthTargetViewInfo (m_depthTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_params.depthFormat);
277 m_depthTargetView = createImageView(vk, device, &depthTargetViewInfo);;
278 attachments.push_back(*m_depthTargetView);
279 }
280 const VkAttachmentReference colorAttachmentReference = hasColor ? makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) : AttachmentReference();
281 const VkAttachmentReference depthAttachmentReference = hasDepth ? makeAttachmentReference(hasColor ? 1u : 0u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) : AttachmentReference();
282 renderPassCreateInfo.addSubpass(SubpassDescription(
283 VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
284 (VkSubpassDescriptionFlags)0, // flags
285 0u, // inputAttachmentCount
286 DE_NULL, // inputAttachments
287 hasColor ? 1 : 0, // colorAttachmentCount
288 hasColor ? &colorAttachmentReference : DE_NULL, // colorAttachments
289 DE_NULL, // resolveAttachments
290 depthAttachmentReference, // depthStencilAttachment
291 0u, // preserveAttachmentCount
292 DE_NULL)); // preserveAttachments
293 m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
294 }
295 const FramebufferCreateInfo framebufferCreateInfo (*m_renderPass, attachments, WIDTH, HEIGHT, 1);
296 m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
297
298 // Vertex input
299 const VkVertexInputBindingDescription vertexInputBindingDescription =
300 {
301 0u, // uint32_t binding;
302 sizeof(Vec4), // uint32_t stride;
303 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
304 };
305
306 const VkVertexInputAttributeDescription vertexInputAttributeDescription =
307 {
308 0u, // uint32_t location;
309 0u, // uint32_t binding;
310 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
311 0u // uint32_t offset;
312 };
313
314 const PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription,
315 1, &vertexInputAttributeDescription);
316
317 // Graphics pipeline
318 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
319 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, m_context.getBinaryCollection().get(hasColor ? "frag" : "frag_depthonly"), 0));
320
321 const VkPushConstantRange pcRange = vk::VkPushConstantRange { VkShaderStageFlagBits::VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ClearStep::color) };
322 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo (0u, DE_NULL, 1u, &pcRange);
323 m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
324
325 const VkRect2D scissor = makeRect2D(WIDTH, HEIGHT);
326 const VkViewport viewport = makeViewport(WIDTH, HEIGHT);
327
328 const auto vkCbAttachmentState = makePipelineColorBlendAttachmentState(
329 m_params.enableBlend ? VK_TRUE : VK_FALSE, // VkBool32 blendEnable
330 VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor
331 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstColorBlendFactor
332 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
333 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
334 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor
335 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
336 VK_COLOR_COMPONENT_R_BIT | // VkColorComponentFlags colorWriteMask
337 VK_COLOR_COMPONENT_G_BIT |
338 VK_COLOR_COMPONENT_B_BIT |
339 VK_COLOR_COMPONENT_A_BIT);
340 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
341 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vertexModule, "main", VK_SHADER_STAGE_VERTEX_BIT));
342 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
343 pipelineCreateInfo.addState (PipelineCreateInfo::VertexInputState (vertexInputState));
344 pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(vertexData.topology));
345 pipelineCreateInfo.addState (PipelineCreateInfo::ColorBlendState (1, &vkCbAttachmentState));
346 pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState (1, std::vector<VkViewport>(1, viewport), std::vector<VkRect2D>(1, scissor)));
347 pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState (hasDepth, hasDepth, VK_COMPARE_OP_ALWAYS, VK_FALSE, VK_FALSE));
348 pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState ());
349 pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState ());
350 m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
351 }
352
clearAttachments(const DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,const ClearOp clearOp,const size_t stepIndex)353 void MultipleClearsTest::clearAttachments (const DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, const ClearOp clearOp, const size_t stepIndex)
354 {
355 const Vec4& color = m_params.steps[stepIndex].color;
356 const float depth = m_params.steps[stepIndex].depth;
357 switch(clearOp) {
358 case ClearOp::LOAD:
359 break;
360 case ClearOp::DRAW:
361 {
362 const auto& vertexData = verticesByTopology[(size_t)m_params.topology];
363 const deUint32 verticesCount = vertexData.verticesCount;
364 vk.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(color), color.getPtr());
365 vk.cmdDraw(cmdBuffer, verticesCount, 1, static_cast<deUint32>(verticesCount * stepIndex), 0);
366 }
367 break;
368 case ClearOp::CLEAR:
369 {
370 vector<VkClearAttachment> clearAttachments;
371 if (m_params.colorFormat != VK_FORMAT_UNDEFINED)
372 {
373 const VkClearAttachment clearAttachment =
374 {
375 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
376 static_cast<deUint32>(clearAttachments.size()), // uint32_t colorAttachment
377 makeClearValueColor(color) // VkClearValue clearValue
378 };
379 clearAttachments.push_back(clearAttachment);
380 }
381 if (m_params.depthFormat != VK_FORMAT_UNDEFINED)
382 {
383 const VkClearAttachment clearAttachment =
384 {
385 VK_IMAGE_ASPECT_DEPTH_BIT, // VkImageAspectFlags aspectMask
386 static_cast<deUint32>(clearAttachments.size()), // uint32_t colorAttachment
387 makeClearValueDepthStencil(depth, 0) // VkClearValue clearValue
388 };
389 clearAttachments.push_back(clearAttachment);
390 }
391 const VkClearRect clearRect =
392 {
393 makeRect2D(WIDTH, HEIGHT), // VkRect2D rect
394 0, // uint32_t baseArrayLayer
395 1 // uint32_t layerCount
396 };
397 vk.cmdClearAttachments(cmdBuffer, static_cast<deUint32>(clearAttachments.size()), clearAttachments.data(), 1, &clearRect);
398 }
399 break;
400 default:
401 break;
402 }
403 }
404
iterate(void)405 tcu::TestStatus MultipleClearsTest::iterate (void)
406 {
407 const DeviceInterface& vk = m_context.getDeviceInterface();
408 const VkDevice device = m_context.getDevice();
409 const VkQueue queue = m_context.getUniversalQueue();
410 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
411
412 const CmdPoolCreateInfo cmdPoolCreateInfo (queueFamilyIndex);
413 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, &cmdPoolCreateInfo));
414 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
415
416 const bool hasColor = m_params.colorFormat != VK_FORMAT_UNDEFINED;
417 const bool hasDepth = m_params.depthFormat != VK_FORMAT_UNDEFINED;
418
419 beginCommandBuffer(vk, *cmdBuffer);
420 if (hasColor)
421 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);
422 if (hasDepth)
423 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);
424
425 if (!m_params.steps.empty() && m_params.steps[0].clearOp == ClearOp::LOAD)
426 beginRenderPass(vk, *cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, WIDTH, HEIGHT), m_params.steps[0].color, m_params.steps[0].depth, 0);
427 else
428 beginRenderPass(vk, *cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, WIDTH, HEIGHT));
429 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
430 {
431 const VkDeviceSize offset = 0;
432 const VkBuffer buffer = m_vertexBuffer->object();
433 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &offset);
434 }
435 for(deUint32 i = 0; i < m_params.repeatCount; ++i)
436 for(size_t j = 0; j < m_params.steps.size(); ++j)
437 {
438 const auto& step = m_params.steps[j];
439 // ClearOp::LOAD only supported for first step
440 DE_ASSERT(j == 0 || step.clearOp != ClearOp::LOAD);
441 clearAttachments(vk, *cmdBuffer, step.clearOp, j);
442 }
443
444 endRenderPass(vk, *cmdBuffer);
445
446 if (hasDepth)
447 {
448 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 };
449 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
450 }
451 if (hasColor)
452 {
453 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 };
454 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
455 }
456
457 if (hasColor)
458 transition2DImage(vk, *cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_ASPECT_COLOR_BIT,
459 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
460 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
461 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_HOST_BIT);
462 if (hasDepth)
463 transition2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_ASPECT_DEPTH_BIT,
464 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
465 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
466 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_HOST_BIT);
467
468 endCommandBuffer(vk, *cmdBuffer);
469 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
470
471 VK_CHECK(vk.queueWaitIdle(queue));
472
473 if (hasColor)
474 {
475 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);
476
477 for(int z = 0; z < resultImage.getDepth(); ++z)
478 for(int y = 0; y < resultImage.getHeight(); ++y)
479 for(int x = 0; x < resultImage.getWidth(); ++x)
480 {
481 const Vec4 difference = m_params.expectedColor - resultImage.getPixel(x,y,z);
482 if (abs(difference.x()) >= m_params.colorEpsilon || abs(difference.y()) >= m_params.colorEpsilon || abs(difference.z()) >= m_params.colorEpsilon)
483 {
484 ostringstream msg;
485 msg << "Color value mismatch, expected: " << m_params.expectedColor << ", got: " << resultImage.getPixel(x,y,z) << " at " << "(" << x << ", " << y << ", " << z << ")";
486 return tcu::TestStatus::fail(msg.str());
487 }
488 }
489 }
490 if (hasDepth)
491 {
492 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);
493
494 for(int z = 0; z < resultImage.getDepth(); ++z)
495 for(int y = 0; y < resultImage.getHeight(); ++y)
496 for(int x = 0; x < resultImage.getWidth(); ++x)
497 {
498 const float difference = m_params.expectedDepth - resultImage.getPixDepth(x,y,z);
499 if (abs(difference) >= m_params.depthEpsilon)
500 {
501 ostringstream msg;
502 msg << "Depth value mismatch, expected: " << m_params.expectedDepth << ", got: " << resultImage.getPixDepth(x,y,z) << " at " << "(" << x << ", " << y << ", " << z << ")";
503 return tcu::TestStatus::fail(msg.str());
504 }
505 }
506 }
507 return tcu::TestStatus::pass("Pass");
508 }
509
510 class MultipleClearsWithinRenderPassTest : public TestCase
511 {
512 public:
MultipleClearsWithinRenderPassTest(tcu::TestContext & testCtx,const string & name,const string & description,const TestParams & params)513 MultipleClearsWithinRenderPassTest (tcu::TestContext& testCtx, const string& name, const string& description, const TestParams& params)
514 : TestCase(testCtx, name, description)
515 , m_params(params)
516 {
517 DE_ASSERT(m_params.steps.size() <= static_cast<size_t>(TEST_MAX_STEPS_COUNT));
518 }
519
initPrograms(SourceCollections & programCollection) const520 virtual void initPrograms (SourceCollections& programCollection) const
521 {
522 {
523 ostringstream src;
524 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
525 << "\n"
526 << "layout(location = 0) in vec4 in_position;\n"
527 << "\n"
528 << "out gl_PerVertex {\n"
529 << " vec4 gl_Position;\n"
530 << "};\n"
531 << "\n"
532 << "void main(void)\n"
533 << "{\n"
534 << " gl_Position = in_position;\n"
535 << "}\n";
536 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
537 }
538 {
539 ostringstream src;
540 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
541 << "\n"
542 << "layout(push_constant) uniform Color { vec4 color; } u_color;\n"
543 << "layout(location = 0) out vec4 out_color;\n"
544 << "\n"
545 << "void main(void)\n"
546 << "{\n"
547 << " out_color = u_color.color;\n"
548 << "}\n";
549 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
550 }
551 {
552 ostringstream src;
553 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
554 << "\n"
555 << "layout(push_constant) uniform Color { vec4 color; } u_color;\n"
556 << "\n"
557 << "void main(void)\n"
558 << "{\n"
559 << "}\n";
560 programCollection.glslSources.add("frag_depthonly") << glu::FragmentSource(src.str());
561 }
562 }
563
checkSupport(Context & context) const564 virtual void checkSupport (Context& context) const
565 {
566 VkImageFormatProperties imageFormatProperties;
567 const auto& vki = context.getInstanceInterface();
568 const auto& vkd = context.getPhysicalDevice();
569 if (m_params.colorFormat != VK_FORMAT_UNDEFINED)
570 {
571 const auto colorUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
572 if (vki.getPhysicalDeviceImageFormatProperties(vkd, m_params.colorFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, colorUsage, 0u, &imageFormatProperties) != VK_SUCCESS)
573 TCU_THROW(NotSupportedError, "Color format not supported");
574 }
575 if (m_params.depthFormat != VK_FORMAT_UNDEFINED)
576 {
577 const auto depthUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
578 if (vki.getPhysicalDeviceImageFormatProperties(vkd, m_params.depthFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, depthUsage, 0u, &imageFormatProperties) != VK_SUCCESS)
579 TCU_THROW(NotSupportedError, "Depth format not supported");
580 }
581 }
582
createInstance(Context & context) const583 virtual TestInstance* createInstance (Context& context) const
584 {
585 return new MultipleClearsTest(context, m_params);
586 }
587
588 private:
589 const TestParams m_params;
590 };
591
592 } // anonymous
593
MultipleClearsWithinRenderPassTests(tcu::TestContext & testCtx)594 MultipleClearsWithinRenderPassTests::MultipleClearsWithinRenderPassTests (tcu::TestContext &testCtx)
595 : TestCaseGroup (testCtx, "multiple_clears_within_render_pass", "Tests for multiple clears within render pass")
596 {
597 }
598
~MultipleClearsWithinRenderPassTests()599 MultipleClearsWithinRenderPassTests::~MultipleClearsWithinRenderPassTests ()
600 {
601 }
602
init()603 void MultipleClearsWithinRenderPassTests::init ()
604 {
605 for(const auto &formatPair : formatsToTest)
606 {
607 ostringstream formatSuffix;
608 if (formatPair.colorFormat != VK_FORMAT_UNDEFINED)
609 formatSuffix << "_c" << de::toLower(string(getFormatName(formatPair.colorFormat)).substr(9));
610 if (formatPair.depthFormat != VK_FORMAT_UNDEFINED)
611 formatSuffix << "_d" << de::toLower(string(getFormatName(formatPair.depthFormat)).substr(9));
612 for(const auto &topology : topologiesToTest)
613 {
614 const string testNameSuffix = formatSuffix.str() + verticesByTopology[(deUint32)topology].testNameSuffix;
615 {
616 const TestParams params =
617 {
618 formatPair.colorFormat, // VkFormat colorFormat;
619 formatPair.depthFormat, // VkFormat depthFormat;
620 topology, // Topology topology;
621 Vec4(0.0f, 0.5f, 0.5f, 1.0f), // Vec4 expectedColor;
622 0.01f, // float colorEpsilon;
623 0.9f, // float expectedDepth;
624 0.01f, // float depthEpsilon;
625 1u, // deUint32 repeatCount;
626 true, // bool enableBlend;
627 { // vector<ClearStep> steps;
628 { ClearOp::LOAD , Vec4(1.0f, 0.0f, 0.0f, 1.0f) , 0.7f },
629 { ClearOp::CLEAR , Vec4(0.0f, 1.0f, 0.0f, 1.0f) , 0.3f },
630 { ClearOp::DRAW , Vec4(0.0f, 0.0f, 1.0f, 0.5f) , 0.9f }
631 }
632 };
633 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "load_clear_draw" + testNameSuffix, "Multiple clears within same render pass, methods: load, clear, draw", params));
634 }
635 {
636 const TestParams params =
637 {
638 formatPair.colorFormat, // VkFormat format;
639 formatPair.depthFormat, // VkFormat depthFormat;
640 topology, // Topology topology;
641 Vec4(0.0f, 0.5f, 0.5f, 1.0f), // Vec4 expectedColor;
642 0.01f, // float colorEpsilon;
643 0.9f, // float expectedDepth;
644 0.01f, // float depthEpsilon;
645 1u, // deUint32 repeatCount;
646 true, // bool enableBlend;
647 { // vector<ClearStep> steps;
648 { ClearOp::DRAW , Vec4(1.0f, 0.0f, 0.0f, 1.0f) , 0.7f },
649 { ClearOp::CLEAR , Vec4(0.0f, 1.0f, 0.0f, 1.0f) , 0.3f },
650 { ClearOp::DRAW , Vec4(0.0f, 0.0f, 1.0f, 0.5f) , 0.9f }
651 }
652 };
653 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "draw_clear_draw" + testNameSuffix, "Multiple clears within same render pass, methods: draw, clear, draw", params));
654 }
655 {
656 const TestParams params =
657 {
658 formatPair.colorFormat, // VkFormat format;
659 formatPair.depthFormat, // VkFormat depthFormat;
660 topology, // Topology topology;
661 Vec4(0.0f, 0.5f, 0.5f, 1.0f), // Vec4 expectedColor;
662 0.01f, // float colorEpsilon;
663 0.9f, // float expectedDepth;
664 0.01f, // float depthEpsilon;
665 1u, // deUint32 repeatCount;
666 true, // bool enableBlend;
667 { // vector<ClearStep> steps;
668 { ClearOp::CLEAR , Vec4(1.0f, 0.0f, 0.0f, 1.0f) , 0.7f },
669 { ClearOp::CLEAR , Vec4(0.0f, 1.0f, 0.0f, 1.0f) , 0.3f },
670 { ClearOp::DRAW , Vec4(0.0f, 0.0f, 1.0f, 0.5f) , 0.9f }
671 }
672 };
673 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "clear_clear_draw" + testNameSuffix, "Multiple clears within same render pass, methods: clear, clear, draw", params));
674 }
675 {
676 const TestParams params =
677 {
678 formatPair.colorFormat, // VkFormat format;
679 formatPair.depthFormat, // VkFormat depthFormat;
680 topology, // Topology topology;
681 Vec4(0.0f, 1.0f, 0.0f, 1.0f), // Vec4 expectedColor;
682 0.01f, // float colorEpsilon;
683 0.9f, // float expectedDepth;
684 0.01f, // float depthEpsilon;
685 1u, // deUint32 repeatCount;
686 false, // bool enableBlend;
687 { // vector<ClearStep> steps;
688 { ClearOp::LOAD , Vec4(1.0f, 0.0f, 0.0f, 1.0f) , 0.3f },
689 { ClearOp::CLEAR , Vec4(0.0f, 1.0f, 0.0f, 1.0f) , 0.9f }
690 }
691 };
692 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "load_clear" + testNameSuffix, "Multiple clears within same render pass, methods: load, clear", params));
693 }
694 {
695 const TestParams params =
696 {
697 formatPair.colorFormat, // VkFormat format;
698 formatPair.depthFormat, // VkFormat depthFormat;
699 topology, // Topology topology;
700 Vec4(0.0f, 1.0f, 0.0f, 1.0f), // Vec4 expectedColor;
701 0.01f, // float colorEpsilon;
702 0.9f, // float expectedDepth;
703 0.01f, // float depthEpsilon;
704 1u, // deUint32 repeatCount;
705 false, // bool enableBlend;
706 { // vector<ClearStep> steps;
707 { ClearOp::DRAW , Vec4(1.0f, 0.0f, 0.0f, 1.0f) , 0.3f },
708 { ClearOp::CLEAR , Vec4(0.0f, 1.0f, 0.0f, 1.0f) , 0.9f }
709 }
710 };
711 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "draw_clear" + testNameSuffix, "Multiple clears within same render pass, methods: draw, clear", params));
712 }
713 {
714 const TestParams params =
715 {
716 formatPair.colorFormat, // VkFormat format;
717 formatPair.depthFormat, // VkFormat depthFormat;
718 topology, // Topology topology;
719 Vec4(0.0f, 1.0f, 0.0f, 1.0f), // Vec4 expectedColor;
720 0.01f, // float colorEpsilon;
721 0.9f, // float expectedDepth;
722 0.01f, // float depthEpsilon;
723 1u, // deUint32 repeatCount;
724 false, // bool enableBlend;
725 { // vector<ClearStep> steps;
726 { ClearOp::CLEAR , Vec4(1.0f, 0.0f, 0.0f, 1.0f) , 0.3f },
727 { ClearOp::CLEAR , Vec4(0.0f, 1.0f, 0.0f, 1.0f) , 0.9f }
728 }
729 };
730 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "clear_clear" + testNameSuffix, "Multiple clears within same render pass, methods: clear, clear", params));
731 }
732 }
733 }
734 }
735 } // Draw
736 } // vkt
737