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