1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 ARM Ltd.
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 Pipeline Cache Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelineCacheTests.hpp"
26 #include "vktPipelineClearUtil.hpp"
27 #include "vktPipelineImageUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktTestCase.hpp"
30 #include "vktTestCaseUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkRef.hpp"
37 #include "vkRefUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "deUniquePtr.hpp"
43 #include "deMemory.h"
44 #include "tcuTestLog.hpp"
45
46 #include <sstream>
47 #include <vector>
48
49 namespace vkt
50 {
51 namespace pipeline
52 {
53
54 using namespace vk;
55
56 namespace
57 {
58
59 // helper functions
60
getShaderFlagStr(const VkShaderStageFlags shader,bool isDescription)61 std::string getShaderFlagStr (const VkShaderStageFlags shader,
62 bool isDescription)
63 {
64 std::ostringstream desc;
65 if (shader & VK_SHADER_STAGE_COMPUTE_BIT)
66 {
67 desc << ((isDescription) ? "compute stage" : "compute_stage");
68 }
69 else
70 {
71 desc << ((isDescription) ? "vertex stage" : "vertex_stage");
72 if (shader & VK_SHADER_STAGE_GEOMETRY_BIT)
73 desc << ((isDescription) ? " geometry stage" : "_geometry_stage");
74 if (shader & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
75 desc << ((isDescription) ? " tessellation control stage" : "_tessellation_control_stage");
76 if (shader & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
77 desc << ((isDescription) ? " tessellation evaluation stage" : "_tessellation_evaluation_stage");
78 desc << ((isDescription) ? " fragment stage" : "_fragment_stage");
79 }
80
81 return desc.str();
82 }
83
84 // helper classes
85 class CacheTestParam
86 {
87 public:
88 CacheTestParam (PipelineConstructionType pipelineConstructionType,
89 const VkShaderStageFlags shaders,
90 bool compileCacheMissShaders,
91 VkPipelineCacheCreateFlags pipelineCacheCreateFlags = 0u);
92 virtual ~CacheTestParam (void) = default;
93 virtual const std::string generateTestName (void) const;
94 virtual const std::string generateTestDescription (void) const;
getPipelineConstructionType(void) const95 PipelineConstructionType getPipelineConstructionType (void) const { return m_pipelineConstructionType; }
getShaderFlags(void) const96 VkShaderStageFlags getShaderFlags (void) const { return m_shaders; }
getPipelineCacheCreateFlags(void) const97 VkPipelineCacheCreateFlags getPipelineCacheCreateFlags (void) const { return m_pipelineCacheCreateFlags; }
getCompileMissShaders(void) const98 bool getCompileMissShaders (void) const { return m_compileCacheMissShaders; }
99
100 protected:
101
102 PipelineConstructionType m_pipelineConstructionType;
103 VkShaderStageFlags m_shaders;
104 VkPipelineCacheCreateFlags m_pipelineCacheCreateFlags;
105 bool m_compileCacheMissShaders;
106 };
107
CacheTestParam(PipelineConstructionType pipelineConstructionType,const VkShaderStageFlags shaders,bool compileCacheMissShaders,VkPipelineCacheCreateFlags pipelineCacheCreateFlags)108 CacheTestParam::CacheTestParam (PipelineConstructionType pipelineConstructionType, const VkShaderStageFlags shaders, bool compileCacheMissShaders, VkPipelineCacheCreateFlags pipelineCacheCreateFlags)
109 : m_pipelineConstructionType (pipelineConstructionType)
110 , m_shaders (shaders)
111 , m_pipelineCacheCreateFlags(pipelineCacheCreateFlags)
112 , m_compileCacheMissShaders (compileCacheMissShaders)
113 {
114 }
115
generateTestName(void) const116 const std::string CacheTestParam::generateTestName (void) const
117 {
118 std::string name = getShaderFlagStr(m_shaders, false);
119 if (m_pipelineCacheCreateFlags == VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) {
120 name += "_externally_synchronized";
121 }
122 return name;
123 }
124
generateTestDescription(void) const125 const std::string CacheTestParam::generateTestDescription (void) const
126 {
127 std::string description = getShaderFlagStr(m_shaders, true);
128 if (m_pipelineCacheCreateFlags == VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) {
129 description += "with externally synchronized bit";
130 }
131 return description;
132 }
133
134 template <class Test>
newTestCase(tcu::TestContext & testContext,const CacheTestParam * testParam)135 vkt::TestCase* newTestCase (tcu::TestContext& testContext,
136 const CacheTestParam* testParam)
137 {
138 return new Test(testContext,
139 testParam->generateTestName().c_str(),
140 testParam->generateTestDescription().c_str(),
141 testParam);
142 }
143
createBufferAndBindMemory(Context & context,VkDeviceSize size,VkBufferUsageFlags usage,de::MovePtr<Allocation> * pAlloc)144 Move<VkBuffer> createBufferAndBindMemory (Context& context, VkDeviceSize size, VkBufferUsageFlags usage, de::MovePtr<Allocation>* pAlloc)
145 {
146 const DeviceInterface& vk = context.getDeviceInterface();
147 const VkDevice vkDevice = context.getDevice();
148 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
149
150 const VkBufferCreateInfo vertexBufferParams =
151 {
152 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
153 DE_NULL, // const void* pNext;
154 0u, // VkBufferCreateFlags flags;
155 size, // VkDeviceSize size;
156 usage, // VkBufferUsageFlags usage;
157 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
158 1u, // deUint32 queueFamilyCount;
159 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
160 };
161
162 Move<VkBuffer> vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
163
164 *pAlloc = context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
165 VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
166
167 return vertexBuffer;
168 }
169
createImage2DAndBindMemory(Context & context,VkFormat format,deUint32 width,deUint32 height,VkImageUsageFlags usage,VkSampleCountFlagBits sampleCount,de::details::MovePtr<Allocation> * pAlloc)170 Move<VkImage> createImage2DAndBindMemory (Context& context,
171 VkFormat format,
172 deUint32 width,
173 deUint32 height,
174 VkImageUsageFlags usage,
175 VkSampleCountFlagBits sampleCount,
176 de::details::MovePtr<Allocation>* pAlloc)
177 {
178 const DeviceInterface& vk = context.getDeviceInterface();
179 const VkDevice vkDevice = context.getDevice();
180 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
181
182 const VkImageCreateInfo colorImageParams =
183 {
184 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
185 DE_NULL, // const void* pNext;
186 0u, // VkImageCreateFlags flags;
187 VK_IMAGE_TYPE_2D, // VkImageType imageType;
188 format, // VkFormat format;
189 { width, height, 1u }, // VkExtent3D extent;
190 1u, // deUint32 mipLevels;
191 1u, // deUint32 arraySize;
192 sampleCount, // deUint32 samples;
193 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
194 usage, // VkImageUsageFlags usage;
195 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
196 1u, // deUint32 queueFamilyCount;
197 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
198 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
199 };
200
201 Move<VkImage> image = createImage(vk, vkDevice, &colorImageParams);
202
203 *pAlloc = context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any);
204 VK_CHECK(vk.bindImageMemory(vkDevice, *image, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
205
206 return image;
207 }
208
209 // Test Classes
210 class CacheTest : public vkt::TestCase
211 {
212 public:
CacheTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param)213 CacheTest (tcu::TestContext& testContext,
214 const std::string& name,
215 const std::string& description,
216 const CacheTestParam* param)
217 : vkt::TestCase (testContext, name, description)
218 , m_param (*param)
219 { }
~CacheTest(void)220 virtual ~CacheTest (void) { }
221 protected:
222 const CacheTestParam m_param;
223 };
224
225 class CacheTestInstance : public vkt::TestInstance
226 {
227 public:
228 enum
229 {
230 PIPELINE_CACHE_NDX_NO_CACHE,
231 PIPELINE_CACHE_NDX_CACHED,
232 PIPELINE_CACHE_NDX_COUNT,
233 };
234 CacheTestInstance (Context& context,
235 const CacheTestParam* param);
236 virtual ~CacheTestInstance (void);
237 virtual tcu::TestStatus iterate (void);
238 protected:
239 virtual tcu::TestStatus verifyTestResult (void) = 0;
240 virtual void prepareCommandBuffer (void) = 0;
241 protected:
242 const CacheTestParam* m_param;
243 Move<VkCommandPool> m_cmdPool;
244 Move<VkCommandBuffer> m_cmdBuffer;
245 Move<VkPipelineCache> m_cache;
246 };
247
CacheTestInstance(Context & context,const CacheTestParam * param)248 CacheTestInstance::CacheTestInstance (Context& context,
249 const CacheTestParam* param)
250 : TestInstance (context)
251 , m_param (param)
252 {
253 const DeviceInterface& vk = m_context.getDeviceInterface();
254 const VkDevice vkDevice = m_context.getDevice();
255 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
256
257 // Create command pool
258 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
259
260 // Create command buffer
261 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
262
263 // Create the Pipeline Cache
264 {
265 const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
266 {
267 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
268 DE_NULL, // const void* pNext;
269 m_param->getPipelineCacheCreateFlags(), // VkPipelineCacheCreateFlags flags;
270 0u, // deUintptr initialDataSize;
271 DE_NULL, // const void* pInitialData;
272 };
273
274 m_cache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
275 }
276 }
277
~CacheTestInstance(void)278 CacheTestInstance::~CacheTestInstance (void)
279 {
280 }
281
iterate(void)282 tcu::TestStatus CacheTestInstance::iterate (void)
283 {
284 const DeviceInterface& vk = m_context.getDeviceInterface();
285 const VkDevice vkDevice = m_context.getDevice();
286 const VkQueue queue = m_context.getUniversalQueue();
287
288 prepareCommandBuffer();
289
290 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
291
292 return verifyTestResult();
293 }
294
295 class GraphicsCacheTest : public CacheTest
296 {
297 public:
GraphicsCacheTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param)298 GraphicsCacheTest (tcu::TestContext& testContext,
299 const std::string& name,
300 const std::string& description,
301 const CacheTestParam* param)
302 : CacheTest (testContext, name, description, param)
303 { }
~GraphicsCacheTest(void)304 virtual ~GraphicsCacheTest (void) { }
305 virtual void initPrograms (SourceCollections& programCollection) const;
306 virtual void checkSupport (Context& context) const;
307 virtual TestInstance* createInstance (Context& context) const;
308 };
309
310 class GraphicsCacheTestInstance : public CacheTestInstance
311 {
312 public:
313 GraphicsCacheTestInstance (Context& context,
314 const CacheTestParam* param);
315 virtual ~GraphicsCacheTestInstance (void);
316 protected:
317
318 void preparePipelineWrapper (GraphicsPipelineWrapper& gpw,
319 VkPipelineCache cache,
320 bool useMissShaders);
321 virtual void preparePipelines (void);
322 void prepareRenderPass (VkFramebuffer framebuffer, VkPipeline pipeline);
323 virtual void prepareCommandBuffer (void);
324 virtual tcu::TestStatus verifyTestResult (void);
325
326 protected:
327 const tcu::UVec2 m_renderSize;
328 const VkFormat m_colorFormat;
329 const VkFormat m_depthFormat;
330 Move<VkPipelineLayout> m_pipelineLayout;
331
332 Move<VkImage> m_depthImage;
333 de::MovePtr<Allocation> m_depthImageAlloc;
334 de::MovePtr<Allocation> m_colorImageAlloc[PIPELINE_CACHE_NDX_COUNT];
335 Move<VkImageView> m_depthAttachmentView;
336 VkImageMemoryBarrier m_imageLayoutBarriers[3];
337
338 Move<VkBuffer> m_vertexBuffer;
339 de::MovePtr<Allocation> m_vertexBufferMemory;
340 std::vector<Vertex4RGBA> m_vertices;
341
342 GraphicsPipelineWrapper m_pipeline[PIPELINE_CACHE_NDX_COUNT];
343 Move<VkRenderPass> m_renderPass;
344
345 Move<VkImage> m_colorImage[PIPELINE_CACHE_NDX_COUNT];
346 Move<VkImageView> m_colorAttachmentView[PIPELINE_CACHE_NDX_COUNT];
347 Move<VkFramebuffer> m_framebuffer[PIPELINE_CACHE_NDX_COUNT];
348 };
349
initPrograms(SourceCollections & programCollection) const350 void GraphicsCacheTest::initPrograms (SourceCollections& programCollection) const
351 {
352 enum ShaderCacheOpType
353 {
354 SHADERS_CACHE_OP_HIT = 0,
355 SHADERS_CACHE_OP_MISS,
356
357 SHADERS_CACHE_OP_LAST
358 };
359
360 for (deUint32 shaderOpNdx = 0u; shaderOpNdx < SHADERS_CACHE_OP_LAST; shaderOpNdx++)
361 {
362 const ShaderCacheOpType shaderOp = (ShaderCacheOpType)shaderOpNdx;
363
364 if (shaderOp == SHADERS_CACHE_OP_MISS && !m_param.getCompileMissShaders())
365 continue;
366
367 const std::string missHitDiff = (shaderOp == SHADERS_CACHE_OP_HIT ? "" : " + 0.1");
368 const std::string missSuffix = (shaderOp == SHADERS_CACHE_OP_HIT ? "" : "_miss");
369
370 programCollection.glslSources.add("color_vert" + missSuffix) << glu::VertexSource(
371 "#version 450\n"
372 "layout(location = 0) in vec4 position;\n"
373 "layout(location = 1) in vec4 color;\n"
374 "layout(location = 0) out highp vec4 vtxColor;\n"
375 "out gl_PerVertex { vec4 gl_Position; };\n"
376 "void main (void)\n"
377 "{\n"
378 " gl_Position = position;\n"
379 " vtxColor = color" + missHitDiff + ";\n"
380 "}\n");
381
382 programCollection.glslSources.add("color_frag" + missSuffix) << glu::FragmentSource(
383 "#version 310 es\n"
384 "layout(location = 0) in highp vec4 vtxColor;\n"
385 "layout(location = 0) out highp vec4 fragColor;\n"
386 "void main (void)\n"
387 "{\n"
388 " fragColor = vtxColor" + missHitDiff + ";\n"
389 "}\n");
390
391 VkShaderStageFlags shaderFlag = m_param.getShaderFlags();
392 if (shaderFlag & VK_SHADER_STAGE_GEOMETRY_BIT)
393 {
394 programCollection.glslSources.add("unused_geo" + missSuffix) << glu::GeometrySource(
395 "#version 450 \n"
396 "layout(triangles) in;\n"
397 "layout(triangle_strip, max_vertices = 3) out;\n"
398 "layout(location = 0) in highp vec4 in_vtxColor[];\n"
399 "layout(location = 0) out highp vec4 vtxColor;\n"
400 "out gl_PerVertex { vec4 gl_Position; };\n"
401 "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
402 "void main (void)\n"
403 "{\n"
404 " for(int ndx=0; ndx<3; ndx++)\n"
405 " {\n"
406 " gl_Position = gl_in[ndx].gl_Position;\n"
407 " vtxColor = in_vtxColor[ndx]" + missHitDiff + ";\n"
408 " EmitVertex();\n"
409 " }\n"
410 " EndPrimitive();\n"
411 "}\n");
412 }
413 if (shaderFlag & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
414 {
415 programCollection.glslSources.add("basic_tcs" + missSuffix) << glu::TessellationControlSource(
416 "#version 450 \n"
417 "layout(vertices = 3) out;\n"
418 "layout(location = 0) in highp vec4 color[];\n"
419 "layout(location = 0) out highp vec4 vtxColor[];\n"
420 "out gl_PerVertex { vec4 gl_Position; } gl_out[3];\n"
421 "in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
422 "void main()\n"
423 "{\n"
424 " gl_TessLevelOuter[0] = 4.0;\n"
425 " gl_TessLevelOuter[1] = 4.0;\n"
426 " gl_TessLevelOuter[2] = 4.0;\n"
427 " gl_TessLevelInner[0] = 4.0;\n"
428 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
429 " vtxColor[gl_InvocationID] = color[gl_InvocationID]" + missHitDiff + ";\n"
430 "}\n");
431 }
432 if (shaderFlag & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
433 {
434 programCollection.glslSources.add("basic_tes" + missSuffix) << glu::TessellationEvaluationSource(
435 "#version 450 \n"
436 "layout(triangles, fractional_even_spacing, ccw) in;\n"
437 "layout(location = 0) in highp vec4 colors[];\n"
438 "layout(location = 0) out highp vec4 vtxColor;\n"
439 "out gl_PerVertex { vec4 gl_Position; };\n"
440 "in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
441 "void main() \n"
442 "{\n"
443 " float u = gl_TessCoord.x;\n"
444 " float v = gl_TessCoord.y;\n"
445 " float w = gl_TessCoord.z;\n"
446 " vec4 pos = vec4(0);\n"
447 " vec4 color = vec4(0)" + missHitDiff + ";\n"
448 " pos.xyz += u * gl_in[0].gl_Position.xyz;\n"
449 " color.xyz += u * colors[0].xyz;\n"
450 " pos.xyz += v * gl_in[1].gl_Position.xyz;\n"
451 " color.xyz += v * colors[1].xyz;\n"
452 " pos.xyz += w * gl_in[2].gl_Position.xyz;\n"
453 " color.xyz += w * colors[2].xyz;\n"
454 " pos.w = 1.0;\n"
455 " color.w = 1.0;\n"
456 " gl_Position = pos;\n"
457 " vtxColor = color;\n"
458 "}\n");
459 }
460 }
461 }
462
checkSupport(Context & context) const463 void GraphicsCacheTest::checkSupport (Context& context) const
464 {
465 if (m_param.getShaderFlags() & VK_SHADER_STAGE_GEOMETRY_BIT)
466 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
467 if ((m_param.getShaderFlags() & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ||
468 (m_param.getShaderFlags() & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
469 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
470
471 checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_param.getPipelineConstructionType());
472 }
473
createInstance(Context & context) const474 TestInstance* GraphicsCacheTest::createInstance (Context& context) const
475 {
476 return new GraphicsCacheTestInstance(context, &m_param);
477 }
478
GraphicsCacheTestInstance(Context & context,const CacheTestParam * param)479 GraphicsCacheTestInstance::GraphicsCacheTestInstance (Context& context,
480 const CacheTestParam* param)
481 : CacheTestInstance (context,param)
482 , m_renderSize (32u, 32u)
483 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
484 , m_depthFormat (VK_FORMAT_D16_UNORM)
485 , m_pipeline
486 {
487 { context.getDeviceInterface(), context.getDevice(), param->getPipelineConstructionType() },
488 { context.getDeviceInterface(), context.getDevice(), param->getPipelineConstructionType() },
489 }
490 {
491 const DeviceInterface& vk = m_context.getDeviceInterface();
492 const VkDevice vkDevice = m_context.getDevice();
493
494 // Create vertex buffer
495 {
496 m_vertexBuffer = createBufferAndBindMemory(m_context, 1024u, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &m_vertexBufferMemory);
497
498 m_vertices = createOverlappingQuads();
499 // Load vertices into vertex buffer
500 deMemcpy(m_vertexBufferMemory->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
501 flushAlloc(vk, vkDevice, *m_vertexBufferMemory);
502 }
503
504 // Create render pass
505 m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat, m_depthFormat);
506
507 const VkComponentMapping ComponentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
508 // Create color image
509 {
510 m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE] = createImage2DAndBindMemory(m_context,
511 m_colorFormat,
512 m_renderSize.x(),
513 m_renderSize.y(),
514 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
515 VK_SAMPLE_COUNT_1_BIT,
516 &m_colorImageAlloc[PIPELINE_CACHE_NDX_NO_CACHE]);
517 m_colorImage[PIPELINE_CACHE_NDX_CACHED] = createImage2DAndBindMemory(m_context,
518 m_colorFormat,
519 m_renderSize.x(),
520 m_renderSize.y(),
521 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
522 VK_SAMPLE_COUNT_1_BIT,
523 &m_colorImageAlloc[PIPELINE_CACHE_NDX_CACHED]);
524 }
525
526 // Create depth image
527 {
528 m_depthImage = createImage2DAndBindMemory(m_context,
529 m_depthFormat,
530 m_renderSize.x(),
531 m_renderSize.y(),
532 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
533 VK_SAMPLE_COUNT_1_BIT,
534 &m_depthImageAlloc);
535 }
536
537 // Set up image layout transition barriers
538 {
539 VkImageMemoryBarrier colorImageBarrier =
540 {
541 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
542 DE_NULL, // const void* pNext;
543 0u, // VkAccessFlags srcAccessMask;
544 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
545 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
546 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
547 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
548 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
549 *m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE], // VkImage image;
550 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
551 };
552
553 m_imageLayoutBarriers[0] = colorImageBarrier;
554
555 colorImageBarrier.image = *m_colorImage[PIPELINE_CACHE_NDX_CACHED];
556 m_imageLayoutBarriers[1] = colorImageBarrier;
557
558 const VkImageMemoryBarrier depthImageBarrier =
559 {
560 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
561 DE_NULL, // const void* pNext;
562 0u, // VkAccessFlags srcAccessMask;
563 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
564 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
565 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
566 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
567 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
568 *m_depthImage, // VkImage image;
569 { VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
570 };
571
572 m_imageLayoutBarriers[2] = depthImageBarrier;
573 }
574 // Create color attachment view
575 {
576 VkImageViewCreateInfo colorAttachmentViewParams =
577 {
578 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
579 DE_NULL, // const void* pNext;
580 0u, // VkImageViewCreateFlags flags;
581 *m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE], // VkImage image;
582 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
583 m_colorFormat, // VkFormat format;
584 ComponentMappingRGBA, // VkComponentMapping components;
585 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
586 };
587
588 m_colorAttachmentView[PIPELINE_CACHE_NDX_NO_CACHE] = createImageView(vk, vkDevice, &colorAttachmentViewParams);
589
590 colorAttachmentViewParams.image = *m_colorImage[PIPELINE_CACHE_NDX_CACHED];
591 m_colorAttachmentView[PIPELINE_CACHE_NDX_CACHED] = createImageView(vk, vkDevice, &colorAttachmentViewParams);
592 }
593
594 // Create depth attachment view
595 {
596 const VkImageViewCreateInfo depthAttachmentViewParams =
597 {
598 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
599 DE_NULL, // const void* pNext;
600 0u, // VkImageViewCreateFlags flags;
601 *m_depthImage, // VkImage image;
602 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
603 m_depthFormat, // VkFormat format;
604 ComponentMappingRGBA, // VkComponentMapping components;
605 { VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
606 };
607
608 m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams);
609 }
610
611 // Create framebuffer
612 {
613 VkImageView attachmentBindInfos[2] =
614 {
615 *m_colorAttachmentView[PIPELINE_CACHE_NDX_NO_CACHE],
616 *m_depthAttachmentView,
617 };
618
619 const VkFramebufferCreateInfo framebufferParams =
620 {
621 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
622 DE_NULL, // const void* pNext;
623 0u, // VkFramebufferCreateFlags flags;
624 *m_renderPass, // VkRenderPass renderPass;
625 2u, // deUint32 attachmentCount;
626 attachmentBindInfos, // const VkImageView* pAttachments;
627 (deUint32)m_renderSize.x(), // deUint32 width;
628 (deUint32)m_renderSize.y(), // deUint32 height;
629 1u, // deUint32 layers;
630 };
631
632 m_framebuffer[PIPELINE_CACHE_NDX_NO_CACHE] = createFramebuffer(vk, vkDevice, &framebufferParams);
633
634 attachmentBindInfos[0] = *m_colorAttachmentView[PIPELINE_CACHE_NDX_CACHED];
635 m_framebuffer[PIPELINE_CACHE_NDX_CACHED] = createFramebuffer(vk, vkDevice, &framebufferParams);
636 }
637
638 // Create pipeline layout
639 {
640 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
641 {
642 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
643 DE_NULL, // const void* pNext;
644 0u, // VkPipelineLayoutCreateFlags flags;
645 0u, // deUint32 setLayoutCount;
646 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
647 0u, // deUint32 pushConstantRangeCount;
648 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
649 };
650
651 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
652 }
653 }
654
~GraphicsCacheTestInstance(void)655 GraphicsCacheTestInstance::~GraphicsCacheTestInstance (void)
656 {
657 }
658
preparePipelineWrapper(GraphicsPipelineWrapper & gpw,VkPipelineCache cache,bool useMissShaders=false)659 void GraphicsCacheTestInstance::preparePipelineWrapper(GraphicsPipelineWrapper& gpw,
660 VkPipelineCache cache,
661 bool useMissShaders = false)
662 {
663 static const VkPipelineDepthStencilStateCreateInfo defaultDepthStencilState
664 {
665 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
666 DE_NULL, // const void* pNext;
667 0u, // VkPipelineDepthStencilStateCreateFlags flags;
668 VK_TRUE, // VkBool32 depthTestEnable;
669 VK_TRUE, // VkBool32 depthWriteEnable;
670 VK_COMPARE_OP_LESS_OR_EQUAL, // VkCompareOp depthCompareOp;
671 VK_FALSE, // VkBool32 depthBoundsTestEnable;
672 VK_FALSE, // VkBool32 stencilTestEnable;
673 { // VkStencilOpState front;
674 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
675 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
676 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
677 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
678 0u, // deUint32 compareMask;
679 0u, // deUint32 writeMask;
680 0u, // deUint32 reference;
681 },
682 { // VkStencilOpState back;
683 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
684 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
685 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
686 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
687 0u, // deUint32 compareMask;
688 0u, // deUint32 writeMask;
689 0u, // deUint32 reference;
690 },
691 0.0f, // float minDepthBounds;
692 1.0f, // float maxDepthBounds;
693 };
694
695 static const VkVertexInputBindingDescription defaultVertexInputBindingDescription
696 {
697 0u, // deUint32 binding;
698 sizeof(Vertex4RGBA), // deUint32 strideInBytes;
699 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
700 };
701
702 static const VkVertexInputAttributeDescription defaultVertexInputAttributeDescriptions[]
703 {
704 {
705 0u, // deUint32 location;
706 0u, // deUint32 binding;
707 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
708 0u // deUint32 offsetInBytes;
709 },
710 {
711 1u, // deUint32 location;
712 0u, // deUint32 binding;
713 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
714 DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offsetInBytes;
715 }
716 };
717
718 static const VkPipelineVertexInputStateCreateInfo defaultVertexInputStateParams
719 {
720 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
721 DE_NULL, // const void* pNext;
722 0u, // VkPipelineVertexInputStateCreateFlags flags;
723 1u, // deUint32 vertexBindingDescriptionCount;
724 &defaultVertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
725 2u, // deUint32 vertexAttributeDescriptionCount;
726 defaultVertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
727 };
728
729 const DeviceInterface& vk = m_context.getDeviceInterface();
730 const VkDevice vkDevice = m_context.getDevice();
731 const std::string postfix = useMissShaders ? "_miss" : "";
732
733 auto createModule = [&vk, vkDevice, &postfix](Context& context, std::string shaderName)
734 {
735 return createShaderModule(vk, vkDevice, context.getBinaryCollection().get(shaderName + postfix), 0);
736 };
737
738 // Bind shader stages
739 Move<VkShaderModule> vertShaderModule = createModule(m_context, "color_vert");
740 Move<VkShaderModule> fragShaderModule = createModule(m_context, "color_frag");
741 Move<VkShaderModule> tescShaderModule;
742 Move<VkShaderModule> teseShaderModule;
743 Move<VkShaderModule> geomShaderModule;
744
745 if (m_param->getShaderFlags() & VK_SHADER_STAGE_GEOMETRY_BIT)
746 geomShaderModule = createModule(m_context, "unused_geo");
747 if (m_param->getShaderFlags() & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
748 tescShaderModule = createModule(m_context, "basic_tcs");
749 if (m_param->getShaderFlags() & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
750 teseShaderModule = createModule(m_context, "basic_tes");
751
752 const std::vector<VkViewport> viewport { makeViewport(m_renderSize) };
753 const std::vector<VkRect2D> scissor { makeRect2D(m_renderSize) };
754
755 gpw.setDefaultTopology((m_param->getShaderFlags() & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
756 ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
757 .setDefaultRasterizationState()
758 .setDefaultColorBlendState()
759 .setDefaultMultisampleState()
760 .setupVertexInputState(&defaultVertexInputStateParams)
761 .setupPreRasterizationShaderState(viewport,
762 scissor,
763 *m_pipelineLayout,
764 *m_renderPass,
765 0u,
766 *vertShaderModule,
767 DE_NULL,
768 *tescShaderModule,
769 *teseShaderModule,
770 *geomShaderModule)
771 .setupFragmentShaderState(*m_pipelineLayout, *m_renderPass, 0u, *fragShaderModule, &defaultDepthStencilState)
772 .setupFragmentOutputState(*m_renderPass)
773 .setMonolithicPipelineLayout(*m_pipelineLayout)
774 .buildPipeline(cache);
775 }
776
preparePipelines(void)777 void GraphicsCacheTestInstance::preparePipelines (void)
778 {
779 preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], *m_cache);
780 preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_CACHED], *m_cache);
781 }
782
prepareRenderPass(VkFramebuffer framebuffer,VkPipeline pipeline)783 void GraphicsCacheTestInstance::prepareRenderPass (VkFramebuffer framebuffer, VkPipeline pipeline)
784 {
785 const DeviceInterface& vk = m_context.getDeviceInterface();
786
787 const VkClearValue attachmentClearValues[2] =
788 {
789 defaultClearValue(m_colorFormat),
790 defaultClearValue(m_depthFormat),
791 };
792
793 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), 2u, attachmentClearValues);
794
795 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
796 VkDeviceSize offsets = 0u;
797 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);
798 vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1u, 0u, 0u);
799
800 endRenderPass(vk, *m_cmdBuffer);
801 }
802
prepareCommandBuffer(void)803 void GraphicsCacheTestInstance::prepareCommandBuffer (void)
804 {
805 const DeviceInterface& vk = m_context.getDeviceInterface();
806
807 preparePipelines();
808
809 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
810
811 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
812 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(m_imageLayoutBarriers), m_imageLayoutBarriers);
813
814 prepareRenderPass(*m_framebuffer[PIPELINE_CACHE_NDX_NO_CACHE], m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE].getPipeline());
815
816 // After the first render pass, the images are in correct layouts
817
818 prepareRenderPass(*m_framebuffer[PIPELINE_CACHE_NDX_CACHED], m_pipeline[PIPELINE_CACHE_NDX_CACHED].getPipeline());
819
820 endCommandBuffer(vk, *m_cmdBuffer);
821 }
822
verifyTestResult(void)823 tcu::TestStatus GraphicsCacheTestInstance::verifyTestResult (void)
824 {
825 const DeviceInterface& vk = m_context.getDeviceInterface();
826 const VkDevice vkDevice = m_context.getDevice();
827 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
828
829 const VkQueue queue = m_context.getUniversalQueue();
830 de::MovePtr<tcu::TextureLevel> resultNoCache = readColorAttachment(vk,
831 vkDevice,
832 queue,
833 queueFamilyIndex,
834 m_context.getDefaultAllocator(),
835 *m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE],
836 m_colorFormat,
837 m_renderSize);
838 de::MovePtr<tcu::TextureLevel> resultCache = readColorAttachment(vk,
839 vkDevice,
840 queue,
841 queueFamilyIndex,
842 m_context.getDefaultAllocator(),
843 *m_colorImage[PIPELINE_CACHE_NDX_CACHED],
844 m_colorFormat,
845 m_renderSize);
846
847 bool compareOk = tcu::intThresholdCompare(m_context.getTestContext().getLog(),
848 "IntImageCompare",
849 "Image comparison",
850 resultNoCache->getAccess(),
851 resultCache->getAccess(),
852 tcu::UVec4(1, 1, 1, 1),
853 tcu::COMPARE_LOG_RESULT);
854
855 if (compareOk)
856 return tcu::TestStatus::pass("Render images w/o cached pipeline match.");
857 else
858 return tcu::TestStatus::fail("Render Images mismatch.");
859 }
860
861 class ComputeCacheTest : public CacheTest
862 {
863 public:
ComputeCacheTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param)864 ComputeCacheTest (tcu::TestContext& testContext,
865 const std::string& name,
866 const std::string& description,
867 const CacheTestParam* param)
868 : CacheTest (testContext, name, description, param)
869 { }
~ComputeCacheTest(void)870 virtual ~ComputeCacheTest (void) { }
871 virtual void initPrograms (SourceCollections& programCollection) const;
872 virtual TestInstance* createInstance (Context& context) const;
873 };
874
875 class ComputeCacheTestInstance : public CacheTestInstance
876 {
877 public:
878 ComputeCacheTestInstance (Context& context,
879 const CacheTestParam* param);
880 virtual ~ComputeCacheTestInstance (void);
881 virtual void prepareCommandBuffer (void);
882 protected:
883 virtual tcu::TestStatus verifyTestResult (void);
884 void buildBuffers (void);
885 void buildDescriptorSets (deUint32 ndx);
886 void buildShader (void);
887 void buildPipeline (deUint32 ndx);
888 protected:
889 Move<VkBuffer> m_inputBuf;
890 de::MovePtr<Allocation> m_inputBufferAlloc;
891 Move<VkShaderModule> m_computeShaderModule;
892
893 Move<VkBuffer> m_outputBuf[PIPELINE_CACHE_NDX_COUNT];
894 de::MovePtr<Allocation> m_outputBufferAlloc[PIPELINE_CACHE_NDX_COUNT];
895
896 Move<VkDescriptorPool> m_descriptorPool[PIPELINE_CACHE_NDX_COUNT];
897 Move<VkDescriptorSetLayout> m_descriptorSetLayout[PIPELINE_CACHE_NDX_COUNT];
898 Move<VkDescriptorSet> m_descriptorSet[PIPELINE_CACHE_NDX_COUNT];
899
900 Move<VkPipelineLayout> m_pipelineLayout[PIPELINE_CACHE_NDX_COUNT];
901 Move<VkPipeline> m_pipeline[PIPELINE_CACHE_NDX_COUNT];
902 };
903
initPrograms(SourceCollections & programCollection) const904 void ComputeCacheTest::initPrograms (SourceCollections& programCollection) const
905 {
906 programCollection.glslSources.add("basic_compute") << glu::ComputeSource(
907 "#version 310 es\n"
908 "layout(local_size_x = 1) in;\n"
909 "layout(std430) buffer;\n"
910 "layout(binding = 0) readonly buffer Input0\n"
911 "{\n"
912 " vec4 elements[];\n"
913 "} input_data0;\n"
914 "layout(binding = 1) writeonly buffer Output\n"
915 "{\n"
916 " vec4 elements[];\n"
917 "} output_data;\n"
918 "void main()\n"
919 "{\n"
920 " uint ident = gl_GlobalInvocationID.x;\n"
921 " output_data.elements[ident] = input_data0.elements[ident] * input_data0.elements[ident];\n"
922 "}");
923 }
924
createInstance(Context & context) const925 TestInstance* ComputeCacheTest::createInstance (Context& context) const
926 {
927 return new ComputeCacheTestInstance(context, &m_param);
928 }
929
buildBuffers(void)930 void ComputeCacheTestInstance::buildBuffers (void)
931 {
932 const DeviceInterface& vk = m_context.getDeviceInterface();
933 const VkDevice vkDevice = m_context.getDevice();
934
935 // Create buffer object, allocate storage, and generate input data
936 const VkDeviceSize size = sizeof(tcu::Vec4) * 128u;
937 m_inputBuf = createBufferAndBindMemory(m_context, size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, &m_inputBufferAlloc);
938
939 // Initialize input buffer
940 tcu::Vec4* pVec = reinterpret_cast<tcu::Vec4*>(m_inputBufferAlloc->getHostPtr());
941 for (deUint32 ndx = 0u; ndx < 128u; ndx++)
942 {
943 for (deUint32 component = 0u; component < 4u; component++)
944 pVec[ndx][component]= (float)(ndx * (component + 1u));
945 }
946 flushAlloc(vk, vkDevice, *m_inputBufferAlloc);
947
948 // Clear the output buffer
949 for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
950 {
951 m_outputBuf[ndx] = createBufferAndBindMemory(m_context, size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, &m_outputBufferAlloc[ndx]);
952
953 pVec = reinterpret_cast<tcu::Vec4*>(m_outputBufferAlloc[ndx]->getHostPtr());
954
955 for (deUint32 i = 0; i < (size / sizeof(tcu::Vec4)); i++)
956 pVec[i] = tcu::Vec4(0.0f);
957
958 flushAlloc(vk, vkDevice, *m_outputBufferAlloc[ndx]);
959 }
960 }
961
buildDescriptorSets(deUint32 ndx)962 void ComputeCacheTestInstance::buildDescriptorSets (deUint32 ndx)
963 {
964 const DeviceInterface& vk = m_context.getDeviceInterface();
965 const VkDevice vkDevice = m_context.getDevice();
966
967 // Create descriptor set layout
968 DescriptorSetLayoutBuilder descLayoutBuilder;
969
970 for (deUint32 bindingNdx = 0u; bindingNdx < 2u; bindingNdx++)
971 descLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
972
973 m_descriptorSetLayout[ndx] = descLayoutBuilder.build(vk, vkDevice);
974
975 std::vector<VkDescriptorBufferInfo> descriptorInfos;
976 descriptorInfos.push_back(makeDescriptorBufferInfo(*m_inputBuf, 0u, sizeof(tcu::Vec4) * 128u));
977 descriptorInfos.push_back(makeDescriptorBufferInfo(*m_outputBuf[ndx], 0u, sizeof(tcu::Vec4) * 128u));
978
979 // Create descriptor pool
980 m_descriptorPool[ndx] = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u).build(vk,
981 vkDevice,
982 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
983 1u);
984
985 // Create descriptor set
986 const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
987 {
988 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
989 DE_NULL, // const void* pNext;
990 *m_descriptorPool[ndx], // VkDescriptorPool descriptorPool;
991 1u, // deUint32 setLayoutCount;
992 &m_descriptorSetLayout[ndx].get(), // const VkDescriptorSetLayout* pSetLayouts;
993 };
994 m_descriptorSet[ndx] = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocInfo);
995
996 DescriptorSetUpdateBuilder builder;
997 for (deUint32 descriptorNdx = 0u; descriptorNdx < 2u; descriptorNdx++)
998 {
999 builder.writeSingle(*m_descriptorSet[ndx],
1000 DescriptorSetUpdateBuilder::Location::binding(descriptorNdx),
1001 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
1002 &descriptorInfos[descriptorNdx]);
1003 }
1004 builder.update(vk, vkDevice);
1005 }
1006
buildShader(void)1007 void ComputeCacheTestInstance::buildShader (void)
1008 {
1009 const DeviceInterface& vk = m_context.getDeviceInterface();
1010 const VkDevice vkDevice = m_context.getDevice();
1011
1012 // Create compute shader
1013 VkShaderModuleCreateInfo shaderModuleCreateInfo =
1014 {
1015 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType;
1016 DE_NULL, // const void* pNext;
1017 0u, // VkShaderModuleCreateFlags flags;
1018 m_context.getBinaryCollection().get("basic_compute").getSize(), // deUintptr codeSize;
1019 (deUint32*)m_context.getBinaryCollection().get("basic_compute").getBinary(), // const deUint32* pCode;
1020 };
1021 m_computeShaderModule = createShaderModule(vk, vkDevice, &shaderModuleCreateInfo);
1022 }
1023
buildPipeline(deUint32 ndx)1024 void ComputeCacheTestInstance::buildPipeline (deUint32 ndx)
1025 {
1026 const DeviceInterface& vk = m_context.getDeviceInterface();
1027 const VkDevice vkDevice = m_context.getDevice();
1028
1029 // Create compute pipeline layout
1030 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1031 {
1032 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1033 DE_NULL, // const void* pNext;
1034 0u, // VkPipelineLayoutCreateFlags flags;
1035 1u, // deUint32 setLayoutCount;
1036 &m_descriptorSetLayout[ndx].get(), // const VkDescriptorSetLayout* pSetLayouts;
1037 0u, // deUint32 pushConstantRangeCount;
1038 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
1039 };
1040
1041 m_pipelineLayout[ndx] = createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo);
1042
1043 const VkPipelineShaderStageCreateInfo stageCreateInfo =
1044 {
1045 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1046 DE_NULL, // const void* pNext;
1047 0u, // VkPipelineShaderStageCreateFlags flags;
1048 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
1049 *m_computeShaderModule, // VkShaderModule module;
1050 "main", // const char* pName;
1051 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
1052 };
1053
1054 const VkComputePipelineCreateInfo pipelineCreateInfo =
1055 {
1056 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
1057 DE_NULL, // const void* pNext;
1058 0u, // VkPipelineCreateFlags flags;
1059 stageCreateInfo, // VkPipelineShaderStageCreateInfo stage;
1060 *m_pipelineLayout[ndx], // VkPipelineLayout layout;
1061 (VkPipeline)0, // VkPipeline basePipelineHandle;
1062 0u, // deInt32 basePipelineIndex;
1063 };
1064
1065 m_pipeline[ndx] = createComputePipeline(vk, vkDevice, *m_cache, &pipelineCreateInfo);
1066 }
1067
ComputeCacheTestInstance(Context & context,const CacheTestParam * param)1068 ComputeCacheTestInstance::ComputeCacheTestInstance (Context& context,
1069 const CacheTestParam* param)
1070 : CacheTestInstance (context, param)
1071 {
1072 buildBuffers();
1073
1074 buildDescriptorSets(PIPELINE_CACHE_NDX_NO_CACHE);
1075
1076 buildDescriptorSets(PIPELINE_CACHE_NDX_CACHED);
1077
1078 buildShader();
1079
1080 buildPipeline(PIPELINE_CACHE_NDX_NO_CACHE);
1081
1082 buildPipeline(PIPELINE_CACHE_NDX_CACHED);
1083 }
1084
~ComputeCacheTestInstance(void)1085 ComputeCacheTestInstance::~ComputeCacheTestInstance (void)
1086 {
1087 }
1088
prepareCommandBuffer(void)1089 void ComputeCacheTestInstance::prepareCommandBuffer (void)
1090 {
1091 const DeviceInterface& vk = m_context.getDeviceInterface();
1092
1093 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1094
1095 for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
1096 {
1097 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline[ndx]);
1098 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout[ndx], 0u, 1u, &m_descriptorSet[ndx].get(), 0u, DE_NULL);
1099 vk.cmdDispatch(*m_cmdBuffer, 128u, 1u, 1u);
1100 }
1101
1102 endCommandBuffer(vk, *m_cmdBuffer);
1103 }
1104
verifyTestResult(void)1105 tcu::TestStatus ComputeCacheTestInstance::verifyTestResult (void)
1106 {
1107 const DeviceInterface& vk = m_context.getDeviceInterface();
1108 const VkDevice vkDevice = m_context.getDevice();
1109
1110 // Read the content of output buffers
1111 invalidateAlloc(vk, vkDevice, *m_outputBufferAlloc[PIPELINE_CACHE_NDX_NO_CACHE]);
1112
1113 invalidateAlloc(vk, vkDevice, *m_outputBufferAlloc[PIPELINE_CACHE_NDX_CACHED]);
1114 // Compare the content
1115 deUint8* bufNoCache = reinterpret_cast<deUint8*>(m_outputBufferAlloc[PIPELINE_CACHE_NDX_NO_CACHE]->getHostPtr());
1116 deUint8* bufCached = reinterpret_cast<deUint8*>(m_outputBufferAlloc[PIPELINE_CACHE_NDX_CACHED]->getHostPtr());
1117 for (deUint32 ndx = 0u; ndx < sizeof(tcu::Vec4) * 128u; ndx++)
1118 {
1119 if (bufNoCache[ndx] != bufCached[ndx])
1120 {
1121 return tcu::TestStatus::fail("Output buffers w/o cached pipeline mismatch.");
1122 }
1123 }
1124
1125 return tcu::TestStatus::pass("Output buffers w/o cached pipeline match.");
1126 }
1127
1128 class PipelineFromCacheTest : public GraphicsCacheTest
1129 {
1130 public:
1131 PipelineFromCacheTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param);
~PipelineFromCacheTest(void)1132 virtual ~PipelineFromCacheTest (void) { }
1133 virtual TestInstance* createInstance (Context& context) const;
1134 };
1135
PipelineFromCacheTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param)1136 PipelineFromCacheTest::PipelineFromCacheTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param)
1137 : GraphicsCacheTest(testContext, name, description, param)
1138 {
1139 }
1140
1141 class PipelineFromCacheTestInstance : public GraphicsCacheTestInstance
1142 {
1143 public:
1144 PipelineFromCacheTestInstance (Context& context, const CacheTestParam* param);
1145 virtual ~PipelineFromCacheTestInstance (void);
1146
1147 protected:
1148 void preparePipelines(void);
1149
1150 protected:
1151 Move<VkPipelineCache> m_newCache;
1152 deUint8* m_data;
1153 };
1154
createInstance(Context & context) const1155 TestInstance* PipelineFromCacheTest::createInstance (Context& context) const
1156 {
1157 return new PipelineFromCacheTestInstance(context, &m_param);
1158 }
1159
PipelineFromCacheTestInstance(Context & context,const CacheTestParam * param)1160 PipelineFromCacheTestInstance::PipelineFromCacheTestInstance (Context& context, const CacheTestParam* param)
1161 : GraphicsCacheTestInstance (context, param)
1162 , m_data (DE_NULL)
1163 {
1164 const DeviceInterface& vk = m_context.getDeviceInterface();
1165 const VkDevice vkDevice = m_context.getDevice();
1166
1167 // Create more pipeline caches
1168 {
1169 size_t dataSize = 0u;
1170
1171 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1172
1173 m_data = new deUint8[dataSize];
1174 DE_ASSERT(m_data);
1175 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data));
1176
1177 const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
1178 {
1179 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
1180 DE_NULL, // const void* pNext;
1181 0u, // VkPipelineCacheCreateFlags flags;
1182 dataSize, // deUintptr initialDataSize;
1183 m_data, // const void* pInitialData;
1184 };
1185 m_newCache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
1186 }
1187 }
1188
~PipelineFromCacheTestInstance(void)1189 PipelineFromCacheTestInstance::~PipelineFromCacheTestInstance (void)
1190 {
1191 delete[] m_data;
1192 }
1193
preparePipelines(void)1194 void PipelineFromCacheTestInstance::preparePipelines (void)
1195 {
1196 preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], *m_cache);
1197 preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_CACHED], *m_newCache);
1198 }
1199
1200 class PipelineFromIncompleteCacheTest : public GraphicsCacheTest
1201 {
1202 public:
1203 PipelineFromIncompleteCacheTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param);
~PipelineFromIncompleteCacheTest(void)1204 virtual ~PipelineFromIncompleteCacheTest (void) {}
1205 virtual TestInstance* createInstance (Context& context) const;
1206 };
1207
PipelineFromIncompleteCacheTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param)1208 PipelineFromIncompleteCacheTest::PipelineFromIncompleteCacheTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param)
1209 : GraphicsCacheTest(testContext, name, description, param)
1210 {
1211 }
1212
1213 class PipelineFromIncompleteCacheTestInstance : public GraphicsCacheTestInstance
1214 {
1215 public:
1216 PipelineFromIncompleteCacheTestInstance(Context& context, const CacheTestParam* param);
1217 virtual ~PipelineFromIncompleteCacheTestInstance(void);
1218 protected:
1219 void preparePipelines(void);
1220 protected:
1221 Move<VkPipelineCache> m_newCache;
1222 deUint8* m_data;
1223 };
1224
createInstance(Context & context) const1225 TestInstance* PipelineFromIncompleteCacheTest::createInstance (Context& context) const
1226 {
1227 return new PipelineFromIncompleteCacheTestInstance(context, &m_param);
1228 }
1229
PipelineFromIncompleteCacheTestInstance(Context & context,const CacheTestParam * param)1230 PipelineFromIncompleteCacheTestInstance::PipelineFromIncompleteCacheTestInstance (Context& context, const CacheTestParam* param)
1231 : GraphicsCacheTestInstance (context, param)
1232 , m_data (DE_NULL)
1233 {
1234 const DeviceInterface& vk = m_context.getDeviceInterface();
1235 const VkDevice vkDevice = m_context.getDevice();
1236
1237 // Create more pipeline caches
1238 {
1239 size_t dataSize = 0u;
1240 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1241
1242 if (dataSize == 0)
1243 TCU_THROW(NotSupportedError, "Empty pipeline cache - unable to test");
1244
1245 dataSize--;
1246
1247 m_data = new deUint8[dataSize];
1248 DE_ASSERT(m_data);
1249 if (vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data) != VK_INCOMPLETE)
1250 TCU_THROW(TestError, "GetPipelineCacheData should return VK_INCOMPLETE state!");
1251
1252 const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
1253 {
1254 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
1255 DE_NULL, // const void* pNext;
1256 0u, // VkPipelineCacheCreateFlags flags;
1257 dataSize, // deUintptr initialDataSize;
1258 m_data, // const void* pInitialData;
1259 };
1260 m_newCache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
1261 }
1262 }
1263
~PipelineFromIncompleteCacheTestInstance(void)1264 PipelineFromIncompleteCacheTestInstance::~PipelineFromIncompleteCacheTestInstance (void)
1265 {
1266 delete[] m_data;
1267 }
1268
preparePipelines(void)1269 void PipelineFromIncompleteCacheTestInstance::preparePipelines (void)
1270 {
1271 preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], *m_cache);
1272 preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_CACHED], *m_newCache);
1273 }
1274
1275 enum MergeCacheType
1276 {
1277 MERGE_CACHE_EMPTY = 0,
1278 MERGE_CACHE_FROM_DATA,
1279 MERGE_CACHE_HIT,
1280 MERGE_CACHE_MISS,
1281 MERGE_CACHE_MISS_AND_HIT,
1282 MERGE_CACHE_MERGED,
1283
1284 MERGE_CACHE_TYPE_LAST = MERGE_CACHE_MERGED
1285 };
1286
getMergeCacheTypeStr(MergeCacheType type)1287 std::string getMergeCacheTypeStr (MergeCacheType type)
1288 {
1289 switch (type)
1290 {
1291 case MERGE_CACHE_EMPTY:
1292 return "empty";
1293 case MERGE_CACHE_FROM_DATA:
1294 return "from_data";
1295 case MERGE_CACHE_HIT:
1296 return "hit";
1297 case MERGE_CACHE_MISS_AND_HIT:
1298 return "misshit";
1299 case MERGE_CACHE_MISS:
1300 return "miss";
1301 case MERGE_CACHE_MERGED:
1302 return "merged";
1303 }
1304 TCU_FAIL("unhandled merge cache type");
1305 }
1306
getMergeCacheTypesStr(const std::vector<MergeCacheType> & types)1307 std::string getMergeCacheTypesStr (const std::vector<MergeCacheType>& types)
1308 {
1309 std::string ret;
1310 for (size_t idx = 0; idx < types.size(); ++idx)
1311 {
1312 if (ret.size())
1313 ret += '_';
1314 ret += getMergeCacheTypeStr(types[idx]);
1315 }
1316 return ret;
1317 }
1318
1319
1320 class MergeCacheTestParam
1321 {
1322 public:
1323 MergeCacheType destCacheType;
1324 std::vector<MergeCacheType> srcCacheTypes;
1325 };
1326
1327 class MergeCacheTest : public GraphicsCacheTest
1328 {
1329 public:
MergeCacheTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param,const MergeCacheTestParam * mergeCacheParam)1330 MergeCacheTest (tcu::TestContext& testContext,
1331 const std::string& name,
1332 const std::string& description,
1333 const CacheTestParam* param,
1334 const MergeCacheTestParam* mergeCacheParam)
1335 : GraphicsCacheTest (testContext, name, description, param)
1336 , m_mergeCacheParam (*mergeCacheParam)
1337 { }
~MergeCacheTest(void)1338 virtual ~MergeCacheTest (void) { }
1339 virtual TestInstance* createInstance (Context& context) const;
1340 private:
1341 const MergeCacheTestParam m_mergeCacheParam;
1342 };
1343
1344 class MergeCacheTestInstance : public GraphicsCacheTestInstance
1345 {
1346 public:
1347 MergeCacheTestInstance (Context& context,
1348 const CacheTestParam* param,
1349 const MergeCacheTestParam* mergeCacheParam);
1350 private:
1351 Move<VkPipelineCache> createPipelineCache (const DeviceInterface& vk, VkDevice device, MergeCacheType type);
1352
1353 protected:
1354 void preparePipelines (void);
1355
1356 protected:
1357 Move<VkPipelineCache> m_cacheMerged;
1358 };
1359
createInstance(Context & context) const1360 TestInstance* MergeCacheTest::createInstance (Context& context) const
1361 {
1362 return new MergeCacheTestInstance(context, &m_param, &m_mergeCacheParam);
1363 }
1364
MergeCacheTestInstance(Context & context,const CacheTestParam * param,const MergeCacheTestParam * mergeCacheParam)1365 MergeCacheTestInstance::MergeCacheTestInstance (Context& context, const CacheTestParam* param, const MergeCacheTestParam* mergeCacheParam)
1366 : GraphicsCacheTestInstance (context, param)
1367 {
1368 const DeviceInterface& vk = m_context.getDeviceInterface();
1369 const VkDevice vkDevice = m_context.getDevice();
1370
1371 // Create a merge destination cache
1372 m_cacheMerged = createPipelineCache(vk, vkDevice, mergeCacheParam->destCacheType);
1373
1374 // Create more pipeline caches
1375 std::vector<VkPipelineCache> sourceCaches (mergeCacheParam->srcCacheTypes.size());
1376 typedef de::SharedPtr<Move<VkPipelineCache> > PipelineCachePtr;
1377 std::vector<PipelineCachePtr> sourceCachePtrs (sourceCaches.size());
1378 {
1379 for (size_t sourceIdx = 0; sourceIdx < mergeCacheParam->srcCacheTypes.size(); sourceIdx++)
1380 {
1381 // vk::Move is not copyable, so create it on heap and wrap into de::SharedPtr
1382 PipelineCachePtr pipelineCachePtr (new Move<VkPipelineCache>());
1383 *pipelineCachePtr = createPipelineCache(vk, vkDevice, mergeCacheParam->srcCacheTypes[sourceIdx]);
1384
1385 sourceCachePtrs[sourceIdx] = pipelineCachePtr;
1386 sourceCaches[sourceIdx] = **pipelineCachePtr;
1387 }
1388 }
1389
1390 // Merge the caches
1391 VK_CHECK(vk.mergePipelineCaches(vkDevice, *m_cacheMerged, static_cast<deUint32>(sourceCaches.size()), &sourceCaches[0]));
1392 }
1393
createPipelineCache(const DeviceInterface & vk,VkDevice device,MergeCacheType type)1394 Move<VkPipelineCache> MergeCacheTestInstance::createPipelineCache (const DeviceInterface& vk, VkDevice device, MergeCacheType type)
1395 {
1396 VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
1397 {
1398 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
1399 DE_NULL, // const void* pNext;
1400 0u, // VkPipelineCacheCreateFlags flags;
1401 0u, // deUintptr initialDataSize;
1402 DE_NULL, // const void* pInitialData;
1403 };
1404
1405 GraphicsPipelineWrapper localPipeline (vk, device, m_param->getPipelineConstructionType());
1406 GraphicsPipelineWrapper localMissPipeline (vk, device, m_param->getPipelineConstructionType());
1407
1408 switch (type)
1409 {
1410 case MERGE_CACHE_EMPTY:
1411 {
1412 return vk::createPipelineCache(vk, device, &pipelineCacheCreateInfo);
1413 }
1414 case MERGE_CACHE_FROM_DATA:
1415 {
1416 // Create a cache with init data from m_cache
1417 size_t dataSize = 0u;
1418 VK_CHECK(vk.getPipelineCacheData(device, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1419
1420 std::vector<deUint8> data(dataSize);
1421 VK_CHECK(vk.getPipelineCacheData(device, *m_cache, (deUintptr*)&dataSize, &data[0]));
1422
1423 pipelineCacheCreateInfo.initialDataSize = data.size();
1424 pipelineCacheCreateInfo.pInitialData = &data[0];
1425 return vk::createPipelineCache(vk, device, &pipelineCacheCreateInfo);
1426 }
1427 case MERGE_CACHE_HIT:
1428 {
1429 Move<VkPipelineCache> ret = createPipelineCache(vk, device, MERGE_CACHE_EMPTY);
1430
1431 preparePipelineWrapper(localPipeline, *ret);
1432
1433 return ret;
1434 }
1435 case MERGE_CACHE_MISS:
1436 {
1437 Move<VkPipelineCache> ret = createPipelineCache(vk, device, MERGE_CACHE_EMPTY);
1438
1439 preparePipelineWrapper(localMissPipeline, *ret, true);
1440
1441 return ret;
1442 }
1443 case MERGE_CACHE_MISS_AND_HIT:
1444 {
1445 Move<VkPipelineCache> ret = createPipelineCache(vk, device, MERGE_CACHE_EMPTY);
1446
1447 preparePipelineWrapper(localPipeline, *ret);
1448 preparePipelineWrapper(localMissPipeline, *ret, true);
1449
1450 return ret;
1451 }
1452 case MERGE_CACHE_MERGED:
1453 {
1454 Move<VkPipelineCache> cache1 = createPipelineCache(vk, device, MERGE_CACHE_FROM_DATA);
1455 Move<VkPipelineCache> cache2 = createPipelineCache(vk, device, MERGE_CACHE_HIT);
1456 Move<VkPipelineCache> cache3 = createPipelineCache(vk, device, MERGE_CACHE_MISS);
1457
1458 const VkPipelineCache sourceCaches[] =
1459 {
1460 *cache1,
1461 *cache2,
1462 *cache3
1463 };
1464
1465 Move<VkPipelineCache> ret = createPipelineCache(vk, device, MERGE_CACHE_EMPTY);
1466
1467 // Merge the caches
1468 VK_CHECK(vk.mergePipelineCaches(device, *ret, DE_LENGTH_OF_ARRAY(sourceCaches), sourceCaches));
1469
1470 return ret;
1471 }
1472 }
1473 TCU_FAIL("unhandled merge cache type");
1474 }
1475
preparePipelines(void)1476 void MergeCacheTestInstance::preparePipelines(void)
1477 {
1478 preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], *m_cache);
1479
1480 // Create pipeline from merged cache
1481 preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_CACHED], *m_cacheMerged);
1482 }
1483
1484 class CacheHeaderTest : public GraphicsCacheTest
1485 {
1486 public:
CacheHeaderTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param)1487 CacheHeaderTest (tcu::TestContext& testContext,
1488 const std::string& name,
1489 const std::string& description,
1490 const CacheTestParam* param)
1491 : GraphicsCacheTest(testContext, name, description, param)
1492 { }
~CacheHeaderTest(void)1493 virtual ~CacheHeaderTest (void) { }
1494 virtual TestInstance* createInstance(Context& context) const;
1495 };
1496
1497 class CacheHeaderTestInstance : public GraphicsCacheTestInstance
1498 {
1499 public:
1500 CacheHeaderTestInstance (Context& context, const CacheTestParam* param);
1501 virtual ~CacheHeaderTestInstance (void);
1502 protected:
1503 deUint8* m_data;
1504
1505 struct CacheHeader
1506 {
1507 deUint32 HeaderLength;
1508 deUint32 HeaderVersion;
1509 deUint32 VendorID;
1510 deUint32 DeviceID;
1511 deUint8 PipelineCacheUUID[VK_UUID_SIZE];
1512 } m_header;
1513 };
1514
createInstance(Context & context) const1515 TestInstance* CacheHeaderTest::createInstance (Context& context) const
1516 {
1517 return new CacheHeaderTestInstance(context, &m_param);
1518 }
1519
CacheHeaderTestInstance(Context & context,const CacheTestParam * param)1520 CacheHeaderTestInstance::CacheHeaderTestInstance (Context& context, const CacheTestParam* param)
1521 : GraphicsCacheTestInstance (context, param)
1522 , m_data (DE_NULL)
1523 {
1524 const DeviceInterface& vk = m_context.getDeviceInterface();
1525 const VkDevice vkDevice = m_context.getDevice();
1526
1527 // Create more pipeline caches
1528 {
1529 // Create a cache with init data from m_cache
1530 size_t dataSize = 0u;
1531 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1532
1533 if (dataSize < sizeof(m_header))
1534 TCU_THROW(TestError, "Pipeline cache size is smaller than header size");
1535
1536 m_data = new deUint8[dataSize];
1537 DE_ASSERT(m_data);
1538 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data));
1539
1540 deMemcpy(&m_header, m_data, sizeof(m_header));
1541
1542 if (m_header.HeaderLength - VK_UUID_SIZE != 16)
1543 TCU_THROW(TestError, "Invalid header size!");
1544
1545 if (m_header.HeaderVersion != 1)
1546 TCU_THROW(TestError, "Invalid header version!");
1547
1548 if (m_header.VendorID != m_context.getDeviceProperties().vendorID)
1549 TCU_THROW(TestError, "Invalid header vendor ID!");
1550
1551 if (m_header.DeviceID != m_context.getDeviceProperties().deviceID)
1552 TCU_THROW(TestError, "Invalid header device ID!");
1553
1554 if (deMemCmp(&m_header.PipelineCacheUUID, &m_context.getDeviceProperties().pipelineCacheUUID, VK_UUID_SIZE) != 0)
1555 TCU_THROW(TestError, "Invalid header pipeline cache UUID!");
1556 }
1557 }
1558
~CacheHeaderTestInstance(void)1559 CacheHeaderTestInstance::~CacheHeaderTestInstance (void)
1560 {
1561 delete[] m_data;
1562 }
1563
1564 class InvalidSizeTest : public GraphicsCacheTest
1565 {
1566 public:
1567 InvalidSizeTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param);
~InvalidSizeTest(void)1568 virtual ~InvalidSizeTest (void) {}
1569 virtual TestInstance* createInstance (Context& context) const;
1570 };
1571
InvalidSizeTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param)1572 InvalidSizeTest::InvalidSizeTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param)
1573 : GraphicsCacheTest(testContext, name, description, param)
1574 {
1575 }
1576
1577 class InvalidSizeTestInstance : public GraphicsCacheTestInstance
1578 {
1579 public:
1580 InvalidSizeTestInstance (Context& context, const CacheTestParam* param);
1581 virtual ~InvalidSizeTestInstance (void);
1582 protected:
1583 deUint8* m_data;
1584 deUint8* m_zeroBlock;
1585 };
1586
createInstance(Context & context) const1587 TestInstance* InvalidSizeTest::createInstance (Context& context) const
1588 {
1589 return new InvalidSizeTestInstance(context, &m_param);
1590 }
1591
InvalidSizeTestInstance(Context & context,const CacheTestParam * param)1592 InvalidSizeTestInstance::InvalidSizeTestInstance (Context& context, const CacheTestParam* param)
1593 : GraphicsCacheTestInstance (context, param)
1594 , m_data (DE_NULL)
1595 , m_zeroBlock (DE_NULL)
1596 {
1597 const DeviceInterface& vk = m_context.getDeviceInterface();
1598 const VkDevice vkDevice = m_context.getDevice();
1599
1600 // Create more pipeline caches
1601 try
1602 {
1603 // Create a cache with init data from m_cache
1604 size_t dataSize = 0u;
1605 size_t savedDataSize = 0u;
1606 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1607 savedDataSize = dataSize;
1608
1609 // If the value of dataSize is less than the maximum size that can be retrieved by the pipeline cache,
1610 // at most pDataSize bytes will be written to pData, and vkGetPipelineCacheData will return VK_INCOMPLETE.
1611 dataSize--;
1612
1613 m_data = new deUint8[savedDataSize];
1614 deMemset(m_data, 0, savedDataSize);
1615 DE_ASSERT(m_data);
1616 if (vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data) != VK_INCOMPLETE)
1617 TCU_THROW(TestError, "GetPipelineCacheData should return VK_INCOMPLETE state!");
1618
1619 delete[] m_data;
1620 m_data = DE_NULL;
1621
1622 // If the value of dataSize is less than what is necessary to store the header,
1623 // nothing will be written to pData and zero will be written to dataSize.
1624 dataSize = 16 + VK_UUID_SIZE - 1;
1625
1626 m_data = new deUint8[savedDataSize];
1627 deMemset(m_data, 0, savedDataSize);
1628 DE_ASSERT(m_data);
1629 if (vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data) != VK_INCOMPLETE)
1630 TCU_THROW(TestError, "GetPipelineCacheData should return VK_INCOMPLETE state!");
1631
1632 m_zeroBlock = new deUint8[savedDataSize];
1633 deMemset(m_zeroBlock, 0, savedDataSize);
1634 if (deMemCmp(m_data, m_zeroBlock, savedDataSize) != 0 || dataSize != 0)
1635 TCU_THROW(TestError, "Data needs to be empty and data size should be 0 when invalid size is passed to GetPipelineCacheData!");
1636 }
1637 catch (...)
1638 {
1639 delete[] m_data;
1640 delete[] m_zeroBlock;
1641 throw;
1642 }
1643 }
1644
~InvalidSizeTestInstance(void)1645 InvalidSizeTestInstance::~InvalidSizeTestInstance (void)
1646 {
1647 delete[] m_data;
1648 delete[] m_zeroBlock;
1649 }
1650
1651 class ZeroSizeTest : public GraphicsCacheTest
1652 {
1653 public:
1654 ZeroSizeTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param);
~ZeroSizeTest(void)1655 virtual ~ZeroSizeTest (void) {}
1656 virtual TestInstance* createInstance (Context& context) const;
1657 };
1658
ZeroSizeTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param)1659 ZeroSizeTest::ZeroSizeTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param)
1660 : GraphicsCacheTest(testContext, name, description, param)
1661 {
1662 }
1663
1664 class ZeroSizeTestInstance : public GraphicsCacheTestInstance
1665 {
1666 public:
1667 ZeroSizeTestInstance (Context& context, const CacheTestParam* param);
1668 virtual ~ZeroSizeTestInstance (void);
1669 protected:
1670 deUint8* m_data;
1671 deUint8* m_zeroBlock;
1672 };
1673
createInstance(Context & context) const1674 TestInstance* ZeroSizeTest::createInstance (Context& context) const
1675 {
1676 return new ZeroSizeTestInstance(context, &m_param);
1677 }
1678
ZeroSizeTestInstance(Context & context,const CacheTestParam * param)1679 ZeroSizeTestInstance::ZeroSizeTestInstance (Context& context, const CacheTestParam* param)
1680 : GraphicsCacheTestInstance (context, param)
1681 , m_data (DE_NULL)
1682 , m_zeroBlock (DE_NULL)
1683 {
1684 const DeviceInterface& vk = m_context.getDeviceInterface();
1685 const VkDevice vkDevice = m_context.getDevice();
1686
1687 // Create more pipeline caches
1688 try
1689 {
1690 // Create a cache with init data from m_cache
1691 size_t dataSize = 0u;
1692
1693 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1694
1695 m_data = new deUint8[dataSize];
1696 deMemset(m_data, 0, dataSize);
1697 DE_ASSERT(m_data);
1698
1699 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data));
1700
1701 {
1702 // Create a cache with initialDataSize = 0 & pInitialData != NULL
1703 const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
1704 {
1705 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
1706 DE_NULL, // const void* pNext;
1707 0u, // VkPipelineCacheCreateFlags flags;
1708 0u, // deUintptr initialDataSize;
1709 m_data, // const void* pInitialData;
1710 };
1711
1712 const Unique<VkPipelineCache> pipelineCache (createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo));
1713 }
1714 }
1715 catch (...)
1716 {
1717 delete[] m_data;
1718 delete[] m_zeroBlock;
1719 throw;
1720 }
1721 }
1722
~ZeroSizeTestInstance(void)1723 ZeroSizeTestInstance::~ZeroSizeTestInstance (void)
1724 {
1725 delete[] m_data;
1726 delete[] m_zeroBlock;
1727 }
1728
1729 class InvalidBlobTest : public GraphicsCacheTest
1730 {
1731 public:
1732 InvalidBlobTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param);
~InvalidBlobTest(void)1733 virtual ~InvalidBlobTest (void) {}
1734 virtual TestInstance* createInstance (Context& context) const;
1735 };
1736
InvalidBlobTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param)1737 InvalidBlobTest::InvalidBlobTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param)
1738 : GraphicsCacheTest(testContext, name, description, param)
1739 {
1740 }
1741
1742 class InvalidBlobTestInstance : public GraphicsCacheTestInstance
1743 {
1744 public:
1745 InvalidBlobTestInstance (Context& context, const CacheTestParam* param);
1746 virtual ~InvalidBlobTestInstance (void);
1747 protected:
1748 deUint8* m_data;
1749 deUint8* m_zeroBlock;
1750 };
1751
createInstance(Context & context) const1752 TestInstance* InvalidBlobTest::createInstance (Context& context) const
1753 {
1754 return new InvalidBlobTestInstance(context, &m_param);
1755 }
1756
InvalidBlobTestInstance(Context & context,const CacheTestParam * param)1757 InvalidBlobTestInstance::InvalidBlobTestInstance (Context& context, const CacheTestParam* param)
1758 : GraphicsCacheTestInstance (context, param)
1759 , m_data (DE_NULL)
1760 , m_zeroBlock (DE_NULL)
1761 {
1762 const DeviceInterface& vk = m_context.getDeviceInterface();
1763 const VkDevice vkDevice = m_context.getDevice();
1764
1765 // Create more pipeline caches
1766 try
1767 {
1768 // Create a cache with init data from m_cache
1769 size_t dataSize = 0u;
1770
1771 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1772
1773 m_data = new deUint8[dataSize];
1774 deMemset(m_data, 0, dataSize);
1775 DE_ASSERT(m_data);
1776
1777 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data));
1778
1779 const struct
1780 {
1781 deUint32 offset;
1782 std::string name;
1783 } headerLayout[] =
1784 {
1785 { 4u, "pipeline cache header version" },
1786 { 8u, "vendor ID" },
1787 { 12u, "device ID" },
1788 { 16u, "pipeline cache ID" }
1789 };
1790
1791 for (deUint32 i = 0u; i < DE_LENGTH_OF_ARRAY(headerLayout); i++)
1792 {
1793 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Creating pipeline cache using previously retrieved data with invalid " << headerLayout[i].name << tcu::TestLog::EndMessage;
1794
1795 m_data[headerLayout[i].offset] = (deUint8)(m_data[headerLayout[i].offset] + 13u); // Add arbitrary number to create an invalid value
1796
1797 const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
1798 {
1799 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
1800 DE_NULL, // const void* pNext;
1801 0u, // VkPipelineCacheCreateFlags flags;
1802 dataSize, // deUintptr initialDataSize;
1803 m_data, // const void* pInitialData;
1804 };
1805
1806 const Unique<VkPipelineCache> pipelineCache (createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo));
1807
1808 m_data[headerLayout[i].offset] = (deUint8)(m_data[headerLayout[i].offset] - 13u); // Return to original value
1809 }
1810 }
1811 catch (...)
1812 {
1813 delete[] m_data;
1814 delete[] m_zeroBlock;
1815 throw;
1816 }
1817 }
1818
~InvalidBlobTestInstance(void)1819 InvalidBlobTestInstance::~InvalidBlobTestInstance (void)
1820 {
1821 delete[] m_data;
1822 delete[] m_zeroBlock;
1823 }
1824 } // anonymous
1825
createCacheTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)1826 tcu::TestCaseGroup* createCacheTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
1827 {
1828 de::MovePtr<tcu::TestCaseGroup> cacheTests (new tcu::TestCaseGroup(testCtx, "cache", "pipeline cache tests"));
1829
1830 const VkShaderStageFlags vertFragStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
1831 const VkShaderStageFlags vertGeomFragStages = vertFragStages | VK_SHADER_STAGE_GEOMETRY_BIT;
1832 const VkShaderStageFlags vertTesFragStages = vertFragStages | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
1833
1834 // Graphics Pipeline Tests
1835 {
1836 de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics_tests", "Test pipeline cache with graphics pipeline."));
1837
1838 const CacheTestParam testParams[] =
1839 {
1840 CacheTestParam(pipelineConstructionType, vertFragStages, false),
1841 CacheTestParam(pipelineConstructionType, vertGeomFragStages, false),
1842 CacheTestParam(pipelineConstructionType, vertTesFragStages, false),
1843 CacheTestParam(pipelineConstructionType, vertFragStages, false, VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT),
1844 CacheTestParam(pipelineConstructionType, vertGeomFragStages, false, VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT),
1845 CacheTestParam(pipelineConstructionType, vertTesFragStages, false, VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT),
1846 };
1847
1848 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1849 graphicsTests->addChild(newTestCase<GraphicsCacheTest>(testCtx, &testParams[i]));
1850
1851 cacheTests->addChild(graphicsTests.release());
1852 }
1853
1854 // Graphics Pipeline Tests
1855 {
1856 de::MovePtr<tcu::TestCaseGroup> graphicsTests(new tcu::TestCaseGroup(testCtx, "pipeline_from_get_data", "Test pipeline cache with graphics pipeline."));
1857
1858 const CacheTestParam testParams[] =
1859 {
1860 CacheTestParam(pipelineConstructionType, vertFragStages, false),
1861 CacheTestParam(pipelineConstructionType, vertGeomFragStages, false),
1862 CacheTestParam(pipelineConstructionType, vertTesFragStages, false),
1863 };
1864
1865 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1866 graphicsTests->addChild(newTestCase<PipelineFromCacheTest>(testCtx, &testParams[i]));
1867
1868 cacheTests->addChild(graphicsTests.release());
1869 }
1870
1871 // Graphics Pipeline Tests
1872 {
1873 de::MovePtr<tcu::TestCaseGroup> graphicsTests(new tcu::TestCaseGroup(testCtx, "pipeline_from_incomplete_get_data", "Test pipeline cache with graphics pipeline."));
1874
1875 const CacheTestParam testParams[] =
1876 {
1877 CacheTestParam(pipelineConstructionType, vertFragStages, false),
1878 CacheTestParam(pipelineConstructionType, vertGeomFragStages, false),
1879 CacheTestParam(pipelineConstructionType, vertTesFragStages, false),
1880 };
1881
1882 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1883 graphicsTests->addChild(newTestCase<PipelineFromIncompleteCacheTest>(testCtx, &testParams[i]));
1884
1885 cacheTests->addChild(graphicsTests.release());
1886 }
1887
1888 // Compute Pipeline Tests - don't repeat those tests for graphics pipeline library
1889 if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1890 {
1891 de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute_tests", "Test pipeline cache with compute pipeline."));
1892
1893 const CacheTestParam testParams[] =
1894 {
1895 CacheTestParam(pipelineConstructionType, VK_SHADER_STAGE_COMPUTE_BIT, false),
1896 };
1897
1898 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1899 computeTests->addChild(newTestCase<ComputeCacheTest>(testCtx, &testParams[i]));
1900
1901 cacheTests->addChild(computeTests.release());
1902 }
1903
1904 // Merge cache Tests
1905 {
1906 de::MovePtr<tcu::TestCaseGroup> mergeTests (new tcu::TestCaseGroup(testCtx, "merge", "Cache merging tests"));
1907
1908 const CacheTestParam testParams[] =
1909 {
1910 CacheTestParam(pipelineConstructionType, vertFragStages, true),
1911 CacheTestParam(pipelineConstructionType, vertGeomFragStages, true),
1912 CacheTestParam(pipelineConstructionType, vertTesFragStages, true),
1913 };
1914
1915 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1916 {
1917
1918 de::MovePtr<tcu::TestCaseGroup> mergeStagesTests(new tcu::TestCaseGroup(testCtx, testParams[i].generateTestName().c_str(), testParams[i].generateTestDescription().c_str()));
1919
1920 for (deUint32 destTypeIdx = 0u; destTypeIdx <= MERGE_CACHE_TYPE_LAST; destTypeIdx++)
1921 for (deUint32 srcType1Idx = 0u; srcType1Idx <= MERGE_CACHE_TYPE_LAST; srcType1Idx++)
1922 {
1923
1924 MergeCacheTestParam cacheTestParam;
1925 cacheTestParam.destCacheType = MergeCacheType(destTypeIdx);
1926 cacheTestParam.srcCacheTypes.push_back(MergeCacheType(srcType1Idx));
1927
1928 // merge with one cache
1929 {
1930 std::string testName = "src_" + getMergeCacheTypesStr(cacheTestParam.srcCacheTypes) + "_dst_" + getMergeCacheTypeStr(cacheTestParam.destCacheType);
1931 mergeStagesTests->addChild(new MergeCacheTest(testCtx,
1932 testName.c_str(),
1933 "Merge the caches test.",
1934 &testParams[i],
1935 &cacheTestParam));
1936 }
1937
1938 // merge with two caches
1939 for (deUint32 srcType2Idx = 0u; srcType2Idx <= MERGE_CACHE_TYPE_LAST; srcType2Idx++)
1940 {
1941 MergeCacheTestParam cacheTestParamTwoCaches = cacheTestParam;
1942
1943 cacheTestParamTwoCaches.srcCacheTypes.push_back(MergeCacheType(srcType2Idx));
1944
1945 std::string testName = "src_" + getMergeCacheTypesStr(cacheTestParamTwoCaches.srcCacheTypes) + "_dst_" + getMergeCacheTypeStr(cacheTestParamTwoCaches.destCacheType);
1946 mergeStagesTests->addChild(new MergeCacheTest(testCtx,
1947 testName.c_str(),
1948 "Merge the caches test.",
1949 &testParams[i],
1950 &cacheTestParamTwoCaches));
1951 }
1952 }
1953 mergeTests->addChild(mergeStagesTests.release());
1954 }
1955 cacheTests->addChild(mergeTests.release());
1956 }
1957
1958 // Misc Tests
1959 {
1960 de::MovePtr<tcu::TestCaseGroup> miscTests(new tcu::TestCaseGroup(testCtx, "misc_tests", "Misc tests that can not be categorized to other group."));
1961
1962 const CacheTestParam testParam(pipelineConstructionType, vertFragStages, false);
1963
1964 miscTests->addChild(new CacheHeaderTest(testCtx,
1965 "cache_header_test",
1966 "Cache header test.",
1967 &testParam));
1968
1969 miscTests->addChild(new InvalidSizeTest(testCtx,
1970 "invalid_size_test",
1971 "Invalid size test.",
1972 &testParam));
1973
1974 miscTests->addChild(new ZeroSizeTest(testCtx,
1975 "zero_size_test",
1976 "Zero size test.",
1977 &testParam));
1978
1979 miscTests->addChild(new InvalidBlobTest(testCtx,
1980 "invalid_blob_test",
1981 "Invalid cache blob test.",
1982 &testParam));
1983
1984 cacheTests->addChild(miscTests.release());
1985 }
1986
1987 return cacheTests.release();
1988 }
1989
1990 } // pipeline
1991
1992 } // vkt
1993