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