2018-11-24 13:54:46 +01:00
|
|
|
|
#pragma once
|
2016-02-21 16:50:49 +01:00
|
|
|
|
#include "VKVertexProgram.h"
|
|
|
|
|
|
#include "VKFragmentProgram.h"
|
|
|
|
|
|
#include "../Common/ProgramStateCache.h"
|
2017-08-10 21:40:20 +02:00
|
|
|
|
#include "Utilities/hash.h"
|
2018-04-12 13:13:13 +02:00
|
|
|
|
#include "VKHelpers.h"
|
2019-05-24 15:31:46 +02:00
|
|
|
|
#include "VKRenderPass.h"
|
2016-03-20 02:26:51 +01:00
|
|
|
|
|
|
|
|
|
|
namespace vk
|
|
|
|
|
|
{
|
|
|
|
|
|
struct pipeline_props
|
|
|
|
|
|
{
|
2018-04-12 13:13:13 +02:00
|
|
|
|
graphics_pipeline_state state;
|
2019-05-24 15:31:46 +02:00
|
|
|
|
u64 renderpass_key;
|
2016-03-20 02:26:51 +01:00
|
|
|
|
|
|
|
|
|
|
bool operator==(const pipeline_props& other) const
|
|
|
|
|
|
{
|
2019-05-30 17:38:18 +02:00
|
|
|
|
if (renderpass_key != other.renderpass_key)
|
2016-03-20 02:26:51 +01:00
|
|
|
|
return false;
|
2017-08-04 23:11:14 +02:00
|
|
|
|
|
2019-05-30 17:38:18 +02:00
|
|
|
|
if (memcmp(&state.ia, &other.state.ia, sizeof(VkPipelineInputAssemblyStateCreateInfo)))
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
if (memcmp(&state.att_state[0], &other.state.att_state[0], sizeof(VkPipelineColorBlendAttachmentState)))
|
2016-03-20 02:26:51 +01:00
|
|
|
|
return false;
|
2017-08-04 23:11:14 +02:00
|
|
|
|
|
2018-04-12 13:13:13 +02:00
|
|
|
|
if (memcmp(&state.rs, &other.state.rs, sizeof(VkPipelineRasterizationStateCreateInfo)))
|
2016-03-20 02:26:51 +01:00
|
|
|
|
return false;
|
2017-08-04 23:11:14 +02:00
|
|
|
|
|
2019-05-30 17:38:18 +02:00
|
|
|
|
// Cannot memcmp cs due to pAttachments being a pointer to memory
|
|
|
|
|
|
if (state.cs.logicOp != other.state.cs.logicOp ||
|
2018-04-12 13:13:13 +02:00
|
|
|
|
state.cs.logicOpEnable != other.state.cs.logicOpEnable ||
|
|
|
|
|
|
memcmp(state.cs.blendConstants, other.state.cs.blendConstants, 4 * sizeof(f32)))
|
2016-06-19 03:53:49 +02:00
|
|
|
|
return false;
|
2017-08-04 23:11:14 +02:00
|
|
|
|
|
2018-04-12 13:13:13 +02:00
|
|
|
|
if (memcmp(&state.ds, &other.state.ds, sizeof(VkPipelineDepthStencilStateCreateInfo)))
|
2016-09-21 15:41:29 +02:00
|
|
|
|
return false;
|
2016-07-17 18:57:50 +02:00
|
|
|
|
|
2019-05-30 17:38:18 +02:00
|
|
|
|
if (state.ms.rasterizationSamples != VK_SAMPLE_COUNT_1_BIT)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (memcmp(&state.ms, &other.state.ms, sizeof(VkPipelineMultisampleStateCreateInfo)))
|
|
|
|
|
|
return false;
|
2019-09-17 14:44:03 +02:00
|
|
|
|
|
|
|
|
|
|
if (state.temp_storage.msaa_sample_mask != other.state.temp_storage.msaa_sample_mask)
|
|
|
|
|
|
return false;
|
2019-05-30 17:38:18 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
2016-03-20 02:26:51 +01:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-10 21:40:20 +02:00
|
|
|
|
namespace rpcs3
|
2016-03-20 02:26:51 +01:00
|
|
|
|
{
|
2017-08-10 21:40:20 +02:00
|
|
|
|
template <>
|
|
|
|
|
|
size_t hash_struct<vk::pipeline_props>(const vk::pipeline_props &pipelineProperties)
|
2016-03-20 02:26:51 +01:00
|
|
|
|
{
|
2019-05-30 17:38:18 +02:00
|
|
|
|
size_t seed = hash_base(pipelineProperties.renderpass_key);
|
2018-04-12 13:13:13 +02:00
|
|
|
|
seed ^= hash_struct(pipelineProperties.state.ia);
|
|
|
|
|
|
seed ^= hash_struct(pipelineProperties.state.ds);
|
|
|
|
|
|
seed ^= hash_struct(pipelineProperties.state.rs);
|
2019-05-30 17:38:18 +02:00
|
|
|
|
seed ^= hash_struct(pipelineProperties.state.ms);
|
2019-09-17 14:44:03 +02:00
|
|
|
|
seed ^= hash_base(pipelineProperties.state.temp_storage.msaa_sample_mask);
|
2017-08-10 21:40:20 +02:00
|
|
|
|
|
2018-07-11 22:51:29 +02:00
|
|
|
|
// Do not compare pointers to memory!
|
|
|
|
|
|
VkPipelineColorBlendStateCreateInfo tmp;
|
|
|
|
|
|
memcpy(&tmp, &pipelineProperties.state.cs, sizeof(VkPipelineColorBlendStateCreateInfo));
|
2017-08-10 21:40:20 +02:00
|
|
|
|
tmp.pAttachments = nullptr;
|
|
|
|
|
|
|
2018-04-12 13:13:13 +02:00
|
|
|
|
seed ^= hash_struct(pipelineProperties.state.att_state[0]);
|
2018-07-11 22:51:29 +02:00
|
|
|
|
return hash_base(seed);
|
2016-03-20 02:26:51 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-21 16:50:49 +01:00
|
|
|
|
struct VKTraits
|
|
|
|
|
|
{
|
|
|
|
|
|
using vertex_program_type = VKVertexProgram;
|
|
|
|
|
|
using fragment_program_type = VKFragmentProgram;
|
2016-03-20 02:26:51 +01:00
|
|
|
|
using pipeline_storage_type = std::unique_ptr<vk::glsl::program>;
|
|
|
|
|
|
using pipeline_properties = vk::pipeline_props;
|
2016-02-21 16:50:49 +01:00
|
|
|
|
|
|
|
|
|
|
static
|
2017-08-10 21:40:20 +02:00
|
|
|
|
void recompile_fragment_program(const RSXFragmentProgram &RSXFP, fragment_program_type& fragmentProgramData, size_t ID)
|
2016-02-21 16:50:49 +01:00
|
|
|
|
{
|
|
|
|
|
|
fragmentProgramData.Decompile(RSXFP);
|
2017-08-10 21:40:20 +02:00
|
|
|
|
fragmentProgramData.id = static_cast<u32>(ID);
|
2017-11-06 00:06:16 +01:00
|
|
|
|
fragmentProgramData.Compile();
|
2016-02-21 16:50:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
2017-08-10 21:40:20 +02:00
|
|
|
|
void recompile_vertex_program(const RSXVertexProgram &RSXVP, vertex_program_type& vertexProgramData, size_t ID)
|
2016-02-21 16:50:49 +01:00
|
|
|
|
{
|
|
|
|
|
|
vertexProgramData.Decompile(RSXVP);
|
2017-08-10 21:40:20 +02:00
|
|
|
|
vertexProgramData.id = static_cast<u32>(ID);
|
2017-11-06 00:06:16 +01:00
|
|
|
|
vertexProgramData.Compile();
|
2016-02-21 16:50:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-02-23 15:35:44 +01:00
|
|
|
|
static
|
|
|
|
|
|
void validate_pipeline_properties(const VKVertexProgram&, const VKFragmentProgram &fp, vk::pipeline_props& properties)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Explicitly disable writing to undefined registers
|
2018-04-12 13:13:13 +02:00
|
|
|
|
properties.state.att_state[0].colorWriteMask &= fp.output_color_masks[0];
|
|
|
|
|
|
properties.state.att_state[1].colorWriteMask &= fp.output_color_masks[1];
|
|
|
|
|
|
properties.state.att_state[2].colorWriteMask &= fp.output_color_masks[2];
|
|
|
|
|
|
properties.state.att_state[3].colorWriteMask &= fp.output_color_masks[3];
|
2018-02-23 15:35:44 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-02-21 16:50:49 +01:00
|
|
|
|
static
|
2017-08-09 13:30:15 +02:00
|
|
|
|
pipeline_storage_type build_pipeline(const vertex_program_type &vertexProgramData, const fragment_program_type &fragmentProgramData,
|
|
|
|
|
|
const vk::pipeline_props &pipelineProperties, VkDevice dev, VkPipelineLayout common_pipeline_layout)
|
2016-02-21 16:50:49 +01:00
|
|
|
|
{
|
2016-03-20 02:26:51 +01:00
|
|
|
|
VkPipelineShaderStageCreateInfo shader_stages[2] = {};
|
|
|
|
|
|
shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
|
|
|
|
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
|
|
|
|
|
shader_stages[0].module = vertexProgramData.handle;
|
|
|
|
|
|
shader_stages[0].pName = "main";
|
|
|
|
|
|
|
|
|
|
|
|
shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
|
|
|
|
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
|
|
shader_stages[1].module = fragmentProgramData.handle;
|
|
|
|
|
|
shader_stages[1].pName = "main";
|
|
|
|
|
|
|
|
|
|
|
|
VkDynamicState dynamic_state_descriptors[VK_DYNAMIC_STATE_RANGE_SIZE] = {};
|
|
|
|
|
|
VkPipelineDynamicStateCreateInfo dynamic_state_info = {};
|
|
|
|
|
|
dynamic_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
|
|
|
|
|
dynamic_state_descriptors[dynamic_state_info.dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT;
|
|
|
|
|
|
dynamic_state_descriptors[dynamic_state_info.dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR;
|
|
|
|
|
|
dynamic_state_descriptors[dynamic_state_info.dynamicStateCount++] = VK_DYNAMIC_STATE_LINE_WIDTH;
|
2017-08-04 23:11:14 +02:00
|
|
|
|
dynamic_state_descriptors[dynamic_state_info.dynamicStateCount++] = VK_DYNAMIC_STATE_BLEND_CONSTANTS;
|
|
|
|
|
|
dynamic_state_descriptors[dynamic_state_info.dynamicStateCount++] = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK;
|
|
|
|
|
|
dynamic_state_descriptors[dynamic_state_info.dynamicStateCount++] = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK;
|
|
|
|
|
|
dynamic_state_descriptors[dynamic_state_info.dynamicStateCount++] = VK_DYNAMIC_STATE_STENCIL_REFERENCE;
|
2017-09-18 19:58:51 +02:00
|
|
|
|
dynamic_state_descriptors[dynamic_state_info.dynamicStateCount++] = VK_DYNAMIC_STATE_DEPTH_BIAS;
|
2019-10-28 22:07:38 +01:00
|
|
|
|
|
|
|
|
|
|
if (vk::get_current_renderer()->get_depth_bounds_support())
|
|
|
|
|
|
{
|
|
|
|
|
|
dynamic_state_descriptors[dynamic_state_info.dynamicStateCount++] = VK_DYNAMIC_STATE_DEPTH_BOUNDS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-03-20 02:26:51 +01:00
|
|
|
|
dynamic_state_info.pDynamicStates = dynamic_state_descriptors;
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineVertexInputStateCreateInfo vi = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineViewportStateCreateInfo vp = {};
|
|
|
|
|
|
vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
|
|
|
|
|
vp.viewportCount = 1;
|
|
|
|
|
|
vp.scissorCount = 1;
|
|
|
|
|
|
|
2019-05-30 17:38:18 +02:00
|
|
|
|
VkPipelineMultisampleStateCreateInfo ms = pipelineProperties.state.ms;
|
|
|
|
|
|
verify("Multisample state mismatch!" HERE), ms.rasterizationSamples == VkSampleCountFlagBits((pipelineProperties.renderpass_key >> 16) & 0xF);
|
|
|
|
|
|
if (ms.rasterizationSamples != VK_SAMPLE_COUNT_1_BIT)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Update the sample mask pointer
|
|
|
|
|
|
ms.pSampleMask = &pipelineProperties.state.temp_storage.msaa_sample_mask;
|
|
|
|
|
|
}
|
2016-03-20 02:26:51 +01:00
|
|
|
|
|
2018-07-11 22:51:29 +02:00
|
|
|
|
// Rebase pointers from pipeline structure in case it is moved/copied
|
|
|
|
|
|
VkPipelineColorBlendStateCreateInfo cs = pipelineProperties.state.cs;
|
|
|
|
|
|
cs.pAttachments = pipelineProperties.state.att_state;
|
|
|
|
|
|
|
2016-03-20 02:26:51 +01:00
|
|
|
|
VkPipeline pipeline;
|
|
|
|
|
|
VkGraphicsPipelineCreateInfo info = {};
|
|
|
|
|
|
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
|
|
|
|
|
info.pVertexInputState = &vi;
|
2018-04-12 13:13:13 +02:00
|
|
|
|
info.pInputAssemblyState = &pipelineProperties.state.ia;
|
|
|
|
|
|
info.pRasterizationState = &pipelineProperties.state.rs;
|
2018-07-11 22:51:29 +02:00
|
|
|
|
info.pColorBlendState = &cs;
|
2016-03-20 02:26:51 +01:00
|
|
|
|
info.pMultisampleState = &ms;
|
|
|
|
|
|
info.pViewportState = &vp;
|
2018-04-12 13:13:13 +02:00
|
|
|
|
info.pDepthStencilState = &pipelineProperties.state.ds;
|
2016-03-20 02:26:51 +01:00
|
|
|
|
info.stageCount = 2;
|
|
|
|
|
|
info.pStages = shader_stages;
|
|
|
|
|
|
info.pDynamicState = &dynamic_state_info;
|
|
|
|
|
|
info.layout = common_pipeline_layout;
|
|
|
|
|
|
info.basePipelineIndex = -1;
|
|
|
|
|
|
info.basePipelineHandle = VK_NULL_HANDLE;
|
2019-05-24 15:31:46 +02:00
|
|
|
|
info.renderPass = vk::get_renderpass(dev, pipelineProperties.renderpass_key);
|
2016-03-20 02:26:51 +01:00
|
|
|
|
|
|
|
|
|
|
CHECK_RESULT(vkCreateGraphicsPipelines(dev, nullptr, 1, &info, NULL, &pipeline));
|
2016-02-21 16:50:49 +01:00
|
|
|
|
|
2018-11-24 13:54:46 +01:00
|
|
|
|
pipeline_storage_type result = std::make_unique<vk::glsl::program>(dev, pipeline, vertexProgramData.uniforms, fragmentProgramData.uniforms);
|
|
|
|
|
|
result->link();
|
2016-02-21 16:50:49 +01:00
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2019-05-24 15:31:46 +02:00
|
|
|
|
struct VKProgramBuffer : public program_state_cache<VKTraits>
|
2016-02-21 16:50:49 +01:00
|
|
|
|
{
|
2020-03-09 10:15:59 +01:00
|
|
|
|
VKProgramBuffer(decompiler_callback_t callback)
|
2016-08-24 02:50:07 +02:00
|
|
|
|
{
|
2020-03-09 10:15:59 +01:00
|
|
|
|
notify_pipeline_compiled = callback;
|
2016-08-24 02:50:07 +02:00
|
|
|
|
}
|
2017-08-09 13:30:15 +02:00
|
|
|
|
|
2020-03-09 10:15:59 +01:00
|
|
|
|
u64 get_hash(const vk::pipeline_props &props)
|
2017-08-09 13:30:15 +02:00
|
|
|
|
{
|
2017-08-10 21:40:20 +02:00
|
|
|
|
return rpcs3::hash_struct<vk::pipeline_props>(props);
|
2017-08-09 13:30:15 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-03-09 10:15:59 +01:00
|
|
|
|
u64 get_hash(const RSXVertexProgram &prog)
|
2017-08-09 13:30:15 +02:00
|
|
|
|
{
|
2017-12-02 16:20:52 +01:00
|
|
|
|
return program_hash_util::vertex_program_utils::get_vertex_program_ucode_hash(prog);
|
2017-08-09 13:30:15 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-03-09 10:15:59 +01:00
|
|
|
|
u64 get_hash(const RSXFragmentProgram &prog)
|
2017-08-09 13:30:15 +02:00
|
|
|
|
{
|
2017-12-02 16:20:52 +01:00
|
|
|
|
return program_hash_util::fragment_program_utils::get_fragment_program_ucode_hash(prog);
|
2017-08-09 13:30:15 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename... Args>
|
|
|
|
|
|
void add_pipeline_entry(RSXVertexProgram &vp, RSXFragmentProgram &fp, vk::pipeline_props &props, Args&& ...args)
|
|
|
|
|
|
{
|
|
|
|
|
|
vp.skip_vertex_input_check = true;
|
2020-03-09 10:15:59 +01:00
|
|
|
|
get_graphics_pipeline(vp, fp, props, false, false, std::forward<Args>(args)...);
|
2017-08-09 13:30:15 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-06-01 18:49:29 +02:00
|
|
|
|
void preload_programs(RSXVertexProgram &vp, RSXFragmentProgram &fp)
|
|
|
|
|
|
{
|
|
|
|
|
|
vp.skip_vertex_input_check = true;
|
|
|
|
|
|
search_vertex_program(vp);
|
|
|
|
|
|
search_fragment_program(fp);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-09 13:30:15 +02:00
|
|
|
|
bool check_cache_missed() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_cache_miss_flag;
|
|
|
|
|
|
}
|
2016-02-21 16:50:49 +01:00
|
|
|
|
};
|