Skip to content

Commit 4428ab3

Browse files
Add options to save and load pipeline caches (#1276)
* Add options to save and load pipeline caches Add three options `--save-pipeline-cache`, `--load-pipeline-cache` and `--add-new-pipeline-caches` to manually handle pipeline cache creation/loading instead of using the ones saved in the capture file. This is useful when pipeline creation is slow on the target system. You can generate the cache once then run the trace multiple times, or generate it on a faster device type with the same GPU and driver. When using `--save-pipeline-cache` the contents of the pipeline caches are written to the specified file just before their destruction, and just before the destruction of the last bound pipeline for caches created by `--create-new-pipeline-cache`, or at the end of the program if no destruction occurs before. When using `--load-pipeline-cache` the contents of the pipeline caches are loaded just before their creation, and just before the creation of the pipeline for caches created by `--create-new-pipeline-cache`. If set, allows gfxreconstruct to create new vkPipelineCache objects when it encounters a pipeline created without cache. This option can be used in coordination with `--save-pipeline-cache` and `--load-pipeline-cache`. Change-Id: I40667416efe4c88033c386f6ec5fd53a86dd58ca * Warn when using both async pipeline-creation and pipeline-cache features * Consolidate duplicated OverrideDestroyPipeline-flavors into one * work review comments * Respect options_.omit_pipeline_cache_data and do not load any pipeline-data if set. --------- Co-authored-by: Fabian Schmidt <[email protected]>
1 parent ce13272 commit 4428ab3

10 files changed

+552
-112
lines changed

USAGE_android.md

+17
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,23 @@ optional arguments:
925925
Print all block information.
926926
--pbis <index1,index2>
927927
Print block information between block index1 and block index2.
928+
--save-pipeline-cache DEVICE_FILE
929+
If set, produces pipeline caches at replay time instead
930+
of using the one saved at capture time and save those
931+
caches in DEVICE_FILE.
932+
(forwarded to replay tool)
933+
--load-pipeline-cache DEVICE_FILE
934+
If set, loads data created by the
935+
`--save-pipeline-cache` option in DEVICE_FILE
936+
and uses it to create the pipelines instead of the
937+
pipeline caches saved at capture time.
938+
(forwarded to replay tool)
939+
--add-new-pipeline-caches
940+
If set, allows gfxreconstruct to create new
941+
vkPipelineCache objects when it encounters a pipeline
942+
created without cache. This option can be used in
943+
coordination with `--save-pipeline-cache` and
944+
`--load-pipeline-cache`. (forwarded to replay tool)
928945
```
929946

930947
The command will force-stop an active replay process before starting the replay

USAGE_desktop_Vulkan.md

+12
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,18 @@ Optional arguments:
800800
Specify the number of asynchronous pipeline-creation jobs as integer.
801801
If <num_jobs> is negative it will be added to the number of cpu-cores, e.g. -1 -> num_cores - 1.
802802
Default: 0 (do not use asynchronous operations)
803+
--save-pipeline-cache <cache-file>
804+
If set, produces pipeline caches at replay time instead of using
805+
the one saved at capture time and save those caches in <cache-file>.
806+
--load-pipeline-cache <cache-file>
807+
If set, loads data created by the `--save-pipeline-cache`
808+
option in <cache-file> and uses it to create the pipelines instead
809+
of the pipeline caches saved at capture time.
810+
--add-new-pipeline-caches
811+
If set, allows gfxreconstruct to create new vkPipelineCache objects
812+
when it encounters a pipeline created without cache. This option can
813+
be used in coordination with `--save-pipeline-cache` and
814+
`--load-pipeline-cache`.
803815
804816
```
805817

android/scripts/gfxrecon.py

+14
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ def CreateReplayParser():
116116
parser.add_argument('--pbi-all', action='store_true', default=False, help='Print all block information.')
117117
parser.add_argument('--pbis', metavar='RANGES', default=False, help='Print block information between block index1 and block index2')
118118
parser.add_argument('--pcj', '--pipeline-creation-jobs', action='store_true', default=False, help='Specify the number of pipeline-creation-jobs or background-threads.')
119+
parser.add_argument('--save-pipeline-cache', metavar='DEVICE_FILE', help='If set, produces pipeline caches at replay time instead of using the one saved at capture time and save those caches in DEVICE_FILE. (forwarded to replay tool)')
120+
parser.add_argument('--load-pipeline-cache', metavar='DEVICE_FILE', help='If set, loads data created by the `--save-pipeline-cache` option in DEVICE_FILE and uses it to create the pipelines instead of the pipeline caches saved at capture time. (forwarded to replay tool)')
121+
parser.add_argument('--add-new-pipeline-caches', action='store_true', default=False, help='If set, allows gfxreconstruct to create new vkPipelineCache objects when it encounters a pipeline created without cache. This option can be used in coordination with `--save-pipeline-cache` and `--load-pipeline-cache`. (forwarded to replay tool)')
119122
return parser
120123

121124
def MakeExtrasString(args):
@@ -290,6 +293,17 @@ def MakeExtrasString(args):
290293
arg_list.append('--pcj')
291294
arg_list.append('{}'.format(args.pcj))
292295

296+
if args.save_pipeline_cache:
297+
arg_list.append('--save-pipeline-cache')
298+
arg_list.append('{}'.format(args.save_pipeline_cache))
299+
300+
if args.load_pipeline_cache:
301+
arg_list.append('--load-pipeline-cache')
302+
arg_list.append('{}'.format(args.load_pipeline_cache))
303+
304+
if args.add_new_pipeline_caches:
305+
arg_list.append('--add-new-pipeline-caches')
306+
293307
if args.file:
294308
arg_list.append(args.file)
295309
elif not args.version:

framework/decode/vulkan_replay_consumer_base.cpp

+443-98
Large diffs are not rendered by default.

framework/decode/vulkan_replay_consumer_base.h

+28-1
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,11 @@ class VulkanReplayConsumerBase : public VulkanConsumer
951951
const StructPointerDecoder<Decoded_VkAllocationCallbacks>* pAllocator,
952952
HandlePointerDecoder<VkPipelineCache>* pPipelineCache);
953953

954+
void OverrideDestroyPipelineCache(PFN_vkDestroyPipelineCache func,
955+
const VulkanDeviceInfo* device_info,
956+
const VulkanPipelineCacheInfo* pipeline_cache_info,
957+
const StructPointerDecoder<Decoded_VkAllocationCallbacks>* pAllocator);
958+
954959
VkResult OverrideResetDescriptorPool(PFN_vkResetDescriptorPool func,
955960
VkResult original_result,
956961
const VulkanDeviceInfo* device_info,
@@ -1205,6 +1210,16 @@ class VulkanReplayConsumerBase : public VulkanConsumer
12051210
const VulkanDeviceInfo* device_info,
12061211
const StructPointerDecoder<Decoded_VkAccelerationStructureDeviceAddressInfoKHR>* pInfo);
12071212

1213+
VkResult OverrideCreateRayTracingPipelinesNV(
1214+
PFN_vkCreateRayTracingPipelinesNV func,
1215+
VkResult original_result,
1216+
const VulkanDeviceInfo* device_info,
1217+
const VulkanPipelineCacheInfo* pipeline_cache_info,
1218+
uint32_t createInfoCount,
1219+
const StructPointerDecoder<Decoded_VkRayTracingPipelineCreateInfoNV>* pCreateInfos,
1220+
const StructPointerDecoder<Decoded_VkAllocationCallbacks>* pAllocator,
1221+
HandlePointerDecoder<VkPipeline>* pPipelines);
1222+
12081223
VkResult OverrideGetRayTracingShaderGroupHandlesKHR(PFN_vkGetRayTracingShaderGroupHandlesKHR func,
12091224
VkResult original_result,
12101225
const VulkanDeviceInfo* device_info,
@@ -1361,7 +1376,7 @@ class VulkanReplayConsumerBase : public VulkanConsumer
13611376

13621377
void OverrideDestroyPipeline(PFN_vkDestroyPipeline func,
13631378
const VulkanDeviceInfo* device_info,
1364-
VulkanPipelineInfo* pipeline_info,
1379+
const VulkanPipelineInfo* pipeline_info,
13651380
const StructPointerDecoder<Decoded_VkAllocationCallbacks>* pAllocator);
13661381

13671382
void OverrideDestroyRenderPass(PFN_vkDestroyRenderPass func,
@@ -1547,6 +1562,15 @@ class VulkanReplayConsumerBase : public VulkanConsumer
15471562
VkShaderCreateInfoEXT* create_infos,
15481563
const format::HandleId* shaders) const;
15491564

1565+
void LoadPipelineCache(format::HandleId id, std::vector<char>& pipelineCacheData);
1566+
void SavePipelineCache(format::HandleId id, const VulkanDeviceInfo* device_info, VkPipelineCache pipelineCache);
1567+
VkPipelineCache CreateNewPipelineCache(const VulkanDeviceInfo* device_info, format::HandleId id);
1568+
void TrackNewPipelineCache(const VulkanDeviceInfo* device_info,
1569+
format::HandleId id,
1570+
VkPipelineCache pipelineCache,
1571+
VkPipeline* pipelines,
1572+
uint32_t pipelineCount);
1573+
15501574
private:
15511575
struct HardwareBufferInfo
15521576
{
@@ -1659,6 +1683,9 @@ class VulkanReplayConsumerBase : public VulkanConsumer
16591683
void* capture_pipeline_cache_data_;
16601684
bool matched_replay_cache_data_exist_ = false;
16611685
std::vector<uint8_t> matched_replay_cache_data_;
1686+
1687+
std::unordered_map<format::HandleId, std::pair<const VulkanDeviceInfo*, VkPipelineCache>> tracked_pipeline_caches_;
1688+
std::unordered_map<VkPipeline, format::HandleId> pipeline_cache_correspondances_;
16621689
};
16631690

16641691
GFXRECON_END_NAMESPACE(decode)

framework/decode/vulkan_replay_options.h

+4
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ struct VulkanReplayOptions : public ReplayOptions
9696
bool dump_resources_dump_separate_alpha{ false };
9797

9898
bool preload_measurement_range{ false };
99+
100+
std::string load_pipeline_cache_filename;
101+
std::string save_pipeline_cache_filename;
102+
bool add_new_pipeline_caches;
99103
};
100104

101105
GFXRECON_END_NAMESPACE(decode)

framework/generated/generated_vulkan_replay_consumer.cpp

+10-11
Original file line numberDiff line numberDiff line change
@@ -923,11 +923,10 @@ void VulkanReplayConsumer::Process_vkDestroyPipelineCache(
923923
format::HandleId pipelineCache,
924924
StructPointerDecoder<Decoded_VkAllocationCallbacks>* pAllocator)
925925
{
926-
VkDevice in_device = MapHandle<VulkanDeviceInfo>(device, &CommonObjectInfoTable::GetVkDeviceInfo);
927-
VkPipelineCache in_pipelineCache = MapHandle<VulkanPipelineCacheInfo>(pipelineCache, &CommonObjectInfoTable::GetVkPipelineCacheInfo);
928-
const VkAllocationCallbacks* in_pAllocator = GetAllocationCallbacks(pAllocator);
926+
auto in_device = GetObjectInfoTable().GetVkDeviceInfo(device);
927+
auto in_pipelineCache = GetObjectInfoTable().GetVkPipelineCacheInfo(pipelineCache);
929928

930-
GetDeviceTable(in_device)->DestroyPipelineCache(in_device, in_pipelineCache, in_pAllocator);
929+
OverrideDestroyPipelineCache(GetDeviceTable(in_device->handle)->DestroyPipelineCache, in_device, in_pipelineCache, pAllocator);
931930
RemoveHandle(pipelineCache, &CommonObjectInfoTable::RemoveVkPipelineCacheInfo);
932931
}
933932

@@ -7549,19 +7548,19 @@ void VulkanReplayConsumer::Process_vkCreateRayTracingPipelinesNV(
75497548
StructPointerDecoder<Decoded_VkAllocationCallbacks>* pAllocator,
75507549
HandlePointerDecoder<VkPipeline>* pPipelines)
75517550
{
7552-
VkDevice in_device = MapHandle<VulkanDeviceInfo>(device, &CommonObjectInfoTable::GetVkDeviceInfo);
7553-
VkPipelineCache in_pipelineCache = MapHandle<VulkanPipelineCacheInfo>(pipelineCache, &CommonObjectInfoTable::GetVkPipelineCacheInfo);
7554-
const VkRayTracingPipelineCreateInfoNV* in_pCreateInfos = pCreateInfos->GetPointer();
7551+
auto in_device = GetObjectInfoTable().GetVkDeviceInfo(device);
7552+
auto in_pipelineCache = GetObjectInfoTable().GetVkPipelineCacheInfo(pipelineCache);
7553+
75557554
MapStructArrayHandles(pCreateInfos->GetMetaStructPointer(), pCreateInfos->GetLength(), GetObjectInfoTable());
7556-
const VkAllocationCallbacks* in_pAllocator = GetAllocationCallbacks(pAllocator);
75577555
if (!pPipelines->IsNull()) { pPipelines->SetHandleLength(createInfoCount); }
75587556
if (omitted_pipeline_cache_data_) {AllowCompileDuringPipelineCreation(createInfoCount, pCreateInfos->GetPointer());}
7559-
VkPipeline* out_pPipelines = pPipelines->GetHandlePointer();
7557+
std::vector<VulkanPipelineInfo> handle_info(createInfoCount);
7558+
for (size_t i = 0; i < createInfoCount; ++i) { pPipelines->SetConsumerData(i, &handle_info[i]); }
75607559

7561-
VkResult replay_result = GetDeviceTable(in_device)->CreateRayTracingPipelinesNV(in_device, in_pipelineCache, createInfoCount, in_pCreateInfos, in_pAllocator, out_pPipelines);
7560+
VkResult replay_result = OverrideCreateRayTracingPipelinesNV(GetDeviceTable(in_device->handle)->CreateRayTracingPipelinesNV, returnValue, in_device, in_pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
75627561
CheckResult("vkCreateRayTracingPipelinesNV", returnValue, replay_result, call_info);
75637562

7564-
AddHandles<VulkanPipelineInfo>(device, pPipelines->GetPointer(), pPipelines->GetLength(), out_pPipelines, createInfoCount, &CommonObjectInfoTable::AddVkPipelineInfo);
7563+
AddHandles<VulkanPipelineInfo>(device, pPipelines->GetPointer(), pPipelines->GetLength(), pPipelines->GetHandlePointer(), createInfoCount, std::move(handle_info), &CommonObjectInfoTable::AddVkPipelineInfo);
75657564
}
75667565

75677566
void VulkanReplayConsumer::Process_vkGetRayTracingShaderGroupHandlesKHR(

framework/generated/khronos_generators/vulkan_generators/replay_overrides.json

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"vkCreateShaderModule": "OverrideCreateShaderModule",
5858
"vkGetPipelineCacheData": "OverrideGetPipelineCacheData",
5959
"vkCreatePipelineCache": "OverrideCreatePipelineCache",
60+
"vkDestroyPipelineCache": "OverrideDestroyPipelineCache",
6061
"vkResetDescriptorPool": "OverrideResetDescriptorPool",
6162
"vkCreateDescriptorUpdateTemplate": "OverrideCreateDescriptorUpdateTemplate",
6263
"vkCreateDescriptorUpdateTemplateKHR": "OverrideCreateDescriptorUpdateTemplate",
@@ -93,6 +94,7 @@
9394
"vkGetBufferDeviceAddressKHR": "OverrideGetBufferDeviceAddress",
9495
"vkGetBufferDeviceAddressEXT": "OverrideGetBufferDeviceAddress",
9596
"vkGetAccelerationStructureDeviceAddressKHR": "OverrideGetAccelerationStructureDeviceAddressKHR",
97+
"vkCreateRayTracingPipelinesNV": "OverrideCreateRayTracingPipelinesNV",
9698
"vkGetRayTracingShaderGroupHandlesKHR": "OverrideGetRayTracingShaderGroupHandlesKHR",
9799
"vkGetAndroidHardwareBufferPropertiesANDROID": "OverrideGetAndroidHardwareBufferPropertiesANDROID",
98100
"vkDeferredOperationJoinKHR": "OverrideDeferredOperationJoinKHR",

tools/replay/replay_settings.h

+15-2
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,16 @@ const char kOptions[] =
3636
"--dump-resources-dump-depth-attachment,--dump-"
3737
"resources-dump-vertex-index-buffers,--dump-resources-json-output-per-command,--dump-resources-dump-immutable-"
3838
"resources,--dump-resources-dump-all-image-subresources,--dump-resources-dump-raw-images,--dump-resources-dump-"
39-
"separate-alpha,--pbi-all,--preload-measurement-range";
39+
"separate-alpha,--pbi-all,--preload-measurement-range, --add-new-pipeline-caches";
4040
const char kArguments[] =
4141
"--log-level,--log-file,--gpu,--gpu-group,--pause-frame,--wsi,--surface-index,-m|--memory-translation,"
4242
"--replace-shaders,--screenshots,--denied-messages,--allowed-messages,--screenshot-format,--"
4343
"screenshot-dir,--screenshot-prefix,--screenshot-size,--screenshot-scale,--mfr|--measurement-frame-range,--fw|--"
4444
"force-windowed,--fwo|--force-windowed-origin,--batching-memory-usage,--measurement-file,--swapchain,--sgfs|--skip-"
4545
"get-fence-status,--sgfr|--"
4646
"skip-get-fence-ranges,--dump-resources,--dump-resources-scale,--dump-resources-image-format,--dump-resources-dir,"
47-
"--dump-resources-dump-color-attachment-index,--pbis,--pcj|--pipeline-creation-jobs";
47+
"--dump-resources-dump-color-attachment-index,--pbis,--pcj|--pipeline-creation-jobs,--save-pipeline-cache,--load-"
48+
"pipeline-cache";
4849

4950
static void PrintUsage(const char* exe_name)
5051
{
@@ -332,6 +333,18 @@ static void PrintUsage(const char* exe_name)
332333
GFXRECON_WRITE_CONSOLE(" \t\tIf <num_jobs> is negative it will be added to the number of cpu-cores");
333334
GFXRECON_WRITE_CONSOLE(" \t\tDefault: 0 (do not use asynchronous operations).");
334335
GFXRECON_WRITE_CONSOLE(" \t\tSame as --pcj <num_jobs>");
336+
GFXRECON_WRITE_CONSOLE(" --save-pipeline-cache <cache-file>");
337+
GFXRECON_WRITE_CONSOLE(" \t\tIf set, produces pipeline caches at replay time instead of using");
338+
GFXRECON_WRITE_CONSOLE(" \t\tthe one saved at capture time and save those caches in <cache-file>.");
339+
GFXRECON_WRITE_CONSOLE(" --load-pipeline-cache <cache-file>");
340+
GFXRECON_WRITE_CONSOLE(" \t\tIf set, loads data created by the `--save-pipeline-cache`");
341+
GFXRECON_WRITE_CONSOLE(" \t\toption in <cache-file> and uses it to create the pipelines instead");
342+
GFXRECON_WRITE_CONSOLE(" \t\tof the pipeline caches saved at capture time.");
343+
GFXRECON_WRITE_CONSOLE(" --add-new-pipeline-caches");
344+
GFXRECON_WRITE_CONSOLE(" \t\tIf set, allows gfxreconstruct to create new vkPipelineCache objects");
345+
GFXRECON_WRITE_CONSOLE(" \t\twhen it encounters a pipeline created without cache. This option can");
346+
GFXRECON_WRITE_CONSOLE(" \t\tbe used in coordination with `--save-pipeline-cache` and");
347+
GFXRECON_WRITE_CONSOLE(" \t\t`--load-pipeline-cache`.");
335348
#if defined(WIN32)
336349
GFXRECON_WRITE_CONSOLE("")
337350
GFXRECON_WRITE_CONSOLE("D3D12 only:")

tools/tool_settings.h

+7
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ const char kPrintBlockInfoAllOption[] = "--pbi-all";
124124
const char kPrintBlockInfosArgument[] = "--pbis";
125125
const char kNumPipelineCreationJobs[] = "--pipeline-creation-jobs";
126126
const char kPreloadMeasurementRangeOption[] = "--preload-measurement-range";
127+
const char kSavePipelineCacheArgument[] = "--save-pipeline-cache";
128+
const char kLoadPipelineCacheArgument[] = "--load-pipeline-cache";
129+
const char kCreateNewPipelineCacheOption[] = "--add-new-pipeline-caches";
127130
#if defined(WIN32)
128131
const char kDxTwoPassReplay[] = "--dx12-two-pass-replay";
129132
const char kDxOverrideObjectNames[] = "--dx12-override-object-names";
@@ -1109,6 +1112,10 @@ GetVulkanReplayOptions(const gfxrecon::util::ArgumentParser& arg_parse
11091112
replay_options.dump_resources_color_attachment_index = std::stoi(dr_color_att_idx);
11101113
}
11111114

1115+
replay_options.save_pipeline_cache_filename = arg_parser.GetArgumentValue(kSavePipelineCacheArgument);
1116+
replay_options.load_pipeline_cache_filename = arg_parser.GetArgumentValue(kLoadPipelineCacheArgument);
1117+
replay_options.add_new_pipeline_caches = arg_parser.IsOptionSet(kCreateNewPipelineCacheOption);
1118+
11121119
return replay_options;
11131120
}
11141121

0 commit comments

Comments
 (0)