1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2022 LunarG, Inc.
6 * Copyright (c) 2022 The Khronos Group Inc.
7 * Copyright (c) 2022 Google LLC
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Dynamic State Clear Tests
25 *//*--------------------------------------------------------------------*/
26
27 #include "vktDynamicStateClearTests.hpp"
28
29 #include "vktDynamicStateBaseClass.hpp"
30 #include "vktDynamicStateTestCaseUtil.hpp"
31
32 #include "vkImageUtil.hpp"
33 #include "vkCmdUtil.hpp"
34
35 #include "tcuImageCompare.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuRGBA.hpp"
38 #include "vkQueryUtil.hpp"
39
40
41 namespace vkt
42 {
43 namespace DynamicState
44 {
45
46 using namespace Draw;
47
48 namespace
49 {
50
51 class CmdBaseCase : public DynamicStateBaseClass
52 {
53 public:
CmdBaseCase(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)54 CmdBaseCase (Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
55 : DynamicStateBaseClass (context, pipelineConstructionType, vertexShaderName, fragmentShaderName)
56 {
57 m_topology = vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
58
59 m_data.push_back(PositionColorVertex(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
60 m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
61
62 m_attachmentState.blendEnable = VK_TRUE;
63 m_attachmentState.srcColorBlendFactor = vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
64 m_attachmentState.dstColorBlendFactor = vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
65 m_attachmentState.colorBlendOp = vk::VK_BLEND_OP_ADD;
66 m_attachmentState.srcAlphaBlendFactor = vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
67 m_attachmentState.dstAlphaBlendFactor = vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
68 m_attachmentState.alphaBlendOp = vk::VK_BLEND_OP_ADD;
69 }
70
buildReferenceFrame(int lineWidth)71 virtual tcu::Texture2D buildReferenceFrame (int lineWidth)
72 {
73 (void)lineWidth;
74 DE_ASSERT(false);
75 return tcu::Texture2D(tcu::TextureFormat(), 0, 0);
76 }
77
command(bool)78 virtual void command (bool)
79 {
80 DE_ASSERT(false);
81 }
82
iterate(void)83 virtual tcu::TestStatus iterate (void)
84 {
85 tcu::TestLog& log = m_context.getTestContext().getLog();
86 const vk::InstanceInterface& vkInstance = m_context.getInstanceInterface();
87 const vk::VkPhysicalDevice vkPhysicalDevice = m_context.getPhysicalDevice();
88 const vk::VkQueue queue = m_context.getUniversalQueue();
89 const vk::VkDevice device = m_context.getDevice();
90
91 const float lineWidth = getPhysicalDeviceProperties(vkInstance, vkPhysicalDevice).limits.lineWidthRange[1];
92
93 vk::beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
94
95 // set dynamic states
96 const vk::VkViewport viewport = { 0.0f, 0.0f, static_cast<float>(WIDTH / 2), static_cast<float>(HEIGHT / 2), 0.0f, 0.0f };
97 const vk::VkRect2D scissor = { { 0, 0 }, { WIDTH, HEIGHT } };
98
99 setDynamicViewportState(1, &viewport, &scissor);
100 setDynamicRasterizationState(lineWidth);
101 setDynamicBlendState(0.75f, 0.75f, 0.75f, 0.75f);
102 setDynamicDepthStencilState(0.0f, 1.0f);
103
104 const vk::VkExtent3D imageExtent = { WIDTH, HEIGHT, 1 };
105
106 vk::VkImageFormatProperties imageFormatProperties(getPhysicalDeviceImageFormatProperties(vkInstance, vkPhysicalDevice, m_colorAttachmentFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0));
107 if ((imageFormatProperties.sampleCounts & m_samples) == 0)
108 TCU_THROW(NotSupportedError, "Color image type not supported");
109
110 const ImageCreateInfo imageCreateInfo (vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, imageExtent, 1, 1, m_samples, vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
111 m_image = Image::createAndAlloc(m_vk, device, imageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
112
113 transition2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, 0u, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
114 transition2DImage(m_vk, *m_cmdBuffer, m_image->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, 0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
115
116 // should not interfere with dynamic state
117 command(false);
118
119 const vk::VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } };
120 beginRenderPassWithClearColor(clearColor, true, true);
121
122 command(true);
123
124 m_pipeline.bind(*m_cmdBuffer);
125
126 const vk::VkDeviceSize vertexBufferOffset = 0;
127 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
128 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
129
130 m_vk.cmdDraw(*m_cmdBuffer, 2, 1, 0, 0);
131
132 m_renderPass.end(m_vk, *m_cmdBuffer);
133 endCommandBuffer(m_vk, *m_cmdBuffer);
134
135 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
136
137 // validation
138 {
139 tcu::Texture2D referenceFrame = buildReferenceFrame(static_cast<int>(lineWidth));
140
141 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
142 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
143 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
144
145 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
146 referenceFrame.getLevel(0), renderedFrame, 0.05f,
147 tcu::COMPARE_LOG_RESULT))
148 {
149 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
150 }
151
152 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
153 }
154 }
155
156 de::SharedPtr<Draw::Image> m_image;
157 vk::VkSampleCountFlagBits m_samples = vk::VK_SAMPLE_COUNT_1_BIT;
158 };
159
160 class ClearTestInstance : public CmdBaseCase
161 {
162 public:
ClearTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,ShaderMap shaders)163 ClearTestInstance (Context& context, vk::PipelineConstructionType pipelineConstructionType, ShaderMap shaders)
164 : CmdBaseCase (context, pipelineConstructionType, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
165 {
166 DynamicStateBaseClass::initialize();
167 }
168
command(bool renderPassActive)169 virtual void command (bool renderPassActive)
170 {
171 if (renderPassActive) {
172 // Clear attachment
173 vk::VkClearValue clearValue;
174 clearValue.color.float32[0] = 1.0f;
175 clearValue.color.float32[1] = 1.0f;
176 clearValue.color.float32[2] = 1.0f;
177 clearValue.color.float32[3] = 1.0f;
178 const vk::VkClearAttachment clearAttachment =
179 {
180 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
181 0u, // uint32_t colorAttachment
182 clearValue // VkClearValue clearValue
183 };
184 const vk::VkClearRect rect = { { { 0, 0 }, { WIDTH, HEIGHT } }, 0, 1 };
185 m_vk.cmdClearAttachments(*m_cmdBuffer, 1, &clearAttachment, 1, &rect);
186 }
187 }
188
buildReferenceFrame(int lineWidth)189 virtual tcu::Texture2D buildReferenceFrame (int lineWidth)
190 {
191 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), WIDTH, HEIGHT);
192 referenceFrame.allocLevel(0);
193
194 const deInt32 frameWidth = referenceFrame.getWidth();
195 const deInt32 frameHeight = referenceFrame.getHeight();
196
197 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
198
199 for (int y = 0; y < frameHeight; y++)
200 {
201 for (int x = 0; x < frameWidth; x++)
202 {
203 if (y < frameHeight / 2 && y >= 32 - lineWidth / 2 && y < 32 + lineWidth / 2 && x >= frameWidth / 4 && x < frameWidth / 2)
204 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.25f, 0.5f, 0.25f, 0.5f), x, y);
205 else
206 referenceFrame.getLevel(0).setPixel(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), x, y);
207 }
208 }
209
210 return referenceFrame;
211 }
212 };
213
214 class BlitTestInstance : public CmdBaseCase
215 {
216 public:
BlitTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,ShaderMap shaders)217 BlitTestInstance (Context& context, vk::PipelineConstructionType pipelineConstructionType, ShaderMap shaders)
218 : CmdBaseCase (context, pipelineConstructionType, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
219 {
220 DynamicStateBaseClass::initialize();
221 }
222
command(bool renderPassActive)223 virtual void command (bool renderPassActive)
224 {
225 if (!renderPassActive) {
226 const vk::VkImageBlit blitRegion =
227 {
228 // Src
229 {
230 vk::VK_IMAGE_ASPECT_COLOR_BIT,
231 0, // mipLevel
232 0, // arrayLayer
233 1 // layerCount
234 },
235 {
236 { 0, 0, 0 },
237 {
238 WIDTH,
239 HEIGHT,
240 1
241 },
242 },
243
244 // Dst
245 {
246 vk::VK_IMAGE_ASPECT_COLOR_BIT,
247 0, // mipLevel
248 0, // arrayLayer
249 1 // layerCount
250 },
251 {
252 { 0, 0, 0 },
253 {
254 WIDTH,
255 HEIGHT,
256 1u
257 }
258 }
259 };
260 m_vk.cmdBlitImage(*m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, m_image->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, &blitRegion, vk::VK_FILTER_NEAREST);
261 }
262 }
263
buildReferenceFrame(int lineWidth)264 virtual tcu::Texture2D buildReferenceFrame (int lineWidth)
265 {
266 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), WIDTH, HEIGHT);
267 referenceFrame.allocLevel(0);
268
269 const deInt32 frameWidth = referenceFrame.getWidth();
270 const deInt32 frameHeight = referenceFrame.getHeight();
271
272 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
273
274 for (int y = 0; y < frameHeight; y++)
275 {
276 for (int x = 0; x < frameWidth; x++)
277 {
278 if (y < frameHeight / 2 && y >= 32 - lineWidth / 2 && y < 32 + lineWidth / 2 && x >= frameWidth / 4 && x < frameWidth / 2)
279 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.25f, 0.0f, 0.5f), x, y);
280 }
281 }
282
283 return referenceFrame;
284 }
285 };
286
287 class CopyTestInstance : public CmdBaseCase
288 {
289 public:
CopyTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,ShaderMap shaders)290 CopyTestInstance (Context& context, vk::PipelineConstructionType pipelineConstructionType, ShaderMap shaders)
291 : CmdBaseCase (context, pipelineConstructionType, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
292 {
293 DynamicStateBaseClass::initialize();
294 }
295
command(bool renderPassActive)296 virtual void command (bool renderPassActive)
297 {
298 if (!renderPassActive) {
299 const vk::VkImageSubresourceLayers imgSubResLayers =
300 {
301 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
302 0u, // deUint32 mipLevel;
303 0u, // deUint32 baseArrayLayer;
304 1u, // deUint32 layerCount;
305 };
306 const vk::VkOffset3D offset = { 0, 0, 0 };
307 const vk::VkExtent3D extent = { WIDTH, HEIGHT, 1 };
308
309 const vk::VkImageCopy copyRegion =
310 {
311 imgSubResLayers, // VkImageSubresourceCopy srcSubresource;
312 offset, // VkOffset3D srcOffset;
313 imgSubResLayers, // VkImageSubresourceCopy destSubresource;
314 offset, // VkOffset3D destOffset;
315 extent, // VkExtent3D extent;
316 };
317
318 m_vk.cmdCopyImage(*m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, m_image->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, ©Region);
319 }
320 }
321
buildReferenceFrame(int lineWidth)322 virtual tcu::Texture2D buildReferenceFrame (int lineWidth)
323 {
324 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), WIDTH, HEIGHT);
325 referenceFrame.allocLevel(0);
326
327 const deInt32 frameWidth = referenceFrame.getWidth();
328 const deInt32 frameHeight = referenceFrame.getHeight();
329
330 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
331
332 for (int y = 0; y < frameHeight; y++)
333 {
334 for (int x = 0; x < frameWidth; x++)
335 {
336 if (y < frameHeight / 2 && y >= 32 - lineWidth / 2 && y < 32 + lineWidth / 2 && x >= frameWidth / 4 && x < frameWidth / 2)
337 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.25f, 0.0f, 0.5f), x, y);
338 }
339 }
340
341 return referenceFrame;
342 }
343 };
344
345 class ResolveTestInstance : public CmdBaseCase
346 {
347 public:
ResolveTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,ShaderMap shaders)348 ResolveTestInstance (Context& context, vk::PipelineConstructionType pipelineConstructionType, ShaderMap shaders)
349 : CmdBaseCase (context, pipelineConstructionType, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
350 {
351 DynamicStateBaseClass::initialize();
352
353 m_samples = vk::VK_SAMPLE_COUNT_2_BIT;
354 }
355
command(bool renderPassActive)356 virtual void command (bool renderPassActive)
357 {
358 if (!renderPassActive) {
359 const vk::VkImageSubresourceLayers imgSubResLayers =
360 {
361 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
362 0u, // deUint32 mipLevel;
363 0u, // deUint32 baseArrayLayer;
364 1u, // deUint32 layerCount;
365 };
366 const vk::VkOffset3D offset = { 0, 0, 0 };
367 const vk::VkExtent3D extent = { WIDTH, HEIGHT, 1 };
368
369 const vk::VkImageResolve resolveRegion =
370 {
371 imgSubResLayers, // VkImageSubresourceLayers srcSubresource;
372 offset, // VkOffset3D srcOffset;
373 imgSubResLayers, // VkImageSubresourceLayers dstSubresource;
374 offset, // VkOffset3D dstOffset;
375 extent, // VkExtent3D extent;
376 };
377 m_vk.cmdResolveImage(*m_cmdBuffer, m_image->object(), vk::VK_IMAGE_LAYOUT_GENERAL, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, &resolveRegion);
378
379 const vk::VkImageSubresourceRange subresourceRange =
380 {
381 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
382 0u, // uint32_t baseMipLevel;
383 1u, // uint32_t levelCount;
384 0u, // uint32_t baseArrayLayer;
385 1u, // uint32_t layerCount;
386 };
387 const vk::VkImageMemoryBarrier imageBarrier =
388 {
389 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
390 DE_NULL, // const void* pNext;
391 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
392 vk::VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
393 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout;
394 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
395 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
396 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
397 m_image->object(), // VkImage image;
398 subresourceRange, // VkImageSubresourceRange subresourceRange;
399 };
400 m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
401 }
402 }
403
buildReferenceFrame(int lineWidth)404 virtual tcu::Texture2D buildReferenceFrame (int lineWidth)
405 {
406 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), WIDTH, HEIGHT);
407 referenceFrame.allocLevel(0);
408
409 const deInt32 frameWidth = referenceFrame.getWidth();
410 const deInt32 frameHeight = referenceFrame.getHeight();
411
412 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
413
414 for (int y = 0; y < frameHeight; y++)
415 {
416 for (int x = 0; x < frameWidth; x++)
417 {
418 if (y < frameHeight / 2 && y >= 32 - lineWidth / 2 && y < 32 + lineWidth / 2 && x >= frameWidth / 4 && x < frameWidth / 2)
419 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.25f, 0.0f, 0.5f), x, y);
420 }
421 }
422
423 return referenceFrame;
424 }
425 };
426
427 } //anonymous
428
DynamicStateClearTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)429 DynamicStateClearTests::DynamicStateClearTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
430 : TestCaseGroup (testCtx, "image")
431 , m_pipelineConstructionType (pipelineConstructionType)
432 {
433 /* Left blank on purpose */
434 }
435
~DynamicStateClearTests()436 DynamicStateClearTests::~DynamicStateClearTests()
437 {
438 }
439
init(void)440 void DynamicStateClearTests::init (void)
441 {
442 ShaderMap shaderPaths;
443 shaderPaths[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
444 shaderPaths[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
445
446 // Clear attachment after setting dynamic states
447 addChild(new InstanceFactory<ClearTestInstance>(m_testCtx, "clear", m_pipelineConstructionType, shaderPaths));
448 // Blit image after setting dynamic states
449 addChild(new InstanceFactory<BlitTestInstance>(m_testCtx, "blit", m_pipelineConstructionType, shaderPaths));
450 // Copy image after setting dynamic states
451 addChild(new InstanceFactory<CopyTestInstance>(m_testCtx, "copy", m_pipelineConstructionType, shaderPaths));
452 // Resolve image after setting dynamic states
453 addChild(new InstanceFactory<ResolveTestInstance>(m_testCtx, "resolve", m_pipelineConstructionType, shaderPaths));
454 }
455
456 } // DynamicState
457 } // vkt
458