mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
vk/rsx: Bug fixes (#2092)
* vk: fix separate front and back lighting * vk: Inlined arrays can have emulated primitives too! * vk: Use float input attribs for better compatibility * vk: Free resources during shutdown
This commit is contained in:
parent
12099b3144
commit
9beb2d8ae0
@ -108,7 +108,7 @@ class program_state_cache
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
size_t m_next_id = 0;
|
size_t m_next_id = 0;
|
||||||
binary_to_vertex_program m_vertex_shader_cache;
|
binary_to_vertex_program m_vertex_shader_cache;
|
||||||
binary_to_fragment_program m_fragment_shader_cache;
|
binary_to_fragment_program m_fragment_shader_cache;
|
||||||
|
@ -52,6 +52,9 @@ void VKFragmentDecompilerThread::insertHeader(std::stringstream & OS)
|
|||||||
|
|
||||||
void VKFragmentDecompilerThread::insertIntputs(std::stringstream & OS)
|
void VKFragmentDecompilerThread::insertIntputs(std::stringstream & OS)
|
||||||
{
|
{
|
||||||
|
//It is possible for the two_sided_enabled flag to be set without actual 2-sided outputs
|
||||||
|
bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output);
|
||||||
|
|
||||||
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
|
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
|
||||||
{
|
{
|
||||||
for (const ParamItem& PI : PT.items)
|
for (const ParamItem& PI : PT.items)
|
||||||
@ -62,7 +65,7 @@ void VKFragmentDecompilerThread::insertIntputs(std::stringstream & OS)
|
|||||||
const vk::varying_register_t ® = vk::get_varying_register(PI.name);
|
const vk::varying_register_t ® = vk::get_varying_register(PI.name);
|
||||||
std::string var_name = PI.name;
|
std::string var_name = PI.name;
|
||||||
|
|
||||||
if (m_prog.front_back_color_enabled)
|
if (two_sided_enabled)
|
||||||
{
|
{
|
||||||
if (m_prog.back_color_diffuse_output && var_name == "diff_color")
|
if (m_prog.back_color_diffuse_output && var_name == "diff_color")
|
||||||
var_name = "back_diff_color";
|
var_name = "back_diff_color";
|
||||||
@ -78,15 +81,16 @@ void VKFragmentDecompilerThread::insertIntputs(std::stringstream & OS)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_prog.front_back_color_enabled)
|
if (two_sided_enabled)
|
||||||
{
|
{
|
||||||
if (m_prog.front_color_diffuse_output)
|
//Only include the front counterparts if the default output is for back only and exists.
|
||||||
|
if (m_prog.front_color_diffuse_output && m_prog.back_color_diffuse_output)
|
||||||
{
|
{
|
||||||
const vk::varying_register_t ® = vk::get_varying_register("front_diff_color");
|
const vk::varying_register_t ® = vk::get_varying_register("front_diff_color");
|
||||||
OS << "layout(location=" << reg.reg_location << ") in vec4 front_diff_color;" << std::endl;
|
OS << "layout(location=" << reg.reg_location << ") in vec4 front_diff_color;" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_prog.front_color_specular_output)
|
if (m_prog.front_color_specular_output && m_prog.back_color_specular_output)
|
||||||
{
|
{
|
||||||
const vk::varying_register_t ® = vk::get_varying_register("front_spec_color");
|
const vk::varying_register_t ® = vk::get_varying_register("front_spec_color");
|
||||||
OS << "layout(location=" << reg.reg_location << ") in vec4 front_spec_color;" << std::endl;
|
OS << "layout(location=" << reg.reg_location << ") in vec4 front_spec_color;" << std::endl;
|
||||||
@ -221,22 +225,48 @@ void VKFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
|
|||||||
|
|
||||||
OS << " vec4 ssa = gl_FrontFacing ? vec4(1.) : vec4(-1.);\n";
|
OS << " vec4 ssa = gl_FrontFacing ? vec4(1.) : vec4(-1.);\n";
|
||||||
|
|
||||||
// search if there is fogc in inputs
|
bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output);
|
||||||
|
|
||||||
|
//Some registers require redirection
|
||||||
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
|
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
|
||||||
{
|
{
|
||||||
for (const ParamItem& PI : PT.items)
|
for (const ParamItem& PI : PT.items)
|
||||||
{
|
{
|
||||||
if (m_prog.front_back_color_enabled)
|
if (two_sided_enabled)
|
||||||
{
|
{
|
||||||
if (PI.name == "spec_color" && m_prog.back_color_specular_output && m_prog.front_color_specular_output)
|
if (PI.name == "spec_color")
|
||||||
{
|
{
|
||||||
OS << " vec4 spec_color = gl_FrontFacing ? front_spec_color : back_spec_color;\n";
|
//Only redirect/rename variables if the back_color exists
|
||||||
|
if (m_prog.back_color_specular_output)
|
||||||
|
{
|
||||||
|
if (m_prog.back_color_specular_output && m_prog.front_color_specular_output)
|
||||||
|
{
|
||||||
|
OS << " vec4 spec_color = gl_FrontFacing ? front_spec_color : back_spec_color;\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OS << " vec4 spec_color = back_spec_color;\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PI.name == "diff_color" && m_prog.back_color_diffuse_output && m_prog.front_color_diffuse_output)
|
else if (PI.name == "diff_color")
|
||||||
{
|
{
|
||||||
OS << " vec4 diff_color = gl_FrontFacing ? front_diff_color : back_diff_color;\n";
|
//Only redirect/rename variables if the back_color exists
|
||||||
|
if (m_prog.back_color_diffuse_output)
|
||||||
|
{
|
||||||
|
if (m_prog.back_color_diffuse_output && m_prog.front_color_diffuse_output)
|
||||||
|
{
|
||||||
|
OS << " vec4 diff_color = gl_FrontFacing ? front_diff_color : back_diff_color;\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OS << " vec4 diff_color = back_diff_color;\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,16 +402,9 @@ void VKFragmentProgram::Delete()
|
|||||||
|
|
||||||
if (handle)
|
if (handle)
|
||||||
{
|
{
|
||||||
if (Emu.IsStopped())
|
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
||||||
{
|
vkDestroyShaderModule(dev, handle, NULL);
|
||||||
LOG_WARNING(RSX, "VKFragmentProgram::Delete(): vkDestroyShaderModule(0x%X) avoided", handle);
|
handle = nullptr;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
|
||||||
vkDestroyShaderModule(dev, handle, NULL);
|
|
||||||
handle = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,46 +512,66 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan)
|
|||||||
|
|
||||||
VKGSRender::~VKGSRender()
|
VKGSRender::~VKGSRender()
|
||||||
{
|
{
|
||||||
|
//Wait for queue
|
||||||
vkQueueWaitIdle(m_swap_chain->get_present_queue());
|
vkQueueWaitIdle(m_swap_chain->get_present_queue());
|
||||||
|
|
||||||
|
//Sync objects
|
||||||
if (m_present_semaphore)
|
if (m_present_semaphore)
|
||||||
{
|
{
|
||||||
vkDestroySemaphore((*m_device), m_present_semaphore, nullptr);
|
vkDestroySemaphore((*m_device), m_present_semaphore, nullptr);
|
||||||
m_present_semaphore = nullptr;
|
m_present_semaphore = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::destroy_global_resources();
|
if (m_submit_fence)
|
||||||
|
{
|
||||||
|
vkDestroyFence(*m_device, m_submit_fence, nullptr);
|
||||||
|
m_submit_fence = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: Properly destroy shader modules instead of calling clear...
|
//Shaders
|
||||||
m_prog_buffer.clear();
|
m_prog_buffer.clear();
|
||||||
|
|
||||||
m_index_buffer_ring_info.heap.release();
|
//Global resources
|
||||||
m_uniform_buffer_ring_info.heap.release();
|
vk::destroy_global_resources();
|
||||||
m_attrib_ring_info.heap.release();
|
|
||||||
m_texture_upload_buffer_ring_info.heap.release();
|
//Data heaps/buffers
|
||||||
null_buffer.release();
|
m_index_buffer_ring_info.heap.reset();
|
||||||
null_buffer_view.release();
|
m_uniform_buffer_ring_info.heap.reset();
|
||||||
|
m_attrib_ring_info.heap.reset();
|
||||||
|
m_texture_upload_buffer_ring_info.heap.reset();
|
||||||
|
|
||||||
|
//Fallback bindables
|
||||||
|
null_buffer.reset();
|
||||||
|
null_buffer_view.reset();
|
||||||
|
|
||||||
|
//Temporary objects
|
||||||
m_buffer_view_to_clean.clear();
|
m_buffer_view_to_clean.clear();
|
||||||
m_sampler_to_clean.clear();
|
m_sampler_to_clean.clear();
|
||||||
m_framebuffer_to_clean.clear();
|
m_framebuffer_to_clean.clear();
|
||||||
|
|
||||||
|
//Render passes
|
||||||
for (auto &render_pass : m_render_passes)
|
for (auto &render_pass : m_render_passes)
|
||||||
if (render_pass)
|
if (render_pass)
|
||||||
vkDestroyRenderPass(*m_device, render_pass, nullptr);
|
vkDestroyRenderPass(*m_device, render_pass, nullptr);
|
||||||
|
|
||||||
|
//Textures
|
||||||
m_rtts.destroy();
|
m_rtts.destroy();
|
||||||
|
m_texture_cache.destroy();
|
||||||
|
|
||||||
|
//Pipeline descriptors
|
||||||
vkDestroyPipelineLayout(*m_device, pipeline_layout, nullptr);
|
vkDestroyPipelineLayout(*m_device, pipeline_layout, nullptr);
|
||||||
vkDestroyDescriptorSetLayout(*m_device, descriptor_layouts, nullptr);
|
vkDestroyDescriptorSetLayout(*m_device, descriptor_layouts, nullptr);
|
||||||
|
|
||||||
descriptor_pool.destroy();
|
descriptor_pool.destroy();
|
||||||
|
|
||||||
|
//Command buffer
|
||||||
m_command_buffer.destroy();
|
m_command_buffer.destroy();
|
||||||
m_command_buffer_pool.destroy();
|
m_command_buffer_pool.destroy();
|
||||||
|
|
||||||
|
//Device handles/contexts
|
||||||
m_swap_chain->destroy();
|
m_swap_chain->destroy();
|
||||||
|
|
||||||
m_thread_context.close();
|
m_thread_context.close();
|
||||||
|
|
||||||
delete m_swap_chain;
|
delete m_swap_chain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ private:
|
|||||||
* Creates and fills an index buffer emulating unsupported primitive type.
|
* Creates and fills an index buffer emulating unsupported primitive type.
|
||||||
* Returns index_count and (offset_in_index_buffer, index_type)
|
* Returns index_count and (offset_in_index_buffer, index_type)
|
||||||
*/
|
*/
|
||||||
std::tuple<u32, std::tuple<VkDeviceSize, VkIndexType> > generate_emulating_index_buffer(const rsx::draw_clause &clause);
|
std::tuple<u32, std::tuple<VkDeviceSize, VkIndexType> > generate_emulating_index_buffer(const rsx::draw_clause &clause, u32 vertex_count);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool load_program();
|
bool load_program();
|
||||||
|
@ -151,4 +151,11 @@ struct VKTraits
|
|||||||
|
|
||||||
class VKProgramBuffer : public program_state_cache<VKTraits>
|
class VKProgramBuffer : public program_state_cache<VKTraits>
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
program_state_cache<VKTraits>::clear();
|
||||||
|
m_vertex_shader_cache.clear();
|
||||||
|
m_fragment_shader_cache.clear();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -159,11 +159,11 @@ namespace rsx
|
|||||||
|
|
||||||
struct vk_render_targets : public rsx::surface_store<vk_render_target_traits>
|
struct vk_render_targets : public rsx::surface_store<vk_render_target_traits>
|
||||||
{
|
{
|
||||||
|
|
||||||
void destroy()
|
void destroy()
|
||||||
{
|
{
|
||||||
m_render_targets_storage.clear();
|
m_render_targets_storage.clear();
|
||||||
m_depth_stencil_storage.clear();
|
m_depth_stencil_storage.clear();
|
||||||
|
invalidated_resources.clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -134,6 +134,23 @@ namespace vk
|
|||||||
unlock_memory_region(static_cast<u32>(obj.protected_rgn_start), static_cast<u32>(obj.native_rsx_size));
|
unlock_memory_region(static_cast<u32>(obj.protected_rgn_start), static_cast<u32>(obj.native_rsx_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void purge_cache()
|
||||||
|
{
|
||||||
|
for (cached_texture_object &tex : m_cache)
|
||||||
|
{
|
||||||
|
if (tex.exists)
|
||||||
|
m_dirty_textures.push_back(std::move(tex.uploaded_texture));
|
||||||
|
|
||||||
|
if (tex.locked)
|
||||||
|
unlock_object(tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_temporary_image_view.clear();
|
||||||
|
m_dirty_textures.clear();
|
||||||
|
|
||||||
|
m_cache.resize(0);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
texture_cache() {}
|
texture_cache() {}
|
||||||
@ -141,7 +158,7 @@ namespace vk
|
|||||||
|
|
||||||
void destroy()
|
void destroy()
|
||||||
{
|
{
|
||||||
m_cache.resize(0);
|
purge_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::image_view* upload_texture(command_buffer cmd, rsx::texture &tex, rsx::vk_render_targets &m_rtts, const vk::memory_type_mapping &memory_type_mapping, vk_data_heap& upload_heap, vk::buffer* upload_buffer)
|
vk::image_view* upload_texture(command_buffer cmd, rsx::texture &tex, rsx::vk_render_targets &m_rtts, const vk::memory_type_mapping &memory_type_mapping, vk_data_heap& upload_heap, vk::buffer* upload_buffer)
|
||||||
|
@ -242,7 +242,7 @@ VKGSRender::upload_vertex_data()
|
|||||||
{
|
{
|
||||||
if (primitives_emulated)
|
if (primitives_emulated)
|
||||||
{
|
{
|
||||||
std::tie(index_count, index_info) = generate_emulating_index_buffer(rsx::method_registers.current_draw_clause);
|
std::tie(index_count, index_info) = generate_emulating_index_buffer(rsx::method_registers.current_draw_clause, rsx::method_registers.current_draw_clause.get_elements_count());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -256,6 +256,11 @@ VKGSRender::upload_vertex_data()
|
|||||||
if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::inlined_array)
|
if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::inlined_array)
|
||||||
{
|
{
|
||||||
index_count = upload_inlined_array();
|
index_count = upload_inlined_array();
|
||||||
|
|
||||||
|
if (primitives_emulated)
|
||||||
|
{
|
||||||
|
std::tie(index_count, index_info) = generate_emulating_index_buffer(rsx::method_registers.current_draw_clause, index_count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array || rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed)
|
if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::array || rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed)
|
||||||
@ -454,6 +459,7 @@ u32 VKGSRender::upload_inlined_array()
|
|||||||
m_buffer_view_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, data_size));
|
m_buffer_view_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, data_size));
|
||||||
m_program->bind_uniform(m_buffer_view_to_clean.back()->value, s_reg_table[index], descriptor_sets);
|
m_program->bind_uniform(m_buffer_view_to_clean.back()->value, s_reg_table[index], descriptor_sets);
|
||||||
}
|
}
|
||||||
|
|
||||||
return vertex_draw_count;
|
return vertex_draw_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,10 +484,8 @@ std::tuple<u32, u32, u32, std::tuple<VkDeviceSize, VkIndexType>> VKGSRender::upl
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::tuple<u32, std::tuple<VkDeviceSize, VkIndexType> > VKGSRender::generate_emulating_index_buffer(const rsx::draw_clause &clause)
|
std::tuple<u32, std::tuple<VkDeviceSize, VkIndexType> > VKGSRender::generate_emulating_index_buffer(const rsx::draw_clause &clause, u32 vertex_count)
|
||||||
{
|
{
|
||||||
u32 vertex_count = clause.get_elements_count();
|
|
||||||
|
|
||||||
u32 index_count = get_index_count(clause.primitive, vertex_count);
|
u32 index_count = get_index_count(clause.primitive, vertex_count);
|
||||||
u32 upload_size = index_count * sizeof(u16);
|
u32 upload_size = index_count * sizeof(u16);
|
||||||
|
|
||||||
|
@ -196,13 +196,9 @@ namespace vk
|
|||||||
if (real_input.location != PI.location)
|
if (real_input.location != PI.location)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::string vecType = " vec4 ";
|
|
||||||
if (real_input.int_type)
|
|
||||||
vecType = " ivec4 ";
|
|
||||||
|
|
||||||
if (!real_input.is_array)
|
if (!real_input.is_array)
|
||||||
{
|
{
|
||||||
OS << vecType << PI.name << " = texelFetch(" << PI.name << "_buffer, 0);" << std::endl;
|
OS << " vec4 " << PI.name << " = vec4(texelFetch(" << PI.name << "_buffer, 0));" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,19 +206,19 @@ namespace vk
|
|||||||
{
|
{
|
||||||
if (real_input.is_modulo)
|
if (real_input.is_modulo)
|
||||||
{
|
{
|
||||||
OS << vecType << PI.name << "= texelFetch(" << PI.name << "_buffer, gl_VertexIndex %" << real_input.frequency << ");" << std::endl;
|
OS << " vec4 " << PI.name << "= vec4(texelFetch(" << PI.name << "_buffer, gl_VertexIndex %" << real_input.frequency << "));" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OS << vecType << PI.name << "= texelFetch(" << PI.name << "_buffer, gl_VertexIndex /" << real_input.frequency << ");" << std::endl;
|
OS << " vec4 " << PI.name << "= vec4(texelFetch(" << PI.name << "_buffer, gl_VertexIndex /" << real_input.frequency << "));" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OS << vecType << PI.name << "= texelFetch(" << PI.name << "_buffer, gl_VertexIndex).rgba;" << std::endl;
|
OS << " vec4 " << PI.name << "= vec4(texelFetch(" << PI.name << "_buffer, gl_VertexIndex).rgba);" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OS << " vec4 " << PI.name << "= texelFetch(" << PI.name << "_buffer, gl_VertexIndex).rgba;" << std::endl;
|
OS << " vec4 " << PI.name << "= vec4(texelFetch(" << PI.name << "_buffer, gl_VertexIndex).rgba);" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,15 +332,8 @@ void VKVertexProgram::Delete()
|
|||||||
|
|
||||||
if (handle)
|
if (handle)
|
||||||
{
|
{
|
||||||
if (Emu.IsStopped())
|
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
||||||
{
|
vkDestroyShaderModule(dev, handle, nullptr);
|
||||||
LOG_WARNING(RSX, "VKVertexProgram::Delete(): vkDestroyShaderModule(0x%X) avoided", handle);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
|
||||||
vkDestroyShaderModule(dev, handle, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
handle = nullptr;
|
handle = nullptr;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user