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:
kd-11 2016-08-24 03:50:07 +03:00 committed by raven02
parent 12099b3144
commit 9beb2d8ae0
9 changed files with 115 additions and 55 deletions

View File

@ -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;

View File

@ -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 &reg = vk::get_varying_register(PI.name); const vk::varying_register_t &reg = 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 &reg = vk::get_varying_register("front_diff_color"); const vk::varying_register_t &reg = 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 &reg = vk::get_varying_register("front_spec_color"); const vk::varying_register_t &reg = 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")
{
//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"; 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")
{
//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"; OS << " vec4 diff_color = gl_FrontFacing ? front_diff_color : back_diff_color;\n";
}
else
{
OS << " vec4 diff_color = back_diff_color;\n";
}
}
continue; continue;
} }
} }
@ -371,18 +401,11 @@ void VKFragmentProgram::Delete()
shader.clear(); shader.clear();
if (handle) if (handle)
{
if (Emu.IsStopped())
{
LOG_WARNING(RSX, "VKFragmentProgram::Delete(): vkDestroyShaderModule(0x%X) avoided", handle);
}
else
{ {
VkDevice dev = (VkDevice)*vk::get_current_renderer(); VkDevice dev = (VkDevice)*vk::get_current_renderer();
vkDestroyShaderModule(dev, handle, NULL); vkDestroyShaderModule(dev, handle, NULL);
handle = nullptr; handle = nullptr;
} }
}
} }
void VKFragmentProgram::SetInputs(std::vector<vk::glsl::program_input>& inputs) void VKFragmentProgram::SetInputs(std::vector<vk::glsl::program_input>& inputs)

View File

@ -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;
} }

View File

@ -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();

View File

@ -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();
}
}; };

View File

@ -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();
} }
}; };
} }

View File

@ -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)

View File

@ -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);

View File

@ -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;
} }
} }
@ -335,16 +331,9 @@ void VKVertexProgram::Delete()
shader.clear(); shader.clear();
if (handle) if (handle)
{
if (Emu.IsStopped())
{
LOG_WARNING(RSX, "VKVertexProgram::Delete(): vkDestroyShaderModule(0x%X) avoided", handle);
}
else
{ {
VkDevice dev = (VkDevice)*vk::get_current_renderer(); VkDevice dev = (VkDevice)*vk::get_current_renderer();
vkDestroyShaderModule(dev, handle, nullptr); vkDestroyShaderModule(dev, handle, nullptr);
}
handle = nullptr; handle = nullptr;
} }