blob: bd0a405d36a20352bed8378a9c777ddfb81ecec9 [file] [log] [blame]
/*
* Copyright (c) 2023-2024 Valve Corporation
* Copyright (c) 2023-2024 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*/
#include <vulkan/vulkan_core.h>
#include "../framework/layer_validation_tests.h"
#include "../framework/pipeline_helper.h"
#include "../framework/shader_object_helper.h"
#include "generated/vk_function_pointers.h"
void DeviceGeneratedCommandsTest::InitBasicDeviceGeneratedCommands() {
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::deviceGeneratedCommands);
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT dgc_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(dgc_props);
if ((dgc_props.supportedIndirectCommandsShaderStagesPipelineBinding & VK_SHADER_STAGE_COMPUTE_BIT) == 0) {
GTEST_SKIP() << "VK_SHADER_STAGE_COMPUTE_BIT is not supported.";
} else if ((dgc_props.supportedIndirectCommandsShaderStagesPipelineBinding & VK_SHADER_STAGE_VERTEX_BIT) == 0) {
GTEST_SKIP() << "VK_SHADER_STAGE_VERTEX_BIT is not supported.";
}
}
// "If vkGetGeneratedCommandsMemoryRequirementsEXT returns a non-zero size, preprocessAddress must not be NULL"
// Does the query and updates with preprocessAddress if needed
void DeviceGeneratedCommandsTest::SetPreProcessBuffer(VkGeneratedCommandsInfoEXT& generated_commands_info) {
VkGeneratedCommandsMemoryRequirementsInfoEXT dgc_mem_reqs = vku::InitStructHelper();
dgc_mem_reqs.indirectCommandsLayout = generated_commands_info.indirectCommandsLayout;
dgc_mem_reqs.indirectExecutionSet = generated_commands_info.indirectExecutionSet;
dgc_mem_reqs.maxSequenceCount = generated_commands_info.maxSequenceCount;
dgc_mem_reqs.maxDrawCount = generated_commands_info.maxDrawCount;
VkDeviceAddress pre_process_address = 0;
VkMemoryRequirements2 mem_reqs2 = vku::InitStructHelper();
vk::GetGeneratedCommandsMemoryRequirementsEXT(device(), &dgc_mem_reqs, &mem_reqs2);
const VkDeviceSize pre_process_size = mem_reqs2.memoryRequirements.size;
if (pre_process_size > 0) {
VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper();
allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
VkBufferUsageFlags2CreateInfo buffer_usage_flags = vku::InitStructHelper();
buffer_usage_flags.usage = VK_BUFFER_USAGE_2_PREPROCESS_BUFFER_BIT_EXT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
VkBufferCreateInfo buffer_ci = vku::InitStructHelper(&buffer_usage_flags);
buffer_ci.size = pre_process_size;
pre_process_buffer_->init(*m_device, buffer_ci, 0, &allocate_flag_info);
pre_process_address = pre_process_buffer_->Address();
}
generated_commands_info.preprocessSize = pre_process_size;
generated_commands_info.preprocessAddress = pre_process_address;
}
class PositiveDeviceGeneratedCommands : public DeviceGeneratedCommandsTest {};
TEST_F(PositiveDeviceGeneratedCommands, CreateIndirectExecutionSetPipeline) {
RETURN_IF_SKIP(InitBasicDeviceGeneratedCommands());
InitRenderTarget();
VkPipelineCreateFlags2CreateInfo pipe_flags2 = vku::InitStructHelper();
pipe_flags2.flags = VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_EXT;
CreatePipelineHelper pipe(*this, &pipe_flags2);
pipe.CreateGraphicsPipeline();
vkt::IndirectExecutionSet exe_set(*m_device, pipe.Handle(), 1);
}
TEST_F(PositiveDeviceGeneratedCommands, CreateIndirectExecutionSetShaderObject) {
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderObject);
RETURN_IF_SKIP(InitBasicDeviceGeneratedCommands());
InitRenderTarget();
const auto vert_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl);
VkShaderCreateInfoEXT vert_create_info =
ShaderCreateInfoFlag(vert_spv, VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT);
const vkt::Shader vertShader(*m_device, vert_create_info);
const VkShaderEXT shaders[] = {vertShader.handle()};
OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}});
VkIndirectExecutionSetShaderLayoutInfoEXT exe_set_layouts = vku::InitStructHelper();
exe_set_layouts.setLayoutCount = 1;
exe_set_layouts.pSetLayouts = &descriptor_set.layout_.handle();
VkIndirectExecutionSetShaderInfoEXT exe_set_shader_info = vku::InitStructHelper();
exe_set_shader_info.shaderCount = 1;
exe_set_shader_info.pInitialShaders = shaders;
exe_set_shader_info.pSetLayoutInfos = &exe_set_layouts;
exe_set_shader_info.maxShaderCount = 1;
exe_set_shader_info.pushConstantRangeCount = 0;
vkt::IndirectExecutionSet exe_set(*m_device, exe_set_shader_info);
}
TEST_F(PositiveDeviceGeneratedCommands, CreateIndirectCommandsLayout) {
RETURN_IF_SKIP(InitBasicDeviceGeneratedCommands());
VkIndirectCommandsLayoutTokenEXT token = vku::InitStructHelper();
token.type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_EXT;
token.offset = 0;
VkIndirectCommandsLayoutCreateInfoEXT command_layout_ci = vku::InitStructHelper();
command_layout_ci.shaderStages = VK_SHADER_STAGE_VERTEX_BIT;
command_layout_ci.pipelineLayout = VK_NULL_HANDLE;
command_layout_ci.tokenCount = 1;
command_layout_ci.pTokens = &token;
VkIndirectCommandsLayoutEXT command_layout;
vk::CreateIndirectCommandsLayoutEXT(device(), &command_layout_ci, nullptr, &command_layout);
vk::DestroyIndirectCommandsLayoutEXT(device(), command_layout, nullptr);
}
TEST_F(PositiveDeviceGeneratedCommands, GetGeneratedCommandsMemoryRequirements) {
RETURN_IF_SKIP(InitBasicDeviceGeneratedCommands());
InitRenderTarget();
VkIndirectCommandsLayoutTokenEXT token = vku::InitStructHelper();
token.type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_EXT;
token.offset = 0;
VkIndirectCommandsLayoutCreateInfoEXT command_layout_ci = vku::InitStructHelper();
command_layout_ci.shaderStages = VK_SHADER_STAGE_VERTEX_BIT;
command_layout_ci.pipelineLayout = VK_NULL_HANDLE;
command_layout_ci.tokenCount = 1;
command_layout_ci.pTokens = &token;
vkt::IndirectCommandsLayout command_layout(*m_device, command_layout_ci);
VkPipelineCreateFlags2CreateInfo pipe_flags2 = vku::InitStructHelper();
pipe_flags2.flags = VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_EXT;
CreatePipelineHelper pipe(*this, &pipe_flags2);
pipe.CreateGraphicsPipeline();
VkGeneratedCommandsPipelineInfoEXT pipeline_info = vku::InitStructHelper();
pipeline_info.pipeline = pipe.Handle();
VkGeneratedCommandsMemoryRequirementsInfoEXT req_info = vku::InitStructHelper(&pipeline_info);
req_info.maxSequenceCount = 1;
req_info.indirectExecutionSet = VK_NULL_HANDLE;
req_info.indirectCommandsLayout = command_layout.handle();
VkMemoryRequirements2 mem_req2 = vku::InitStructHelper();
vk::GetGeneratedCommandsMemoryRequirementsEXT(device(), &req_info, &mem_req2);
}
TEST_F(PositiveDeviceGeneratedCommands, PushConstant) {
RETURN_IF_SKIP(InitBasicDeviceGeneratedCommands());
VkIndirectCommandsPushConstantTokenEXT pc_token;
pc_token.updateRange = {VK_SHADER_STAGE_VERTEX_BIT, 8, 8};
VkIndirectCommandsLayoutTokenEXT tokens[2];
tokens[0] = vku::InitStructHelper();
tokens[0].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_EXT;
tokens[0].data.pPushConstant = &pc_token;
tokens[0].offset = 0;
tokens[1] = vku::InitStructHelper();
tokens[1].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_EXT;
tokens[1].offset = 8;
const std::vector<VkPushConstantRange> pc_range = {{VK_SHADER_STAGE_VERTEX_BIT, 4, 12}};
vkt::PipelineLayout pipeline_layout(*m_device, {}, pc_range);
VkIndirectCommandsLayoutCreateInfoEXT command_layout_ci = vku::InitStructHelper();
command_layout_ci.shaderStages = VK_SHADER_STAGE_VERTEX_BIT;
command_layout_ci.pipelineLayout = pipeline_layout.handle();
command_layout_ci.tokenCount = 2;
command_layout_ci.pTokens = tokens;
vkt::IndirectCommandsLayout command_layout(*m_device, command_layout_ci);
}
TEST_F(PositiveDeviceGeneratedCommands, CmdExecuteGeneratedCommandsGraphics) {
RETURN_IF_SKIP(InitBasicDeviceGeneratedCommands());
InitRenderTarget();
VkPipelineCreateFlags2CreateInfo pipe_flags2 = vku::InitStructHelper();
pipe_flags2.flags = VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_EXT;
CreatePipelineHelper pipe(*this, &pipe_flags2);
pipe.CreateGraphicsPipeline();
vkt::IndirectExecutionSet exe_set(*m_device, pipe.Handle(), 1);
VkIndirectCommandsExecutionSetTokenEXT exe_set_token = {VK_INDIRECT_EXECUTION_SET_INFO_TYPE_PIPELINES_EXT,
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT};
VkIndirectCommandsLayoutTokenEXT tokens[2];
tokens[0] = vku::InitStructHelper();
tokens[0].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_EXECUTION_SET_EXT;
tokens[0].data.pExecutionSet = &exe_set_token;
tokens[0].offset = 0;
tokens[1] = vku::InitStructHelper();
tokens[1].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_EXT;
tokens[1].offset = 8;
VkIndirectCommandsLayoutCreateInfoEXT command_layout_ci = vku::InitStructHelper();
command_layout_ci.shaderStages = VK_SHADER_STAGE_VERTEX_BIT;
command_layout_ci.pipelineLayout = VK_NULL_HANDLE;
command_layout_ci.tokenCount = 2;
command_layout_ci.pTokens = tokens;
vkt::IndirectCommandsLayout command_layout(*m_device, command_layout_ci);
VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper();
allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
vkt::Buffer block_buffer(*m_device, 64, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, kHostVisibleMemProps, &allocate_flag_info);
VkGeneratedCommandsInfoEXT generated_commands_info = vku::InitStructHelper();
generated_commands_info.shaderStages = VK_SHADER_STAGE_VERTEX_BIT;
generated_commands_info.indirectExecutionSet = exe_set.handle();
generated_commands_info.indirectCommandsLayout = command_layout.handle();
generated_commands_info.indirectAddressSize = 64;
generated_commands_info.indirectAddress = block_buffer.Address();
generated_commands_info.sequenceCountAddress = 0;
generated_commands_info.maxSequenceCount = 1;
generated_commands_info.maxDrawCount = 1;
SetPreProcessBuffer(generated_commands_info);
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle());
vk::CmdExecuteGeneratedCommandsEXT(m_command_buffer.handle(), false, &generated_commands_info);
m_command_buffer.End();
}
TEST_F(PositiveDeviceGeneratedCommands, UpdateIndirectExecutionSetPipeline) {
RETURN_IF_SKIP(InitBasicDeviceGeneratedCommands());
InitRenderTarget();
VkPipelineCreateFlags2CreateInfo pipe_flags2 = vku::InitStructHelper();
pipe_flags2.flags = VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_EXT;
CreatePipelineHelper pipe(*this, &pipe_flags2);
pipe.CreateGraphicsPipeline();
vkt::IndirectExecutionSet exe_set(*m_device, pipe.Handle(), 4);
VkWriteIndirectExecutionSetPipelineEXT write_exe_sets[3];
write_exe_sets[0] = vku::InitStructHelper();
write_exe_sets[0].index = 1;
write_exe_sets[0].pipeline = pipe.Handle();
write_exe_sets[1] = vku::InitStructHelper();
write_exe_sets[1].index = 2;
write_exe_sets[1].pipeline = pipe.Handle();
write_exe_sets[2] = vku::InitStructHelper();
write_exe_sets[2].index = 3;
write_exe_sets[2].pipeline = pipe.Handle();
vk::UpdateIndirectExecutionSetPipelineEXT(device(), exe_set.handle(), 3, write_exe_sets);
}
TEST_F(PositiveDeviceGeneratedCommands, UpdateIndirectExecutionSetShader) {
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderObject);
RETURN_IF_SKIP(InitBasicDeviceGeneratedCommands());
InitRenderTarget();
const auto vert_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl);
VkShaderCreateInfoEXT vert_create_info =
ShaderCreateInfoFlag(vert_spv, VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT);
const vkt::Shader vertShader(*m_device, vert_create_info);
const VkShaderEXT shaders[] = {vertShader.handle()};
OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}});
VkIndirectExecutionSetShaderLayoutInfoEXT exe_set_layouts = vku::InitStructHelper();
exe_set_layouts.setLayoutCount = 1;
exe_set_layouts.pSetLayouts = &descriptor_set.layout_.handle();
VkIndirectExecutionSetShaderInfoEXT exe_set_shader_info = vku::InitStructHelper();
exe_set_shader_info.shaderCount = 1;
exe_set_shader_info.pInitialShaders = shaders;
exe_set_shader_info.pSetLayoutInfos = &exe_set_layouts;
exe_set_shader_info.maxShaderCount = 1;
exe_set_shader_info.pushConstantRangeCount = 0;
vkt::IndirectExecutionSet exe_set(*m_device, exe_set_shader_info);
VkWriteIndirectExecutionSetShaderEXT write_exe_set = vku::InitStructHelper();
write_exe_set.index = 0;
write_exe_set.shader = vertShader.handle();
vk::UpdateIndirectExecutionSetShaderEXT(device(), exe_set.handle(), 1, &write_exe_set);
}
TEST_F(PositiveDeviceGeneratedCommands, CmdExecuteGeneratedCommandsCompute) {
RETURN_IF_SKIP(InitBasicDeviceGeneratedCommands());
VkIndirectCommandsExecutionSetTokenEXT exe_set_token = {VK_INDIRECT_EXECUTION_SET_INFO_TYPE_PIPELINES_EXT,
VK_SHADER_STAGE_COMPUTE_BIT};
VkIndirectCommandsLayoutTokenEXT tokens[2];
tokens[0] = vku::InitStructHelper();
tokens[0].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_EXECUTION_SET_EXT;
tokens[0].data.pExecutionSet = &exe_set_token;
tokens[0].offset = 0;
tokens[1] = vku::InitStructHelper();
tokens[1].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_EXT;
tokens[1].offset = 8;
VkIndirectCommandsLayoutCreateInfoEXT command_layout_ci = vku::InitStructHelper();
command_layout_ci.shaderStages = VK_SHADER_STAGE_COMPUTE_BIT;
command_layout_ci.pipelineLayout = VK_NULL_HANDLE;
command_layout_ci.tokenCount = 2;
command_layout_ci.pTokens = tokens;
vkt::IndirectCommandsLayout command_layout(*m_device, command_layout_ci);
VkPipelineCreateFlags2CreateInfo pipe_flags2 = vku::InitStructHelper();
pipe_flags2.flags = VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_EXT;
CreateComputePipelineHelper pipe(*this, &pipe_flags2);
pipe.CreateComputePipeline();
vkt::IndirectExecutionSet exe_set(*m_device, pipe.Handle(), 1);
VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper();
allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
vkt::Buffer block_buffer(*m_device, 64, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, kHostVisibleMemProps, &allocate_flag_info);
VkGeneratedCommandsInfoEXT generated_commands_info = vku::InitStructHelper();
generated_commands_info.shaderStages = VK_SHADER_STAGE_COMPUTE_BIT;
generated_commands_info.indirectExecutionSet = exe_set.handle();
generated_commands_info.indirectCommandsLayout = command_layout.handle();
generated_commands_info.indirectAddressSize = 64;
generated_commands_info.indirectAddress = block_buffer.Address();
generated_commands_info.sequenceCountAddress = 0;
generated_commands_info.maxSequenceCount = 1;
generated_commands_info.maxDrawCount = 1;
SetPreProcessBuffer(generated_commands_info);
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer.handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipe.Handle());
vk::CmdExecuteGeneratedCommandsEXT(m_command_buffer.handle(), false, &generated_commands_info);
m_command_buffer.End();
}
TEST_F(PositiveDeviceGeneratedCommands, ExecuteShaderObjectVertex) {
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shaderObject);
AddRequiredFeature(vkt::Feature::dynamicRendering);
RETURN_IF_SKIP(InitBasicDeviceGeneratedCommands());
InitRenderTarget();
VkIndirectCommandsExecutionSetTokenEXT exe_set_token = {VK_INDIRECT_EXECUTION_SET_INFO_TYPE_SHADER_OBJECTS_EXT,
VK_SHADER_STAGE_VERTEX_BIT};
VkIndirectCommandsLayoutTokenEXT tokens[2];
tokens[0] = vku::InitStructHelper();
tokens[0].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_EXECUTION_SET_EXT;
tokens[0].data.pExecutionSet = &exe_set_token;
tokens[0].offset = 0;
tokens[1] = vku::InitStructHelper();
tokens[1].type = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_EXT;
tokens[1].offset = 8;
VkIndirectCommandsLayoutCreateInfoEXT command_layout_ci = vku::InitStructHelper();
command_layout_ci.shaderStages = VK_INDIRECT_EXECUTION_SET_INFO_TYPE_SHADER_OBJECTS_EXT;
command_layout_ci.pipelineLayout = VK_NULL_HANDLE;
command_layout_ci.tokenCount = 2;
command_layout_ci.pTokens = tokens;
vkt::IndirectCommandsLayout command_layout(*m_device, command_layout_ci);
const auto vert_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl);
VkShaderCreateInfoEXT vert_create_info =
ShaderCreateInfoFlag(vert_spv, VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT);
const vkt::Shader vertShader(*m_device, vert_create_info);
const VkShaderEXT shaders[] = {vertShader.handle()};
OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}});
VkIndirectExecutionSetShaderLayoutInfoEXT exe_set_layouts = vku::InitStructHelper();
exe_set_layouts.setLayoutCount = 1;
exe_set_layouts.pSetLayouts = &descriptor_set.layout_.handle();
VkIndirectExecutionSetShaderInfoEXT exe_set_shader_info = vku::InitStructHelper();
exe_set_shader_info.shaderCount = 1;
exe_set_shader_info.pInitialShaders = shaders;
exe_set_shader_info.pSetLayoutInfos = &exe_set_layouts;
exe_set_shader_info.maxShaderCount = 1;
exe_set_shader_info.pushConstantRangeCount = 0;
vkt::IndirectExecutionSet exe_set(*m_device, exe_set_shader_info);
VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper();
allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
vkt::Buffer block_buffer(*m_device, 64, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, kHostVisibleMemProps, &allocate_flag_info);
VkGeneratedCommandsInfoEXT generated_commands_info = vku::InitStructHelper();
generated_commands_info.shaderStages = VK_SHADER_STAGE_VERTEX_BIT;
generated_commands_info.indirectExecutionSet = exe_set.handle();
generated_commands_info.indirectCommandsLayout = command_layout.handle();
generated_commands_info.indirectAddressSize = 64;
generated_commands_info.indirectAddress = block_buffer.Address();
generated_commands_info.sequenceCountAddress = 0;
generated_commands_info.maxSequenceCount = 1;
generated_commands_info.maxDrawCount = 1;
SetPreProcessBuffer(generated_commands_info);
m_command_buffer.Begin();
m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea());
const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_VERTEX_BIT};
vk::CmdBindShadersEXT(m_command_buffer.handle(), 1u, stages, shaders);
SetDefaultDynamicStatesAll(m_command_buffer.handle());
vk::CmdExecuteGeneratedCommandsEXT(m_command_buffer.handle(), false, &generated_commands_info);
m_command_buffer.EndRendering();
m_command_buffer.End();
}