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