Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 30 additions & 36 deletions backends/vulkan/runtime/api/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,11 @@ void Context::cmd_reset_querypool() {

void Context::report_shader_dispatch_start(
const std::string& shader_name,
const utils::uvec3& global_wg_size,
const utils::WorkgroupSize& local_wg_size,
const GlobalWorkGrid& gwg,
const LocalWorkGroup& lwg,
const uint32_t dispatch_id) {
if (querypool_) {
querypool_.shader_profile_begin(
cmd_,
dispatch_id,
shader_name,
vkapi::create_extent3d(global_wg_size),
vkapi::create_extent3d((utils::uvec3)local_wg_size));
querypool_.shader_profile_begin(cmd_, dispatch_id, shader_name, gwg, lwg);
}
}

Expand Down Expand Up @@ -133,7 +128,7 @@ void Context::check_device_capabilities(const vkapi::ShaderInfo& shader) {

vkapi::DescriptorSet Context::get_descriptor_set(
const vkapi::ShaderInfo& shader_descriptor,
const utils::WorkgroupSize& local_workgroup_size,
const LocalWorkGroup& lwg,
const vkapi::SpecVarList& additional_constants,
const uint32_t push_constants_size) {
VkDescriptorSetLayout shader_layout =
Expand All @@ -142,10 +137,7 @@ vkapi::DescriptorSet Context::get_descriptor_set(
VkPipelineLayout pipeline_layout =
pipeline_layout_cache().retrieve(shader_layout, push_constants_size);

vkapi::SpecVarList spec_constants = {
SV(local_workgroup_size[0u]),
SV(local_workgroup_size[1u]),
SV(local_workgroup_size[2u])};
vkapi::SpecVarList spec_constants = {SV(lwg[0u]), SV(lwg[1u]), SV(lwg[2u])};

spec_constants.append(additional_constants);

Expand All @@ -158,7 +150,7 @@ vkapi::DescriptorSet Context::get_descriptor_set(
spec_constants,
resolved_required_subgroup_size});

cmd_.bind_pipeline(pipeline, pipeline_layout, local_workgroup_size);
cmd_.bind_pipeline(pipeline, pipeline_layout, lwg);

return descriptor_pool().get_descriptor_set(
shader_layout, shader_descriptor.kernel_layout);
Expand All @@ -168,30 +160,35 @@ void Context::register_shader_dispatch(
const vkapi::DescriptorSet& descriptors,
vkapi::PipelineBarrier& pipeline_barrier,
const vkapi::ShaderInfo& shader_descriptor,
const utils::uvec3& global_workgroup_size,
const GlobalWorkGrid& gwg,
const LocalWorkGroup& lwg,
const void* push_constants_data,
const uint32_t push_constants_size) {
vkapi::Adapter* const adapter = adapter_ptr();
const LocalWorkGroup& dispatch_lwg =
gwg.required_lwg_size().is_valid() ? gwg.required_lwg_size() : lwg;
dispatch_lwg.validate(
adapter->max_compute_workgroup_size(),
adapter->max_compute_workgroup_invocations());
gwg.validate(
dispatch_lwg,
adapter->max_compute_workgroup_count(),
shader_descriptor.out_tile_size);

// Adjust the global workgroup size based on the output tile size
uint32_t global_wg_w = utils::div_up(
global_workgroup_size[0u], shader_descriptor.out_tile_size[0u]);
uint32_t global_wg_h = utils::div_up(
global_workgroup_size[1u], shader_descriptor.out_tile_size[1u]);
uint32_t global_wg_d = utils::div_up(
global_workgroup_size[2u], shader_descriptor.out_tile_size[2u]);
uint32_t gwg_w = utils::div_up(gwg[0u], shader_descriptor.out_tile_size[0u]);
uint32_t gwg_h = utils::div_up(gwg[1u], shader_descriptor.out_tile_size[1u]);
uint32_t gwg_d = utils::div_up(gwg[2u], shader_descriptor.out_tile_size[2u]);

// Submitting a global work group size of 0 is undefined behaviour. If this is
// detected then submit a single workgroup instead.
if (global_wg_w == 0u || global_wg_h == 0u || global_wg_d == 0u) {
global_wg_w = 1u;
global_wg_h = 1u;
global_wg_d = 1u;
if (gwg_w == 0u || gwg_h == 0u || gwg_d == 0u) {
gwg_w = 1u;
gwg_h = 1u;
gwg_d = 1u;
}

const utils::uvec3 effective_global_wg = {
global_wg_w,
global_wg_h,
global_wg_d,
};
const GlobalWorkGrid effective_gwg({gwg_w, gwg_h, gwg_d}, kExplicitWorkGrid);

cmd_.bind_descriptors(descriptors.get_bind_handle());
cmd_.insert_barrier(pipeline_barrier);
Expand All @@ -205,7 +202,7 @@ void Context::register_shader_dispatch(
pipeline_layout, push_constants_data, push_constants_size);
}

cmd_.dispatch(effective_global_wg);
cmd_.dispatch(effective_gwg, dispatch_lwg);
}

void Context::register_barrier(vkapi::PipelineBarrier& pipeline_barrier) {
Expand Down Expand Up @@ -324,11 +321,8 @@ VkPipeline Context::get_shader_pipeline(
VkPipelineLayout pipeline_layout =
pipeline_layout_cache().retrieve(shader_layout, push_constants_size);

const utils::WorkgroupSize local_workgroup_size(4u, 4u, 1u);
vkapi::SpecVarList spec_constants = {
SV(local_workgroup_size[0u]),
SV(local_workgroup_size[1u]),
SV(local_workgroup_size[2u])};
const LocalWorkGroup lwg(4u, 4u, 1u);
vkapi::SpecVarList spec_constants = {SV(lwg[0u]), SV(lwg[1u]), SV(lwg[2u])};

spec_constants.append(additional_constants);

Expand Down
39 changes: 19 additions & 20 deletions backends/vulkan/runtime/api/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <executorch/backends/vulkan/runtime/vk_api/Adapter.h>
#include <executorch/backends/vulkan/runtime/vk_api/Command.h>
#include <executorch/backends/vulkan/runtime/vk_api/Descriptor.h>
#include <executorch/backends/vulkan/runtime/vk_api/DispatchGrid.h>
#include <executorch/backends/vulkan/runtime/vk_api/Fence.h>
#include <executorch/backends/vulkan/runtime/vk_api/QueryPool.h>
#include <executorch/backends/vulkan/runtime/vk_api/Runtime.h>
Expand Down Expand Up @@ -150,8 +151,8 @@ class Context final {
*/
void report_shader_dispatch_start(
const std::string& shader_name,
const utils::uvec3& global_wg_size,
const utils::WorkgroupSize& local_wg_size,
const GlobalWorkGrid& gwg,
const LocalWorkGroup& lwg,
const uint32_t dispatch_id = UINT32_MAX);

/*
Expand Down Expand Up @@ -190,21 +191,22 @@ class Context final {

vkapi::DescriptorSet get_descriptor_set(
const vkapi::ShaderInfo&,
const utils::WorkgroupSize&,
const LocalWorkGroup&,
const vkapi::SpecVarList&,
const uint32_t push_constants_size);

inline vkapi::DescriptorSet get_descriptor_set(
const vkapi::ShaderInfo& shader_descriptor,
const utils::WorkgroupSize& local_work_group_size) {
return get_descriptor_set(shader_descriptor, local_work_group_size, {}, 0u);
const LocalWorkGroup& lwg) {
return get_descriptor_set(shader_descriptor, lwg, {}, 0u);
}

void register_shader_dispatch(
const vkapi::DescriptorSet&,
vkapi::PipelineBarrier&,
const vkapi::ShaderInfo&,
const utils::uvec3&,
const GlobalWorkGrid&,
const LocalWorkGroup&,
const void* = nullptr,
const uint32_t = 0);

Expand All @@ -219,8 +221,8 @@ class Context final {
bool submit_compute_job(
const vkapi::ShaderInfo&,
vkapi::PipelineBarrier&,
const utils::uvec3&,
const utils::uvec3&,
const GlobalWorkGrid&,
const LocalWorkGroup&,
const vkapi::SpecVarList&,
VkFence fence_handle,
const uint32_t dispatch_id,
Expand Down Expand Up @@ -333,8 +335,8 @@ template <typename... Arguments>
inline bool Context::submit_compute_job(
const vkapi::ShaderInfo& shader,
vkapi::PipelineBarrier& pipeline_barrier,
const utils::uvec3& global_work_group,
const utils::uvec3& local_work_group_size,
const GlobalWorkGrid& gwg,
const LocalWorkGroup& lwg,
const vkapi::SpecVarList& specialization_constants,
VkFence fence_handle,
const uint32_t dispatch_id,
Expand Down Expand Up @@ -367,20 +369,17 @@ inline bool Context::submit_compute_job(

set_cmd();

const LocalWorkGroup& dispatch_lwg =
gwg.required_lwg_size().is_valid() ? gwg.required_lwg_size() : lwg;

report_shader_dispatch_start(
shader.kernel_name,
global_work_group,
utils::WorkgroupSize(local_work_group_size),
dispatch_id);
shader.kernel_name, gwg, dispatch_lwg, dispatch_id);

// Factor out template parameter independent code to minimize code bloat.
// Note that push constants are not exposed yet via this API, therefore the
// push constants size is assumed to be 0.
vkapi::DescriptorSet descriptor_set = get_descriptor_set(
shader,
utils::WorkgroupSize(local_work_group_size),
specialization_constants,
0u);
vkapi::DescriptorSet descriptor_set =
get_descriptor_set(shader, dispatch_lwg, specialization_constants, 0u);

detail::bind(
descriptor_set,
Expand All @@ -389,7 +388,7 @@ inline bool Context::submit_compute_job(

// Factor out template parameter independent code to minimize code bloat.
register_shader_dispatch(
descriptor_set, pipeline_barrier, shader, global_work_group);
descriptor_set, pipeline_barrier, shader, gwg, dispatch_lwg);

report_shader_dispatch_end();

Expand Down
79 changes: 30 additions & 49 deletions backends/vulkan/runtime/graph/ComputeGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ void ComputeGraph::update_descriptor_counts(

void ComputeGraph::register_pipeline_to_create(
const vkapi::ShaderInfo& shader_info,
const utils::WorkgroupSize& local_workgroup_size,
const LocalWorkGroup& lwg,
const vkapi::SpecVarList& spec_vars,
const std::vector<PushConstantDataInfo>& push_constants) {
VkDescriptorSetLayout shader_layout =
Expand All @@ -857,10 +857,7 @@ void ComputeGraph::register_pipeline_to_create(
pc_offset += pc.write(pc_data.data(), pc_offset, kMaxPushConstantSize);
}

vkapi::SpecVarList spec_constants = {
SV(local_workgroup_size[0u]),
SV(local_workgroup_size[1u]),
SV(local_workgroup_size[2u])};
vkapi::SpecVarList spec_constants = {SV(lwg[0u]), SV(lwg[1u]), SV(lwg[2u])};

spec_constants.append(spec_vars);

Expand Down Expand Up @@ -889,62 +886,46 @@ void ComputeGraph::register_pipeline_to_create(
pipeline_descriptors_.insert(desc);
}

utils::uvec3 ComputeGraph::create_global_wg_size(const ValueRef idx) {
GlobalWorkGrid ComputeGraph::create_gwg(const ValueRef idx) {
if (is_buffer_storage(idx)) {
return {uint32_t(numel_of(idx)), 1u, 1u};
return create_linear_gwg(utils::safe_downcast<uint64_t>(numel_of(idx)));
}
return logical_limits_of(idx);
}

utils::uvec3 ComputeGraph::create_local_wg_size(
const utils::uvec3 global_wg_size) {
if (config_.enable_local_wg_size_override) {
return config_.local_wg_size_override;
}
return GlobalWorkGrid(
utils::make_uvec3(logical_limits_of(idx)), kTextureExtentsWorkGrid);
}

// array containing axis index and global workgroup size
std::pair<uint32_t, uint32_t> global_wg_size_desc[] = {
{0u, global_wg_size[0]},
{1u, global_wg_size[1]},
{2u, global_wg_size[2]}};
GlobalWorkGrid ComputeGraph::create_linear_gwg(const uint64_t numel) {
vkapi::Adapter* const adapter = context()->adapter_ptr();
GlobalWorkGrid gwg(
{utils::safe_downcast<uint32_t>(numel), 1u, 1u}, kLinearWorkGrid);
gwg.wrap_linear_dispatch(
adapter->max_compute_workgroup_count(),
adapter->recommended_lwg_nthreads());
return gwg;
}

// sort the global workgroup size in descending order
if (global_wg_size_desc[0].second < global_wg_size_desc[1].second) {
std::swap(global_wg_size_desc[0], global_wg_size_desc[1]);
}
if (global_wg_size_desc[1].second < global_wg_size_desc[2].second) {
std::swap(global_wg_size_desc[1], global_wg_size_desc[2]);
}
if (global_wg_size_desc[0].second < global_wg_size_desc[1].second) {
std::swap(global_wg_size_desc[0], global_wg_size_desc[1]);
LocalWorkGroup ComputeGraph::create_lwg(const GlobalWorkGrid& gwg) {
if (gwg.required_lwg_size().is_valid()) {
return gwg.required_lwg_size();
}

utils::uvec3 local_group_size = {
8,
std::max(1u, std::min(4u, global_wg_size_desc[1].second)),
std::max(1u, std::min(2u, global_wg_size_desc[2].second))};
vkapi::Adapter* const adapter = context()->adapter_ptr();

if (global_wg_size_desc[2u].second == 1) {
if (global_wg_size_desc[1u].second == 1) {
local_group_size[0u] = 64;
local_group_size[1u] = 1;
} else if (global_wg_size_desc[1u].second % 4 == 0) {
local_group_size[0u] = 16;
local_group_size[1u] = 4;
} else {
local_group_size[0u] = 32;
local_group_size[1u] = 2;
}
utils::uvec3 shape_weights{
gwg[0] > 1u ? 1u : 0u, gwg[1] > 1u ? 1u : 0u, gwg[2] > 1u ? 1u : 0u};
if (shape_weights == utils::uvec3{0u, 0u, 0u}) {
shape_weights[0] = 1u;
}

return {
local_group_size[global_wg_size_desc[0].first],
local_group_size[global_wg_size_desc[1].first],
local_group_size[global_wg_size_desc[2].first]};
LocalWorkGroup lwg(
LwgShape(shape_weights), adapter->recommended_lwg_nthreads());
lwg.fit_to_global(gwg);
return lwg;
}

utils::uvec3 ComputeGraph::create_local_wg_size(const ValueRef idx) {
return create_local_wg_size(create_global_wg_size(idx));
LocalWorkGroup ComputeGraph::create_lwg(const ValueRef idx) {
return create_lwg(create_gwg(idx));
}

void ComputeGraph::bind_tensor_to_descriptor_set(
Expand Down
Loading
Loading