1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief VK_EXT_shader_stencil_export tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktPipelineStencilExportTests.hpp"
25 #include "vktPipelineMakeUtil.hpp"
26 #include "vktPipelineClearUtil.hpp"
27 #include "vktPipelineImageUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktPipelineReferenceRenderer.hpp"
30 #include "vktPipelineUniqueRandomIterator.hpp"
31 #include "vktTestCase.hpp"
32 #include "vktTestCaseUtil.hpp"
33
34 #include "vkImageUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkRef.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43
44 #include "tcuTestLog.hpp"
45 #include "tcuImageCompare.hpp"
46
47 #include "deMemory.h"
48 #include "deRandom.hpp"
49 #include "deStringUtil.hpp"
50 #include "deUniquePtr.hpp"
51
52 #include <algorithm>
53 #include <sstream>
54 #include <vector>
55
56 namespace vkt
57 {
58 namespace pipeline
59 {
60
61 using namespace vk;
62 using tcu::Vec4;
63 using tcu::Vec2;
64 using tcu::UVec2;
65 using tcu::UVec4;
66 using de::UniquePtr;
67 using de::MovePtr;
68 using de::SharedPtr;
69
70 namespace
71 {
72
73 struct TestParams
74 {
75 PipelineConstructionType pipelineConstructionType;
76 vk::VkFormat stencilFormat;
77 bool early_and_late;
78 };
79
80 static const std::string ExecutionModeStencil[] =
81 {
82 "StencilRefGreaterFrontAMD",
83 "StencilRefLessFrontAMD",
84 "StencilRefGreaterBackAMD",
85 "StencilRefLessBackAMD",
86 "StencilRefUnchangedFrontAMD",
87 "StencilRefUnchangedBackAMD",
88 };
89
90 enum ExecutionModeEarlyAndLate
91 {
92 MODE_STENCIL_REF_GREATER_FRONT_AMD = 0,
93 MODE_STENCIL_REF_LESS_FRONT_AMD,
94 MODE_STENCIL_REF_GREATER_BACK_AMD,
95 MODE_STENCIL_REF_LESS_BACK_AMD,
96 MODE_STENCIL_REF_UNCHANGED_FRONT_AMD,
97 MODE_STENCIL_REF_UNCHANGED_BACK_AMD,
98 MODE_COUNT_AMD
99 };
100
initPrograms(SourceCollections & programCollection,TestParams paramaeters)101 void initPrograms (SourceCollections& programCollection, TestParams paramaeters)
102 {
103 // Vertex shader.
104 {
105 std::ostringstream src;
106 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
107 << "vec2 positions[6] = vec2[](\n"
108 << " vec2(-1.0, -1.0),\n"
109 << " vec2(-1.0, +1.0),\n"
110 << " vec2(+1.0, -1.0),\n"
111 << " vec2(+1.0, +1.0),\n"
112 << " vec2(+1.0, -1.0),\n"
113 << " vec2(-1.0, +1.0)\n"
114 << "\n"
115 << ");\n"
116 << "\n"
117 << "void main(void)\n"
118 << "{\n"
119 << " gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
120 << "}\n";
121 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
122 }
123
124 // Fragment shader that writes to Stencil buffer.
125 if (paramaeters.early_and_late)
126 {
127 for (int stencilModeNdx = 0; stencilModeNdx < 6; stencilModeNdx++)
128 {
129 const std::string src =
130 "; SPIR-V\n"
131 "; Version: 1.0\n"
132 "; Bound: 36\n"
133 "; Schema: 0\n"
134 "OpCapability Shader\n"
135 "OpCapability StencilExportEXT\n"
136 "OpExtension \"SPV_EXT_shader_stencil_export\"\n"
137 "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
138 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
139 "OpMemoryModel Logical GLSL450\n"
140 "OpEntryPoint Fragment %4 \"main\" %12 %31\n"
141 "OpExecutionMode %4 StencilRefReplacingEXT\n"
142 "OpExecutionMode %4 OriginUpperLeft\n"
143 "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
144 "OpExecutionMode %4 " + ExecutionModeStencil[stencilModeNdx] + "\n"
145 "OpDecorate %12 BuiltIn FragCoord\n"
146 "OpDecorate %31 BuiltIn FragStencilRefEXT\n"
147 "%2 = OpTypeVoid\n"
148 "%3 = OpTypeFunction %2\n"
149 "%6 = OpTypeInt 32 1\n"
150 "%7 = OpTypePointer Function %6\n"
151 "%9 = OpTypeFloat 32\n"
152 "%10 = OpTypeVector %9 4\n"
153 "%11 = OpTypePointer Input %10\n"
154 "%12 = OpVariable %11 Input\n"
155 "%13 = OpTypeInt 32 0\n"
156 "%14 = OpConstant %13 0\n"
157 "%15 = OpTypePointer Input %9\n"
158 "%19 = OpConstant %6 4\n"
159 "%21 = OpConstant %6 2\n"
160 "%24 = OpConstant %13 1\n"
161 "%30 = OpTypePointer Output %6\n"
162 "%31 = OpVariable %30 Output\n"
163 "%4 = OpFunction %2 None %3\n"
164 "%5 = OpLabel\n"
165 "%8 = OpVariable %7 Function\n"
166 "%23 = OpVariable %7 Function\n"
167 "%16 = OpAccessChain %15 %12 %14\n"
168 "%17 = OpLoad %9 %16\n"
169 "%18 = OpConvertFToS %6 %17\n"
170 "%20 = OpShiftRightArithmetic %6 %18 %19\n"
171 "%22 = OpSMod %6 %20 %21\n"
172 "OpStore %8 %22\n"
173 "%25 = OpAccessChain %15 %12 %24\n"
174 "%26 = OpLoad %9 %25\n"
175 "%27 = OpConvertFToS %6 %26\n"
176 "%28 = OpShiftRightArithmetic %6 %27 %19\n"
177 "%29 = OpSMod %6 %28 %21\n"
178 "OpStore %23 %29\n"
179 "%32 = OpLoad %6 %8\n"
180 "%33 = OpLoad %6 %23\n"
181 "%34 = OpIAdd %6 %32 %33\n"
182 "%35 = OpSMod %6 %34 %21\n"
183 "OpStore %31 %35\n"
184 "OpReturn\n"
185 "OpFunctionEnd\n";
186
187 std::ostringstream shaderName;
188 shaderName << "frag-stencil" << stencilModeNdx;
189 programCollection.spirvAsmSources.add(shaderName.str()) << src << SpirVAsmBuildOptions(programCollection.usedVulkanVersion, SPIRV_VERSION_1_1);
190 }
191 }
192 else
193 {
194 std::ostringstream src;
195 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
196 << "#extension GL_ARB_shader_stencil_export: enable\n"
197 << "\n"
198 << "void main(void)\n"
199 << "{\n"
200 << " int refX = (int(gl_FragCoord.x) >> 4) % 2;\n"
201 << " int refY = (int(gl_FragCoord.y) >> 4) % 2;\n"
202 << " gl_FragStencilRefARB = (refX + refY) % 2;\n"
203 << "}\n";
204 programCollection.glslSources.add("frag-stencil0") << glu::FragmentSource(src.str());
205 }
206
207 // Fragment shader that writes to Color buffer.
208 {
209 std::ostringstream src;
210 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
211 << "layout(location = 0) out highp vec4 fragColor;\n"
212 << "\n"
213 << "void main(void)\n"
214 << "{\n"
215 << " fragColor = vec4(0, 0, 1, 1);\n"
216 << "}\n";
217 programCollection.glslSources.add("frag-color") << glu::FragmentSource(src.str());
218 }
219 }
220
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)221 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
222 {
223 VkFormatProperties formatProps;
224
225 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
226
227 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
228 }
229
makeImageCreateInfo(const VkFormat format,const UVec2 & size,VkImageUsageFlags usage)230 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, VkImageUsageFlags usage)
231 {
232 const VkImageCreateInfo imageParams =
233 {
234 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
235 DE_NULL, // const void* pNext;
236 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
237 VK_IMAGE_TYPE_2D, // VkImageType imageType;
238 format, // VkFormat format;
239 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
240 1u, // deUint32 mipLevels;
241 1u, // deUint32 arrayLayers;
242 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
243 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
244 usage, // VkImageUsageFlags usage;
245 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
246 0u, // deUint32 queueFamilyIndexCount;
247 DE_NULL, // const deUint32* pQueueFamilyIndices;
248 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
249 };
250 return imageParams;
251 }
252
makeTestRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat stencilFormat)253 Move<VkRenderPass> makeTestRenderPass (const DeviceInterface& vk,
254 const VkDevice device,
255 const VkFormat colorFormat,
256 const VkFormat stencilFormat)
257 {
258 VkAttachmentDescription attachmentDescriptions[] =
259 {
260 {
261 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
262 colorFormat, // VkFormat format;
263 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
264 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
265 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
266 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
267 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
268 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
269 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
270 },
271 {
272 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
273 stencilFormat, // VkFormat format;
274 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
275 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp;
276 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp;
277 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
278 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
279 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
280 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
281 },
282 };
283
284 VkAttachmentReference colorAttachmentReference =
285 {
286 0, // deUint32 attachment;
287 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
288 };
289
290 VkAttachmentReference stencilAttachmentReference =
291 {
292 1, // deUint32 attachment;
293 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
294 };
295
296 VkSubpassDescription subpasses[] =
297 {
298 {
299 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
300 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
301 0u, // deUint32 inputAttachmentCount;
302 DE_NULL, // const VkAttachmentReference* pInputAttachments;
303 0u, // deUint32 colorAttachmentCount;
304 DE_NULL, // const VkAttachmentReference* pColorAttachments;
305 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
306 &stencilAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
307 0u, // deUint32 preserveAttachmentCount;
308 DE_NULL // const deUint32* pPreserveAttachments;
309 },
310 {
311 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
312 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
313 0u, // deUint32 inputAttachmentCount;
314 DE_NULL, // const VkAttachmentReference* pInputAttachments;
315 1u, // deUint32 colorAttachmentCount;
316 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
317 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
318 &stencilAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
319 0u, // deUint32 preserveAttachmentCount;
320 DE_NULL // const deUint32* pPreserveAttachments;
321 },
322 };
323
324 VkSubpassDependency dependency =
325 {
326 0u, // uint32_t srcSubpass;
327 1u, // uint32_t dstSubpass;
328 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags srcStageMask;
329 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags dstStageMask;
330 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
331 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
332 0u, // VkDependencyFlags dependencyFlags;
333 };
334
335 const VkRenderPassCreateInfo renderPassInfo =
336 {
337 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
338 DE_NULL, // const void* pNext;
339 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
340 2u, // deUint32 attachmentCount;
341 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
342 2u, // deUint32 subpassCount;
343 &subpasses[0], // const VkSubpassDescription* pSubpasses;
344 1u, // deUint32 dependencyCount;
345 &dependency, // const VkSubpassDependency* pDependencies;
346 };
347
348 return createRenderPass(vk, device, &renderPassInfo);
349 }
350
preparePipelineWrapper(GraphicsPipelineWrapper & gpw,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const deUint32 subpass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const UVec2 renderSize,const bool useColor,const bool earlyLate=false)351 void preparePipelineWrapper(GraphicsPipelineWrapper& gpw,
352 const VkPipelineLayout pipelineLayout,
353 const VkRenderPass renderPass,
354 const deUint32 subpass,
355 const VkShaderModule vertexModule,
356 const VkShaderModule fragmentModule,
357 const UVec2 renderSize,
358 const bool useColor,
359 const bool earlyLate = false)
360 {
361 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
362 {
363 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
364 DE_NULL, // const void* pNext;
365 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
366 0u, // uint32_t vertexBindingDescriptionCount;
367 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
368 0u, // uint32_t vertexAttributeDescriptionCount;
369 DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
370 };
371
372 const std::vector<VkViewport> viewport { makeViewport(renderSize) };
373 const std::vector<VkRect2D> scissor { makeRect2D(renderSize) };
374
375 const VkStencilOpState stencilOpState = makeStencilOpState(
376 useColor ? VK_STENCIL_OP_KEEP : VK_STENCIL_OP_REPLACE, // stencil fail
377 useColor ? VK_STENCIL_OP_KEEP : (earlyLate ? VK_STENCIL_OP_KEEP : VK_STENCIL_OP_REPLACE), // depth & stencil pass
378 useColor ? VK_STENCIL_OP_KEEP : (earlyLate ? VK_STENCIL_OP_KEEP : VK_STENCIL_OP_REPLACE), // depth only fail
379 useColor ? VK_COMPARE_OP_EQUAL : (earlyLate ? VK_COMPARE_OP_EQUAL : VK_COMPARE_OP_NEVER), // compare op VK_COMPARE_OP_ALWAYS
380 useColor ? 0xffu : 0xffu, // compare mask
381 useColor ? 0u : 0xffu, // write mask
382 useColor ? 0u : 1u); // reference
383
384 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo
385 {
386 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
387 DE_NULL, // const void* pNext;
388 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
389 VK_FALSE, // VkBool32 depthTestEnable;
390 VK_FALSE, // VkBool32 depthWriteEnable;
391 VK_COMPARE_OP_NEVER, // VkCompareOp depthCompareOp;
392 VK_FALSE, // VkBool32 depthBoundsTestEnable;
393 VK_TRUE, // VkBool32 stencilTestEnable;
394 stencilOpState, // VkStencilOpState front;
395 stencilOpState, // VkStencilOpState back;
396 0.0f, // float minDepthBounds;
397 1.0f, // float maxDepthBounds;
398 };
399
400 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
401 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState
402 {
403 VK_FALSE, // VkBool32 blendEnable;
404 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor;
405 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
406 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
407 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor;
408 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
409 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
410 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
411 };
412
413 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo
414 {
415 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
416 DE_NULL, // const void* pNext;
417 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
418 VK_FALSE, // VkBool32 logicOpEnable;
419 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
420 1u, // deUint32 attachmentCount;
421 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
422 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
423 };
424
425 gpw.setDefaultRasterizationState()
426 .setDefaultMultisampleState()
427 .setupVertexInputState(&vertexInputStateInfo)
428 .setupPreRasterizationShaderState(viewport,
429 scissor,
430 pipelineLayout,
431 renderPass,
432 subpass,
433 vertexModule)
434 .setupFragmentShaderState(pipelineLayout, renderPass, subpass, fragmentModule, &pipelineDepthStencilStateInfo)
435 .setupFragmentOutputState(renderPass, subpass, &pipelineColorBlendStateInfo)
436 .setMonolithicPipelineLayout(pipelineLayout)
437 .buildPipeline();
438 }
439
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const deUint32 patternSize,const Vec4 & clearColor,const Vec4 & color)440 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format,
441 const UVec2& renderSize,
442 const deUint32 patternSize,
443 const Vec4& clearColor,
444 const Vec4& color)
445 {
446 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
447 tcu::clear(image.getAccess(), clearColor);
448
449 deUint32 rows = renderSize.y() / patternSize;
450 deUint32 cols = renderSize.x() / patternSize;
451
452 for (deUint32 i = 0; i < rows; i++)
453 {
454 for (deUint32 j = 0; j < cols; j++)
455 {
456 if ((i + j) % 2 == 0)
457 tcu::clear(tcu::getSubregion(image.getAccess(), i * patternSize, j * patternSize, patternSize, patternSize), color);
458 }
459 }
460
461 return image;
462 }
463
testStencilExportReplace(Context & context,TestParams params)464 tcu::TestStatus testStencilExportReplace (Context& context, TestParams params)
465 {
466 auto& log = context.getTestContext().getLog();
467 log << tcu::TestLog::Message << "Drawing to stencil using shader then using it for another draw." << tcu::TestLog::EndMessage;
468
469 const DeviceInterface& vk = context.getDeviceInterface();
470 const VkDevice device = context.getDevice();
471 Allocator& allocator = context.getDefaultAllocator();
472
473 const UVec2 renderSize (128, 128);
474 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
475 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
476 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
477
478 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
479 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
480
481 // Zero color buffer.
482 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
483 flushAlloc(vk, device, *colorBufferAlloc);
484
485 // Draw two subpasses: first write the stencil data, then use that data when writing color.
486 //
487 // The first pass will produce a checkerboard stencil by having the shader filling gl_FragStencilRefARB with 0 or 1,
488 // and using OP_REPLACE to write those values to the stencil buffer.
489 //
490 // The second pass will use the stencil with a compare operation EQUAL with reference value 0.
491 {
492 const VkImageSubresourceRange stencilSubresourceRange = makeImageSubresourceRange (VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u);
493 Move<VkImage> stencilImage = makeImage (vk, device, makeImageCreateInfo(params.stencilFormat, renderSize, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
494 MovePtr<Allocation> stencilImageAlloc = bindImage (vk, device, allocator, *stencilImage, MemoryRequirement::Any);
495 Move<VkImageView> stencilAttachment = makeImageView (vk, device, *stencilImage, VK_IMAGE_VIEW_TYPE_2D, params.stencilFormat, stencilSubresourceRange);
496
497 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange (VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
498 Move<VkImage> colorImage = makeImage (vk, device, makeImageCreateInfo(colorFormat, renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
499 MovePtr<Allocation> colorImageAlloc = bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any);
500 Move<VkImageView> colorAttachment = makeImageView (vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
501
502 Move<VkShaderModule> vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0);
503 Move<VkShaderModule> fragmentColorModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag-color"), 0);
504
505 Move<VkRenderPass> renderPass = makeTestRenderPass (vk, device, colorFormat, params.stencilFormat);
506 Move<VkPipelineLayout> pipelineLayout = makePipelineLayout (vk, device);
507 GraphicsPipelineWrapper colorPipeline (vk, device, params.pipelineConstructionType);
508
509 preparePipelineWrapper(colorPipeline, *pipelineLayout, *renderPass, 1, *vertexModule, *fragmentColorModule, renderSize, true);
510
511 const VkImageView attachments[] =
512 {
513 *colorAttachment,
514 *stencilAttachment,
515 };
516 Move<VkFramebuffer> framebuffer = makeFramebuffer (vk, device, *renderPass, 2u, &attachments[0], renderSize.x(), renderSize.y());
517
518 Move<VkCommandPool> cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex());
519 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
520 const VkQueue queue = context.getUniversalQueue ();
521 tcu::TextureLevel referenceImage = generateReferenceImage (mapVkFormat(colorFormat), renderSize, 1 << 4, clearColor, Vec4(0, 0, 1, 1));
522
523 const int stencilModeCount = (params.early_and_late ? MODE_COUNT_AMD : 1);
524
525 for (int stencilModeNdx = 0; stencilModeNdx < stencilModeCount; stencilModeNdx++)
526 {
527 std::ostringstream shaderName;
528 shaderName << "frag-stencil" << stencilModeNdx;
529
530 Move<VkShaderModule> fragmentStencilModule = createShaderModule(vk, device, context.getBinaryCollection().get(shaderName.str()), 0);
531 GraphicsPipelineWrapper stencilPipeline (vk, device, params.pipelineConstructionType);
532
533 preparePipelineWrapper(stencilPipeline, *pipelineLayout, *renderPass, 0, *vertexModule, *fragmentStencilModule, renderSize, false);
534 beginCommandBuffer(vk, *cmdBuffer);
535 if (params.early_and_late)
536 {
537 switch (stencilModeNdx)
538 {
539 case MODE_STENCIL_REF_GREATER_FRONT_AMD:
540 case MODE_STENCIL_REF_GREATER_BACK_AMD:
541 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), clearColor, 0.0, 1u);//0
542 break;
543 case MODE_STENCIL_REF_LESS_FRONT_AMD:
544 case MODE_STENCIL_REF_LESS_BACK_AMD:
545 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), clearColor, 0.0, 1u);//10
546 break;
547 default:
548 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), clearColor, 0.0, 1u);
549 break;
550 }
551 }
552 else
553 {
554 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), clearColor, 0.0, 0u);
555 }
556
557 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, stencilPipeline.getPipeline());
558 vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
559
560 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
561
562 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, colorPipeline.getPipeline());
563 vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
564
565 endRenderPass(vk, *cmdBuffer);
566
567 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, tcu::IVec2(renderSize.x(), renderSize.y()));
568
569 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
570 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
571
572 // Compare the resulting color buffer.
573 {
574 invalidateAlloc(vk, device, *colorBufferAlloc);
575 const tcu::ConstPixelBufferAccess resultImage(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferAlloc->getHostPtr());
576
577 if (!tcu::floatThresholdCompare(log, "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
578 TCU_FAIL("Rendered image is not correct" + (params.early_and_late ? (" for OpExecutionMode: " + ExecutionModeStencil[stencilModeNdx]) : ""));
579 }
580 }
581 }
582 return tcu::TestStatus::pass("OK");
583 }
584
checkSupport(Context & context,TestParams params)585 void checkSupport (Context& context, TestParams params)
586 {
587 context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
588
589 if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), params.stencilFormat))
590 TCU_THROW(NotSupportedError, "Image format not supported");
591
592 checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), params.pipelineConstructionType);
593
594 #ifndef CTS_USES_VULKANSC
595 if (params.early_and_late)
596 {
597 context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
598 if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
599 TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
600 }
601 #endif
602 }
603
604 } // anonymous
605
createStencilExportTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)606 tcu::TestCaseGroup* createStencilExportTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
607 {
608 struct
609 {
610 const vk::VkFormat format;
611 const std::string name;
612 } kFormats[] =
613 {
614 { vk::VK_FORMAT_S8_UINT, "s8_uint" },
615 { vk::VK_FORMAT_D24_UNORM_S8_UINT, "d24_unorm_s8_uint" },
616 { vk::VK_FORMAT_D32_SFLOAT_S8_UINT, "d32_sfloat_s8_uint" },
617 };
618
619 TestParams params
620 {
621 pipelineConstructionType,
622 vk::VK_FORMAT_S8_UINT,
623 false
624 };
625
626 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_stencil_export", ""));
627 for (int fmtIdx = 0; fmtIdx < DE_LENGTH_OF_ARRAY(kFormats); ++fmtIdx)
628 {
629 params.stencilFormat = kFormats[fmtIdx].format;
630 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, kFormats[fmtIdx].name.c_str(), ""));
631 addFunctionCaseWithPrograms(formatGroup.get(), "op_replace", "", checkSupport, initPrograms, testStencilExportReplace, params);
632 #ifndef CTS_USES_VULKANSC
633 params.early_and_late = true;
634 addFunctionCaseWithPrograms(formatGroup.get(), "op_replace_early_and_late", "", checkSupport, initPrograms, testStencilExportReplace, params);
635 params.early_and_late = false;
636 #endif
637 group->addChild(formatGroup.release());
638 }
639 return group.release();
640 }
641
642 } // pipeline
643 } // vkt
644