Skip to content

Commit 1eb9309

Browse files
authored
[ET-VK] Add utility functions to get pipeline executable properties
Differential Revision: D69125488 Pull Request resolved: #8182
1 parent a5c7609 commit 1eb9309

File tree

5 files changed

+269
-1
lines changed

5 files changed

+269
-1
lines changed

backends/vulkan/runtime/api/Context.cpp

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88

99
#include <executorch/backends/vulkan/runtime/api/Context.h>
1010

11+
#ifdef VULKAN_DEBUG
12+
#include <iomanip>
13+
#include <iostream>
14+
#endif // VULKAN_DEBUG
15+
1116
#ifndef VULKAN_DESCRIPTOR_POOL_SIZE
1217
#define VULKAN_DESCRIPTOR_POOL_SIZE 1024u
1318
#endif
@@ -261,5 +266,220 @@ Context* context() {
261266
return context.get();
262267
}
263268

269+
#ifdef VULKAN_DEBUG
270+
271+
#ifdef VK_KHR_pipeline_executable_properties
272+
273+
VkPipeline Context::get_shader_pipeline(
274+
const vkapi::ShaderInfo& shader,
275+
const vkapi::SpecVarList& spec_constants) {
276+
const uint32_t push_constants_size = 128u;
277+
278+
VkDescriptorSetLayout shader_layout =
279+
shader_layout_cache().retrieve(shader.kernel_layout);
280+
VkPipelineLayout pipeline_layout =
281+
pipeline_layout_cache().retrieve(shader_layout, push_constants_size);
282+
283+
vkapi::SpecVarList spec_constants_full_list = {4u, 4u, 1u};
284+
spec_constants_full_list.append(spec_constants);
285+
286+
VkPipeline pipeline = pipeline_cache().retrieve(
287+
{pipeline_layout,
288+
shader_cache().retrieve(shader),
289+
spec_constants_full_list});
290+
291+
return pipeline;
292+
}
293+
294+
std::vector<VkPipelineExecutablePropertiesKHR>
295+
Context::get_pipeline_executable_props(const VkPipeline pipeline) {
296+
VkPipelineInfoKHR pipeline_info{
297+
VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR,
298+
nullptr,
299+
pipeline,
300+
};
301+
302+
uint32_t shader_props_count = 0u;
303+
vkGetPipelineExecutablePropertiesKHR(
304+
device(), &pipeline_info, &shader_props_count, nullptr);
305+
306+
std::vector<VkPipelineExecutablePropertiesKHR> pipeline_props(
307+
shader_props_count);
308+
for (int i = 0; i < shader_props_count; i++) {
309+
pipeline_props.at(i).sType =
310+
VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR;
311+
pipeline_props.at(i).pNext = nullptr;
312+
}
313+
vkGetPipelineExecutablePropertiesKHR(
314+
device(), &pipeline_info, &shader_props_count, pipeline_props.data());
315+
316+
return pipeline_props;
317+
}
318+
319+
std::tuple<
320+
std::vector<VkPipelineExecutableInternalRepresentationKHR>,
321+
std::vector<std::vector<char>>>
322+
Context::get_shader_executable_irs(
323+
const VkPipeline pipeline,
324+
const uint32_t pipeline_exec_idx) {
325+
VkPipelineExecutableInfoKHR exec_info{
326+
VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR,
327+
nullptr,
328+
pipeline,
329+
pipeline_exec_idx,
330+
};
331+
332+
uint32_t ir_count;
333+
VK_CHECK(vkGetPipelineExecutableInternalRepresentationsKHR(
334+
device(), &exec_info, &ir_count, nullptr));
335+
336+
std::vector<VkPipelineExecutableInternalRepresentationKHR> irs(ir_count);
337+
for (int i = 0; i < ir_count; i++) {
338+
irs.at(i).sType =
339+
VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR;
340+
irs.at(i).pNext = nullptr;
341+
irs.at(i).pData = nullptr;
342+
}
343+
VK_CHECK(vkGetPipelineExecutableInternalRepresentationsKHR(
344+
device(), &exec_info, &ir_count, irs.data()));
345+
346+
std::vector<std::vector<char>> irs_data(ir_count);
347+
for (int i = 0; i < ir_count; i++) {
348+
irs_data.at(i).resize(irs.at(i).dataSize);
349+
irs.at(i).pData = irs_data.at(i).data();
350+
}
351+
VK_CHECK(vkGetPipelineExecutableInternalRepresentationsKHR(
352+
device(), &exec_info, &ir_count, irs.data()));
353+
354+
return std::make_tuple(irs, irs_data);
355+
}
356+
357+
std::vector<VkPipelineExecutableStatisticKHR>
358+
Context::get_shader_executable_stats(
359+
const VkPipeline pipeline,
360+
const uint32_t pipeline_exec_idx) {
361+
VkPipelineExecutableInfoKHR exec_info{
362+
VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR,
363+
nullptr,
364+
pipeline,
365+
pipeline_exec_idx,
366+
};
367+
368+
uint32_t stats_count;
369+
VK_CHECK(vkGetPipelineExecutableStatisticsKHR(
370+
device(), &exec_info, &stats_count, NULL));
371+
372+
std::vector<VkPipelineExecutableStatisticKHR> shader_stats(stats_count);
373+
for (int i = 0; i < stats_count; i++) {
374+
shader_stats.at(i).sType =
375+
VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR;
376+
shader_stats.at(i).pNext = nullptr;
377+
}
378+
vkGetPipelineExecutableStatisticsKHR(
379+
device(), &exec_info, &stats_count, shader_stats.data());
380+
381+
return shader_stats;
382+
}
383+
384+
std::ostream& operator<<(
385+
std::ostream& os,
386+
const VkPipelineExecutablePropertiesKHR& props) {
387+
os << std::left << std::setw(10) << "name: " << props.name << std::endl;
388+
os << std::left << std::setw(10) << "descr: " << props.description
389+
<< std::endl;
390+
os << std::left << std::setw(10) << "subgroup: " << props.subgroupSize
391+
<< std::endl;
392+
393+
return os;
394+
}
395+
396+
std::ostream& operator<<(
397+
std::ostream& os,
398+
const VkPipelineExecutableInternalRepresentationKHR& ir) {
399+
os << std::left << std::setw(10) << "descr: " << ir.description << std::endl;
400+
os << std::left << std::setw(10) << "isText: " << ir.isText << std::endl;
401+
os << std::left << std::setw(10) << "size: " << ir.dataSize << std::endl;
402+
if (ir.isText) {
403+
os << "text:" << std::endl;
404+
char* str = (char*)ir.pData;
405+
os << str << std::endl;
406+
}
407+
return os;
408+
}
409+
410+
std::ostream& operator<<(
411+
std::ostream& os,
412+
VkPipelineExecutableStatisticKHR& stat) {
413+
os << stat.name << ": ";
414+
switch (stat.format) {
415+
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR:
416+
os << (stat.value.b32 ? "true" : "false") << std::endl;
417+
break;
418+
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR:
419+
os << stat.value.i64 << std::endl;
420+
break;
421+
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR:
422+
os << stat.value.u64 << std::endl;
423+
break;
424+
case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR:
425+
os << stat.value.f64 << std::endl;
426+
break;
427+
default:
428+
break;
429+
}
430+
os << " " << stat.description << std::endl;
431+
return os;
432+
}
433+
434+
std::ostream& operator<<(
435+
std::ostream& os,
436+
std::vector<VkPipelineExecutableStatisticKHR>& shader_stats) {
437+
for (int i = 0; i < shader_stats.size(); i++) {
438+
VkPipelineExecutableStatisticKHR& stat = shader_stats.at(i);
439+
os << stat;
440+
}
441+
return os;
442+
}
443+
444+
void Context::print_shader_executable_properties(
445+
const vkapi::ShaderInfo& shader,
446+
const vkapi::SpecVarList& spec_constants) {
447+
VkPipeline pipeline = get_shader_pipeline(shader, spec_constants);
448+
449+
std::vector<VkPipelineExecutablePropertiesKHR> pipeline_props_list =
450+
get_pipeline_executable_props(pipeline);
451+
452+
VK_CHECK_COND(pipeline_props_list.size() == 1u);
453+
454+
std::cout << pipeline_props_list.at(0) << std::endl;
455+
456+
std::tuple<
457+
std::vector<VkPipelineExecutableInternalRepresentationKHR>,
458+
std::vector<std::vector<char>>>
459+
irs_and_irs_data = get_shader_executable_irs(pipeline, 0u);
460+
461+
std::vector<VkPipelineExecutableInternalRepresentationKHR>& irs =
462+
std::get<0>(irs_and_irs_data);
463+
464+
std::cout << "Found " << irs.size() << " IRs" << std::endl << std::endl;
465+
for (int i = 0; i < irs.size(); i++) {
466+
std::cout << "====== IR " << i << ": " << irs.at(i).name
467+
<< " ======" << std::endl;
468+
std::cout << irs.at(i) << std::endl;
469+
}
470+
471+
std::vector<VkPipelineExecutableStatisticKHR> shader_stats =
472+
get_shader_executable_stats(pipeline, 0u);
473+
std::cout << "Found " << shader_stats.size() << " Statistics" << std::endl;
474+
if (shader_stats.size() > 0) {
475+
std::cout << "====== Statistics: ======" << std::endl;
476+
std::cout << shader_stats << std::endl;
477+
}
478+
}
479+
480+
#endif // VK_KHR_pipeline_executable_properties
481+
482+
#endif // VULKAN_DEBUG
483+
264484
} // namespace api
265485
} // namespace vkcompute

backends/vulkan/runtime/api/Context.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,36 @@ class Context final {
228228
const bool final_use = false);
229229

230230
void flush();
231+
232+
#ifdef VULKAN_DEBUG
233+
234+
#ifdef VK_KHR_pipeline_executable_properties
235+
236+
VkPipeline get_shader_pipeline(
237+
const vkapi::ShaderInfo& shader,
238+
const vkapi::SpecVarList& spec_constants);
239+
240+
std::vector<VkPipelineExecutablePropertiesKHR> get_pipeline_executable_props(
241+
const VkPipeline pipeline);
242+
243+
std::tuple<
244+
std::vector<VkPipelineExecutableInternalRepresentationKHR>,
245+
std::vector<std::vector<char>>>
246+
get_shader_executable_irs(
247+
const VkPipeline pipeline,
248+
const uint32_t pipeline_exec_idx = 0u);
249+
250+
std::vector<VkPipelineExecutableStatisticKHR> get_shader_executable_stats(
251+
const VkPipeline pipeline,
252+
const uint32_t pipeline_exec_idx = 0u);
253+
254+
void print_shader_executable_properties(
255+
const vkapi::ShaderInfo& shader,
256+
const vkapi::SpecVarList& spec_constants);
257+
258+
#endif // VK_KHR_pipeline_executable_properties
259+
260+
#endif // VULKAN_DEBUG
231261
};
232262

233263
bool available();

backends/vulkan/runtime/vk_api/Adapter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ VkDevice create_logical_device(
8282
#ifdef VK_KHR_shader_float16_int8
8383
VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME,
8484
#endif /* VK_KHR_shader_float16_int8 */
85+
#if defined(VK_KHR_pipeline_executable_properties) && defined(VULKAN_DEBUG)
86+
VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME,
87+
#endif /* VK_KHR_pipeline_executable_properties */
8588
};
8689

8790
std::vector<const char*> enabled_device_extensions;

backends/vulkan/runtime/vk_api/Pipeline.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,16 @@ ComputePipeline::ComputePipeline(
287287
&specialization_info, // pSpecializationInfo
288288
};
289289

290+
VkPipelineCreateFlags flags = 0u;
291+
#if defined(VULKAN_DEBUG) && defined(VK_KHR_pipeline_executable_properties)
292+
flags = VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR |
293+
VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR | flags;
294+
#endif /* VULKAN_DEBUG && VK_KHR_pipeline_executable_properties */
295+
290296
const VkComputePipelineCreateInfo compute_pipeline_create_info{
291297
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // sType
292298
nullptr, // pNext
293-
0u, // flags
299+
flags, // flags
294300
shader_stage_create_info, // stage
295301
descriptor.pipeline_layout, // layout
296302
VK_NULL_HANDLE, // basePipelineHandle

backends/vulkan/test/vulkan_compute_api_test.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ TEST_F(VulkanComputeAPITest, print_adapter) {
101101
std::cout << *(context()->adapter_ptr()) << std::endl;
102102
}
103103

104+
#if defined(VULKAN_DEBUG) && defined(VK_KHR_pipeline_executable_properties)
105+
106+
TEST_F(VulkanComputeAPITest, print_shader_executable_properties) {
107+
context()->print_shader_executable_properties(
108+
VK_KERNEL(binary_add_nobroadcast__test_half), {0});
109+
}
110+
111+
#endif // VULKAN_DEBUG && VK_KHR_pipeline_executable_properties
112+
104113
std::vector<int64_t> get_reference_strides(
105114
const std::vector<int64_t>& sizes,
106115
const utils::GPUMemoryLayout layout,

0 commit comments

Comments
 (0)