rsx: Reimplement vertex layout streaming

- Remove string comparisons from the hot-path!
- Use attribute streaming and push constants to avoid forcing a descriptor block copy every other draw call/pass.
  While this isn't so bad on nvidia cards, it makes AMD cards a slideshow.
This commit is contained in:
kd-11 2019-06-18 16:38:50 +03:00 committed by kd-11
parent 59ee74a275
commit 6a32f716db
7 changed files with 140 additions and 96 deletions

View file

@ -366,20 +366,36 @@ namespace glsl
" // [32-60] starting offset\n" " // [32-60] starting offset\n"
" // [60-61] swap bytes flag\n" " // [60-61] swap bytes flag\n"
" // [61-62] volatile flag\n" " // [61-62] volatile flag\n"
" // [62-63] modulo enable flag\n" " // [62-63] modulo enable flag\n";
" int block = (location >> 1);\n"
" int sub_block = (location & 1) << 1;\n" if (rules == glsl_rules_opengl4)
" uint attrib0 = ref(input_attributes_blob[block], sub_block + 0);\n" {
" uint attrib1 = ref(input_attributes_blob[block], sub_block + 1);\n" // Data is packed into a ubo
OS <<
" int block = (location >> 1);\n"
" int sub_block = (location & 1) << 1;\n"
" uvec2 attrib = uvec2(\n"
" ref(input_attributes_blob[block], sub_block + 0),\n"
" ref(input_attributes_blob[block], sub_block + 1));\n";
}
else
{
// Fetch parameters streamed separately from draw parameters
OS <<
" location += int(layout_ptr_offset);\n"
" uvec2 attrib = texelFetch(vertex_layout_stream, location).xy;\n\n";
}
OS <<
" attribute_desc result;\n" " attribute_desc result;\n"
" result.stride = attrib0 & 0xFF;\n" " result.stride = attrib.x & 0xFF;\n"
" result.frequency = (attrib0 >> 8) & 0xFFFF;\n" " result.frequency = (attrib.x >> 8) & 0xFFFF;\n"
" result.type = (attrib0 >> 24) & 0x7;\n" " result.type = (attrib.x >> 24) & 0x7;\n"
" result.attribute_size = (attrib0 >> 27) & 0x7;\n" " result.attribute_size = (attrib.x >> 27) & 0x7;\n"
" result.starting_offset = (attrib1 & 0x1FFFFFFF);\n" " result.starting_offset = (attrib.y & 0x1FFFFFFF);\n"
" result.swap_bytes = ((attrib1 >> 29) & 0x1) != 0;\n" " result.swap_bytes = ((attrib.y >> 29) & 0x1) != 0;\n"
" result.is_volatile = ((attrib1 >> 30) & 0x1) != 0;\n" " result.is_volatile = ((attrib.y >> 30) & 0x1) != 0;\n"
" result.modulo = ((attrib1 >> 31) & 0x1) != 0;\n" " result.modulo = ((attrib.y >> 31) & 0x1) != 0;\n"
" return result;\n" " return result;\n"
"}\n\n" "}\n\n"

View file

@ -185,13 +185,13 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
if (!constants_block.empty()) if (!constants_block.empty())
{ {
OS << "layout(std140, set = 0, binding = 3) uniform FragmentConstantsBuffer\n"; OS << "layout(std140, set = 0, binding = 2) uniform FragmentConstantsBuffer\n";
OS << "{\n"; OS << "{\n";
OS << constants_block; OS << constants_block;
OS << "};\n\n"; OS << "};\n\n";
} }
OS << "layout(std140, set = 0, binding = 4) uniform FragmentStateBuffer\n"; OS << "layout(std140, set = 0, binding = 3) uniform FragmentStateBuffer\n";
OS << "{\n"; OS << "{\n";
OS << " float fog_param0;\n"; OS << " float fog_param0;\n";
OS << " float fog_param1;\n"; OS << " float fog_param1;\n";
@ -203,7 +203,7 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
OS << " float wpos_bias;\n"; OS << " float wpos_bias;\n";
OS << "};\n\n"; OS << "};\n\n";
OS << "layout(std140, set = 0, binding = 5) uniform TextureParametersBuffer\n"; OS << "layout(std140, set = 0, binding = 4) uniform TextureParametersBuffer\n";
OS << "{\n"; OS << "{\n";
OS << " vec4 texture_parameters[16];\n"; OS << " vec4 texture_parameters[16];\n";
OS << "};\n\n"; OS << "};\n\n";

View file

@ -279,7 +279,7 @@ namespace
size_t idx = 0; size_t idx = 0;
// Vertex stream, one stream for cacheable data, one stream for transient data // Vertex stream, one stream for cacheable data, one stream for transient data
for (int i = 0; i < 2; i++) for (int i = 0; i < 3; i++)
{ {
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
bindings[idx].descriptorCount = 1; bindings[idx].descriptorCount = 1;
@ -316,13 +316,6 @@ namespace
idx++; idx++;
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
bindings[idx].descriptorCount = 1;
bindings[idx].stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS;
bindings[idx].binding = VERTEX_LAYOUT_BIND_SLOT;
idx++;
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
bindings[idx].descriptorCount = 1; bindings[idx].descriptorCount = 1;
bindings[idx].stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; bindings[idx].stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS;
@ -350,6 +343,11 @@ namespace
verify(HERE), idx == VK_NUM_DESCRIPTOR_BINDINGS; verify(HERE), idx == VK_NUM_DESCRIPTOR_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;
VkDescriptorSetLayoutCreateInfo infos = {}; VkDescriptorSetLayoutCreateInfo infos = {};
infos.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; infos.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
infos.pBindings = bindings.data(); infos.pBindings = bindings.data();
@ -362,6 +360,8 @@ namespace
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_info.setLayoutCount = 1; layout_info.setLayoutCount = 1;
layout_info.pSetLayouts = &set_layout; layout_info.pSetLayouts = &set_layout;
layout_info.pushConstantRangeCount = 1;
layout_info.pPushConstantRanges = push_constants.data();
VkPipelineLayout result; VkPipelineLayout result;
CHECK_RESULT(vkCreatePipelineLayout(dev, &layout_info, nullptr, &result)); CHECK_RESULT(vkCreatePipelineLayout(dev, &layout_info, nullptr, &result));
@ -491,7 +491,7 @@ VKGSRender::VKGSRender() : GSRender()
m_fragment_env_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment env buffer"); m_fragment_env_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment env buffer");
m_vertex_env_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "vertex env buffer"); m_vertex_env_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "vertex env buffer");
m_fragment_texture_params_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment texture params buffer"); m_fragment_texture_params_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment texture params buffer");
m_vertex_layout_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "vertex layout buffer"); m_vertex_layout_ring_info.create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "vertex layout buffer");
m_fragment_constants_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment constants buffer"); m_fragment_constants_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment constants buffer");
m_transform_constants_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_TRANSFORM_CONSTANTS_BUFFER_SIZE_M * 0x100000, "transform constants buffer"); m_transform_constants_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_TRANSFORM_CONSTANTS_BUFFER_SIZE_M * 0x100000, "transform constants buffer");
m_index_buffer_ring_info.create(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_INDEX_RING_BUFFER_SIZE_M * 0x100000, "index buffer"); m_index_buffer_ring_info.create(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_INDEX_RING_BUFFER_SIZE_M * 0x100000, "index buffer");
@ -588,6 +588,7 @@ VKGSRender::~VKGSRender()
m_persistent_attribute_storage.reset(); m_persistent_attribute_storage.reset();
m_volatile_attribute_storage.reset(); m_volatile_attribute_storage.reset();
m_vertex_layout_storage.reset();
//Global resources //Global resources
vk::destroy_global_resources(); vk::destroy_global_resources();
@ -1050,23 +1051,22 @@ void VKGSRender::emit_geometry(u32 sub_index)
if (sub_index == 0) if (sub_index == 0)
{ {
analyse_inputs_interleaved(m_vertex_layout); analyse_inputs_interleaved(m_vertex_layout);
}
if (!m_vertex_layout.validate()) if (!m_vertex_layout.validate())
{
// No vertex inputs enabled
// Execute remainining pipeline barriers with NOP draw
do
{ {
draw_call.execute_pipeline_dependencies(); // No vertex inputs enabled
// Execute remainining pipeline barriers with NOP draw
do
{
draw_call.execute_pipeline_dependencies();
}
while (draw_call.next());
draw_call.end();
return;
} }
while (draw_call.next());
draw_call.end();
return;
} }
else if (draw_call.execute_pipeline_dependencies() & rsx::vertex_base_changed)
if (sub_index > 0 && draw_call.execute_pipeline_dependencies() & rsx::vertex_base_changed)
{ {
// Rebase vertex bases instead of // Rebase vertex bases instead of
for (auto &info : m_vertex_layout.interleaved_blocks) for (auto &info : m_vertex_layout.interleaved_blocks)
@ -1092,18 +1092,21 @@ void VKGSRender::emit_geometry(u32 sub_index)
auto persistent_buffer = m_persistent_attribute_storage ? m_persistent_attribute_storage->value : null_buffer_view->value; auto persistent_buffer = m_persistent_attribute_storage ? m_persistent_attribute_storage->value : null_buffer_view->value;
auto volatile_buffer = m_volatile_attribute_storage ? m_volatile_attribute_storage->value : null_buffer_view->value; auto volatile_buffer = m_volatile_attribute_storage ? m_volatile_attribute_storage->value : null_buffer_view->value;
auto layout_stream = m_vertex_layout_storage ? m_vertex_layout_storage->value : null_buffer_view->value;
bool update_descriptors = false; bool update_descriptors = false;
if (sub_index == 0) if (sub_index == 0)
{ {
update_descriptors = true; update_descriptors = true;
// Allocate stream layout memory for this batch
m_vertex_layout_stream_info.range = rsx::method_registers.current_draw_clause.pass_count() * 128;
m_vertex_layout_stream_info.offset = m_vertex_layout_ring_info.alloc<256>(m_vertex_layout_stream_info.range);
// m_vertex_layout_stream_info.buffer = m_vertex_layout_ring_info.heap->value;
} }
else else if (persistent_buffer != old_persistent_buffer || volatile_buffer != old_volatile_buffer)
{ {
// Vertex env update will change information in the descriptor set // Need to update descriptors; make a copy for the next draw
// Make a copy for the next draw call
// TODO: Restructure program to allow use of push constants when possible
// NOTE: AMD has insuffecient push constants buffer memory which is unfortunate
VkDescriptorSet new_descriptor_set = allocate_descriptor_set(); VkDescriptorSet new_descriptor_set = allocate_descriptor_set();
std::array<VkCopyDescriptorSet, VK_NUM_DESCRIPTOR_BINDINGS> copy_set; std::array<VkCopyDescriptorSet, VK_NUM_DESCRIPTOR_BINDINGS> copy_set;
@ -1126,20 +1129,17 @@ void VKGSRender::emit_geometry(u32 sub_index)
vkUpdateDescriptorSets(*m_device, 0, 0, VK_NUM_DESCRIPTOR_BINDINGS, copy_set.data()); vkUpdateDescriptorSets(*m_device, 0, 0, VK_NUM_DESCRIPTOR_BINDINGS, copy_set.data());
m_current_frame->descriptor_set = new_descriptor_set; m_current_frame->descriptor_set = new_descriptor_set;
if (persistent_buffer != old_persistent_buffer || volatile_buffer != old_volatile_buffer) update_descriptors = true;
{
// Rare event, we need to actually change the descriptors
update_descriptors = true;
}
} }
// Update vertex fetch parameters // Update vertex fetch parameters
update_vertex_env(upload_info); update_vertex_env(sub_index, upload_info);
if (update_descriptors) if (update_descriptors)
{ {
m_program->bind_uniform(persistent_buffer, vk::glsl::program_input_type::input_type_texel_buffer, "persistent_input_stream", m_current_frame->descriptor_set); m_program->bind_uniform(persistent_buffer, VERTEX_BUFFERS_FIRST_BIND_SLOT, m_current_frame->descriptor_set);
m_program->bind_uniform(volatile_buffer, vk::glsl::program_input_type::input_type_texel_buffer, "volatile_input_stream", m_current_frame->descriptor_set); m_program->bind_uniform(volatile_buffer, VERTEX_BUFFERS_FIRST_BIND_SLOT + 1, m_current_frame->descriptor_set);
m_program->bind_uniform(layout_stream, VERTEX_BUFFERS_FIRST_BIND_SLOT + 2, m_current_frame->descriptor_set);
} }
// Bind the new set of descriptors for use with this draw call // Bind the new set of descriptors for use with this draw call
@ -2736,22 +2736,40 @@ void VKGSRender::load_program_env()
m_graphics_state &= ~handled_flags; m_graphics_state &= ~handled_flags;
} }
void VKGSRender::update_vertex_env(const vk::vertex_upload_info& vertex_info) void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_info)
{ {
auto mem = m_vertex_layout_ring_info.alloc<256>(256); // Actual allocation must have been done previously
auto buf = (u32*)m_vertex_layout_ring_info.map(mem, 128 + 16); u32 base_offset;
buf[0] = vertex_info.vertex_index_base; if (!m_vertex_layout_storage ||
buf[1] = vertex_info.vertex_index_offset; !m_vertex_layout_storage->in_range(m_vertex_layout_stream_info.offset, m_vertex_layout_stream_info.range, base_offset))
buf += 4; {
verify("Incompatible driver (MacOS?)" HERE), m_texbuffer_view_size >= m_vertex_layout_stream_info.range;
fill_vertex_layout_state(m_vertex_layout, vertex_info.first_vertex, vertex_info.allocated_vertex_count, (s32*)buf, if (m_vertex_layout_storage)
m_current_frame->buffer_views_to_clean.push_back(std::move(m_vertex_layout_storage));
// View 64M blocks at a time (different drivers will only allow a fixed viewable heap size, 64M should be safe)
const size_t view_size = (base_offset + m_texbuffer_view_size) > m_vertex_layout_ring_info.size() ? m_vertex_layout_ring_info.size() - base_offset : m_texbuffer_view_size;
m_vertex_layout_storage = std::make_unique<vk::buffer_view>(*m_device, m_vertex_layout_ring_info.heap->value, VK_FORMAT_R32G32_UINT, base_offset, view_size);
base_offset = 0;
}
u32 draw_info[4];
draw_info[0] = vertex_info.vertex_index_base;
draw_info[1] = vertex_info.vertex_index_offset;
draw_info[2] = id;
draw_info[3] = (id * 16) + (base_offset / 8);
vkCmdPushConstants(*m_current_command_buffer, pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 16, draw_info);
const size_t data_offset = (id * 128) + m_vertex_layout_stream_info.offset;
auto dst = m_vertex_layout_ring_info.map(data_offset, 128);
fill_vertex_layout_state(m_vertex_layout, vertex_info.first_vertex, vertex_info.allocated_vertex_count, (s32*)dst,
vertex_info.persistent_window_offset, vertex_info.volatile_window_offset); vertex_info.persistent_window_offset, vertex_info.volatile_window_offset);
m_vertex_layout_ring_info.unmap(); m_vertex_layout_ring_info.unmap();
m_vertex_layout_buffer_info = { m_vertex_layout_ring_info.heap->value, mem, 128 + 16 };
m_program->bind_uniform(m_vertex_layout_buffer_info, VERTEX_LAYOUT_BIND_SLOT, m_current_frame->descriptor_set);
} }
void VKGSRender::init_buffers(rsx::framebuffer_creation_context context, bool skip_reading) void VKGSRender::init_buffers(rsx::framebuffer_creation_context context, bool skip_reading)

View file

@ -379,6 +379,7 @@ private:
std::unique_ptr<vk::buffer_view> m_persistent_attribute_storage; std::unique_ptr<vk::buffer_view> m_persistent_attribute_storage;
std::unique_ptr<vk::buffer_view> m_volatile_attribute_storage; std::unique_ptr<vk::buffer_view> m_volatile_attribute_storage;
std::unique_ptr<vk::buffer_view> m_vertex_layout_storage;
resource_manager m_resource_manager; resource_manager m_resource_manager;
@ -432,9 +433,9 @@ private:
VkDescriptorBufferInfo m_vertex_env_buffer_info; VkDescriptorBufferInfo m_vertex_env_buffer_info;
VkDescriptorBufferInfo m_fragment_env_buffer_info; VkDescriptorBufferInfo m_fragment_env_buffer_info;
VkDescriptorBufferInfo m_vertex_layout_stream_info;
VkDescriptorBufferInfo m_vertex_constants_buffer_info; VkDescriptorBufferInfo m_vertex_constants_buffer_info;
VkDescriptorBufferInfo m_fragment_constants_buffer_info; VkDescriptorBufferInfo m_fragment_constants_buffer_info;
VkDescriptorBufferInfo m_vertex_layout_buffer_info;
VkDescriptorBufferInfo m_fragment_texture_params_buffer_info; VkDescriptorBufferInfo m_fragment_texture_params_buffer_info;
std::array<frame_context_t, VK_MAX_ASYNC_FRAMES> frame_context_storage; std::array<frame_context_t, VK_MAX_ASYNC_FRAMES> frame_context_storage;
@ -512,7 +513,7 @@ private:
bool load_program(); bool load_program();
void load_program_env(); void load_program_env();
void update_vertex_env(const vk::vertex_upload_info& vertex_info); void update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_info);
public: public:
void init_buffers(rsx::framebuffer_creation_context context, bool skip_reading = false); void init_buffers(rsx::framebuffer_creation_context context, bool skip_reading = false);

View file

@ -34,12 +34,11 @@
#define OCCLUSION_MAX_POOL_SIZE DESCRIPTOR_MAX_DRAW_CALLS #define OCCLUSION_MAX_POOL_SIZE DESCRIPTOR_MAX_DRAW_CALLS
#define VERTEX_PARAMS_BIND_SLOT 0 #define VERTEX_PARAMS_BIND_SLOT 0
#define VERTEX_LAYOUT_BIND_SLOT 1 #define VERTEX_CONSTANT_BUFFERS_BIND_SLOT 1
#define VERTEX_CONSTANT_BUFFERS_BIND_SLOT 2 #define FRAGMENT_CONSTANT_BUFFERS_BIND_SLOT 2
#define FRAGMENT_CONSTANT_BUFFERS_BIND_SLOT 3 #define FRAGMENT_STATE_BIND_SLOT 3
#define FRAGMENT_STATE_BIND_SLOT 4 #define FRAGMENT_TEXTURE_PARAMS_BIND_SLOT 4
#define FRAGMENT_TEXTURE_PARAMS_BIND_SLOT 5 #define VERTEX_BUFFERS_FIRST_BIND_SLOT 5
#define VERTEX_BUFFERS_FIRST_BIND_SLOT 6
#define TEXTURES_FIRST_BIND_SLOT 8 #define TEXTURES_FIRST_BIND_SLOT 8
#define VERTEX_TEXTURES_FIRST_BIND_SLOT 24 //8+16 #define VERTEX_TEXTURES_FIRST_BIND_SLOT 24 //8+16
@ -3199,6 +3198,7 @@ public:
void bind_uniform(const VkDescriptorImageInfo &image_descriptor, const std::string &uniform_name, VkDescriptorType type, VkDescriptorSet &descriptor_set); void bind_uniform(const VkDescriptorImageInfo &image_descriptor, const std::string &uniform_name, VkDescriptorType type, VkDescriptorSet &descriptor_set);
void bind_uniform(const VkDescriptorImageInfo &image_descriptor, int texture_unit, ::glsl::program_domain domain, VkDescriptorSet &descriptor_set, bool is_stencil_mirror = false); void bind_uniform(const VkDescriptorImageInfo &image_descriptor, int texture_unit, ::glsl::program_domain domain, VkDescriptorSet &descriptor_set, bool is_stencil_mirror = false);
void bind_uniform(const VkDescriptorBufferInfo &buffer_descriptor, uint32_t binding_point, VkDescriptorSet &descriptor_set); void bind_uniform(const VkDescriptorBufferInfo &buffer_descriptor, uint32_t binding_point, VkDescriptorSet &descriptor_set);
void bind_uniform(const VkBufferView &buffer_view, uint32_t binding_point, VkDescriptorSet &descriptor_set);
void bind_uniform(const VkBufferView &buffer_view, program_input_type type, const std::string &binding_name, VkDescriptorSet &descriptor_set); void bind_uniform(const VkBufferView &buffer_view, program_input_type type, const std::string &binding_name, VkDescriptorSet &descriptor_set);
void bind_buffer(const VkDescriptorBufferInfo &buffer_descriptor, uint32_t binding_point, VkDescriptorType type, VkDescriptorSet &descriptor_set); void bind_buffer(const VkDescriptorBufferInfo &buffer_descriptor, uint32_t binding_point, VkDescriptorType type, VkDescriptorSet &descriptor_set);

View file

@ -174,28 +174,33 @@ namespace vk
bind_buffer(buffer_descriptor, binding_point, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptor_set); bind_buffer(buffer_descriptor, binding_point, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptor_set);
} }
void program::bind_uniform(const VkBufferView &buffer_view, uint32_t binding_point, VkDescriptorSet &descriptor_set)
{
const VkWriteDescriptorSet descriptor_writer =
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
nullptr, // pNext
descriptor_set, // dstSet
binding_point, // dstBinding
0, // dstArrayElement
1, // descriptorCount
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,// descriptorType
nullptr, // pImageInfo
nullptr, // pBufferInfo
&buffer_view // pTexelBufferView
};
vkUpdateDescriptorSets(m_device, 1, &descriptor_writer, 0, nullptr);
attribute_location_mask |= (1ull << binding_point);
}
void program::bind_uniform(const VkBufferView &buffer_view, program_input_type type, const std::string &binding_name, VkDescriptorSet &descriptor_set) void program::bind_uniform(const VkBufferView &buffer_view, program_input_type type, const std::string &binding_name, VkDescriptorSet &descriptor_set)
{ {
for (const auto &uniform : uniforms[type]) for (const auto &uniform : uniforms[type])
{ {
if (uniform.name == binding_name) if (uniform.name == binding_name)
{ {
const VkWriteDescriptorSet descriptor_writer = bind_uniform(buffer_view, uniform.location, descriptor_set);
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
nullptr, // pNext
descriptor_set, // dstSet
uniform.location, // dstBinding
0, // dstArrayElement
1, // descriptorCount
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,// descriptorType
nullptr, // pImageInfo
nullptr, // pBufferInfo
&buffer_view // pTexelBufferView
};
vkUpdateDescriptorSets(m_device, 1, &descriptor_writer, 0, nullptr);
attribute_location_mask |= (1ull << uniform.location);
return; return;
} }
} }

View file

@ -42,11 +42,12 @@ void VKVertexDecompilerThread::insertHeader(std::stringstream &OS)
OS << " float z_far;\n"; OS << " float z_far;\n";
OS << "};\n\n"; OS << "};\n\n";
OS << "layout(std140, set = 0, binding = 1) uniform VertexLayoutBuffer\n"; OS << "layout(push_constant) uniform VertexLayoutBuffer\n";
OS << "{\n"; OS << "{\n";
OS << " uint vertex_base_index;\n"; OS << " uint vertex_base_index;\n";
OS << " uint vertex_index_offset;\n"; OS << " uint vertex_index_offset;\n";
OS << " uvec4 input_attributes_blob[16 / 2];\n"; OS << " uint draw_id;\n";
OS << " uint layout_ptr_offset;\n";
OS << "};\n\n"; OS << "};\n\n";
vk::glsl::program_input in; vk::glsl::program_input in;
@ -55,16 +56,13 @@ void VKVertexDecompilerThread::insertHeader(std::stringstream &OS)
in.name = "VertexContextBuffer"; in.name = "VertexContextBuffer";
in.type = vk::glsl::input_type_uniform_buffer; in.type = vk::glsl::input_type_uniform_buffer;
inputs.push_back(in); inputs.push_back(in);
in.location = VERTEX_LAYOUT_BIND_SLOT;
in.name = "VertexLayoutBuffer";
inputs.push_back(in);
} }
void VKVertexDecompilerThread::insertInputs(std::stringstream & OS, const std::vector<ParamType>& inputs) void VKVertexDecompilerThread::insertInputs(std::stringstream & OS, const std::vector<ParamType>& inputs)
{ {
OS << "layout(set=0, binding=6) uniform usamplerBuffer persistent_input_stream;\n"; //Data stream with persistent vertex data (cacheable) OS << "layout(set=0, binding=5) uniform usamplerBuffer persistent_input_stream;\n"; // Data stream with persistent vertex data (cacheable)
OS << "layout(set=0, binding=7) uniform usamplerBuffer volatile_input_stream;\n"; //Data stream with per-draw data (registers and immediate draw data) OS << "layout(set=0, binding=6) uniform usamplerBuffer volatile_input_stream;\n"; // Data stream with per-draw data (registers and immediate draw data)
OS << "layout(set=0, binding=7) uniform usamplerBuffer vertex_layout_stream;\n"; // Data stream defining vertex data layout
vk::glsl::program_input in; vk::glsl::program_input in;
in.location = VERTEX_BUFFERS_FIRST_BIND_SLOT; in.location = VERTEX_BUFFERS_FIRST_BIND_SLOT;
@ -78,11 +76,17 @@ void VKVertexDecompilerThread::insertInputs(std::stringstream & OS, const std::v
in.name = "volatile_input_stream"; in.name = "volatile_input_stream";
in.type = vk::glsl::input_type_texel_buffer; in.type = vk::glsl::input_type_texel_buffer;
this->inputs.push_back(in); this->inputs.push_back(in);
in.location = VERTEX_BUFFERS_FIRST_BIND_SLOT + 2;
in.domain = glsl::glsl_vertex_program;
in.name = "vertex_layout_stream";
in.type = vk::glsl::input_type_texel_buffer;
this->inputs.push_back(in);
} }
void VKVertexDecompilerThread::insertConstants(std::stringstream & OS, const std::vector<ParamType> & constants) void VKVertexDecompilerThread::insertConstants(std::stringstream & OS, const std::vector<ParamType> & constants)
{ {
OS << "layout(std140, set=0, binding = 2) uniform VertexConstantsBuffer\n"; OS << "layout(std140, set=0, binding = 1) uniform VertexConstantsBuffer\n";
OS << "{\n"; OS << "{\n";
OS << " vec4 vc[468];\n"; OS << " vec4 vc[468];\n";
OS << "};\n\n"; OS << "};\n\n";