From 6a32f716db2dc5989b1c3802c55317455b157043 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 18 Jun 2019 16:38:50 +0300 Subject: [PATCH] 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. --- rpcs3/Emu/RSX/Common/GLSLCommon.h | 42 +++++++--- rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp | 6 +- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 108 ++++++++++++++----------- rpcs3/Emu/RSX/VK/VKGSRender.h | 5 +- rpcs3/Emu/RSX/VK/VKHelpers.h | 12 +-- rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp | 37 +++++---- rpcs3/Emu/RSX/VK/VKVertexProgram.cpp | 26 +++--- 7 files changed, 140 insertions(+), 96 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/GLSLCommon.h b/rpcs3/Emu/RSX/Common/GLSLCommon.h index fd010272d5..b80699a3b3 100644 --- a/rpcs3/Emu/RSX/Common/GLSLCommon.h +++ b/rpcs3/Emu/RSX/Common/GLSLCommon.h @@ -366,20 +366,36 @@ namespace glsl " // [32-60] starting offset\n" " // [60-61] swap bytes flag\n" " // [61-62] volatile flag\n" - " // [62-63] modulo enable flag\n" - " int block = (location >> 1);\n" - " int sub_block = (location & 1) << 1;\n" - " uint attrib0 = ref(input_attributes_blob[block], sub_block + 0);\n" - " uint attrib1 = ref(input_attributes_blob[block], sub_block + 1);\n" + " // [62-63] modulo enable flag\n"; + + if (rules == glsl_rules_opengl4) + { + // 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" - " result.stride = attrib0 & 0xFF;\n" - " result.frequency = (attrib0 >> 8) & 0xFFFF;\n" - " result.type = (attrib0 >> 24) & 0x7;\n" - " result.attribute_size = (attrib0 >> 27) & 0x7;\n" - " result.starting_offset = (attrib1 & 0x1FFFFFFF);\n" - " result.swap_bytes = ((attrib1 >> 29) & 0x1) != 0;\n" - " result.is_volatile = ((attrib1 >> 30) & 0x1) != 0;\n" - " result.modulo = ((attrib1 >> 31) & 0x1) != 0;\n" + " result.stride = attrib.x & 0xFF;\n" + " result.frequency = (attrib.x >> 8) & 0xFFFF;\n" + " result.type = (attrib.x >> 24) & 0x7;\n" + " result.attribute_size = (attrib.x >> 27) & 0x7;\n" + " result.starting_offset = (attrib.y & 0x1FFFFFFF);\n" + " result.swap_bytes = ((attrib.y >> 29) & 0x1) != 0;\n" + " result.is_volatile = ((attrib.y >> 30) & 0x1) != 0;\n" + " result.modulo = ((attrib.y >> 31) & 0x1) != 0;\n" " return result;\n" "}\n\n" diff --git a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp index 547327d108..b8e1f07890 100644 --- a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp @@ -185,13 +185,13 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS) 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 << constants_block; 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 << " float fog_param0;\n"; OS << " float fog_param1;\n"; @@ -203,7 +203,7 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS) OS << " float wpos_bias;\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 << " vec4 texture_parameters[16];\n"; OS << "};\n\n"; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index cdc66f5ae6..7452f762cf 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -279,7 +279,7 @@ namespace size_t idx = 0; // 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].descriptorCount = 1; @@ -316,13 +316,6 @@ namespace 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].descriptorCount = 1; bindings[idx].stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; @@ -350,6 +343,11 @@ namespace verify(HERE), idx == VK_NUM_DESCRIPTOR_BINDINGS; + std::array push_constants; + push_constants[0].offset = 0; + push_constants[0].size = 16; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + VkDescriptorSetLayoutCreateInfo infos = {}; infos.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; infos.pBindings = bindings.data(); @@ -362,6 +360,8 @@ namespace 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)); @@ -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_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_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_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"); @@ -588,6 +588,7 @@ VKGSRender::~VKGSRender() m_persistent_attribute_storage.reset(); m_volatile_attribute_storage.reset(); + m_vertex_layout_storage.reset(); //Global resources vk::destroy_global_resources(); @@ -1050,23 +1051,22 @@ void VKGSRender::emit_geometry(u32 sub_index) if (sub_index == 0) { analyse_inputs_interleaved(m_vertex_layout); - } - if (!m_vertex_layout.validate()) - { - // No vertex inputs enabled - // Execute remainining pipeline barriers with NOP draw - do + if (!m_vertex_layout.validate()) { - 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; } - - if (sub_index > 0 && draw_call.execute_pipeline_dependencies() & rsx::vertex_base_changed) + else if (draw_call.execute_pipeline_dependencies() & rsx::vertex_base_changed) { // Rebase vertex bases instead of 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 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; if (sub_index == 0) { 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 - // 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 + // Need to update descriptors; make a copy for the next draw VkDescriptorSet new_descriptor_set = allocate_descriptor_set(); std::array 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()); m_current_frame->descriptor_set = new_descriptor_set; - if (persistent_buffer != old_persistent_buffer || volatile_buffer != old_volatile_buffer) - { - // Rare event, we need to actually change the descriptors - update_descriptors = true; - } + update_descriptors = true; } // Update vertex fetch parameters - update_vertex_env(upload_info); + update_vertex_env(sub_index, upload_info); 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(volatile_buffer, vk::glsl::program_input_type::input_type_texel_buffer, "volatile_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, 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 @@ -2736,22 +2736,40 @@ void VKGSRender::load_program_env() 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); - auto buf = (u32*)m_vertex_layout_ring_info.map(mem, 128 + 16); + // Actual allocation must have been done previously + u32 base_offset; - buf[0] = vertex_info.vertex_index_base; - buf[1] = vertex_info.vertex_index_offset; - buf += 4; + if (!m_vertex_layout_storage || + !m_vertex_layout_storage->in_range(m_vertex_layout_stream_info.offset, m_vertex_layout_stream_info.range, base_offset)) + { + 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(*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); 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) diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 8760dd4fd3..c6e7a5e3e2 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -379,6 +379,7 @@ private: std::unique_ptr m_persistent_attribute_storage; std::unique_ptr m_volatile_attribute_storage; + std::unique_ptr m_vertex_layout_storage; resource_manager m_resource_manager; @@ -432,9 +433,9 @@ private: VkDescriptorBufferInfo m_vertex_env_buffer_info; VkDescriptorBufferInfo m_fragment_env_buffer_info; + VkDescriptorBufferInfo m_vertex_layout_stream_info; VkDescriptorBufferInfo m_vertex_constants_buffer_info; VkDescriptorBufferInfo m_fragment_constants_buffer_info; - VkDescriptorBufferInfo m_vertex_layout_buffer_info; VkDescriptorBufferInfo m_fragment_texture_params_buffer_info; std::array frame_context_storage; @@ -512,7 +513,7 @@ private: bool load_program(); 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: void init_buffers(rsx::framebuffer_creation_context context, bool skip_reading = false); diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index fa97b4f228..2b056b63bd 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -34,12 +34,11 @@ #define OCCLUSION_MAX_POOL_SIZE DESCRIPTOR_MAX_DRAW_CALLS #define VERTEX_PARAMS_BIND_SLOT 0 -#define VERTEX_LAYOUT_BIND_SLOT 1 -#define VERTEX_CONSTANT_BUFFERS_BIND_SLOT 2 -#define FRAGMENT_CONSTANT_BUFFERS_BIND_SLOT 3 -#define FRAGMENT_STATE_BIND_SLOT 4 -#define FRAGMENT_TEXTURE_PARAMS_BIND_SLOT 5 -#define VERTEX_BUFFERS_FIRST_BIND_SLOT 6 +#define VERTEX_CONSTANT_BUFFERS_BIND_SLOT 1 +#define FRAGMENT_CONSTANT_BUFFERS_BIND_SLOT 2 +#define FRAGMENT_STATE_BIND_SLOT 3 +#define FRAGMENT_TEXTURE_PARAMS_BIND_SLOT 4 +#define VERTEX_BUFFERS_FIRST_BIND_SLOT 5 #define TEXTURES_FIRST_BIND_SLOT 8 #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, 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 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_buffer(const VkDescriptorBufferInfo &buffer_descriptor, uint32_t binding_point, VkDescriptorType type, VkDescriptorSet &descriptor_set); diff --git a/rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp b/rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp index e83b1d31e0..7378ca9f10 100644 --- a/rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp +++ b/rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp @@ -174,28 +174,33 @@ namespace vk 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) { for (const auto &uniform : uniforms[type]) { if (uniform.name == binding_name) { - const VkWriteDescriptorSet descriptor_writer = - { - 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); + bind_uniform(buffer_view, uniform.location, descriptor_set); return; } } diff --git a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp index 5e309527fe..297713f8e4 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp @@ -42,11 +42,12 @@ void VKVertexDecompilerThread::insertHeader(std::stringstream &OS) OS << " float z_far;\n"; OS << "};\n\n"; - OS << "layout(std140, set = 0, binding = 1) uniform VertexLayoutBuffer\n"; + OS << "layout(push_constant) uniform VertexLayoutBuffer\n"; OS << "{\n"; - OS << " uint vertex_base_index;\n"; - OS << " uint vertex_index_offset;\n"; - OS << " uvec4 input_attributes_blob[16 / 2];\n"; + OS << " uint vertex_base_index;\n"; + OS << " uint vertex_index_offset;\n"; + OS << " uint draw_id;\n"; + OS << " uint layout_ptr_offset;\n"; OS << "};\n\n"; vk::glsl::program_input in; @@ -55,16 +56,13 @@ void VKVertexDecompilerThread::insertHeader(std::stringstream &OS) in.name = "VertexContextBuffer"; in.type = vk::glsl::input_type_uniform_buffer; 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& 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=7) uniform usamplerBuffer volatile_input_stream;\n"; //Data stream with per-draw data (registers and immediate draw data) + OS << "layout(set=0, binding=5) uniform usamplerBuffer persistent_input_stream;\n"; // Data stream with persistent vertex data (cacheable) + 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; 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.type = vk::glsl::input_type_texel_buffer; 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 & constants) { - OS << "layout(std140, set=0, binding = 2) uniform VertexConstantsBuffer\n"; + OS << "layout(std140, set=0, binding = 1) uniform VertexConstantsBuffer\n"; OS << "{\n"; OS << " vec4 vc[468];\n"; OS << "};\n\n";