mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-02 04:51:26 +12:00
vk: Update shader interpreter to use dynamic binding layout
This commit is contained in:
parent
dd28d100d6
commit
16a0ae6a7b
11 changed files with 200 additions and 386 deletions
|
@ -20,8 +20,9 @@ namespace program_common
|
|||
COMPILER_OPT_ENABLE_KIL = (1 << 11),
|
||||
COMPILER_OPT_ENABLE_STIPPLING = (1 << 12),
|
||||
COMPILER_OPT_ENABLE_INSTANCING = (1 << 13),
|
||||
COMPILER_OPT_ENABLE_VTX_TEXTURES = (1 << 14),
|
||||
|
||||
COMPILER_OPT_MAX = COMPILER_OPT_ENABLE_INSTANCING
|
||||
COMPILER_OPT_MAX = COMPILER_OPT_ENABLE_VTX_TEXTURES
|
||||
};
|
||||
|
||||
static std::string get_vertex_interpreter()
|
||||
|
|
|
@ -8,157 +8,6 @@
|
|||
|
||||
namespace vk
|
||||
{
|
||||
rsx::simple_array<VkDescriptorSetLayoutBinding> get_common_binding_table()
|
||||
{
|
||||
const auto& binding_table = vk::get_current_renderer()->get_pipeline_binding_table();
|
||||
rsx::simple_array<VkDescriptorSetLayoutBinding> bindings(binding_table.instancing_constants_buffer_slot + 1);
|
||||
|
||||
u32 idx = 0;
|
||||
|
||||
// Vertex stream, one stream for cacheable data, one stream for transient data
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
bindings[idx].binding = binding_table.vertex_buffers_first_bind_slot + i;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
idx++;
|
||||
}
|
||||
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[idx].binding = binding_table.fragment_constant_buffers_bind_slot;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[idx].binding = binding_table.fragment_state_bind_slot;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[idx].binding = binding_table.fragment_texture_params_bind_slot;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
bindings[idx].binding = binding_table.vertex_constant_buffers_bind_slot;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS;
|
||||
bindings[idx].binding = binding_table.vertex_params_bind_slot;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
bindings[idx].binding = binding_table.conditional_render_predicate_slot;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[idx].binding = binding_table.rasterizer_env_bind_slot;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
bindings[idx].binding = binding_table.instancing_lookup_table_bind_slot;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
bindings[idx].binding = binding_table.instancing_constants_buffer_slot;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
return bindings;
|
||||
}
|
||||
|
||||
std::tuple<VkPipelineLayout, VkDescriptorSetLayout, rsx::simple_array<VkDescriptorSetLayoutBinding>>
|
||||
get_common_pipeline_layout(VkDevice dev)
|
||||
{
|
||||
const auto& binding_table = vk::get_current_renderer()->get_pipeline_binding_table();
|
||||
auto bindings = get_common_binding_table();
|
||||
u32 idx = ::size32(bindings);
|
||||
|
||||
bindings.resize(binding_table.total_descriptor_bindings);
|
||||
|
||||
for (auto binding = binding_table.textures_first_bind_slot;
|
||||
binding < binding_table.vertex_textures_first_bind_slot;
|
||||
binding++)
|
||||
{
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[idx].binding = binding;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
idx++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rsx::limits::vertex_textures_count; i++)
|
||||
{
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
bindings[idx].binding = binding_table.vertex_textures_first_bind_slot + i;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
idx++;
|
||||
}
|
||||
|
||||
ensure(idx == binding_table.total_descriptor_bindings);
|
||||
|
||||
std::array<VkPushConstantRange, 1> push_constants;
|
||||
push_constants[0].offset = 0;
|
||||
push_constants[0].size = 20;
|
||||
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
|
||||
if (vk::emulate_conditional_rendering())
|
||||
{
|
||||
// Conditional render toggle
|
||||
push_constants[0].size = 24;
|
||||
}
|
||||
|
||||
const auto set_layout = vk::descriptors::create_layout(bindings);
|
||||
|
||||
VkPipelineLayoutCreateInfo layout_info = {};
|
||||
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
layout_info.setLayoutCount = 1;
|
||||
layout_info.pSetLayouts = &set_layout;
|
||||
layout_info.pushConstantRangeCount = 1;
|
||||
layout_info.pPushConstantRanges = push_constants.data();
|
||||
|
||||
VkPipelineLayout result;
|
||||
CHECK_RESULT(vkCreatePipelineLayout(dev, &layout_info, nullptr, &result));
|
||||
return std::make_tuple(result, set_layout, bindings);
|
||||
}
|
||||
|
||||
rsx::simple_array<VkDescriptorPoolSize> get_descriptor_pool_sizes(const rsx::simple_array<VkDescriptorSetLayoutBinding>& bindings)
|
||||
{
|
||||
// Compile descriptor pool sizes
|
||||
|
|
|
@ -5,13 +5,6 @@
|
|||
|
||||
namespace vk
|
||||
{
|
||||
// Grab standard layout for decompiled RSX programs. Also used by the interpreter.
|
||||
// FIXME: This generates a bloated monstrosity that needs to die.
|
||||
std::tuple<VkPipelineLayout, VkDescriptorSetLayout, rsx::simple_array<VkDescriptorSetLayoutBinding>> get_common_pipeline_layout(VkDevice dev);
|
||||
|
||||
// Returns the standard binding layout without texture slots. Those have special handling depending on the consumer.
|
||||
rsx::simple_array<VkDescriptorSetLayoutBinding> get_common_binding_table();
|
||||
|
||||
// Returns an array of pool sizes that can be used to generate a proper descriptor pool
|
||||
rsx::simple_array<VkDescriptorPoolSize> get_descriptor_pool_sizes(const rsx::simple_array<VkDescriptorSetLayoutBinding>& bindings);
|
||||
}
|
||||
|
|
|
@ -555,7 +555,7 @@ bool VKGSRender::bind_texture_env()
|
|||
{
|
||||
m_program->bind_uniform({ fs_sampler_handles[i]->value, view->value, view->image()->current_layout },
|
||||
vk::glsl::binding_set_index_fragment,
|
||||
m_fragment_prog->binding_table.ftex_location[i]);
|
||||
m_fs_binding_table->ftex_location[i]);
|
||||
|
||||
if (current_fragment_program.texture_state.redirected_textures & (1 << i))
|
||||
{
|
||||
|
@ -576,7 +576,7 @@ bool VKGSRender::bind_texture_env()
|
|||
|
||||
m_program->bind_uniform({ m_stencil_mirror_sampler->value, stencil_view->value, stencil_view->image()->current_layout },
|
||||
vk::glsl::binding_set_index_fragment,
|
||||
m_fragment_prog->binding_table.ftex_stencil_location[i]);
|
||||
m_fs_binding_table->ftex_stencil_location[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -584,13 +584,13 @@ bool VKGSRender::bind_texture_env()
|
|||
const VkImageViewType view_type = vk::get_view_type(current_fragment_program.get_texture_dimension(i));
|
||||
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer, view_type)->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
vk::glsl::binding_set_index_fragment,
|
||||
m_fragment_prog->binding_table.ftex_location[i]);
|
||||
m_fs_binding_table->ftex_location[i]);
|
||||
|
||||
if (current_fragment_program.texture_state.redirected_textures & (1 << i))
|
||||
{
|
||||
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer, view_type)->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
vk::glsl::binding_set_index_fragment,
|
||||
m_fragment_prog->binding_table.ftex_stencil_location[i]);
|
||||
m_fs_binding_table->ftex_stencil_location[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -605,7 +605,7 @@ bool VKGSRender::bind_texture_env()
|
|||
const auto view_type = vk::get_view_type(current_vertex_program.get_texture_dimension(i));
|
||||
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer, view_type)->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
vk::glsl::binding_set_index_vertex,
|
||||
m_vertex_prog->binding_table.vtex_location[i]);
|
||||
m_vs_binding_table->vtex_location[i]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -628,7 +628,7 @@ bool VKGSRender::bind_texture_env()
|
|||
|
||||
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(*m_current_command_buffer, view_type)->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
|
||||
vk::glsl::binding_set_index_vertex,
|
||||
m_vertex_prog->binding_table.vtex_location[i]);
|
||||
m_vs_binding_table->vtex_location[i]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -637,7 +637,7 @@ bool VKGSRender::bind_texture_env()
|
|||
|
||||
m_program->bind_uniform({ vs_sampler_handles[i]->value, image_ptr->value, image_ptr->image()->current_layout },
|
||||
vk::glsl::binding_set_index_vertex,
|
||||
m_vertex_prog->binding_table.vtex_location[i]);
|
||||
m_vs_binding_table->vtex_location[i]);
|
||||
}
|
||||
|
||||
return out_of_memory;
|
||||
|
@ -874,10 +874,9 @@ void VKGSRender::emit_geometry(u32 sub_index)
|
|||
ensure(m_vertex_layout_storage);
|
||||
if (update_descriptors)
|
||||
{
|
||||
const auto& binding_table = m_vertex_prog->binding_table;
|
||||
m_program->bind_uniform(persistent_buffer, vk::glsl::binding_set_index_vertex, binding_table.vertex_buffers_location);
|
||||
m_program->bind_uniform(volatile_buffer, vk::glsl::binding_set_index_vertex, binding_table.vertex_buffers_location + 1);
|
||||
m_program->bind_uniform(m_vertex_layout_storage->value, vk::glsl::binding_set_index_vertex, binding_table.vertex_buffers_location + 2);
|
||||
m_program->bind_uniform(persistent_buffer, vk::glsl::binding_set_index_vertex, m_vs_binding_table->vertex_buffers_location);
|
||||
m_program->bind_uniform(volatile_buffer, vk::glsl::binding_set_index_vertex, m_vs_binding_table->vertex_buffers_location + 1);
|
||||
m_program->bind_uniform(m_vertex_layout_storage->value, vk::glsl::binding_set_index_vertex, m_vs_binding_table->vertex_buffers_location + 2);
|
||||
}
|
||||
|
||||
bool reload_state = (!m_current_draw.subdraw_id++);
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace vk
|
|||
class shader_interpreter;
|
||||
}
|
||||
|
||||
struct VKFragmentDecompilerThread : public FragmentProgramDecompiler
|
||||
class VKFragmentDecompilerThread : public FragmentProgramDecompiler
|
||||
{
|
||||
friend class vk::shader_interpreter;
|
||||
|
||||
|
|
|
@ -1780,8 +1780,11 @@ bool VKGSRender::load_program()
|
|||
m_program = m_shader_interpreter.get(
|
||||
m_pipeline_properties,
|
||||
current_fp_metadata,
|
||||
current_vp_metadata,
|
||||
current_vertex_program.ctrl,
|
||||
current_fragment_program.ctrl);
|
||||
|
||||
std::tie(m_vs_binding_table, m_fs_binding_table) = get_binding_table();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1879,6 +1882,7 @@ bool VKGSRender::load_program()
|
|||
m_program = m_shader_interpreter.get(
|
||||
m_pipeline_properties,
|
||||
current_fp_metadata,
|
||||
current_vp_metadata,
|
||||
current_vertex_program.ctrl,
|
||||
current_fragment_program.ctrl);
|
||||
|
||||
|
@ -1900,6 +1904,16 @@ bool VKGSRender::load_program()
|
|||
}
|
||||
}
|
||||
|
||||
if (m_program)
|
||||
{
|
||||
std::tie(m_vs_binding_table, m_fs_binding_table) = get_binding_table();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vs_binding_table = nullptr;
|
||||
m_fs_binding_table = nullptr;
|
||||
}
|
||||
|
||||
return m_program != nullptr;
|
||||
}
|
||||
|
||||
|
@ -1911,13 +1925,14 @@ void VKGSRender::load_program_env()
|
|||
}
|
||||
|
||||
const u32 fragment_constants_size = current_fp_metadata.program_constants_buffer_length;
|
||||
const bool is_interpreter = m_shader_interpreter.is_interpreter(m_program);
|
||||
|
||||
const bool update_transform_constants = !!(m_graphics_state & rsx::pipeline_state::transform_constants_dirty);
|
||||
const bool update_fragment_constants = !!(m_graphics_state & rsx::pipeline_state::fragment_constants_dirty);
|
||||
const bool update_vertex_env = !!(m_graphics_state & rsx::pipeline_state::vertex_state_dirty);
|
||||
const bool update_fragment_env = !!(m_graphics_state & rsx::pipeline_state::fragment_state_dirty);
|
||||
const bool update_fragment_texture_env = !!(m_graphics_state & rsx::pipeline_state::fragment_texture_state_dirty);
|
||||
const bool update_instruction_buffers = (!!m_interpreter_state && m_shader_interpreter.is_interpreter(m_program));
|
||||
const bool update_instruction_buffers = (!!m_interpreter_state && is_interpreter);
|
||||
const bool update_raster_env = (rsx::method_registers.polygon_stipple_enabled() && !!(m_graphics_state & rsx::pipeline_state::polygon_stipple_pattern_dirty));
|
||||
const bool update_instancing_data = rsx::method_registers.current_draw_clause.is_trivial_instanced_draw;
|
||||
|
||||
|
@ -2078,17 +2093,14 @@ void VKGSRender::load_program_env()
|
|||
}
|
||||
}
|
||||
|
||||
const auto& vs_binding_table = m_vertex_prog->binding_table;
|
||||
const auto& fs_binding_table = m_fragment_prog->binding_table;
|
||||
m_program->bind_uniform(m_vertex_env_buffer_info, vk::glsl::binding_set_index_vertex, m_vs_binding_table->context_buffer_location);
|
||||
m_program->bind_uniform(m_fragment_env_buffer_info, vk::glsl::binding_set_index_fragment, m_fs_binding_table->context_buffer_location);
|
||||
m_program->bind_uniform(m_fragment_texture_params_buffer_info, vk::glsl::binding_set_index_fragment, m_fs_binding_table->tex_param_location);
|
||||
m_program->bind_uniform(m_raster_env_buffer_info, vk::glsl::binding_set_index_fragment, m_fs_binding_table->polygon_stipple_params_location);
|
||||
|
||||
m_program->bind_uniform(m_vertex_env_buffer_info, vk::glsl::binding_set_index_vertex, vs_binding_table.context_buffer_location);
|
||||
m_program->bind_uniform(m_fragment_env_buffer_info, vk::glsl::binding_set_index_fragment, fs_binding_table.context_buffer_location);
|
||||
m_program->bind_uniform(m_fragment_texture_params_buffer_info, vk::glsl::binding_set_index_fragment, fs_binding_table.tex_param_location);
|
||||
m_program->bind_uniform(m_raster_env_buffer_info, vk::glsl::binding_set_index_fragment, fs_binding_table.polygon_stipple_params_location);
|
||||
|
||||
if (vs_binding_table.cbuf_location != umax)
|
||||
if (m_vs_binding_table->cbuf_location != umax)
|
||||
{
|
||||
m_program->bind_uniform(m_vertex_constants_buffer_info, vk::glsl::binding_set_index_vertex, vs_binding_table.cbuf_location);
|
||||
m_program->bind_uniform(m_vertex_constants_buffer_info, vk::glsl::binding_set_index_vertex, m_vs_binding_table->cbuf_location);
|
||||
}
|
||||
|
||||
if (m_shader_interpreter.is_interpreter(m_program))
|
||||
|
@ -2096,21 +2108,21 @@ void VKGSRender::load_program_env()
|
|||
m_program->bind_uniform(m_vertex_instructions_buffer_info, vk::glsl::binding_set_index_vertex, m_shader_interpreter.get_vertex_instruction_location());
|
||||
m_program->bind_uniform(m_fragment_instructions_buffer_info, vk::glsl::binding_set_index_fragment, m_shader_interpreter.get_fragment_instruction_location());
|
||||
}
|
||||
else if (fs_binding_table.cbuf_location != umax)
|
||||
else if (m_fs_binding_table->cbuf_location != umax)
|
||||
{
|
||||
m_program->bind_uniform(m_fragment_constants_buffer_info, vk::glsl::binding_set_index_fragment, fs_binding_table.cbuf_location);
|
||||
m_program->bind_uniform(m_fragment_constants_buffer_info, vk::glsl::binding_set_index_fragment, m_fs_binding_table->cbuf_location);
|
||||
}
|
||||
|
||||
if (vk::emulate_conditional_rendering())
|
||||
{
|
||||
auto predicate = m_cond_render_buffer ? m_cond_render_buffer->value : vk::get_scratch_buffer(*m_current_command_buffer, 4)->value;
|
||||
m_program->bind_uniform({ predicate, 0, 4 }, vk::glsl::binding_set_index_vertex, vs_binding_table.cr_pred_buffer_location);
|
||||
m_program->bind_uniform({ predicate, 0, 4 }, vk::glsl::binding_set_index_vertex, m_vs_binding_table->cr_pred_buffer_location);
|
||||
}
|
||||
|
||||
if (current_vertex_program.ctrl & RSX_SHADER_CONTROL_INSTANCED_CONSTANTS)
|
||||
{
|
||||
m_program->bind_uniform(m_instancing_indirection_buffer_info, vk::glsl::binding_set_index_vertex, vs_binding_table.instanced_lut_buffer_location);
|
||||
m_program->bind_uniform(m_instancing_constants_array_buffer_info, vk::glsl::binding_set_index_vertex, vs_binding_table.instanced_cbuf_location);
|
||||
m_program->bind_uniform(m_instancing_indirection_buffer_info, vk::glsl::binding_set_index_vertex, m_vs_binding_table->instanced_lut_buffer_location);
|
||||
m_program->bind_uniform(m_instancing_constants_array_buffer_info, vk::glsl::binding_set_index_vertex, m_vs_binding_table->instanced_cbuf_location);
|
||||
}
|
||||
|
||||
// Clear flags
|
||||
|
@ -2137,6 +2149,19 @@ void VKGSRender::load_program_env()
|
|||
m_graphics_state.clear(handled_flags);
|
||||
}
|
||||
|
||||
std::pair<const vs_binding_table_t*, const fs_binding_table_t*> VKGSRender::get_binding_table() const
|
||||
{
|
||||
ensure(m_program);
|
||||
|
||||
if (!m_shader_interpreter.is_interpreter(m_program))
|
||||
{
|
||||
return { &m_vertex_prog->binding_table, &m_fragment_prog->binding_table };
|
||||
}
|
||||
|
||||
const auto& [vs, fs] = m_shader_interpreter.get_shaders();
|
||||
return { &vs->binding_table, &fs->binding_table };
|
||||
}
|
||||
|
||||
bool VKGSRender::is_current_program_interpreted() const
|
||||
{
|
||||
return m_program && m_shader_interpreter.is_interpreter(m_program);
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
using namespace vk::vmm_allocation_pool_; // clang workaround.
|
||||
using namespace vk::upscaling_flags_; // ditto
|
||||
|
||||
using vs_binding_table_t = decltype(VKVertexProgram::binding_table);
|
||||
using fs_binding_table_t = decltype(VKFragmentProgram::binding_table);
|
||||
|
||||
namespace vk
|
||||
{
|
||||
using host_data_t = rsx::host_gpu_context_t;
|
||||
|
@ -53,6 +56,9 @@ private:
|
|||
vk::glsl::program *m_prev_program = nullptr;
|
||||
vk::pipeline_props m_pipeline_properties;
|
||||
|
||||
const vs_binding_table_t* m_vs_binding_table = nullptr;
|
||||
const fs_binding_table_t* m_fs_binding_table = nullptr;
|
||||
|
||||
vk::texture_cache m_texture_cache;
|
||||
vk::surface_cache m_rtts;
|
||||
|
||||
|
@ -78,6 +84,8 @@ private:
|
|||
VkDependencyInfoKHR m_async_compute_dependency_info {};
|
||||
VkMemoryBarrier2KHR m_async_compute_memory_barrier {};
|
||||
|
||||
std::pair<const vs_binding_table_t*, const fs_binding_table_t*> get_binding_table() const;
|
||||
|
||||
public:
|
||||
//vk::fbo draw_fbo;
|
||||
std::unique_ptr<vk::vertex_cache> m_vertex_cache;
|
||||
|
|
|
@ -12,23 +12,70 @@
|
|||
|
||||
namespace vk
|
||||
{
|
||||
glsl::shader* shader_interpreter::build_vs(u64 compiler_options)
|
||||
u32 shader_interpreter::init(VKVertexProgram* vk_prog, u64 compiler_options) const
|
||||
{
|
||||
std::memset(&vk_prog->binding_table, 0xff, sizeof(vk_prog->binding_table));
|
||||
|
||||
u32 location = 0;
|
||||
vk_prog->binding_table.vertex_buffers_location = location;
|
||||
location += 3;
|
||||
|
||||
vk_prog->binding_table.context_buffer_location = location++;
|
||||
|
||||
if (vk::emulate_conditional_rendering())
|
||||
{
|
||||
vk_prog->binding_table.cr_pred_buffer_location = location++;
|
||||
}
|
||||
|
||||
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING)
|
||||
{
|
||||
vk_prog->binding_table.instanced_lut_buffer_location = location++;
|
||||
vk_prog->binding_table.instanced_cbuf_location = location++;
|
||||
}
|
||||
else
|
||||
{
|
||||
vk_prog->binding_table.cbuf_location = location++;
|
||||
}
|
||||
|
||||
if (vk::emulate_conditional_rendering())
|
||||
{
|
||||
vk_prog->binding_table.cr_pred_buffer_location = location++;
|
||||
}
|
||||
|
||||
// Return next index
|
||||
return location;
|
||||
}
|
||||
|
||||
u32 shader_interpreter::init(VKFragmentProgram* vk_prog, u64 compiler_opt) const
|
||||
{
|
||||
std::memset(&vk_prog->binding_table, 0xff, sizeof(vk_prog->binding_table));
|
||||
|
||||
vk_prog->binding_table.context_buffer_location = 0;
|
||||
vk_prog->binding_table.tex_param_location = 1;
|
||||
vk_prog->binding_table.polygon_stipple_params_location = 2;
|
||||
|
||||
// Return next index
|
||||
return 3;
|
||||
}
|
||||
|
||||
VKVertexProgram* shader_interpreter::build_vs(u64 compiler_options)
|
||||
{
|
||||
::glsl::shader_properties properties{};
|
||||
properties.domain = ::glsl::program_domain::glsl_vertex_program;
|
||||
properties.require_lit_emulation = true;
|
||||
|
||||
// TODO: Extend decompiler thread
|
||||
// TODO: Rename decompiler thread, it no longer spawns a thread
|
||||
RSXVertexProgram null_prog;
|
||||
std::string shader_str;
|
||||
ParamArray arr;
|
||||
VKVertexProgram vk_prog;
|
||||
|
||||
// Initialize binding layout
|
||||
auto vk_prog = std::make_unique<VKVertexProgram>();
|
||||
m_vertex_instruction_start = init(vk_prog.get(), compiler_options);
|
||||
|
||||
null_prog.ctrl = (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING)
|
||||
? RSX_SHADER_CONTROL_INSTANCED_CONSTANTS
|
||||
: 0;
|
||||
VKVertexDecompilerThread comp(null_prog, shader_str, arr, vk_prog);
|
||||
VKVertexDecompilerThread comp(null_prog, shader_str, arr, *vk_prog);
|
||||
|
||||
// Initialize compiler properties
|
||||
comp.properties.has_indexed_constants = true;
|
||||
|
@ -52,6 +99,12 @@ namespace vk
|
|||
" uvec4 vp_instructions[];\n"
|
||||
"};\n\n";
|
||||
|
||||
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_VTX_TEXTURES)
|
||||
{
|
||||
// FIXME: Unimplemented
|
||||
rsx_log.todo("Vertex textures are currently not implemented for the shader interpreter.");
|
||||
}
|
||||
|
||||
if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING)
|
||||
{
|
||||
builder << "#define _ENABLE_INSTANCED_CONSTANTS\n";
|
||||
|
@ -68,48 +121,29 @@ namespace vk
|
|||
builder << program_common::interpreter::get_vertex_interpreter();
|
||||
const std::string s = builder.str();
|
||||
|
||||
auto vs = std::make_unique<glsl::shader>();
|
||||
auto vs = &vk_prog->shader;
|
||||
vs->create(::glsl::program_domain::glsl_vertex_program, s);
|
||||
vs->compile();
|
||||
|
||||
// Prepare input table
|
||||
const auto& binding_table = vk::get_current_renderer()->get_pipeline_binding_table();
|
||||
// Declare local inputs
|
||||
auto vs_inputs = comp.get_inputs();
|
||||
|
||||
vk::glsl::program_input in;
|
||||
|
||||
in.location = binding_table.vertex_params_bind_slot;
|
||||
in.set = 0;
|
||||
in.domain = ::glsl::glsl_vertex_program;
|
||||
in.name = "VertexContextBuffer";
|
||||
in.type = vk::glsl::input_type_uniform_buffer;
|
||||
m_vs_inputs.push_back(in);
|
||||
in.location = m_vertex_instruction_start;
|
||||
in.type = glsl::input_type_storage_buffer;
|
||||
in.name = "VertexInstructionBlock";
|
||||
vs_inputs.push_back(in);
|
||||
|
||||
in.location = binding_table.vertex_buffers_first_bind_slot;
|
||||
in.name = "persistent_input_stream";
|
||||
in.type = vk::glsl::input_type_texel_buffer;
|
||||
m_vs_inputs.push_back(in);
|
||||
vk_prog->SetInputs(vs_inputs);
|
||||
|
||||
in.location = binding_table.vertex_buffers_first_bind_slot + 1;
|
||||
in.name = "volatile_input_stream";
|
||||
in.type = vk::glsl::input_type_texel_buffer;
|
||||
m_vs_inputs.push_back(in);
|
||||
|
||||
in.location = binding_table.vertex_buffers_first_bind_slot + 2;
|
||||
in.name = "vertex_layout_stream";
|
||||
in.type = vk::glsl::input_type_texel_buffer;
|
||||
m_vs_inputs.push_back(in);
|
||||
|
||||
in.location = binding_table.vertex_constant_buffers_bind_slot;
|
||||
in.name = "VertexConstantsBuffer";
|
||||
in.type = vk::glsl::input_type_uniform_buffer;
|
||||
m_vs_inputs.push_back(in);
|
||||
|
||||
// TODO: Bind textures if needed
|
||||
|
||||
auto ret = vs.get();
|
||||
m_shader_cache[compiler_options].m_vs = std::move(vs);
|
||||
auto ret = vk_prog.get();
|
||||
m_shader_cache[compiler_options].m_vs = std::move(vk_prog);
|
||||
return ret;
|
||||
}
|
||||
|
||||
glsl::shader* shader_interpreter::build_fs(u64 compiler_options)
|
||||
VKFragmentProgram* shader_interpreter::build_fs(u64 compiler_options)
|
||||
{
|
||||
[[maybe_unused]] ::glsl::shader_properties properties{};
|
||||
properties.domain = ::glsl::program_domain::glsl_fragment_program;
|
||||
|
@ -120,10 +154,13 @@ namespace vk
|
|||
ParamArray arr;
|
||||
std::string shader_str;
|
||||
RSXFragmentProgram frag;
|
||||
VKFragmentProgram vk_prog;
|
||||
VKFragmentDecompilerThread comp(shader_str, arr, frag, len, vk_prog);
|
||||
|
||||
const auto& binding_table = vk::get_current_renderer()->get_pipeline_binding_table();
|
||||
auto vk_prog = std::make_unique<VKFragmentProgram>();
|
||||
m_fragment_instruction_start = init(vk_prog.get(), compiler_options);
|
||||
m_fragment_textures_start = m_fragment_instruction_start + 1;
|
||||
|
||||
VKFragmentDecompilerThread comp(shader_str, arr, frag, len, *vk_prog);
|
||||
|
||||
std::stringstream builder;
|
||||
builder <<
|
||||
"#version 450\n"
|
||||
|
@ -199,7 +236,7 @@ namespace vk
|
|||
|
||||
for (int i = 0, bind_location = m_fragment_textures_start; i < 4; ++i)
|
||||
{
|
||||
builder << "layout(set=0, binding=" << bind_location++ << ") " << "uniform " << type_names[i] << " " << type_names[i] << "_array[16];\n";
|
||||
builder << "layout(set=1, binding=" << bind_location++ << ") " << "uniform " << type_names[i] << " " << type_names[i] << "_array[16];\n";
|
||||
}
|
||||
|
||||
builder << "\n"
|
||||
|
@ -211,7 +248,7 @@ namespace vk
|
|||
}
|
||||
|
||||
builder <<
|
||||
"layout(std430, binding=" << m_fragment_instruction_start << ") readonly restrict buffer FragmentInstructionBlock\n"
|
||||
"layout(std430, set=1, binding=" << m_fragment_instruction_start << ") readonly restrict buffer FragmentInstructionBlock\n"
|
||||
"{\n"
|
||||
" uint shader_control;\n"
|
||||
" uint texture_control;\n"
|
||||
|
@ -223,140 +260,35 @@ namespace vk
|
|||
builder << program_common::interpreter::get_fragment_interpreter();
|
||||
const std::string s = builder.str();
|
||||
|
||||
auto fs = std::make_unique<glsl::shader>();
|
||||
auto fs = &vk_prog->shader;
|
||||
fs->create(::glsl::program_domain::glsl_fragment_program, s);
|
||||
fs->compile();
|
||||
|
||||
// Prepare input table
|
||||
// Declare local inputs
|
||||
auto inputs = comp.get_inputs();
|
||||
|
||||
vk::glsl::program_input in;
|
||||
in.location = binding_table.fragment_constant_buffers_bind_slot;
|
||||
in.set = 1;
|
||||
in.domain = ::glsl::glsl_fragment_program;
|
||||
in.name = "FragmentConstantsBuffer";
|
||||
in.type = vk::glsl::input_type_uniform_buffer;
|
||||
m_fs_inputs.push_back(in);
|
||||
|
||||
in.location = binding_table.fragment_state_bind_slot;
|
||||
in.name = "FragmentStateBuffer";
|
||||
m_fs_inputs.push_back(in);
|
||||
|
||||
in.location = binding_table.fragment_texture_params_bind_slot;
|
||||
in.name = "TextureParametersBuffer";
|
||||
m_fs_inputs.push_back(in);
|
||||
in.location = m_fragment_instruction_start;
|
||||
in.type = glsl::input_type_storage_buffer;
|
||||
in.name = "FragmentInstructionBlock";
|
||||
inputs.push_back(in);
|
||||
|
||||
for (int i = 0, location = m_fragment_textures_start; i < 4; ++i, ++location)
|
||||
{
|
||||
in.location = location;
|
||||
in.name = std::string(type_names[i]) + "_array[16]";
|
||||
m_fs_inputs.push_back(in);
|
||||
in.type = glsl::input_type_texture;
|
||||
inputs.push_back(in);
|
||||
}
|
||||
|
||||
auto ret = fs.get();
|
||||
m_shader_cache[compiler_options].m_fs = std::move(fs);
|
||||
vk_prog->SetInputs(inputs);
|
||||
|
||||
auto ret = vk_prog.get();
|
||||
m_shader_cache[compiler_options].m_fs = std::move(vk_prog);
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
std::pair<VkDescriptorSetLayout, VkPipelineLayout> shader_interpreter::create_layout(VkDevice dev)
|
||||
{
|
||||
const auto& binding_table = vk::get_current_renderer()->get_pipeline_binding_table();
|
||||
auto bindings = get_common_binding_table();
|
||||
u32 idx = ::size32(bindings);
|
||||
|
||||
bindings.resize(binding_table.total_descriptor_bindings);
|
||||
|
||||
// Texture 1D array
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
bindings[idx].descriptorCount = 16;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[idx].binding = binding_table.textures_first_bind_slot;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
m_fragment_textures_start = bindings[idx].binding;
|
||||
idx++;
|
||||
|
||||
// Texture 2D array
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
bindings[idx].descriptorCount = 16;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[idx].binding = binding_table.textures_first_bind_slot + 1;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
// Texture 3D array
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
bindings[idx].descriptorCount = 16;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[idx].binding = binding_table.textures_first_bind_slot + 2;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
// Texture CUBE array
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
bindings[idx].descriptorCount = 16;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[idx].binding = binding_table.textures_first_bind_slot + 3;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
// Vertex texture array (2D only)
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
bindings[idx].descriptorCount = 4;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
bindings[idx].binding = binding_table.textures_first_bind_slot + 4;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
idx++;
|
||||
|
||||
// Vertex program ucode block
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
bindings[idx].binding = binding_table.textures_first_bind_slot + 5;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
m_vertex_instruction_start = bindings[idx].binding;
|
||||
idx++;
|
||||
|
||||
// Fragment program ucode block
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings[idx].binding = binding_table.textures_first_bind_slot + 6;
|
||||
bindings[idx].pImmutableSamplers = nullptr;
|
||||
|
||||
m_fragment_instruction_start = bindings[idx].binding;
|
||||
idx++;
|
||||
bindings.resize(idx);
|
||||
|
||||
m_descriptor_pool_sizes = get_descriptor_pool_sizes(bindings);
|
||||
|
||||
std::array<VkPushConstantRange, 1> push_constants;
|
||||
push_constants[0].offset = 0;
|
||||
push_constants[0].size = 16;
|
||||
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
|
||||
if (vk::emulate_conditional_rendering())
|
||||
{
|
||||
// Conditional render toggle
|
||||
push_constants[0].size = 20;
|
||||
}
|
||||
|
||||
const auto set_layout = vk::descriptors::create_layout(bindings);
|
||||
|
||||
VkPipelineLayoutCreateInfo layout_info = {};
|
||||
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
layout_info.setLayoutCount = 1;
|
||||
layout_info.pSetLayouts = &set_layout;
|
||||
layout_info.pushConstantRangeCount = 1;
|
||||
layout_info.pPushConstantRanges = push_constants.data();
|
||||
|
||||
VkPipelineLayout result;
|
||||
CHECK_RESULT(vkCreatePipelineLayout(dev, &layout_info, nullptr, &result));
|
||||
return { set_layout, result };
|
||||
}
|
||||
*/
|
||||
|
||||
void shader_interpreter::init(const vk::render_device& dev)
|
||||
{
|
||||
|
@ -366,19 +298,14 @@ namespace vk
|
|||
void shader_interpreter::destroy()
|
||||
{
|
||||
m_program_cache.clear();
|
||||
|
||||
for (auto &fs : m_shader_cache)
|
||||
{
|
||||
fs.second.m_vs->destroy();
|
||||
fs.second.m_fs->destroy();
|
||||
}
|
||||
|
||||
m_shader_cache.clear();
|
||||
}
|
||||
|
||||
glsl::program* shader_interpreter::link(const vk::pipeline_props& properties, u64 compiler_opt)
|
||||
{
|
||||
glsl::shader *fs, *vs;
|
||||
VKVertexProgram* vs;
|
||||
VKFragmentProgram* fs;
|
||||
|
||||
if (auto found = m_shader_cache.find(compiler_opt); found != m_shader_cache.end())
|
||||
{
|
||||
fs = found->second.m_fs.get();
|
||||
|
@ -393,12 +320,12 @@ namespace vk
|
|||
VkPipelineShaderStageCreateInfo shader_stages[2] = {};
|
||||
shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
shader_stages[0].module = vs->get_handle();
|
||||
shader_stages[0].module = vs->shader.get_handle();
|
||||
shader_stages[0].pName = "main";
|
||||
|
||||
shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
shader_stages[1].module = fs->get_handle();
|
||||
shader_stages[1].module = fs->shader.get_handle();
|
||||
shader_stages[1].pName = "main";
|
||||
|
||||
std::vector<VkDynamicState> dynamic_state_descriptors =
|
||||
|
@ -464,7 +391,13 @@ namespace vk
|
|||
info.renderPass = vk::get_renderpass(m_device, properties.renderpass_key);
|
||||
|
||||
auto compiler = vk::get_pipe_compiler();
|
||||
auto program = compiler->compile(info, vk::pipe_compiler::COMPILE_INLINE, {}, m_vs_inputs, m_fs_inputs);
|
||||
auto program = compiler->compile(
|
||||
info,
|
||||
vk::pipe_compiler::COMPILE_INLINE | vk::pipe_compiler::SEPARATE_SHADER_OBJECTS,
|
||||
{},
|
||||
vs->uniforms,
|
||||
fs->uniforms);
|
||||
|
||||
return program.release();
|
||||
}
|
||||
|
||||
|
@ -486,7 +419,8 @@ namespace vk
|
|||
|
||||
glsl::program* shader_interpreter::get(
|
||||
const vk::pipeline_props& properties,
|
||||
const program_hash_util::fragment_program_utils::fragment_program_metadata& metadata,
|
||||
const program_hash_util::fragment_program_utils::fragment_program_metadata& fp_metadata,
|
||||
const program_hash_util::vertex_program_utils::vertex_program_metadata& vp_metadata,
|
||||
u32 vp_ctrl,
|
||||
u32 fp_ctrl)
|
||||
{
|
||||
|
@ -526,11 +460,12 @@ namespace vk
|
|||
if (fp_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_DEPTH_EXPORT;
|
||||
if (fp_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_F32_EXPORT;
|
||||
if (fp_ctrl & RSX_SHADER_CONTROL_USES_KIL) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_KIL;
|
||||
if (metadata.referenced_textures_mask) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES;
|
||||
if (metadata.has_branch_instructions) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_FLOW_CTRL;
|
||||
if (metadata.has_pack_instructions) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_PACKING;
|
||||
if (fp_metadata.referenced_textures_mask) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES;
|
||||
if (fp_metadata.has_branch_instructions) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_FLOW_CTRL;
|
||||
if (fp_metadata.has_pack_instructions) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_PACKING;
|
||||
if (rsx::method_registers.polygon_stipple_enabled()) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_STIPPLING;
|
||||
if (vp_ctrl & RSX_SHADER_CONTROL_INSTANCED_CONSTANTS) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING;
|
||||
if (vp_metadata.referenced_textures_mask) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_VTX_TEXTURES;
|
||||
|
||||
if (m_current_key == key) [[likely]]
|
||||
{
|
||||
|
@ -567,4 +502,16 @@ namespace vk
|
|||
{
|
||||
return m_fragment_instruction_start;
|
||||
}
|
||||
|
||||
std::pair<VKVertexProgram*, VKFragmentProgram*> shader_interpreter::get_shaders() const
|
||||
{
|
||||
if (auto found = m_shader_cache.find(m_current_key.compiler_opt); found != m_shader_cache.end())
|
||||
{
|
||||
auto fs = found->second.m_fs.get();
|
||||
auto vs = found->second.m_vs.get();
|
||||
return { vs, fs };
|
||||
}
|
||||
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
#include "vkutils/descriptors.h"
|
||||
#include <unordered_map>
|
||||
|
||||
class VKVertexProgram;
|
||||
class VKFragmentProgram;
|
||||
|
||||
namespace vk
|
||||
{
|
||||
using ::program_hash_util::fragment_program_utils;
|
||||
|
@ -12,9 +15,6 @@ namespace vk
|
|||
|
||||
class shader_interpreter
|
||||
{
|
||||
std::vector<glsl::program_input> m_vs_inputs;
|
||||
std::vector<glsl::program_input> m_fs_inputs;
|
||||
|
||||
VkDevice m_device = VK_NULL_HANDLE;
|
||||
glsl::program* m_current_interpreter = nullptr;
|
||||
|
||||
|
@ -39,8 +39,8 @@ namespace vk
|
|||
|
||||
struct shader_cache_entry_t
|
||||
{
|
||||
std::unique_ptr<glsl::shader> m_fs;
|
||||
std::unique_ptr<glsl::shader> m_vs;
|
||||
std::unique_ptr<VKFragmentProgram> m_fs;
|
||||
std::unique_ptr<VKVertexProgram> m_vs;
|
||||
};
|
||||
|
||||
std::unordered_map<pipeline_key, std::unique_ptr<glsl::program>, key_hasher> m_program_cache;
|
||||
|
@ -52,20 +52,27 @@ namespace vk
|
|||
|
||||
pipeline_key m_current_key{};
|
||||
|
||||
glsl::shader* build_vs(u64 compiler_opt);
|
||||
glsl::shader* build_fs(u64 compiler_opt);
|
||||
VKVertexProgram* build_vs(u64 compiler_opt);
|
||||
VKFragmentProgram* build_fs(u64 compiler_opt);
|
||||
glsl::program* link(const vk::pipeline_props& properties, u64 compiler_opt);
|
||||
|
||||
u32 init(VKVertexProgram* vk_prog, u64 compiler_opt) const;
|
||||
u32 init(VKFragmentProgram* vk_prog, u64 compiler_opt) const;
|
||||
|
||||
public:
|
||||
void init(const vk::render_device& dev);
|
||||
void destroy();
|
||||
|
||||
glsl::program* get(
|
||||
const vk::pipeline_props& properties,
|
||||
const program_hash_util::fragment_program_utils::fragment_program_metadata& metadata,
|
||||
const program_hash_util::fragment_program_utils::fragment_program_metadata& fp_metadata,
|
||||
const program_hash_util::vertex_program_utils::vertex_program_metadata& vp_metadata,
|
||||
u32 vp_ctrl,
|
||||
u32 fp_ctrl);
|
||||
|
||||
// Retrieve the shader components that make up the current interpreter
|
||||
std::pair<VKVertexProgram*, VKFragmentProgram*> get_shaders() const;
|
||||
|
||||
bool is_interpreter(const glsl::program* prog) const;
|
||||
|
||||
u32 get_vertex_instruction_location() const;
|
||||
|
|
|
@ -813,7 +813,6 @@ namespace vk
|
|||
|
||||
memory_map = vk::get_memory_mapping(pdev);
|
||||
m_formats_support = vk::get_optimal_tiling_supported_formats(pdev);
|
||||
m_pipeline_binding_table = vk::get_pipeline_binding_table(pdev);
|
||||
|
||||
if (g_cfg.video.disable_vulkan_mem_allocator)
|
||||
{
|
||||
|
@ -1148,15 +1147,4 @@ namespace vk
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
pipeline_binding_table get_pipeline_binding_table(const vk::physical_device& dev)
|
||||
{
|
||||
pipeline_binding_table result{};
|
||||
|
||||
// Need to check how many samplers are supported by the driver
|
||||
const auto usable_samplers = std::min(dev.get_limits().maxPerStageDescriptorSampledImages, 32u);
|
||||
result.vertex_textures_first_bind_slot = result.textures_first_bind_slot + usable_samplers;
|
||||
result.total_descriptor_bindings = result.vertex_textures_first_bind_slot + 4;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,7 +137,6 @@ namespace vk
|
|||
physical_device* pgpu = nullptr;
|
||||
memory_type_mapping memory_map{};
|
||||
gpu_formats_support m_formats_support{};
|
||||
pipeline_binding_table m_pipeline_binding_table{};
|
||||
std::unique_ptr<mem_allocator_base> m_allocator;
|
||||
VkDevice dev = VK_NULL_HANDLE;
|
||||
|
||||
|
@ -168,7 +167,6 @@ namespace vk
|
|||
const physical_device& gpu() const { return *pgpu; }
|
||||
const memory_type_mapping& get_memory_mapping() const { return memory_map; }
|
||||
const gpu_formats_support& get_formats_support() const { return m_formats_support; }
|
||||
const pipeline_binding_table& get_pipeline_binding_table() const { return m_pipeline_binding_table; }
|
||||
const gpu_shader_types_support& get_shader_types_support() const { return pgpu->shader_types_support; }
|
||||
const custom_border_color_features& get_custom_border_color_support() const { return pgpu->custom_border_color_support; }
|
||||
const multidraw_features get_multidraw_support() const { return pgpu->multidraw_support; }
|
||||
|
@ -206,7 +204,6 @@ namespace vk
|
|||
|
||||
memory_type_mapping get_memory_mapping(const physical_device& dev);
|
||||
gpu_formats_support get_optimal_tiling_supported_formats(const physical_device& dev);
|
||||
pipeline_binding_table get_pipeline_binding_table(const physical_device& dev);
|
||||
|
||||
extern const render_device* g_render_device;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue