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