1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020 The Khronos Group Inc.
6 * Copyright (c) 2020 Valve Corporation.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Test frag shader side effects are not removed by optimizations.
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktRasterizationFragShaderSideEffectsTests.hpp"
26 #include "vktTestCase.hpp"
27
28 #include "vkQueryUtil.hpp"
29 #include "vkObjUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkImageWithMemory.hpp"
32 #include "vkBufferWithMemory.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkImageUtil.hpp"
37
38 #include "tcuVector.hpp"
39 #include "tcuMaybe.hpp"
40 #include "tcuTestLog.hpp"
41
42 #include "deUniquePtr.hpp"
43
44 #include <sstream>
45 #include <string>
46 #include <memory>
47 #include <vector>
48 #include <algorithm>
49
50 namespace vkt
51 {
52 namespace rasterization
53 {
54
55 namespace
56 {
57
58 enum class CaseType
59 {
60 KILL,
61 DEMOTE,
62 SAMPLE_MASK_BEFORE,
63 SAMPLE_MASK_AFTER,
64 ALPHA_COVERAGE_BEFORE,
65 ALPHA_COVERAGE_AFTER,
66 DEPTH_BOUNDS,
67 STENCIL_NEVER,
68 DEPTH_NEVER,
69 };
70
71 constexpr deUint32 kFramebufferWidth = 32u;
72 constexpr deUint32 kFramebufferHeight = 32u;
73 constexpr deUint32 kTotalPixels = kFramebufferWidth * kFramebufferHeight;
74
75 constexpr vk::VkFormatFeatureFlags kNeededColorFeatures = (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
76 constexpr vk::VkFormat kColorFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
77 constexpr vk::VkFormatFeatureFlags kNeededDSFeatures = vk::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
78 // VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT must be supported for one of these two, according to the spec.
79 const vk::VkFormat kDepthStencilFormats[] = { vk::VK_FORMAT_D32_SFLOAT_S8_UINT, vk::VK_FORMAT_D24_UNORM_S8_UINT };
80
81 struct DepthBoundsParameters
82 {
83 float minDepthBounds;
84 float maxDepthBounds;
85 float depthValue;
86 };
87
88 struct TestParams
89 {
90 CaseType caseType;
91 tcu::Vec4 clearColor;
92 tcu::Vec4 drawColor;
93 bool colorAtEnd;
94 tcu::Maybe<DepthBoundsParameters> depthBoundsParams;
95
TestParamsvkt::rasterization::__anonc90821310111::TestParams96 TestParams (CaseType type, const tcu::Vec4& clearColor_, const tcu::Vec4& drawColor_, bool colorAtEnd_, const tcu::Maybe<DepthBoundsParameters>& depthBoundsParams_)
97 : caseType (type)
98 , clearColor (clearColor_)
99 , drawColor (drawColor_)
100 , colorAtEnd (colorAtEnd_)
101 , depthBoundsParams (depthBoundsParams_)
102 {
103 if (caseType == CaseType::DEPTH_BOUNDS)
104 DE_ASSERT(static_cast<bool>(depthBoundsParams));
105 }
106 };
107
expectClearColor(CaseType caseType)108 bool expectClearColor (CaseType caseType)
109 {
110 return (caseType != CaseType::ALPHA_COVERAGE_BEFORE && caseType != CaseType::ALPHA_COVERAGE_AFTER);
111 }
112
needsDepthStencilAttachment(CaseType caseType)113 bool needsDepthStencilAttachment (CaseType caseType)
114 {
115 return (caseType == CaseType::DEPTH_BOUNDS || caseType == CaseType::DEPTH_NEVER || caseType == CaseType::STENCIL_NEVER);
116 }
117
makeVkBool32(bool value)118 vk::VkBool32 makeVkBool32 (bool value)
119 {
120 return (value ? VK_TRUE : VK_FALSE);
121 }
122
123 class FragSideEffectsTestCase : public vkt::TestCase
124 {
125 public:
126 FragSideEffectsTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params);
~FragSideEffectsTestCase(void)127 virtual ~FragSideEffectsTestCase (void) {}
128
129 virtual void checkSupport (Context& context) const;
130 virtual void initPrograms (vk::SourceCollections& programCollection) const;
131 virtual TestInstance* createInstance (Context& context) const;
132
133 private:
134 TestParams m_params;
135 };
136
137 class FragSideEffectsInstance : public vkt::TestInstance
138 {
139 public:
140 FragSideEffectsInstance (Context& context, const TestParams& params);
~FragSideEffectsInstance(void)141 virtual ~FragSideEffectsInstance (void) {}
142
143 virtual tcu::TestStatus iterate (void);
144
145 private:
146 TestParams m_params;
147 };
148
FragSideEffectsTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams & params)149 FragSideEffectsTestCase::FragSideEffectsTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
150 : vkt::TestCase (testCtx, name, description)
151 , m_params (params)
152 {}
153
checkSupport(Context & context) const154 void FragSideEffectsTestCase::checkSupport (Context& context) const
155 {
156 const auto& vki = context.getInstanceInterface();
157 const auto physicalDevice = context.getPhysicalDevice();
158
159 if (m_params.caseType == CaseType::DEPTH_BOUNDS)
160 {
161 const auto features = vk::getPhysicalDeviceFeatures(vki, physicalDevice);
162 if (!features.depthBounds)
163 TCU_THROW(NotSupportedError, "Depth bounds test not supported");
164 }
165 else if (m_params.caseType == CaseType::DEMOTE)
166 {
167 context.requireDeviceFunctionality("VK_EXT_shader_demote_to_helper_invocation");
168 }
169
170 const auto colorFormatProperties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kColorFormat);
171 if ((colorFormatProperties.optimalTilingFeatures & kNeededColorFeatures) != kNeededColorFeatures)
172 TCU_THROW(NotSupportedError, "Color format lacks required features");
173 }
174
initPrograms(vk::SourceCollections & programCollection) const175 void FragSideEffectsTestCase::initPrograms (vk::SourceCollections& programCollection) const
176 {
177 std::ostringstream headers;
178 std::ostringstream before;
179 std::ostringstream after;
180
181 std::ostringstream vert;
182 std::ostringstream frag;
183
184 // Depth should be 0 by default unless provided by the depth bounds parameters.
185 const float meshDepth = (m_params.depthBoundsParams ? m_params.depthBoundsParams.get().depthValue : 0.0f);
186 const auto& drawColor = m_params.drawColor;
187
188 vert
189 << "#version 450\n"
190 << "\n"
191 << "layout (location=0) in vec2 inPos;\n"
192 << "\n"
193 << "void main() {\n"
194 << " gl_Position = vec4(inPos, " << meshDepth << ", 1.0);\n"
195 << "}\n"
196 ;
197
198 // Prepare output color statement to be used before or after SSBO write.
199 std::ostringstream colorStatement;
200 if (m_params.caseType == CaseType::ALPHA_COVERAGE_BEFORE || m_params.caseType == CaseType::ALPHA_COVERAGE_AFTER)
201 {
202 // In the alpha coverage cases the alpha color value is supposed to be 0.
203 DE_ASSERT(m_params.drawColor.w() == 0.0f);
204
205 // Leave out the alpha component for these cases.
206 colorStatement << " outColor.rgb = vec3(" << drawColor.x() << ", " << drawColor.y() << ", " << drawColor.z() << ");\n";
207 }
208 else
209 {
210 colorStatement << " outColor = vec4(" << drawColor.x() << ", " << drawColor.y() << ", " << drawColor.z() << ", " << drawColor.w() << ");\n";
211 }
212
213 switch (m_params.caseType)
214 {
215 case CaseType::KILL:
216 after << " discard;\n";
217 break;
218 case CaseType::DEMOTE:
219 headers << "#extension GL_EXT_demote_to_helper_invocation : enable\n";
220 after << " demote;\n";
221 break;
222 case CaseType::SAMPLE_MASK_BEFORE:
223 before << " gl_SampleMask[0] = 0;\n";
224 break;
225 case CaseType::SAMPLE_MASK_AFTER:
226 after << " gl_SampleMask[0] = 0;\n";
227 break;
228 case CaseType::ALPHA_COVERAGE_BEFORE:
229 before << " outColor.a = float(" << drawColor.w() << ");\n";
230 break;
231 case CaseType::ALPHA_COVERAGE_AFTER:
232 after << " outColor.a = float(" << drawColor.w() << ");\n";
233 break;
234 case CaseType::DEPTH_BOUNDS:
235 case CaseType::STENCIL_NEVER:
236 case CaseType::DEPTH_NEVER:
237 break;
238 default:
239 DE_ASSERT(false); break;
240 }
241
242 frag
243 << "#version 450\n"
244 << "layout(set=0, binding=0, std430) buffer OutputBuffer {\n"
245 << " int val[" << kTotalPixels << "];\n"
246 << "} outBuffer;\n"
247 << "layout (location=0) out vec4 outColor;\n"
248 << headers.str()
249 << "\n"
250 << "void main() {\n"
251 << " const ivec2 fragCoord = ivec2(gl_FragCoord);\n"
252 << " const int bufferIndex = (fragCoord.y * " << kFramebufferWidth << ") + fragCoord.x;\n"
253 << (m_params.colorAtEnd ? "" : colorStatement.str())
254 << before.str()
255 << " outBuffer.val[bufferIndex] = 1;\n"
256 << after.str()
257 << (m_params.colorAtEnd ? colorStatement.str() : "")
258 << "}\n"
259 ;
260
261 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
262 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
263 }
264
createInstance(Context & context) const265 TestInstance* FragSideEffectsTestCase::createInstance (Context& context) const
266 {
267 return new FragSideEffectsInstance(context, m_params);
268 }
269
FragSideEffectsInstance(Context & context,const TestParams & params)270 FragSideEffectsInstance::FragSideEffectsInstance (Context& context, const TestParams& params)
271 : vkt::TestInstance (context)
272 , m_params (params)
273 {}
274
iterate(void)275 tcu::TestStatus FragSideEffectsInstance::iterate (void)
276 {
277 const auto& vki = m_context.getInstanceInterface();
278 const auto physicalDevice = m_context.getPhysicalDevice();
279 const auto& vkd = m_context.getDeviceInterface();
280 const auto device = m_context.getDevice();
281 auto& alloc = m_context.getDefaultAllocator();
282 const auto queue = m_context.getUniversalQueue();
283 const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
284
285 // Color and depth/stencil images.
286
287 const vk::VkImageCreateInfo colorCreateInfo =
288 {
289 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
290 nullptr, // const void* pNext;
291 0u, // VkImageCreateFlags flags;
292 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
293 kColorFormat, // VkFormat format;
294 vk::makeExtent3D(kFramebufferWidth, kFramebufferHeight, 1u), // VkExtent3D extent;
295 1u, // deUint32 mipLevels;
296 1u, // deUint32 arrayLayers;
297 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
298 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
299 (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT), // VkImageUsageFlags usage;
300 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
301 0u, // deUint32 queueFamilyIndexCount;
302 nullptr, // const deUint32* pQueueFamilyIndices;
303 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
304 };
305 vk::ImageWithMemory colorImage(vkd, device, alloc, colorCreateInfo, vk::MemoryRequirement::Any);
306
307 std::unique_ptr<vk::ImageWithMemory> depthStencilImage;
308 vk::VkFormat depthStencilFormat = vk::VK_FORMAT_UNDEFINED;
309
310 if (needsDepthStencilAttachment(m_params.caseType))
311 {
312 // Find available image format first.
313 for (int i = 0; i < DE_LENGTH_OF_ARRAY(kDepthStencilFormats); ++i)
314 {
315 const auto dsFormatProperties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kDepthStencilFormats[i]);
316 if ((dsFormatProperties.optimalTilingFeatures & kNeededDSFeatures) == kNeededDSFeatures)
317 {
318 depthStencilFormat = kDepthStencilFormats[i];
319 break;
320 }
321 }
322
323 if (depthStencilFormat == vk::VK_FORMAT_UNDEFINED)
324 TCU_FAIL("No suitable depth/stencil format found");
325
326 const vk::VkImageCreateInfo depthStencilCreateInfo =
327 {
328 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
329 nullptr, // const void* pNext;
330 0u, // VkImageCreateFlags flags;
331 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
332 depthStencilFormat, // VkFormat format;
333 vk::makeExtent3D(kFramebufferWidth, kFramebufferHeight, 1u), // VkExtent3D extent;
334 1u, // deUint32 mipLevels;
335 1u, // deUint32 arrayLayers;
336 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
337 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
338 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, // VkImageUsageFlags usage;
339 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
340 0u, // deUint32 queueFamilyIndexCount;
341 nullptr, // const deUint32* pQueueFamilyIndices;
342 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
343 };
344
345 depthStencilImage.reset(new vk::ImageWithMemory(vkd, device, alloc, depthStencilCreateInfo, vk::MemoryRequirement::Any));
346 }
347
348 // Image views.
349 const auto colorSubresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
350 const auto colorImageView = vk::makeImageView(vkd, device, colorImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kColorFormat, colorSubresourceRange);
351
352 vk::Move<vk::VkImageView> depthStencilImageView;
353 if (depthStencilImage)
354 {
355 const auto depthStencilSubresourceRange = vk::makeImageSubresourceRange((vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, 1u);
356 depthStencilImageView = vk::makeImageView(vkd, device, depthStencilImage.get()->get(), vk::VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, depthStencilSubresourceRange);
357 }
358
359 // Color image buffer.
360 const auto tcuFormat = vk::mapVkFormat(kColorFormat);
361 const auto colorImageBufferSize = static_cast<vk::VkDeviceSize>(kTotalPixels * tcuFormat.getPixelSize());
362 const auto colorImageBufferInfo = vk::makeBufferCreateInfo(colorImageBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
363 vk::BufferWithMemory colorImageBuffer(vkd, device, alloc, colorImageBufferInfo, vk::MemoryRequirement::HostVisible);
364
365 // Vertex buffer.
366 const std::vector<tcu::Vec2> fullScreenQuad =
367 {
368 tcu::Vec2(-1.0f, 1.0f),
369 tcu::Vec2( 1.0f, 1.0f),
370 tcu::Vec2( 1.0f, -1.0f),
371 tcu::Vec2(-1.0f, 1.0f),
372 tcu::Vec2( 1.0f, -1.0f),
373 tcu::Vec2(-1.0f, -1.0f),
374 };
375
376 const auto vertexBufferSize = static_cast<vk::VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type));
377 const auto vertexBufferInfo = vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
378 const vk::VkDeviceSize vertexBufferOffset = 0ull;
379 vk::BufferWithMemory vertexBuffer (vkd, device, alloc, vertexBufferInfo, vk::MemoryRequirement::HostVisible);
380 const auto& vertexBufferAlloc = vertexBuffer.getAllocation();
381
382 deMemcpy(vertexBufferAlloc.getHostPtr(), fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
383 vk::flushAlloc(vkd, device, vertexBufferAlloc);
384
385 // Storage buffer.
386 const auto storageBufferSize = static_cast<vk::VkDeviceSize>(kTotalPixels * sizeof(deInt32));
387 const auto storageBufferInfo = vk::makeBufferCreateInfo(storageBufferSize, (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT));
388 vk::BufferWithMemory storageBuffer (vkd, device, alloc, storageBufferInfo, vk::MemoryRequirement::HostVisible);
389 const auto& storageBufferAlloc = storageBuffer.getAllocation();
390
391 deMemset(storageBufferAlloc.getHostPtr(), 0, static_cast<size_t>(storageBufferSize));
392 vk::flushAlloc(vkd, device, storageBufferAlloc);
393
394 // Descriptor set layout.
395 vk::DescriptorSetLayoutBuilder layoutBuilder;
396 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
397 const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
398
399 // Pipeline layout.
400 const auto pipelineLayout = vk::makePipelineLayout(vkd, device, descriptorSetLayout.get());
401
402 // Descriptor pool.
403 vk::DescriptorPoolBuilder poolBuilder;
404 poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
405 const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
406
407 // Descriptor set.
408 const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
409
410 // Update descriptor set.
411 vk::DescriptorSetUpdateBuilder updateBuilder;
412 const auto descriptorBufferInfo = vk::makeDescriptorBufferInfo(storageBuffer.get(), 0u, storageBufferSize);
413 updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo);
414 updateBuilder.update(vkd, device);
415
416 // Render pass.
417 const auto renderPass = vk::makeRenderPass(vkd, device, kColorFormat, depthStencilFormat);
418
419 // Framebuffer.
420 std::vector<vk::VkImageView> imageViews(1u, colorImageView.get());
421 if (depthStencilImage)
422 imageViews.push_back(depthStencilImageView.get());
423
424 const auto framebuffer = vk::makeFramebuffer(vkd, device, renderPass.get(), static_cast<deUint32>(imageViews.size()), imageViews.data(), kFramebufferWidth, kFramebufferHeight);
425
426 // Shader modules.
427 const auto vertModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
428 const auto fragModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
429
430 // Vertex input state.
431 const auto vertexBinding = vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(sizeof(tcu::Vec2)), vk::VK_VERTEX_INPUT_RATE_VERTEX);
432 const auto vertexAttributes = vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u);
433
434 const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo =
435 {
436 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
437 nullptr, // const void* pNext;
438 0u, // VkPipelineVertexInputStateCreateFlags flags;
439 1u, // deUint32 vertexBindingDescriptionCount;
440 &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
441 1u, // deUint32 vertexAttributeDescriptionCount;
442 &vertexAttributes, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
443 };
444
445 // Input assembly state.
446 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo =
447 {
448 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
449 nullptr, // const void* pNext;
450 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
451 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
452 VK_FALSE, // VkBool32 primitiveRestartEnable;
453 };
454
455 // Viewport state.
456 const auto viewport = vk::makeViewport(kFramebufferWidth, kFramebufferHeight);
457 const auto scissor = vk::makeRect2D(kFramebufferWidth, kFramebufferHeight);
458
459 const vk::VkPipelineViewportStateCreateInfo viewportInfo =
460 {
461 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
462 nullptr, // const void* pNext;
463 0u, // VkPipelineViewportStateCreateFlags flags;
464 1u, // deUint32 viewportCount;
465 &viewport, // const VkViewport* pViewports;
466 1u, // deUint32 scissorCount;
467 &scissor, // const VkRect2D* pScissors;
468 };
469
470 // Rasterization state.
471 const vk::VkPipelineRasterizationStateCreateInfo rasterizationInfo =
472 {
473 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
474 nullptr, // const void* pNext;
475 0u, // VkPipelineRasterizationStateCreateFlags flags;
476 VK_FALSE, // VkBool32 depthClampEnable;
477 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
478 vk::VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
479 vk::VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
480 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
481 VK_FALSE, // VkBool32 depthBiasEnable;
482 0.0f, // float depthBiasConstantFactor;
483 0.0f, // float depthBiasClamp;
484 0.0f, // float depthBiasSlopeFactor;
485 1.0f, // float lineWidth;
486 };
487
488 // Multisample state.
489 const bool alphaToCoverageEnable = (m_params.caseType == CaseType::ALPHA_COVERAGE_BEFORE || m_params.caseType == CaseType::ALPHA_COVERAGE_AFTER);
490 const vk::VkPipelineMultisampleStateCreateInfo multisampleInfo =
491 {
492 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
493 nullptr, // const void* pNext;
494 0u, // VkPipelineMultisampleStateCreateFlags flags;
495 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
496 VK_FALSE, // VkBool32 sampleShadingEnable;
497 0.0f, // float minSampleShading;
498 nullptr, // const VkSampleMask* pSampleMask;
499 makeVkBool32(alphaToCoverageEnable), // VkBool32 alphaToCoverageEnable;
500 VK_FALSE, // VkBool32 alphaToOneEnable;
501 };
502
503 // Depth/stencil state.
504 const auto enableDepthBounds = makeVkBool32(m_params.caseType == CaseType::DEPTH_BOUNDS);
505 const auto enableDepthStencilTest = static_cast<bool>(depthStencilImage);
506
507 const auto depthCompareOp = ((m_params.caseType == CaseType::DEPTH_NEVER) ? vk::VK_COMPARE_OP_NEVER : vk::VK_COMPARE_OP_ALWAYS);
508 const auto stencilCompareOp = ((m_params.caseType == CaseType::STENCIL_NEVER) ? vk::VK_COMPARE_OP_NEVER : vk::VK_COMPARE_OP_ALWAYS);
509 const auto stencilOpState = vk::makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, stencilCompareOp, 0xFFu, 0xFFu, 0u);
510
511 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilInfo =
512 {
513 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
514 nullptr, // const void* pNext;
515 0u, // VkPipelineDepthStencilStateCreateFlags flags;
516 enableDepthStencilTest, // VkBool32 depthTestEnable;
517 enableDepthStencilTest, // VkBool32 depthWriteEnable;
518 depthCompareOp, // VkCompareOp depthCompareOp;
519 enableDepthBounds, // VkBool32 depthBoundsTestEnable;
520 enableDepthStencilTest, // VkBool32 stencilTestEnable;
521 stencilOpState, // VkStencilOpState front;
522 stencilOpState, // VkStencilOpState back;
523 (enableDepthBounds ? m_params.depthBoundsParams.get().minDepthBounds : 0.0f), // float minDepthBounds;
524 (enableDepthBounds ? m_params.depthBoundsParams.get().maxDepthBounds : 1.0f), // float maxDepthBounds;
525 };
526
527 // Color blend state.
528 const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
529 {
530 VK_FALSE, // VkBool32 blendEnable
531 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor
532 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor
533 vk::VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
534 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
535 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor
536 vk::VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
537 vk::VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask
538 | vk::VK_COLOR_COMPONENT_G_BIT
539 | vk::VK_COLOR_COMPONENT_B_BIT
540 | vk::VK_COLOR_COMPONENT_A_BIT
541 };
542
543 const vk::VkPipelineColorBlendStateCreateInfo colorBlendInfo =
544 {
545 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
546 nullptr, // const void* pNext;
547 0u, // VkPipelineColorBlendStateCreateFlags flags;
548 VK_FALSE, // VkBool32 logicOpEnable;
549 vk::VK_LOGIC_OP_NO_OP, // VkLogicOp logicOp;
550 1u, // deUint32 attachmentCount;
551 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
552 { .0f, .0f, .0f, .0f }, // float blendConstants[4];
553 };
554
555 // Graphics pipeline.
556 const auto graphicsPipeline = vk::makeGraphicsPipeline(
557 vkd, device, pipelineLayout.get(),
558 vertModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
559 renderPass.get(), 0u,
560 &vertexInputInfo,
561 &inputAssemblyInfo,
562 nullptr,
563 &viewportInfo,
564 &rasterizationInfo,
565 &multisampleInfo,
566 &depthStencilInfo,
567 &colorBlendInfo);
568
569 // Command buffer.
570 const auto cmdPool = vk::makeCommandPool(vkd, device, queueIndex);
571 const auto cmdBufferPtr = vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
572 const auto cmdBuffer = cmdBufferPtr.get();
573
574 // Draw full-screen quad.
575 std::vector<vk::VkClearValue> clearValues;
576 clearValues.push_back(vk::makeClearValueColor(m_params.clearColor));
577 clearValues.push_back(vk::makeClearValueDepthStencil(1.0f, 0u));
578
579 vk::beginCommandBuffer(vkd, cmdBuffer);
580 vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), vk::makeRect2D(kFramebufferWidth, kFramebufferHeight), static_cast<deUint32>(clearValues.size()), clearValues.data());
581 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.get());
582 vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
583 vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
584 vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(fullScreenQuad.size()), 1u, 0u, 0u);
585 vk::endRenderPass(vkd, cmdBuffer);
586
587 // Image and buffer barriers.
588
589 // Storage buffer frag-write to host-read barrier.
590 const auto storageBufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, storageBuffer.get(), 0u, VK_WHOLE_SIZE);
591
592 // Color image frag-write to transfer-read barrier.
593 const auto colorImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSubresourceRange);
594
595 // Color buffer transfer-write to host-read barrier.
596 const auto colorBufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, colorImageBuffer.get(), 0u, VK_WHOLE_SIZE);
597
598 vk::cmdPipelineBufferMemoryBarrier(vkd, cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, &storageBufferBarrier);
599 vk::cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, &colorImageBarrier);
600 const auto copyRegion = vk::makeBufferImageCopy(vk::makeExtent3D(kFramebufferWidth, kFramebufferHeight, 1u), vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
601 vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImageBuffer.get(), 1u, ©Region);
602 vk::cmdPipelineBufferMemoryBarrier(vkd, cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, &colorBufferBarrier);
603
604 vk::endCommandBuffer(vkd, cmdBuffer);
605 vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
606
607 // Check output.
608 {
609 // Check SSBO contents.
610 vk::invalidateAlloc(vkd, device, storageBufferAlloc);
611 const auto bufferElements = reinterpret_cast<const deInt32*>(storageBufferAlloc.getHostPtr());
612
613 for (deUint32 i = 0; i < kTotalPixels; ++i)
614 {
615 if (bufferElements[i] != 1)
616 {
617 std::ostringstream msg;
618 msg << "Unexpected value in storage buffer element " << i;
619 return tcu::TestStatus::fail("Fail: " + msg.str());
620 }
621 }
622 }
623
624 {
625 // Check color attachment.
626 std::vector<tcu::Vec4> expectedColors(1u, m_params.clearColor);
627 if (!expectClearColor(m_params.caseType))
628 expectedColors.push_back(m_params.drawColor);
629
630 const auto& colorImageBufferAlloc = colorImageBuffer.getAllocation();
631 vk::invalidateAlloc(vkd, device, colorImageBufferAlloc);
632
633 const auto iWidth = static_cast<int>(kFramebufferWidth);
634 const auto iHeight = static_cast<int>(kFramebufferHeight);
635
636 tcu::ConstPixelBufferAccess colorPixels (tcuFormat, iWidth, iHeight, 1, colorImageBufferAlloc.getHostPtr());
637 std::vector<deUint8> errorMaskBuffer (kTotalPixels * tcuFormat.getPixelSize(), 0u);
638 tcu::PixelBufferAccess errorMask (tcuFormat, iWidth, iHeight, 1, errorMaskBuffer.data());
639 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
640 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
641 bool allPixOk = true;
642
643 for (int i = 0; i < iWidth; ++i)
644 for (int j = 0; j < iHeight; ++j)
645 {
646 const auto pixel = colorPixels.getPixel(i, j);
647 const bool pixOk = std::any_of(begin(expectedColors), end(expectedColors), [&pixel](const tcu::Vec4& expected) -> bool { return (pixel == expected); });
648 errorMask.setPixel((pixOk ? green : red), i, j);
649 if (!pixOk)
650 allPixOk = false;
651 }
652
653 if (!allPixOk)
654 {
655 auto& testLog = m_context.getTestContext().getLog();
656 testLog << tcu::TestLog::Image("ColorBuffer", "Result color buffer", colorPixels);
657 testLog << tcu::TestLog::Image("ErrorMask", "Error mask with errors marked in red", errorMask);
658 return tcu::TestStatus::fail("Fail: color buffer with unexpected values; check logged images");
659 }
660 }
661
662 return tcu::TestStatus::pass("Pass");
663 }
664
665 } // anonymous
666
createFragSideEffectsTests(tcu::TestContext & testCtx)667 tcu::TestCaseGroup* createFragSideEffectsTests (tcu::TestContext& testCtx)
668 {
669 de::MovePtr<tcu::TestCaseGroup> fragSideEffectsGroup(new tcu::TestCaseGroup(testCtx, "frag_side_effects", "Test fragment shader side effects are not removed by optimizations"));
670
671 const tcu::Vec4 kDefaultClearColor (0.0f, 0.0f, 0.0f, 1.0f);
672 const tcu::Vec4 kDefaultDrawColor (0.0f, 0.0f, 1.0f, 1.0f);
673 const auto kDefaultDepthBoundsParams = tcu::nothing<DepthBoundsParameters>();
674
675 static const struct
676 {
677 bool colorAtEnd;
678 std::string name;
679 std::string desc;
680 } kColorOrders[] =
681 {
682 { false, "color_at_beginning", "Fragment shader output assignment at the beginning of the shader" },
683 { true, "color_at_end", "Fragment shader output assignment at the end of the shader" },
684 };
685
686 for (int i = 0; i < DE_LENGTH_OF_ARRAY(kColorOrders); ++i)
687 {
688 de::MovePtr<tcu::TestCaseGroup> colorOrderGroup(new tcu::TestCaseGroup(testCtx, kColorOrders[i].name.c_str(), kColorOrders[i].desc.c_str()));
689 const bool colorAtEnd = kColorOrders[i].colorAtEnd;
690
691 {
692 TestParams params(CaseType::KILL, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
693 colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "kill", "OpKill after SSBO write", params));
694 }
695 {
696 TestParams params(CaseType::DEMOTE, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
697 colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "demote", "OpDemoteToHelperInvocation after SSBO write", params));
698 }
699 {
700 TestParams params(CaseType::SAMPLE_MASK_BEFORE, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
701 colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "sample_mask_before", "Set sample mask to zero before SSBO write", params));
702 }
703 {
704 TestParams params(CaseType::SAMPLE_MASK_AFTER, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
705 colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "sample_mask_after", "Set sample mask to zero after SSBO write", params));
706 }
707 {
708 TestParams params(CaseType::STENCIL_NEVER, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
709 colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "stencil_never", "SSBO write with stencil test never passes", params));
710 }
711 {
712 TestParams params(CaseType::DEPTH_NEVER, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
713 colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "depth_never", "SSBO write with depth test never passes", params));
714 }
715 {
716 const tcu::Vec4 drawColor(kDefaultDrawColor.x(), kDefaultDrawColor.y(), kDefaultDrawColor.z(), 0.0f);
717 {
718 TestParams params(CaseType::ALPHA_COVERAGE_BEFORE, kDefaultClearColor, drawColor, colorAtEnd, kDefaultDepthBoundsParams);
719 colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "alpha_coverage_before", "Enable alpha coverage and draw with alpha zero before SSBO write", params));
720 }
721 {
722 TestParams params(CaseType::ALPHA_COVERAGE_AFTER, kDefaultClearColor, drawColor, colorAtEnd, kDefaultDepthBoundsParams);
723 colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "alpha_coverage_after", "Enable alpha coverage and draw with alpha zero after SSBO write", params));
724 }
725 }
726 {
727 DepthBoundsParameters depthBoundsParams = {0.25f, 0.5f, 0.75f}; // min, max, draw depth.
728 TestParams params(CaseType::DEPTH_BOUNDS, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, tcu::just(depthBoundsParams));
729 colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "depth_bounds", "SSBO write with depth bounds test failing", params));
730 }
731
732 fragSideEffectsGroup->addChild(colorOrderGroup.release());
733 }
734
735 return fragSideEffectsGroup.release();
736 }
737
738 } // rasterization
739 } // vkt
740