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
26 #include "vktPipelineMakeUtil.hpp"
27 #include "vktPipelineClearUtil.hpp"
28 #include "vktPipelineImageUtil.hpp"
29 #include "vktPipelineVertexUtil.hpp"
30 #include "vktPipelineReferenceRenderer.hpp"
31 #include "vktPipelineUniqueRandomIterator.hpp"
32 #include "vktTestCase.hpp"
33 #include "vktTestCaseUtil.hpp"
34
35 #include "vkImageUtil.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkRef.hpp"
40 #include "vkRefUtil.hpp"
41 #include "vkTypeUtil.hpp"
42 #include "vkCmdUtil.hpp"
43 #include "vkObjUtil.hpp"
44
45 #include "tcuTestLog.hpp"
46 #include "tcuImageCompare.hpp"
47
48 #include "deMemory.h"
49 #include "deRandom.hpp"
50 #include "deStringUtil.hpp"
51 #include "deUniquePtr.hpp"
52
53 #include <algorithm>
54 #include <sstream>
55 #include <vector>
56
57 namespace vkt
58 {
59 namespace pipeline
60 {
61
62 using namespace vk;
63 using tcu::Vec4;
64 using tcu::Vec2;
65 using tcu::UVec2;
66 using tcu::UVec4;
67 using de::UniquePtr;
68 using de::MovePtr;
69 using de::SharedPtr;
70
71 namespace
72 {
73
initPrograms(SourceCollections & programCollection,vk::VkFormat)74 void initPrograms (SourceCollections& programCollection, vk::VkFormat)
75 {
76 // Vertex shader.
77 {
78 std::ostringstream src;
79 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
80 << "vec2 positions[6] = vec2[](\n"
81 << " vec2(-1.0, -1.0),\n"
82 << " vec2(-1.0, +1.0),\n"
83 << " vec2(+1.0, -1.0),\n"
84 << " vec2(+1.0, +1.0),\n"
85 << " vec2(+1.0, -1.0),\n"
86 << " vec2(-1.0, +1.0)\n"
87 << "\n"
88 << ");\n"
89 << "\n"
90 << "void main(void)\n"
91 << "{\n"
92 << " gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
93 << "}\n";
94 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
95 }
96
97 // Fragment shader that writes to Stencil buffer.
98 {
99 std::ostringstream src;
100 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
101 << "#extension GL_ARB_shader_stencil_export: enable\n"
102 << "\n"
103 << "void main(void)\n"
104 << "{\n"
105 << " int refX = (int(gl_FragCoord.x) >> 4) % 2;\n"
106 << " int refY = (int(gl_FragCoord.y) >> 4) % 2;\n"
107 << " gl_FragStencilRefARB = (refX + refY) % 2;\n"
108 << "}\n";
109 programCollection.glslSources.add("frag-stencil") << glu::FragmentSource(src.str());
110 }
111
112 // Fragment shader that writes to Color buffer.
113 {
114 std::ostringstream src;
115 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
116 << "layout(location = 0) out highp vec4 fragColor;\n"
117 << "\n"
118 << "void main(void)\n"
119 << "{\n"
120 << " fragColor = vec4(0, 0, 1, 1);\n"
121 << "}\n";
122 programCollection.glslSources.add("frag-color") << glu::FragmentSource(src.str());
123 }
124 }
125
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)126 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
127 {
128 VkFormatProperties formatProps;
129
130 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
131
132 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
133 }
134
makeImageCreateInfo(const VkFormat format,const UVec2 & size,VkImageUsageFlags usage)135 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, VkImageUsageFlags usage)
136 {
137 const VkImageCreateInfo imageParams =
138 {
139 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
140 DE_NULL, // const void* pNext;
141 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
142 VK_IMAGE_TYPE_2D, // VkImageType imageType;
143 format, // VkFormat format;
144 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
145 1u, // deUint32 mipLevels;
146 1u, // deUint32 arrayLayers;
147 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
148 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
149 usage, // VkImageUsageFlags usage;
150 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
151 0u, // deUint32 queueFamilyIndexCount;
152 DE_NULL, // const deUint32* pQueueFamilyIndices;
153 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
154 };
155 return imageParams;
156 }
157
makeTestRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat stencilFormat)158 Move<VkRenderPass> makeTestRenderPass (const DeviceInterface& vk,
159 const VkDevice device,
160 const VkFormat colorFormat,
161 const VkFormat stencilFormat)
162 {
163 VkAttachmentDescription attachmentDescriptions[] =
164 {
165 {
166 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
167 colorFormat, // VkFormat format;
168 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
169 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
170 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
171 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
172 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
173 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
174 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
175 },
176 {
177 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
178 stencilFormat, // VkFormat format;
179 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
180 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp;
181 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp;
182 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
183 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
184 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
185 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
186 },
187 };
188
189 VkAttachmentReference colorAttachmentReference =
190 {
191 0, // deUint32 attachment;
192 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
193 };
194
195 VkAttachmentReference stencilAttachmentReference =
196 {
197 1, // deUint32 attachment;
198 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
199 };
200
201 VkSubpassDescription subpasses[] =
202 {
203 {
204 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
205 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
206 0u, // deUint32 inputAttachmentCount;
207 DE_NULL, // const VkAttachmentReference* pInputAttachments;
208 0u, // deUint32 colorAttachmentCount;
209 DE_NULL, // const VkAttachmentReference* pColorAttachments;
210 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
211 &stencilAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
212 0u, // deUint32 preserveAttachmentCount;
213 DE_NULL // const deUint32* pPreserveAttachments;
214 },
215 {
216 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
217 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
218 0u, // deUint32 inputAttachmentCount;
219 DE_NULL, // const VkAttachmentReference* pInputAttachments;
220 1u, // deUint32 colorAttachmentCount;
221 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
222 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
223 &stencilAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
224 0u, // deUint32 preserveAttachmentCount;
225 DE_NULL // const deUint32* pPreserveAttachments;
226 },
227 };
228
229 VkSubpassDependency dependency =
230 {
231 0u, // uint32_t srcSubpass;
232 1u, // uint32_t dstSubpass;
233 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags srcStageMask;
234 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags dstStageMask;
235 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
236 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
237 0u, // VkDependencyFlags dependencyFlags;
238 };
239
240 const VkRenderPassCreateInfo renderPassInfo =
241 {
242 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
243 DE_NULL, // const void* pNext;
244 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
245 2u, // deUint32 attachmentCount;
246 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
247 2u, // deUint32 subpassCount;
248 &subpasses[0], // const VkSubpassDescription* pSubpasses;
249 1u, // deUint32 dependencyCount;
250 &dependency, // const VkSubpassDependency* pDependencies;
251 };
252
253 return createRenderPass(vk, device, &renderPassInfo);
254 }
255
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const deUint32 subpass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const UVec2 renderSize,const bool useColor)256 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
257 const VkDevice device,
258 const VkPipelineLayout pipelineLayout,
259 const VkRenderPass renderPass,
260 const deUint32 subpass,
261 const VkShaderModule vertexModule,
262 const VkShaderModule fragmentModule,
263 const UVec2 renderSize,
264 const bool useColor)
265 {
266 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
267 {
268 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
269 DE_NULL, // const void* pNext;
270 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
271 0u, // uint32_t vertexBindingDescriptionCount;
272 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
273 0u, // uint32_t vertexAttributeDescriptionCount;
274 DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
275 };
276
277 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
278 {
279 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
280 DE_NULL, // const void* pNext;
281 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
282 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
283 VK_FALSE, // VkBool32 primitiveRestartEnable;
284 };
285
286 const VkViewport viewport = makeViewport(renderSize);
287 const VkRect2D scissor = makeRect2D(renderSize);
288 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
289 {
290 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
291 DE_NULL, // const void* pNext;
292 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
293 1u, // uint32_t viewportCount;
294 &viewport, // const VkViewport* pViewports;
295 1u, // uint32_t scissorCount;
296 &scissor, // const VkRect2D* pScissors;
297 };
298
299 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
300 {
301 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
302 DE_NULL, // const void* pNext;
303 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
304 VK_FALSE, // VkBool32 depthClampEnable;
305 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
306 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
307 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
308 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
309 VK_FALSE, // VkBool32 depthBiasEnable;
310 0.0f, // float depthBiasConstantFactor;
311 0.0f, // float depthBiasClamp;
312 0.0f, // float depthBiasSlopeFactor;
313 1.0f, // float lineWidth;
314 };
315
316 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
317 {
318 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
319 DE_NULL, // const void* pNext;
320 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
321 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
322 VK_FALSE, // VkBool32 sampleShadingEnable;
323 0.0f, // float minSampleShading;
324 DE_NULL, // const VkSampleMask* pSampleMask;
325 VK_FALSE, // VkBool32 alphaToCoverageEnable;
326 VK_FALSE // VkBool32 alphaToOneEnable;
327 };
328
329 const VkStencilOpState stencilOpState = makeStencilOpState(
330 useColor ? VK_STENCIL_OP_KEEP : VK_STENCIL_OP_REPLACE, // stencil fail
331 useColor ? VK_STENCIL_OP_KEEP : VK_STENCIL_OP_REPLACE, // depth & stencil pass
332 useColor ? VK_STENCIL_OP_KEEP : VK_STENCIL_OP_REPLACE, // depth only fail
333 useColor ? VK_COMPARE_OP_EQUAL : VK_COMPARE_OP_NEVER, // compare op
334 useColor ? 0xffu : 0u, // compare mask
335 useColor ? 0u : 0xffu, // write mask
336 0u); // reference
337
338 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
339 {
340 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
341 DE_NULL, // const void* pNext;
342 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
343 VK_FALSE, // VkBool32 depthTestEnable;
344 VK_FALSE, // VkBool32 depthWriteEnable;
345 VK_COMPARE_OP_NEVER, // VkCompareOp depthCompareOp;
346 VK_FALSE, // VkBool32 depthBoundsTestEnable;
347 VK_TRUE, // VkBool32 stencilTestEnable;
348 stencilOpState, // VkStencilOpState front;
349 stencilOpState, // VkStencilOpState back;
350 0.0f, // float minDepthBounds;
351 1.0f, // float maxDepthBounds;
352 };
353
354 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
355 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
356 {
357 VK_FALSE, // VkBool32 blendEnable;
358 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor;
359 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
360 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
361 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor;
362 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
363 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
364 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
365 };
366
367 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
368 {
369 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
370 DE_NULL, // const void* pNext;
371 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
372 VK_FALSE, // VkBool32 logicOpEnable;
373 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
374 1u, // deUint32 attachmentCount;
375 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
376 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
377 };
378
379 const VkPipelineShaderStageCreateInfo pShaderStages[] =
380 {
381 {
382 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
383 DE_NULL, // const void* pNext;
384 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
385 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
386 vertexModule, // VkShaderModule module;
387 "main", // const char* pName;
388 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
389 },
390 {
391 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
392 DE_NULL, // const void* pNext;
393 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
394 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
395 fragmentModule, // VkShaderModule module;
396 "main", // const char* pName;
397 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
398 },
399 };
400
401 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
402 {
403 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
404 DE_NULL, // const void* pNext;
405 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
406 2, // deUint32 stageCount;
407 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
408 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
409 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
410 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
411 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
412 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
413 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
414 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
415 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
416 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
417 pipelineLayout, // VkPipelineLayout layout;
418 renderPass, // VkRenderPass renderPass;
419 subpass, // deUint32 subpass;
420 DE_NULL, // VkPipeline basePipelineHandle;
421 0, // deInt32 basePipelineIndex;
422 };
423
424 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
425 }
426
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const deUint32 patternSize,const Vec4 & clearColor,const Vec4 & color)427 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat format,
428 const UVec2& renderSize,
429 const deUint32 patternSize,
430 const Vec4& clearColor,
431 const Vec4& color)
432 {
433 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
434 tcu::clear(image.getAccess(), clearColor);
435
436 deUint32 rows = renderSize.y() / patternSize;
437 deUint32 cols = renderSize.x() / patternSize;
438
439 for (deUint32 i = 0; i < rows; i++)
440 {
441 for (deUint32 j = 0; j < cols; j++)
442 {
443 if ((i + j) % 2 == 0)
444 tcu::clear(tcu::getSubregion(image.getAccess(), i * patternSize, j * patternSize, patternSize, patternSize), color);
445 }
446 }
447
448 return image;
449 }
450
testStencilExportReplace(Context & context,vk::VkFormat stencilFormat)451 tcu::TestStatus testStencilExportReplace (Context& context, vk::VkFormat stencilFormat)
452 {
453 auto& log = context.getTestContext().getLog();
454 log << tcu::TestLog::Message << "Drawing to stencil using shader then using it for another draw." << tcu::TestLog::EndMessage;
455
456 const DeviceInterface& vk = context.getDeviceInterface();
457 const VkDevice device = context.getDevice();
458 Allocator& allocator = context.getDefaultAllocator();
459
460 const UVec2 renderSize (128, 128);
461 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
462 const Vec4 clearColor (0.5f, 0.5f, 0.5f, 1.0f);
463 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
464
465 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
466 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
467
468 // Zero color buffer.
469 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
470 flushAlloc(vk, device, *colorBufferAlloc);
471
472 // Draw two subpasses: first write the stencil data, then use that data when writing color.
473 //
474 // The first pass will produce a checkerboard stencil by having the shader filling gl_FragStencilRefARB with 0 or 1,
475 // and using OP_REPLACE to write those values to the stencil buffer.
476 //
477 // The second pass will use the stencil with a compare operation EQUAL with reference value 0.
478 {
479 const VkImageSubresourceRange stencilSubresourceRange = makeImageSubresourceRange (VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u);
480 Move<VkImage> stencilImage = makeImage (vk, device, makeImageCreateInfo(stencilFormat, renderSize, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
481 MovePtr<Allocation> stencilImageAlloc = bindImage (vk, device, allocator, *stencilImage, MemoryRequirement::Any);
482 Move<VkImageView> stencilAttachment = makeImageView (vk, device, *stencilImage, VK_IMAGE_VIEW_TYPE_2D, stencilFormat, stencilSubresourceRange);
483
484 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange (VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
485 Move<VkImage> colorImage = makeImage (vk, device, makeImageCreateInfo(colorFormat, renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
486 MovePtr<Allocation> colorImageAlloc = bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any);
487 Move<VkImageView> colorAttachment = makeImageView (vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
488
489 Move<VkShaderModule> vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0);
490 Move<VkShaderModule> fragmentStencilModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag-stencil"), 0);
491 Move<VkShaderModule> fragmentColorModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag-color"), 0);
492
493 Move<VkRenderPass> renderPass = makeTestRenderPass (vk, device, colorFormat, stencilFormat);
494 Move<VkPipelineLayout> pipelineLayout = makePipelineLayout (vk, device);
495 Move<VkPipeline> stencilPipeline = makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, 0, *vertexModule, *fragmentStencilModule, renderSize, false);
496 Move<VkPipeline> colorPipeline = makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, 1, *vertexModule, *fragmentColorModule, renderSize, true);
497
498 const VkImageView attachments[] =
499 {
500 *colorAttachment,
501 *stencilAttachment,
502 };
503 Move<VkFramebuffer> framebuffer = makeFramebuffer (vk, device, *renderPass, 2u, &attachments[0], renderSize.x(), renderSize.y());
504
505 Move<VkCommandPool> cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex());
506 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
507
508 const VkQueue queue = context.getUniversalQueue();
509
510 beginCommandBuffer(vk, *cmdBuffer);
511 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), clearColor, 0.0, 0u);
512
513 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *stencilPipeline);
514 vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
515
516 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
517
518 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *colorPipeline);
519 vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
520
521 endRenderPass(vk, *cmdBuffer);
522
523 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, tcu::IVec2(renderSize.x(), renderSize.y()));
524
525 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
526 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
527 }
528
529 // Compare the resulting color buffer.
530 {
531 invalidateAlloc(vk, device, *colorBufferAlloc);
532 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferAlloc->getHostPtr());
533
534 tcu::TextureLevel referenceImage = generateReferenceImage(mapVkFormat(colorFormat), renderSize, 1 << 4, clearColor, Vec4(0, 0, 1, 1));
535
536 if (!tcu::floatThresholdCompare(log, "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
537 TCU_FAIL("Rendered image is not correct");
538 }
539
540 return tcu::TestStatus::pass("OK");
541 }
542
checkSupport(Context & context,vk::VkFormat stencilFormat)543 void checkSupport (Context& context, vk::VkFormat stencilFormat)
544 {
545 context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
546
547 if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), stencilFormat))
548 TCU_THROW(NotSupportedError, "Image format not supported");
549 }
550
551 } // anonymous
552
createStencilExportTests(tcu::TestContext & testCtx)553 tcu::TestCaseGroup* createStencilExportTests (tcu::TestContext& testCtx)
554 {
555 struct
556 {
557 const vk::VkFormat format;
558 const std::string name;
559 } kFormats[] =
560 {
561 { vk::VK_FORMAT_S8_UINT, "s8_uint" },
562 { vk::VK_FORMAT_D24_UNORM_S8_UINT, "d24_unorm_s8_uint" },
563 { vk::VK_FORMAT_D32_SFLOAT_S8_UINT, "d32_sfloat_s8_uint" },
564 };
565
566 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_stencil_export", ""));
567 for (int fmtIdx = 0; fmtIdx < DE_LENGTH_OF_ARRAY(kFormats); ++fmtIdx)
568 {
569 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, kFormats[fmtIdx].name.c_str(), ""));
570 addFunctionCaseWithPrograms<vk::VkFormat>(formatGroup.get(), "op_replace", "", checkSupport, initPrograms, testStencilExportReplace, kFormats[fmtIdx].format);
571 group->addChild(formatGroup.release());
572 }
573 return group.release();
574 }
575
576 } // pipeline
577 } // vkt
578