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;
|
||||
binary_to_vertex_program m_vertex_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)
|
||||
{
|
||||
//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 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);
|
||||
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")
|
||||
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");
|
||||
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");
|
||||
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";
|
||||
|
||||
// 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 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";
|
||||
}
|
||||
else
|
||||
{
|
||||
OS << " vec4 spec_color = back_spec_color;\n";
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
else
|
||||
{
|
||||
OS << " vec4 diff_color = back_diff_color;\n";
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -371,18 +401,11 @@ void VKFragmentProgram::Delete()
|
||||
shader.clear();
|
||||
|
||||
if (handle)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
LOG_WARNING(RSX, "VKFragmentProgram::Delete(): vkDestroyShaderModule(0x%X) avoided", handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
||||
vkDestroyShaderModule(dev, handle, NULL);
|
||||
handle = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VKFragmentProgram::SetInputs(std::vector<vk::glsl::program_input>& inputs)
|
||||
|
@ -512,46 +512,66 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan)
|
||||
|
||||
VKGSRender::~VKGSRender()
|
||||
{
|
||||
//Wait for queue
|
||||
vkQueueWaitIdle(m_swap_chain->get_present_queue());
|
||||
|
||||
//Sync objects
|
||||
if (m_present_semaphore)
|
||||
{
|
||||
vkDestroySemaphore((*m_device), 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_index_buffer_ring_info.heap.release();
|
||||
m_uniform_buffer_ring_info.heap.release();
|
||||
m_attrib_ring_info.heap.release();
|
||||
m_texture_upload_buffer_ring_info.heap.release();
|
||||
null_buffer.release();
|
||||
null_buffer_view.release();
|
||||
//Global resources
|
||||
vk::destroy_global_resources();
|
||||
|
||||
//Data heaps/buffers
|
||||
m_index_buffer_ring_info.heap.reset();
|
||||
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_sampler_to_clean.clear();
|
||||
m_framebuffer_to_clean.clear();
|
||||
|
||||
//Render passes
|
||||
for (auto &render_pass : m_render_passes)
|
||||
if (render_pass)
|
||||
vkDestroyRenderPass(*m_device, render_pass, nullptr);
|
||||
|
||||
//Textures
|
||||
m_rtts.destroy();
|
||||
m_texture_cache.destroy();
|
||||
|
||||
//Pipeline descriptors
|
||||
vkDestroyPipelineLayout(*m_device, pipeline_layout, nullptr);
|
||||
vkDestroyDescriptorSetLayout(*m_device, descriptor_layouts, nullptr);
|
||||
|
||||
descriptor_pool.destroy();
|
||||
|
||||
//Command buffer
|
||||
m_command_buffer.destroy();
|
||||
m_command_buffer_pool.destroy();
|
||||
|
||||
//Device handles/contexts
|
||||
m_swap_chain->destroy();
|
||||
|
||||
m_thread_context.close();
|
||||
|
||||
delete m_swap_chain;
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ private:
|
||||
* Creates and fills an index buffer emulating unsupported primitive 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:
|
||||
bool load_program();
|
||||
|
@ -151,4 +151,11 @@ struct 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>
|
||||
{
|
||||
|
||||
void destroy()
|
||||
{
|
||||
m_render_targets_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));
|
||||
}
|
||||
|
||||
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:
|
||||
|
||||
texture_cache() {}
|
||||
@ -141,7 +158,7 @@ namespace vk
|
||||
|
||||
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)
|
||||
|
@ -242,7 +242,7 @@ VKGSRender::upload_vertex_data()
|
||||
{
|
||||
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
|
||||
{
|
||||
@ -256,6 +256,11 @@ VKGSRender::upload_vertex_data()
|
||||
if (rsx::method_registers.current_draw_clause.command == rsx::draw_command::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)
|
||||
@ -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_program->bind_uniform(m_buffer_view_to_clean.back()->value, s_reg_table[index], descriptor_sets);
|
||||
}
|
||||
|
||||
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 upload_size = index_count * sizeof(u16);
|
||||
|
||||
|
@ -196,13 +196,9 @@ namespace vk
|
||||
if (real_input.location != PI.location)
|
||||
continue;
|
||||
|
||||
std::string vecType = " vec4 ";
|
||||
if (real_input.int_type)
|
||||
vecType = " ivec4 ";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -210,19 +206,19 @@ namespace vk
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (handle)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
LOG_WARNING(RSX, "VKVertexProgram::Delete(): vkDestroyShaderModule(0x%X) avoided", handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
||||
vkDestroyShaderModule(dev, handle, nullptr);
|
||||
}
|
||||
|
||||
handle = nullptr;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user