1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 The Khronos Group Inc.
6 * Copyright (c) 2018 Google Inc.
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 Early pipeline destroying tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelineEarlyDestroyTests.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29 #include "vkMemUtil.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "deUniquePtr.hpp"
34 #include "tcuTexture.hpp"
35 #include "vkImageUtil.hpp"
36 #include "vkImageWithMemory.hpp"
37 #include "vkBufferWithMemory.hpp"
38 #include "vkCmdUtil.hpp"
39
40 namespace vkt
41 {
42 namespace pipeline
43 {
44
45 using namespace vk;
46
47 namespace
48 {
49
initPrograms(SourceCollections & programCollection,bool usePipelineCache)50 void initPrograms (SourceCollections& programCollection, bool usePipelineCache)
51 {
52 DE_UNREF(usePipelineCache);
53
54 programCollection.glslSources.add("color_vert") << glu::VertexSource(
55 "#version 450\n"
56 "vec2 vertices[3];\n"
57 "\n"
58 "void main()\n"
59 "{\n"
60 " vertices[0] = vec2(-1.0, -1.0);\n"
61 " vertices[1] = vec2( 1.0, -1.0);\n"
62 " vertices[2] = vec2( 0.0, 1.0);\n"
63 " gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n"
64 "}\n");
65
66 programCollection.glslSources.add("color_frag") << glu::FragmentSource(
67 "#version 450\n"
68 "\n"
69 "layout(location = 0) out vec4 uFragColor;\n"
70 "\n"
71 "void main()\n"
72 "{\n"
73 " uFragColor = vec4(0,1,0,1);\n"
74 "}\n");
75 }
76
testEarlyDestroy(Context & context,bool usePipelineCache,bool destroyLayout)77 tcu::TestStatus testEarlyDestroy (Context& context, bool usePipelineCache, bool destroyLayout)
78 {
79 const DeviceInterface& vk = context.getDeviceInterface();
80 const VkDevice vkDevice = context.getDevice();
81 const Unique<VkShaderModule> vertexShaderModule (createShaderModule(vk, vkDevice, context.getBinaryCollection().get("color_vert"), 0));
82 const Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vk, vkDevice, context.getBinaryCollection().get("color_frag"), 0));
83
84 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
85 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
86
87 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
88 {
89 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
90 DE_NULL, // const void* pNext;
91 0u, // VkPipelineLayoutCreateFlags flags;
92 0u, // deUint32 setLayoutCount;
93 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
94 0u, // deUint32 pushConstantRangeCount;
95 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
96 };
97
98 // Multiple passes for destroy layout in order to increase the chance of crashing if some resource/state gets carried over from previous iterations.
99 int numTests = destroyLayout ? 3 : 1;
100 for(int i = 0; i < numTests; ++i)
101 {
102 Move<VkPipelineLayout> pipelineLayout (createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo, DE_NULL));
103 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, vkDevice, VK_FORMAT_R8G8B8A8_UNORM));
104 const VkPipelineShaderStageCreateInfo stages[] =
105 {
106 {
107 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
108 DE_NULL, // const void* pNext;
109 0u, // VkPipelineShaderStageCreateFlags flags;
110 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
111 *vertexShaderModule, // VkShaderModule module;
112 "main", // const char* pName;
113 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
114 },
115 {
116 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
117 DE_NULL, // const void* pNext;
118 0u, // VkPipelineShaderStageCreateFlags flags;
119 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
120 *fragmentShaderModule, // VkShaderModule module;
121 "main", // const char* pName;
122 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
123 }
124 };
125 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
126 {
127 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
128 DE_NULL, // const void* pNext;
129 0u, // VkPipelineVertexInputStateCreateFlags flags;
130 0u, // deUint32 vertexBindingDescriptionCount;
131 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
132 0u, // deUint32 vertexAttributeDescriptionCount;
133 DE_NULL // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
134 };
135 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
136 {
137 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
138 DE_NULL, // const void* pNext;
139 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
140 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology;
141 VK_FALSE // VkBool32 primitiveRestartEnable;
142 };
143 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
144 {
145 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
146 DE_NULL, // const void* pNext;
147 0u, // VkPipelineRasterizationStateCreateFlags flags;
148 VK_FALSE, // VkBool32 depthClampEnable;
149 VK_TRUE, // VkBool32 rasterizerDiscardEnable;
150 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
151 VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode;
152 VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace;
153 VK_FALSE, // VkBool32 depthBiasEnable;
154 0.0f, // float depthBiasConstantFactor;
155 0.0f, // float depthBiasClamp;
156 0.0f, // float depthBiasSlopeFactor;
157 1.0f // float lineWidth;
158 };
159 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
160 {
161 VK_FALSE, // VkBool32 blendEnable;
162 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor;
163 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
164 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
165 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor;
166 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
167 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
168 0xf // VkColorComponentFlags colorWriteMask;
169 };
170 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
171 {
172 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
173 DE_NULL, // const void* pNext;
174 0u, // VkPipelineColorBlendStateCreateFlags flags;
175 VK_FALSE, // VkBool32 logicOpEnable;
176 VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp;
177 1u, // deUint32 attachmentCount;
178 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
179 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4];
180 };
181 const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
182 {
183 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
184 DE_NULL, // const void* pNext;
185 0u, // VkPipelineCacheCreateFlags flags;
186 0u, // size_t initialDataSize;
187 DE_NULL // const void* pInitialData;
188 };
189 const Unique<VkPipelineCache> pipelineCache (createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo));
190 const VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo =
191 {
192 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
193 DE_NULL, // const void* pNext;
194 VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT, // VkPipelineCreateFlags flags;
195 2u, // deUint32 stageCount;
196 stages, // const VkPipelineShaderStageCreateInfo* pStages;
197 &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
198 &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
199 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
200 DE_NULL, // const VkPipelineViewportStateCreateInfo* pViewportState;
201 &rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
202 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
203 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
204 &colorBlendStateCreateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
205 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
206 *pipelineLayout, // VkPipelineLayout layout;
207 *renderPass, // VkRenderPass renderPass;
208 0u, // deUint32 subpass;
209 DE_NULL, // VkPipeline basePipelineHandle;
210 0 // int basePipelineIndex;
211 };
212 createGraphicsPipeline(vk, vkDevice, usePipelineCache ? *pipelineCache : DE_NULL, &graphicsPipelineCreateInfo);
213
214 const deUint32 framebufferWidth = 32;
215 const deUint32 framebufferHeight = 32;
216 if (destroyLayout)
217 {
218 // This will destroy the pipelineLayout when going out of enclosing scope
219 Move<VkPipelineLayout> layout(pipelineLayout);
220 }
221 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
222 {
223 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
224 DE_NULL, // const void* pNext;
225 0u, // VkCommandBufferUsageFlags flags;
226 (const VkCommandBufferInheritanceInfo*)DE_NULL // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
227 };
228 if (!destroyLayout) {
229 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
230 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
231 } else {
232 auto& allocator = context.getDefaultAllocator();
233 const auto queue = context.getUniversalQueue();
234 const VkFormat attachmentFormat = VK_FORMAT_R8G8B8A8_UNORM;
235 const tcu::TextureFormat textureFormat = mapVkFormat(attachmentFormat);
236 const VkDeviceSize imageSize = framebufferWidth * framebufferHeight * textureFormat.getPixelSize();
237 const VkImageCreateInfo imageCreateInfo =
238 {
239 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
240 DE_NULL, // const void* pNext;
241 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
242 VK_IMAGE_TYPE_2D, // VkImageType imageType;
243 attachmentFormat, // VkFormat format;
244 { framebufferWidth, framebufferHeight, 1u }, // VkExtent3D extent;
245 1u, // deUint32 mipLevels;
246 1u, // deUint32 arrayLayers;
247 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
248 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
249 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
250 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
251 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags usage;
252 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
253 0u, // deUint32 queueFamilyIndexCount;
254 DE_NULL, // const deUint32* pQueueFamilyIndices;
255 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
256 };
257 const ImageWithMemory attachmentImage (vk, vkDevice, context.getDefaultAllocator(), imageCreateInfo, MemoryRequirement::Any);
258 const VkImageSubresourceRange colorSubresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u };
259 const Unique<VkImageView> attachmentImageView (vk::makeImageView(vk, vkDevice, *attachmentImage, VK_IMAGE_VIEW_TYPE_2D, attachmentFormat, colorSubresourceRange));
260 const VkBufferCreateInfo imageBufferCreateInfo = vk::makeBufferCreateInfo(imageSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
261 const BufferWithMemory imageBuffer (vk, vkDevice, allocator, imageBufferCreateInfo, vk::MemoryRequirement::HostVisible);
262 const Unique<VkFramebuffer> framebuffer (vk::makeFramebuffer(vk, vkDevice, *renderPass, *attachmentImageView, framebufferWidth, framebufferHeight, 1u));
263
264 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
265 const tcu::Vec4 clearColor = { 0.2f, 0.6f, 0.8f, 1.0f };
266 VkClearValue clearValue =
267 {
268 { { clearColor.x(), clearColor.y(),
269 clearColor.z(), clearColor.w() } } // float float32[4];
270 };
271 VkClearAttachment attachment =
272 {
273 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
274 0u, // deUint32 colorAttachment;
275 clearValue // VkClearValue clearValue;
276 };
277 const VkRect2D renderArea = { { 0, 0 }, { framebufferWidth, framebufferHeight } };
278 const VkClearRect rect =
279 {
280 renderArea, // VkRect2D rect
281 0u, // uint32_t baseArrayLayer
282 1u // uint32_t layerCount
283 };
284 const VkRenderPassBeginInfo renderPassBeginInfo =
285 {
286 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
287 DE_NULL, // const void* pNext;
288 *renderPass, // VkRenderPass renderPass;
289 *framebuffer, // VkFramebuffer framebuffer;
290 renderArea, // VkRect2D renderArea;
291 1u, // deUint32 clearValueCount;
292 &clearValue // const VkClearValue* pClearValues;
293 };
294 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
295 vk.cmdClearAttachments(*cmdBuffer, 1, &attachment, 1, &rect);
296 vk.cmdEndRenderPass(*cmdBuffer);
297 vk::copyImageToBuffer(vk, *cmdBuffer, *attachmentImage, *imageBuffer, tcu::IVec2(framebufferWidth, framebufferHeight));
298 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
299
300 vk::submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
301 vk.resetCommandBuffer(*cmdBuffer, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
302 const auto& imageBufferAlloc = imageBuffer.getAllocation();
303 vk::invalidateAlloc(vk, vkDevice, imageBufferAlloc);
304
305 const auto imageBufferPtr = reinterpret_cast<const char*>(imageBufferAlloc.getHostPtr()) + imageBufferAlloc.getOffset();
306 const tcu::ConstPixelBufferAccess imagePixels (textureFormat, framebufferWidth, framebufferHeight, 1u, imageBufferPtr);
307
308 for (int z = 0; z < imagePixels.getDepth(); ++z)
309 for (int y = 0; y < imagePixels.getHeight(); ++y)
310 for (int x = 0; x < imagePixels.getWidth(); ++x)
311 {
312 const auto pixel = imagePixels.getPixel(x, y, z);
313 if (pixel != clearColor) {
314 std::ostringstream msg; msg << "Pixel value mismatch after framebuffer clear." << " diff: " << pixel << " vs " << clearColor;
315
316 return tcu::TestStatus::fail(msg.str()/*"Pixel value mismatch after framebuffer clear."*/);
317 }
318 }
319 }
320 }
321 // Passes as long as no crash occurred.
322 return tcu::TestStatus::pass("Pass");
323 }
324
testEarlyDestroyKeepLayout(Context & context,bool useCache)325 tcu::TestStatus testEarlyDestroyKeepLayout (Context& context, bool useCache)
326 {
327 return testEarlyDestroy (context, useCache, false);
328 }
329
testEarlyDestroyDestroyLayout(Context & context,bool useCache)330 tcu::TestStatus testEarlyDestroyDestroyLayout (Context& context, bool useCache)
331 {
332 return testEarlyDestroy (context, useCache, true);
333 }
334
addEarlyDestroyTestCasesWithFunctions(tcu::TestCaseGroup * group)335 void addEarlyDestroyTestCasesWithFunctions (tcu::TestCaseGroup* group)
336 {
337 addFunctionCaseWithPrograms(group, "cache", "", initPrograms, testEarlyDestroyKeepLayout, true);
338 addFunctionCaseWithPrograms(group, "no_cache", "", initPrograms, testEarlyDestroyKeepLayout, false);
339 addFunctionCaseWithPrograms(group, "cache_destroy_layout", "", initPrograms, testEarlyDestroyDestroyLayout, true);
340 addFunctionCaseWithPrograms(group, "no_cache_destroy_layout", "", initPrograms, testEarlyDestroyDestroyLayout, false);
341 }
342
343 } // anonymous
344
createEarlyDestroyTests(tcu::TestContext & testCtx)345 tcu::TestCaseGroup* createEarlyDestroyTests (tcu::TestContext& testCtx)
346 {
347 return createTestGroup(testCtx, "early_destroy", "Tests where pipeline is destroyed early", addEarlyDestroyTestCasesWithFunctions);
348 }
349
350 } // pipeline
351 } // vkt
352