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