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