diff --git a/rpcs3/Emu/RSX/VK/VKPipelineCompiler.h b/rpcs3/Emu/RSX/VK/VKPipelineCompiler.h index cecb2c1b1b..e1f6812bbf 100644 --- a/rpcs3/Emu/RSX/VK/VKPipelineCompiler.h +++ b/rpcs3/Emu/RSX/VK/VKPipelineCompiler.h @@ -1,164 +1,186 @@ -#pragma once -#include "../rsx_utils.h" -#include "Utilities/hash.h" -#include "Utilities/lockless.h" -#include "VKProgramPipeline.h" -#include "vkutils/graphics_pipeline_state.hpp" - -namespace vk -{ - class render_device; - - struct pipeline_props - { - graphics_pipeline_state state; - u64 renderpass_key; - - bool operator==(const pipeline_props& other) const - { - if (renderpass_key != other.renderpass_key) - return false; - - if (memcmp(&state.ia, &other.state.ia, sizeof(VkPipelineInputAssemblyStateCreateInfo))) - return false; - - if (memcmp(&state.att_state[0], &other.state.att_state[0], sizeof(VkPipelineColorBlendAttachmentState))) - return false; - - if (memcmp(&state.rs, &other.state.rs, sizeof(VkPipelineRasterizationStateCreateInfo))) - return false; - - // Cannot memcmp cs due to pAttachments being a pointer to memory - if (state.cs.logicOp != other.state.cs.logicOp || - state.cs.logicOpEnable != other.state.cs.logicOpEnable || - memcmp(state.cs.blendConstants, other.state.cs.blendConstants, 4 * sizeof(f32))) - return false; - - if (memcmp(&state.ds, &other.state.ds, sizeof(VkPipelineDepthStencilStateCreateInfo))) - return false; - - if (state.ms.rasterizationSamples != VK_SAMPLE_COUNT_1_BIT) - { - if (memcmp(&state.ms, &other.state.ms, sizeof(VkPipelineMultisampleStateCreateInfo))) - return false; - - if (state.temp_storage.msaa_sample_mask != other.state.temp_storage.msaa_sample_mask) - return false; - } - - return true; - } - }; - - class pipe_compiler - { - public: - enum op_flags - { - COMPILE_DEFAULT = 0, - COMPILE_INLINE = 1, - COMPILE_DEFERRED = 2 - }; - - using callback_t = std::function&)>; - - pipe_compiler(); - ~pipe_compiler(); - - void initialize(const vk::render_device* pdev); - - std::unique_ptr compile( - const VkComputePipelineCreateInfo& create_info, - VkPipelineLayout pipe_layout, - op_flags flags, callback_t callback = {}); - - std::unique_ptr compile( - const VkGraphicsPipelineCreateInfo& create_info, - VkPipelineLayout pipe_layout, - op_flags flags, callback_t callback = {}, - const std::vector& vs_inputs = {}, - const std::vector& fs_inputs = {}); - - std::unique_ptr compile( - const vk::pipeline_props &create_info, - VkShaderModule module_handles[2], - VkPipelineLayout pipe_layout, - op_flags flags, callback_t callback = {}, - const std::vector& vs_inputs = {}, - const std::vector& fs_inputs = {}); - - void operator()(); - - private: - class compute_pipeline_props : public VkComputePipelineCreateInfo - { - // Storage for the entry name - std::string entry_name; - - public: - compute_pipeline_props() = default; - compute_pipeline_props(const VkComputePipelineCreateInfo& info) - { - (*static_cast(this)) = info; - entry_name = info.stage.pName; - stage.pName = entry_name.c_str(); - } - }; - - struct pipe_compiler_job - { - bool is_graphics_job; - callback_t callback_func; - - vk::pipeline_props graphics_data; - compute_pipeline_props compute_data; - VkPipelineLayout pipe_layout; - VkShaderModule graphics_modules[2]; - std::vector inputs; - - pipe_compiler_job( - const vk::pipeline_props& props, - VkPipelineLayout layout, - VkShaderModule modules[2], - const std::vector& vs_in, - const std::vector& fs_in, - callback_t func) - { - callback_func = func; - graphics_data = props; - pipe_layout = layout; - graphics_modules[0] = modules[0]; - graphics_modules[1] = modules[1]; - is_graphics_job = true; - - inputs.reserve(vs_in.size() + fs_in.size()); - inputs.insert(inputs.end(), vs_in.begin(), vs_in.end()); - inputs.insert(inputs.end(), fs_in.begin(), fs_in.end()); - } - - pipe_compiler_job( - const VkComputePipelineCreateInfo& props, - VkPipelineLayout layout, - callback_t func) - { - callback_func = func; - compute_data = props; - pipe_layout = layout; - is_graphics_job = false; - } - }; - - const vk::render_device* m_device = nullptr; - lf_queue m_work_queue; - - std::unique_ptr int_compile_compute_pipe(const VkComputePipelineCreateInfo& create_info, VkPipelineLayout pipe_layout); - std::unique_ptr int_compile_graphics_pipe(const VkGraphicsPipelineCreateInfo& create_info, VkPipelineLayout pipe_layout, - const std::vector& vs_inputs, const std::vector& fs_inputs); - std::unique_ptr int_compile_graphics_pipe(const vk::pipeline_props &create_info, VkShaderModule modules[2], VkPipelineLayout pipe_layout, - const std::vector& vs_inputs, const std::vector& fs_inputs); - }; - - void initialize_pipe_compiler(int num_worker_threads = -1); - void destroy_pipe_compiler(); - pipe_compiler* get_pipe_compiler(); -} +#pragma once +#include "../rsx_utils.h" +#include "Utilities/hash.h" +#include "Utilities/lockless.h" +#include "VKProgramPipeline.h" +#include "vkutils/graphics_pipeline_state.hpp" + +namespace vk +{ + class render_device; + + struct pipeline_props + { + graphics_pipeline_state state; + u64 renderpass_key; + + bool operator==(const pipeline_props& other) const + { + if (renderpass_key != other.renderpass_key) + return false; + + if (memcmp(&state.ia, &other.state.ia, sizeof(VkPipelineInputAssemblyStateCreateInfo))) + return false; + + if (memcmp(&state.att_state[0], &other.state.att_state[0], sizeof(VkPipelineColorBlendAttachmentState))) + return false; + + if (memcmp(&state.rs, &other.state.rs, sizeof(VkPipelineRasterizationStateCreateInfo))) + return false; + + // Cannot memcmp cs due to pAttachments being a pointer to memory + if (state.cs.logicOp != other.state.cs.logicOp || + state.cs.logicOpEnable != other.state.cs.logicOpEnable || + memcmp(state.cs.blendConstants, other.state.cs.blendConstants, 4 * sizeof(f32))) + return false; + + if (memcmp(&state.ds, &other.state.ds, sizeof(VkPipelineDepthStencilStateCreateInfo))) + return false; + + if (state.ms.rasterizationSamples != VK_SAMPLE_COUNT_1_BIT) + { + if (memcmp(&state.ms, &other.state.ms, sizeof(VkPipelineMultisampleStateCreateInfo))) + return false; + + if (state.temp_storage.msaa_sample_mask != other.state.temp_storage.msaa_sample_mask) + return false; + } + + return true; + } + }; + + class pipe_compiler + { + public: + enum op_flags + { + COMPILE_DEFAULT = 0, + COMPILE_INLINE = 1, + COMPILE_DEFERRED = 2 + }; + + using callback_t = std::function&)>; + + pipe_compiler(); + ~pipe_compiler(); + + void initialize(const vk::render_device* pdev); + + std::unique_ptr compile( + const VkComputePipelineCreateInfo& create_info, + VkPipelineLayout pipe_layout, + op_flags flags, callback_t callback = {}); + + std::unique_ptr compile( + const VkGraphicsPipelineCreateInfo& create_info, + VkPipelineLayout pipe_layout, + op_flags flags, callback_t callback = {}, + const std::vector& vs_inputs = {}, + const std::vector& fs_inputs = {}); + + std::unique_ptr compile( + const vk::pipeline_props &create_info, + VkShaderModule module_handles[2], + VkPipelineLayout pipe_layout, + op_flags flags, callback_t callback = {}, + const std::vector& vs_inputs = {}, + const std::vector& fs_inputs = {}); + + void operator()(); + + private: + class compute_pipeline_props : public VkComputePipelineCreateInfo + { + // Storage for the entry name + std::string entry_name; + + public: + compute_pipeline_props() = default; + compute_pipeline_props(const VkComputePipelineCreateInfo& info) + { + (*static_cast(this)) = info; + entry_name = info.stage.pName; + stage.pName = entry_name.c_str(); + } + }; + + struct pipe_compiler_job + { + bool is_graphics_job; + callback_t callback_func; + + vk::pipeline_props graphics_data; + compute_pipeline_props compute_data; + VkPipelineLayout pipe_layout; + VkShaderModule graphics_modules[2]; + std::vector inputs; + + pipe_compiler_job( + const vk::pipeline_props& props, + VkPipelineLayout layout, + VkShaderModule modules[2], + const std::vector& vs_in, + const std::vector& fs_in, + callback_t func) + { + callback_func = func; + graphics_data = props; + pipe_layout = layout; + graphics_modules[0] = modules[0]; + graphics_modules[1] = modules[1]; + is_graphics_job = true; + + inputs.reserve(vs_in.size() + fs_in.size()); + inputs.insert(inputs.end(), vs_in.begin(), vs_in.end()); + inputs.insert(inputs.end(), fs_in.begin(), fs_in.end()); + } + + pipe_compiler_job( + const VkComputePipelineCreateInfo& props, + VkPipelineLayout layout, + callback_t func) + { + callback_func = func; + compute_data = props; + pipe_layout = layout; + is_graphics_job = false; + } + }; + + const vk::render_device* m_device = nullptr; + lf_queue m_work_queue; + + std::unique_ptr int_compile_compute_pipe(const VkComputePipelineCreateInfo& create_info, VkPipelineLayout pipe_layout); + std::unique_ptr int_compile_graphics_pipe(const VkGraphicsPipelineCreateInfo& create_info, VkPipelineLayout pipe_layout, + const std::vector& vs_inputs, const std::vector& fs_inputs); + std::unique_ptr int_compile_graphics_pipe(const vk::pipeline_props &create_info, VkShaderModule modules[2], VkPipelineLayout pipe_layout, + const std::vector& vs_inputs, const std::vector& fs_inputs); + }; + + void initialize_pipe_compiler(int num_worker_threads = -1); + void destroy_pipe_compiler(); + pipe_compiler* get_pipe_compiler(); +} + +namespace rpcs3 +{ + template <> + inline usz hash_struct(const vk::pipeline_props& pipelineProperties) + { + usz seed = hash_base(pipelineProperties.renderpass_key); + seed ^= hash_struct(pipelineProperties.state.ia); + seed ^= hash_struct(pipelineProperties.state.ds); + seed ^= hash_struct(pipelineProperties.state.rs); + seed ^= hash_struct(pipelineProperties.state.ms); + seed ^= hash_base(pipelineProperties.state.temp_storage.msaa_sample_mask); + + // Do not compare pointers to memory! + VkPipelineColorBlendStateCreateInfo tmp; + memcpy(&tmp, &pipelineProperties.state.cs, sizeof(VkPipelineColorBlendStateCreateInfo)); + tmp.pAttachments = nullptr; + + seed ^= hash_struct(pipelineProperties.state.att_state[0]); + return hash_base(seed); + } +}