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