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 Discard Tests
25 *//*--------------------------------------------------------------------*/
26
27 #include "vktDynamicStateDiscardTests.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 #include "vkObjUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkBufferWithMemory.hpp"
42
43 namespace vkt
44 {
45 namespace DynamicState
46 {
47 using namespace Draw;
48 using namespace vk;
49
50 enum TestDynamicStateDiscard
51 {
52 TEST_STENCIL,
53 TEST_VIEWPORT,
54 TEST_SCISSOR,
55 TEST_DEPTH,
56 TEST_BLEND_CONSTANTS,
57 TEST_LINE_WIDTH,
58 };
59
pickSupportedStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device)60 VkFormat pickSupportedStencilFormat(const InstanceInterface &instanceInterface, const VkPhysicalDevice device)
61 {
62 static const VkFormat stencilFormats[] = {
63 VK_FORMAT_S8_UINT,
64 VK_FORMAT_D16_UNORM_S8_UINT,
65 VK_FORMAT_D24_UNORM_S8_UINT,
66 VK_FORMAT_D32_SFLOAT_S8_UINT,
67 };
68
69 for (uint32_t i = 0; i < DE_LENGTH_OF_ARRAY(stencilFormats); ++i)
70 {
71 VkFormatProperties formatProps;
72 instanceInterface.getPhysicalDeviceFormatProperties(device, stencilFormats[i], &formatProps);
73
74 if ((formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0)
75 {
76 return stencilFormats[i];
77 }
78 }
79 TCU_FAIL("Cannot find supported stencil format");
80 }
81
isFormatStencil(VkFormat format)82 bool isFormatStencil(VkFormat format)
83 {
84 const auto textureFormat = vk::mapVkFormat(format);
85 return (textureFormat.order == tcu::TextureFormat::DS || textureFormat.order == tcu::TextureFormat::S);
86 }
87
88 class DiscardTestInstance : public DynamicStateBaseClass
89 {
90 public:
91 DiscardTestInstance(Context &context, vk::PipelineConstructionType pipelineConstructionType,
92 const char *vertexShaderName, const char *fragmentShaderName, vk::VkFormat depthStencilFormat);
93
94 virtual void initRenderPass(const vk::VkDevice device);
95 virtual void initFramebuffer(const vk::VkDevice device);
96 virtual void initPipeline(const vk::VkDevice device);
97
98 void beginRenderPass(const vk::VkClearColorValue &clearColor);
99
100 virtual tcu::TestStatus iterate(void);
101
102 protected:
setDynamicState(void)103 virtual void setDynamicState(void)
104 {
105 DE_ASSERT(false);
106 }
verifyResults(void)107 virtual tcu::TestStatus verifyResults(void)
108 {
109 DE_ASSERT(false);
110 return tcu::TestStatus(QP_TEST_RESULT_PASS, "");
111 }
112 const vk::VkFormat m_depthStencilAttachmentFormat;
113
114 de::SharedPtr<Draw::Image> m_depthStencilImage;
115 vk::Move<vk::VkImageView> m_depthStencilView;
116 std::vector<vk::VkDynamicState> m_dynamicStates;
117 VkBool32 m_depthBounds;
118 };
119
DiscardTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName,vk::VkFormat depthStencilFormat)120 DiscardTestInstance::DiscardTestInstance(Context &context, vk::PipelineConstructionType pipelineConstructionType,
121 const char *vertexShaderName, const char *fragmentShaderName,
122 vk::VkFormat depthStencilFormat)
123 : DynamicStateBaseClass(context, pipelineConstructionType, vertexShaderName, fragmentShaderName)
124 , m_depthStencilAttachmentFormat(depthStencilFormat)
125 , m_depthBounds(VK_FALSE)
126 {
127 const vk::VkDevice device = m_context.getDevice();
128
129 const vk::VkExtent3D stencilImageExtent = {WIDTH, HEIGHT, 1};
130 const ImageCreateInfo stencilImageCreateInfo(
131 vk::VK_IMAGE_TYPE_2D, m_depthStencilAttachmentFormat, stencilImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
132 vk::VK_IMAGE_TILING_OPTIMAL,
133 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
134 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
135
136 m_depthStencilImage = Image::createAndAlloc(m_vk, device, stencilImageCreateInfo, m_context.getDefaultAllocator(),
137 m_context.getUniversalQueueFamilyIndex());
138
139 const ImageViewCreateInfo stencilViewInfo(m_depthStencilImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D,
140 m_depthStencilAttachmentFormat);
141 m_depthStencilView = vk::createImageView(m_vk, device, &stencilViewInfo);
142
143 m_topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
144
145 m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
146 m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
147 m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
148 m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
149
150 const vk::VkDescriptorSetLayoutBinding binding = {0u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1,
151 vk::VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL};
152
153 DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo(1, &binding);
154 m_otherSetLayout = vk::createDescriptorSetLayout(m_vk, device, &descriptorSetLayoutCreateInfo);
155 }
156
initRenderPass(const vk::VkDevice device)157 void DiscardTestInstance::initRenderPass(const vk::VkDevice device)
158 {
159 RenderPassCreateInfo renderPassCreateInfo;
160 renderPassCreateInfo.addAttachment(AttachmentDescription(
161 m_colorAttachmentFormat, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_ATTACHMENT_LOAD_OP_LOAD,
162 vk::VK_ATTACHMENT_STORE_OP_STORE, vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, vk::VK_ATTACHMENT_STORE_OP_STORE,
163 vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL));
164 renderPassCreateInfo.addAttachment(AttachmentDescription(
165 m_depthStencilAttachmentFormat, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_ATTACHMENT_LOAD_OP_LOAD,
166 vk::VK_ATTACHMENT_STORE_OP_STORE, vk::VK_ATTACHMENT_LOAD_OP_LOAD, vk::VK_ATTACHMENT_STORE_OP_STORE,
167 vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL));
168
169 const vk::VkAttachmentReference colorAttachmentReference = {0, vk::VK_IMAGE_LAYOUT_GENERAL};
170
171 const vk::VkAttachmentReference stencilAttachmentReference = {1, vk::VK_IMAGE_LAYOUT_GENERAL};
172
173 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, DE_NULL, 1,
174 &colorAttachmentReference, DE_NULL, stencilAttachmentReference,
175 0, DE_NULL));
176
177 m_renderPass = vk::RenderPassWrapper(m_pipelineConstructionType, m_vk, device, &renderPassCreateInfo);
178 }
179
initFramebuffer(const vk::VkDevice device)180 void DiscardTestInstance::initFramebuffer(const vk::VkDevice device)
181 {
182 std::vector<vk::VkImageView> attachments(2);
183 attachments[0] = *m_colorTargetView;
184 attachments[1] = *m_depthStencilView;
185
186 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1);
187
188 m_renderPass.createFramebuffer(m_vk, device, &framebufferCreateInfo,
189 {m_colorTargetImage->object(), m_depthStencilImage->object()});
190 }
191
initPipeline(const vk::VkDevice device)192 void DiscardTestInstance::initPipeline(const vk::VkDevice device)
193 {
194 const vk::ShaderWrapper vs(
195 vk::ShaderWrapper(m_vk, device, m_context.getBinaryCollection().get(m_vertexShaderName), 0));
196 const vk::ShaderWrapper fs(
197 vk::ShaderWrapper(m_vk, device, m_context.getBinaryCollection().get(m_fragmentShaderName), 0));
198 std::vector<vk::VkViewport> viewports{{0.0f, 0.0f, (float)WIDTH, (float)HEIGHT, 0.0f, 1.0f}};
199 std::vector<vk::VkRect2D> scissors{{{0u, 0u}, {WIDTH, HEIGHT}}};
200
201 const PipelineCreateInfo::ColorBlendState::Attachment attachmentState;
202 const PipelineCreateInfo::ColorBlendState colorBlendState(
203 1u, static_cast<const vk::VkPipelineColorBlendAttachmentState *>(&attachmentState));
204 const PipelineCreateInfo::RasterizerState rasterizerState;
205 PipelineCreateInfo::DepthStencilState depthStencilState;
206 const PipelineCreateInfo::DynamicState dynamicState(m_dynamicStates);
207
208 depthStencilState.depthTestEnable = VK_TRUE;
209 depthStencilState.depthWriteEnable = VK_TRUE;
210 depthStencilState.depthCompareOp = VK_COMPARE_OP_ALWAYS;
211 depthStencilState.depthBoundsTestEnable = m_depthBounds;
212 depthStencilState.minDepthBounds = 0.0f;
213 depthStencilState.maxDepthBounds = 1.0f;
214 depthStencilState.stencilTestEnable = VK_TRUE;
215 depthStencilState.front.failOp = VK_STENCIL_OP_KEEP;
216 depthStencilState.front.passOp = VK_STENCIL_OP_REPLACE;
217 depthStencilState.front.depthFailOp = VK_STENCIL_OP_KEEP;
218 depthStencilState.front.compareOp = VK_COMPARE_OP_ALWAYS;
219 depthStencilState.front.compareMask = 0u;
220 depthStencilState.front.writeMask = 0u;
221 depthStencilState.front.reference = 0u;
222 depthStencilState.back.failOp = VK_STENCIL_OP_KEEP;
223 depthStencilState.back.passOp = VK_STENCIL_OP_REPLACE;
224 depthStencilState.back.depthFailOp = VK_STENCIL_OP_KEEP;
225 depthStencilState.back.compareOp = VK_COMPARE_OP_ALWAYS;
226 depthStencilState.back.compareMask = 0u;
227 depthStencilState.back.writeMask = 0u;
228 depthStencilState.back.reference = 0u;
229
230 m_pipeline.setDefaultTopology(m_topology)
231 .setDynamicState(static_cast<const vk::VkPipelineDynamicStateCreateInfo *>(&dynamicState))
232 .setDefaultMultisampleState()
233 .setupVertexInputState(&m_vertexInputState)
234 .setupPreRasterizationShaderState(
235 viewports, scissors, m_pipelineLayout, *m_renderPass, 0u, vs,
236 static_cast<const vk::VkPipelineRasterizationStateCreateInfo *>(&rasterizerState))
237 .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, fs,
238 static_cast<const vk::VkPipelineDepthStencilStateCreateInfo *>(&depthStencilState))
239 .setupFragmentOutputState(*m_renderPass, 0u,
240 static_cast<const vk::VkPipelineColorBlendStateCreateInfo *>(&colorBlendState))
241 .setMonolithicPipelineLayout(m_pipelineLayout)
242 .buildPipeline();
243 }
244
beginRenderPass(const vk::VkClearColorValue & clearColor)245 void DiscardTestInstance::beginRenderPass(const vk::VkClearColorValue &clearColor)
246 {
247 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
248
249 initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
250 vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
251
252 const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
253 m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1,
254 &subresourceRange);
255
256 const vk::VkMemoryBarrier memBarrier = {
257 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, vk::VK_ACCESS_TRANSFER_WRITE_BIT,
258 vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT};
259
260 m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
261 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0,
262 DE_NULL);
263
264 if (isFormatStencil(m_depthStencilAttachmentFormat))
265 {
266 initialTransitionStencil2DImage(m_vk, *m_cmdBuffer, m_depthStencilImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
267 vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
268 }
269 else
270 {
271 initialTransitionDepth2DImage(m_vk, *m_cmdBuffer, m_depthStencilImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
272 vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
273 }
274
275 const vk::VkClearDepthStencilValue depthStencilClearValue = {0.0f, 0};
276 const ImageSubresourceRange subresourceRangeStencil = m_depthStencilAttachmentFormat == vk::VK_FORMAT_S8_UINT ?
277 vk::VK_IMAGE_ASPECT_STENCIL_BIT :
278 vk::VK_IMAGE_ASPECT_DEPTH_BIT;
279 m_vk.cmdClearDepthStencilImage(*m_cmdBuffer, m_depthStencilImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
280 &depthStencilClearValue, 1, &subresourceRangeStencil);
281
282 vk::VkMemoryBarrier dsMemBarrier;
283 dsMemBarrier.sType = vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER;
284 dsMemBarrier.pNext = NULL;
285 dsMemBarrier.srcAccessMask = vk::VK_ACCESS_TRANSFER_WRITE_BIT;
286 dsMemBarrier.dstAccessMask = vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
287 vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
288 vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
289
290 m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
291 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
292 vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
293 vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
294 0, 1, &dsMemBarrier, 0, NULL, 0, NULL);
295
296 m_renderPass.begin(m_vk, *m_cmdBuffer, vk::makeRect2D(0, 0, WIDTH, HEIGHT));
297 }
iterate(void)298 tcu::TestStatus DiscardTestInstance::iterate(void)
299 {
300 const vk::VkQueue queue = m_context.getUniversalQueue();
301 const vk::VkDevice device = m_context.getDevice();
302 Allocator &allocator = m_context.getDefaultAllocator();
303
304 const VkDescriptorPoolSize poolSizes[] = {
305 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u},
306 };
307 const VkDescriptorPoolCreateInfo poolInfo = {
308 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
309 DE_NULL,
310 vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
311 1u, // maxSets
312 DE_LENGTH_OF_ARRAY(poolSizes),
313 poolSizes,
314 };
315
316 vk::Move<vk::VkDescriptorPool> descriptorPool = createDescriptorPool(m_vk, device, &poolInfo);
317 vk::Move<vk::VkDescriptorSet> descriptorSet = makeDescriptorSet(m_vk, device, *descriptorPool, *m_otherSetLayout);
318
319 const vk::VkDeviceSize size = sizeof(int);
320
321 const BufferWithMemory buffer(m_vk, device, allocator,
322 makeBufferCreateInfo(size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
323 MemoryRequirement::HostVisible);
324
325 uint32_t *ptr = (uint32_t *)buffer.getAllocation().getHostPtr();
326 deMemset(ptr, 0u, static_cast<std::size_t>(size));
327
328 {
329 const vk::VkDescriptorBufferInfo bufferInfo = makeDescriptorBufferInfo(*buffer, 0, size);
330 const vk::VkWriteDescriptorSet descriptorWrite = {
331 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
332 DE_NULL,
333 *descriptorSet,
334 0u, // dstBinding
335 0u, // dstArrayElement
336 1u, // descriptorCount
337 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
338 DE_NULL,
339 &bufferInfo,
340 DE_NULL,
341 };
342
343 m_vk.updateDescriptorSets(device, 1, &descriptorWrite, 0u, DE_NULL);
344 }
345
346 const vk::VkClearColorValue clearColor = {{0.0f, 0.0f, 0.0f, 1.0f}};
347 beginRenderPass(clearColor);
348 m_vk.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1,
349 &*descriptorSet, 0, nullptr);
350 m_pipeline.bind(*m_cmdBuffer);
351 const vk::VkDeviceSize vertexBufferOffset = 0;
352 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
353 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
354
355 setDynamicState();
356
357 m_vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
358 m_renderPass.end(m_vk, *m_cmdBuffer);
359 endCommandBuffer(m_vk, *m_cmdBuffer);
360
361 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
362
363 return verifyResults();
364 }
365
366 class StencilTestInstance : public DiscardTestInstance
367 {
368 public:
StencilTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)369 StencilTestInstance(Context &context, vk::PipelineConstructionType pipelineConstructionType,
370 const char *vertexShaderName, const char *fragmentShaderName)
371 : DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName,
372 pickSupportedStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice()))
373 {
374 m_dynamicStates = {vk::VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, vk::VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
375 vk::VK_DYNAMIC_STATE_STENCIL_REFERENCE};
376 const auto features = context.getDeviceFeatures();
377 m_depthBounds = features.depthBounds;
378
379 DynamicStateBaseClass::initialize();
380 }
381
setDynamicState(void)382 virtual void setDynamicState(void)
383 {
384 uint32_t value = 0x80;
385 m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, value);
386 m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, value);
387 m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, value);
388 m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, value);
389 m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, value);
390 m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, value);
391 }
392
verifyResults(void)393 virtual tcu::TestStatus verifyResults(void)
394 {
395 const vk::VkQueue queue = m_context.getUniversalQueue();
396 const vk::VkOffset3D zeroOffset = {0, 0, 0};
397 tcu::ConstPixelBufferAccess renderedFrame =
398 m_depthStencilImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL,
399 zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_STENCIL_BIT);
400 de::SharedPtr<tcu::TextureLevel> stencilFrame;
401
402 if (tcu::isCombinedDepthStencilType(renderedFrame.getFormat().type))
403 {
404 stencilFrame = de::SharedPtr<tcu::TextureLevel>(new tcu::TextureLevel(
405 tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8), WIDTH, HEIGHT, 1u));
406
407 tcu::copy(stencilFrame->getAccess(),
408 tcu::getEffectiveDepthStencilAccess(renderedFrame, tcu::Sampler::MODE_STENCIL));
409 renderedFrame = stencilFrame->getAccess();
410 }
411
412 for (int i = 0; i < WIDTH; ++i)
413 {
414 for (int j = 0; j < HEIGHT; ++j)
415 {
416 const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
417 if (pixel[0] != 0.0f)
418 {
419 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
420 }
421 }
422 }
423 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
424 }
425 };
426
427 class ViewportTestInstance : public DiscardTestInstance
428 {
429 public:
ViewportTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)430 ViewportTestInstance(Context &context, vk::PipelineConstructionType pipelineConstructionType,
431 const char *vertexShaderName, const char *fragmentShaderName)
432 : DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName,
433 pickSupportedStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice()))
434 {
435 m_dynamicStates = {vk::VK_DYNAMIC_STATE_VIEWPORT};
436 DynamicStateBaseClass::initialize();
437 }
438
setDynamicState(void)439 virtual void setDynamicState(void)
440 {
441 vk::VkViewport viewport = vk::makeViewport(tcu::UVec2(WIDTH, HEIGHT));
442 if (vk::isConstructionTypeShaderObject(m_pipelineConstructionType))
443 {
444 #ifndef CTS_USES_VULKANSC
445 m_vk.cmdSetViewportWithCount(*m_cmdBuffer, 1, &viewport);
446 #else
447 m_vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, 1, &viewport);
448 #endif
449 }
450 else
451 {
452 m_vk.cmdSetViewport(*m_cmdBuffer, 0, 1, &viewport);
453 }
454 }
455
verifyResults(void)456 virtual tcu::TestStatus verifyResults(void)
457 {
458 const vk::VkQueue queue = m_context.getUniversalQueue();
459 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_depthStencilAttachmentFormat), WIDTH, HEIGHT);
460 referenceFrame.allocLevel(0);
461
462 const vk::VkOffset3D zeroOffset = {0, 0, 0};
463 const tcu::ConstPixelBufferAccess renderedFrame =
464 m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL,
465 zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
466
467 for (int i = 0; i < WIDTH; ++i)
468 {
469 for (int j = 0; j < HEIGHT; ++j)
470 {
471 const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
472 if (pixel != tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f))
473 {
474 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
475 }
476 }
477 }
478 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
479 }
480 };
481
482 class ScissorTestInstance : public DiscardTestInstance
483 {
484 public:
ScissorTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)485 ScissorTestInstance(Context &context, vk::PipelineConstructionType pipelineConstructionType,
486 const char *vertexShaderName, const char *fragmentShaderName)
487 : DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName,
488 pickSupportedStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice()))
489 {
490 m_dynamicStates = {vk::VK_DYNAMIC_STATE_SCISSOR};
491 DynamicStateBaseClass::initialize();
492 }
493
setDynamicState(void)494 virtual void setDynamicState(void)
495 {
496 vk::VkRect2D scissor = vk::makeRect2D(tcu::UVec2(WIDTH, HEIGHT));
497 if (vk::isConstructionTypeShaderObject(m_pipelineConstructionType))
498 {
499 #ifndef CTS_USES_VULKANSC
500 m_vk.cmdSetScissorWithCount(*m_cmdBuffer, 1, &scissor);
501 #else
502 m_vk.cmdSetScissorWithCountEXT(*m_cmdBuffer, 1, &scissor);
503 #endif
504 }
505 else
506 {
507 m_vk.cmdSetScissor(*m_cmdBuffer, 0, 1, &scissor);
508 }
509 }
510
verifyResults(void)511 virtual tcu::TestStatus verifyResults(void)
512 {
513 const vk::VkQueue queue = m_context.getUniversalQueue();
514 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_depthStencilAttachmentFormat), WIDTH, HEIGHT);
515 referenceFrame.allocLevel(0);
516
517 const vk::VkOffset3D zeroOffset = {0, 0, 0};
518 const tcu::ConstPixelBufferAccess renderedFrame =
519 m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL,
520 zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
521
522 for (int i = 0; i < WIDTH; ++i)
523 {
524 for (int j = 0; j < HEIGHT; ++j)
525 {
526 const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
527 if (pixel != tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f))
528 {
529 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
530 }
531 }
532 }
533 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
534 }
535 };
536
537 class DepthTestInstance : public DiscardTestInstance
538 {
539 public:
DepthTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)540 DepthTestInstance(Context &context, vk::PipelineConstructionType pipelineConstructionType,
541 const char *vertexShaderName, const char *fragmentShaderName)
542 : DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName,
543 vk::VK_FORMAT_D32_SFLOAT)
544 {
545 m_dynamicStates = {vk::VK_DYNAMIC_STATE_DEPTH_BIAS, vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS};
546 DynamicStateBaseClass::initialize();
547 }
548
setDynamicState(void)549 virtual void setDynamicState(void)
550 {
551 m_vk.cmdSetDepthBounds(*m_cmdBuffer, 0.0f, 1.0f);
552 m_vk.cmdSetDepthBias(*m_cmdBuffer, 1.0f, 1.0f, 1.0f);
553 }
554
verifyResults(void)555 virtual tcu::TestStatus verifyResults(void)
556 {
557 const vk::VkQueue queue = m_context.getUniversalQueue();
558 const vk::VkOffset3D zeroOffset = {0, 0, 0};
559 const tcu::ConstPixelBufferAccess renderedFrame =
560 m_depthStencilImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL,
561 zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_DEPTH_BIT);
562
563 for (int i = 0; i < WIDTH; ++i)
564 {
565 for (int j = 0; j < HEIGHT; ++j)
566 {
567 const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
568 if (pixel[0] != 0.0f)
569 {
570 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
571 }
572 }
573 }
574 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
575 }
576 };
577
578 class BlendTestInstance : public DiscardTestInstance
579 {
580 public:
BlendTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)581 BlendTestInstance(Context &context, vk::PipelineConstructionType pipelineConstructionType,
582 const char *vertexShaderName, const char *fragmentShaderName)
583 : DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName,
584 pickSupportedStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice()))
585 {
586 m_dynamicStates = {vk::VK_DYNAMIC_STATE_BLEND_CONSTANTS};
587 DynamicStateBaseClass::initialize();
588 }
589
setDynamicState(void)590 virtual void setDynamicState(void)
591 {
592 float blendConstantsants[4] = {0.0f, 0.0f, 0.0f, 0.0f};
593 m_vk.cmdSetBlendConstants(*m_cmdBuffer, blendConstantsants);
594 }
595
verifyResults(void)596 virtual tcu::TestStatus verifyResults(void)
597 {
598 const vk::VkQueue queue = m_context.getUniversalQueue();
599 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_depthStencilAttachmentFormat), WIDTH, HEIGHT);
600 referenceFrame.allocLevel(0);
601
602 const vk::VkOffset3D zeroOffset = {0, 0, 0};
603 const tcu::ConstPixelBufferAccess renderedFrame =
604 m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL,
605 zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
606
607 for (int i = 0; i < WIDTH; ++i)
608 {
609 for (int j = 0; j < HEIGHT; ++j)
610 {
611 const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
612 if (pixel != tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f))
613 {
614 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
615 }
616 }
617 }
618 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
619 }
620 };
621
622 class LineTestInstance : public DiscardTestInstance
623 {
624 public:
LineTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)625 LineTestInstance(Context &context, vk::PipelineConstructionType pipelineConstructionType,
626 const char *vertexShaderName, const char *fragmentShaderName)
627 : DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName,
628 pickSupportedStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice()))
629 {
630 m_dynamicStates = {vk::VK_DYNAMIC_STATE_LINE_WIDTH};
631 DynamicStateBaseClass::initialize();
632 }
633
setDynamicState(void)634 virtual void setDynamicState(void)
635 {
636 m_vk.cmdSetLineWidth(*m_cmdBuffer, 1.0f);
637 }
638
verifyResults(void)639 virtual tcu::TestStatus verifyResults(void)
640 {
641 const vk::VkQueue queue = m_context.getUniversalQueue();
642 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_depthStencilAttachmentFormat), WIDTH, HEIGHT);
643 referenceFrame.allocLevel(0);
644
645 const vk::VkOffset3D zeroOffset = {0, 0, 0};
646 const tcu::ConstPixelBufferAccess renderedFrame =
647 m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL,
648 zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
649
650 for (int i = 0; i < WIDTH; ++i)
651 {
652 for (int j = 0; j < HEIGHT; ++j)
653 {
654 const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
655 if (pixel != tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f))
656 {
657 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
658 }
659 }
660 }
661 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
662 }
663 };
664
665 class DiscardTestCase : public vkt::TestCase
666 {
667 public:
DiscardTestCase(tcu::TestContext & context,const char * name,vk::PipelineConstructionType pipelineConstructionType,TestDynamicStateDiscard testCase)668 DiscardTestCase(tcu::TestContext &context, const char *name, vk::PipelineConstructionType pipelineConstructionType,
669 TestDynamicStateDiscard testCase)
670 : TestCase(context, name)
671 , m_pipelineConstructionType(pipelineConstructionType)
672 , m_testCase(testCase)
673 , m_depthBounds(false)
674 {
675 }
676
checkSupport(Context & context) const677 virtual void checkSupport(Context &context) const
678 {
679 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
680 m_pipelineConstructionType);
681 }
682
createInstance(Context & context) const683 TestInstance *createInstance(Context &context) const
684 {
685 switch (m_testCase)
686 {
687 case TEST_STENCIL:
688 return new StencilTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
689 case TEST_VIEWPORT:
690 return new ViewportTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
691 case TEST_SCISSOR:
692 return new ScissorTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
693 case TEST_DEPTH:
694 return new DepthTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
695 case TEST_BLEND_CONSTANTS:
696 return new BlendTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
697 case TEST_LINE_WIDTH:
698 return new LineTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
699 default:
700 break;
701 }
702 DE_ASSERT(false);
703 return nullptr;
704 }
705
initPrograms(vk::SourceCollections & programCollection) const706 virtual void initPrograms(vk::SourceCollections &programCollection) const
707 {
708 std::ostringstream vert;
709 vert << "#version 450\n"
710 << "\n"
711 << "layout(location = 0) in vec4 in_position;"
712 << "layout(location = 1) in vec4 in_color;"
713 << "\n"
714 << "layout(location = 0) out vec4 out_color;"
715 << "out gl_PerVertex { vec4 gl_Position; };"
716 << "\n"
717 << "void main ()\n"
718 << "{\n"
719 << " gl_Position = in_position;\n"
720 << " out_color = in_color;\n"
721 << "}\n";
722
723 programCollection.glslSources.add("discard.vert") << glu::VertexSource(vert.str());
724
725 std::ostringstream frag;
726 frag << "#version 450\n"
727 << "\n"
728 << "layout (set=0, binding=0, std140) uniform InputBlock {\n"
729 << " int discard_all;\n"
730 << "} unif;\n"
731 << "\n"
732 << "layout (location = 0) in vec4 in_color;"
733 << "\n"
734 << "layout (location = 0) out vec4 color;"
735 << "\n"
736 << "void main ()\n"
737 << "{\n"
738 << " if (unif.discard_all == 0) {\n"
739 << " discard;\n"
740 << " }\n"
741 << " color = in_color;\n"
742 << "}\n";
743
744 programCollection.glslSources.add("discard.frag") << glu::FragmentSource(frag.str());
745 }
746
747 protected:
748 vk::PipelineConstructionType m_pipelineConstructionType;
749 TestDynamicStateDiscard m_testCase;
750 VkBool32 m_depthBounds;
751 };
752
DynamicStateDiscardTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)753 DynamicStateDiscardTests::DynamicStateDiscardTests(tcu::TestContext &testCtx,
754 vk::PipelineConstructionType pipelineConstructionType)
755 : TestCaseGroup(testCtx, "discard")
756 , m_pipelineConstructionType(pipelineConstructionType)
757 {
758 /* Left blank on purpose */
759 }
760
~DynamicStateDiscardTests()761 DynamicStateDiscardTests::~DynamicStateDiscardTests()
762 {
763 }
764
init(void)765 void DynamicStateDiscardTests::init(void)
766 {
767 // Use dynamic stencil with discard
768 addChild(
769 new DiscardTestCase(m_testCtx, "stencil", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_STENCIL));
770 // Use dynamic viewport with discard
771 addChild(
772 new DiscardTestCase(m_testCtx, "viewport", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_VIEWPORT));
773 // Use dynamic scissor with discard
774 addChild(
775 new DiscardTestCase(m_testCtx, "scissor", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_SCISSOR));
776 // Use dynamic depth with discard
777 addChild(new DiscardTestCase(m_testCtx, "depth", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_DEPTH));
778 // Use dynamic blend constants with discard
779 addChild(new DiscardTestCase(m_testCtx, "blend", m_pipelineConstructionType,
780 TestDynamicStateDiscard::TEST_BLEND_CONSTANTS));
781 // Use dynamic line width with discard
782 addChild(
783 new DiscardTestCase(m_testCtx, "line", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_LINE_WIDTH));
784 }
785
786 } // namespace DynamicState
787 } // namespace vkt
788