mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-08-03 11:23:49 +00:00
230 lines
9.5 KiB
C++
230 lines
9.5 KiB
C++
#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_PIPELINECACHE_H_
|
|
#define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_PIPELINECACHE_H_
|
|
|
|
#include "common/abi.h"
|
|
#include "common/assert.h"
|
|
#include "common/common.h"
|
|
#include "common/threads.h"
|
|
#include "graphics/host_gpu/renderer/renderTarget.h"
|
|
#include "graphics/host_gpu/vulkanCommon.h"
|
|
#include "graphics/shader/shader.h"
|
|
|
|
#include <cstddef>
|
|
#include <memory>
|
|
#include <span>
|
|
#include <type_traits>
|
|
#include <unordered_map>
|
|
|
|
namespace Libs::Graphics {
|
|
|
|
struct GraphicContext;
|
|
struct RenderColorInfo;
|
|
struct RenderDepthInfo;
|
|
class RenderCommandBuffer;
|
|
class DescriptorCache;
|
|
|
|
namespace HW {
|
|
class Context;
|
|
class Shader;
|
|
struct ComputeShaderInfo;
|
|
} // namespace HW
|
|
|
|
#pragma pack(push, 1)
|
|
|
|
struct PipelineStaticParameters {
|
|
float viewport_scale[3] = {};
|
|
float viewport_offset[3] = {};
|
|
bool negative_one_to_one = false;
|
|
bool depth_clip_enable = true;
|
|
int scissor_ltrb[4] = {0};
|
|
vk::PrimitiveTopology topology = vk::PrimitiveTopology::ePointList;
|
|
uint32_t samples = 1;
|
|
bool sample_shading_enable = false;
|
|
bool with_depth = false;
|
|
bool depth_test_enable = false;
|
|
bool depth_write_enable = false;
|
|
vk::CompareOp depth_compare_op = vk::CompareOp::eNever;
|
|
bool depth_bounds_test_enable = false;
|
|
float depth_min_bounds = 0.0f;
|
|
float depth_max_bounds = 0.0f;
|
|
bool stencil_test_enable = false;
|
|
PipelineStencilStaticState stencil_front;
|
|
PipelineStencilStaticState stencil_back;
|
|
uint32_t color_count = 1;
|
|
uint32_t color_mask[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
|
bool cull_front = false;
|
|
bool cull_back = false;
|
|
bool face = false;
|
|
uint8_t color_srcblend[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
|
uint8_t color_comb_fcn[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
|
uint8_t color_destblend[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
|
uint8_t alpha_srcblend[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
|
uint8_t alpha_comb_fcn[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
|
uint8_t alpha_destblend[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
|
bool separate_alpha_blend[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
|
bool blend_enable[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
|
bool blend_bypass[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
|
float blend_color_red = 0.0f;
|
|
float blend_color_green = 0.0f;
|
|
float blend_color_blue = 0.0f;
|
|
float blend_color_alpha = 0.0f;
|
|
|
|
bool operator==(const PipelineStaticParameters& other) const noexcept;
|
|
};
|
|
|
|
#pragma pack(pop)
|
|
|
|
static_assert(std::is_trivially_copyable_v<PipelineStaticParameters>);
|
|
static_assert(std::is_standard_layout_v<PipelineStaticParameters>);
|
|
static_assert(alignof(PipelineStaticParameters) == 1);
|
|
static_assert(sizeof(PipelineStaticParameters) ==
|
|
sizeof(float[3]) + sizeof(float[3]) + sizeof(bool) * 2 + sizeof(int[4]) +
|
|
sizeof(vk::PrimitiveTopology) + sizeof(uint32_t) + sizeof(bool) * 4 +
|
|
sizeof(vk::CompareOp) + sizeof(bool) + sizeof(float) * 2 + sizeof(bool) +
|
|
sizeof(PipelineStencilStaticState) * 2 + sizeof(uint32_t) +
|
|
sizeof(uint32_t[RENDER_COLOR_ATTACHMENTS_MAX]) + sizeof(bool) * 3 +
|
|
sizeof(uint8_t[RENDER_COLOR_ATTACHMENTS_MAX]) * 6 +
|
|
sizeof(bool[RENDER_COLOR_ATTACHMENTS_MAX]) * 3 + sizeof(float) * 4);
|
|
|
|
struct PipelineRenderingState {
|
|
std::array<vk::Format, RENDER_COLOR_ATTACHMENTS_MAX> color_formats {};
|
|
vk::Format depth_format = vk::Format::eUndefined;
|
|
vk::Format stencil_format = vk::Format::eUndefined;
|
|
uint32_t color_count = 0;
|
|
|
|
bool operator==(const PipelineRenderingState&) const = default;
|
|
};
|
|
|
|
class PipelineCache {
|
|
public:
|
|
PipelineCache(GraphicContext& graphics, DescriptorCache& descriptor_cache)
|
|
: m_graphics(graphics), m_descriptor_cache(descriptor_cache) {
|
|
EXIT_NOT_IMPLEMENTED(!Common::Thread::IsMainThread());
|
|
}
|
|
~PipelineCache();
|
|
KYTY_CLASS_NO_COPY(PipelineCache);
|
|
|
|
struct Pipeline {
|
|
vk::PipelineLayout pipeline_layout = nullptr;
|
|
vk::Pipeline pipeline = nullptr;
|
|
};
|
|
|
|
struct GraphicsPipeline: Pipeline {
|
|
ShaderId vs_shader_id;
|
|
ShaderId ps_shader_id;
|
|
};
|
|
|
|
struct ComputePipeline: Pipeline {
|
|
ShaderId cs_shader_id;
|
|
};
|
|
|
|
GraphicsPipeline&
|
|
CreateGraphicsPipeline(RenderColorInfo* colors, uint32_t color_count, RenderDepthInfo& depth,
|
|
ShaderVertexInputInfo& vs_input_info, RenderCommandBuffer& command,
|
|
ShaderPixelInputInfo* ps_input_info, vk::PrimitiveTopology topology,
|
|
bool ps_active, std::span<const uint32_t> vs_spirv,
|
|
std::span<const uint32_t> ps_spirv);
|
|
ComputePipeline& CreateComputePipeline(ShaderComputeInputInfo& input_info,
|
|
const HW::ComputeShaderInfo& cs_regs,
|
|
std::span<const uint32_t> cs_spirv);
|
|
|
|
private:
|
|
struct GraphicsPipelineKey {
|
|
PipelineRenderingState rendering;
|
|
ShaderId vs_shader_id;
|
|
ShaderId ps_shader_id;
|
|
PipelineStaticParameters static_params;
|
|
|
|
bool operator==(const GraphicsPipelineKey& other) const {
|
|
return rendering == other.rendering && vs_shader_id == other.vs_shader_id &&
|
|
ps_shader_id == other.ps_shader_id && static_params == other.static_params;
|
|
}
|
|
};
|
|
|
|
struct ComputePipelineKey {
|
|
ShaderId cs_shader_id;
|
|
|
|
bool operator==(const ComputePipelineKey& other) const {
|
|
return cs_shader_id == other.cs_shader_id;
|
|
}
|
|
};
|
|
|
|
struct PipelineKeyHash {
|
|
static void Mix(std::size_t& hash, std::size_t value) {
|
|
hash ^= value + static_cast<std::size_t>(0x9e3779b97f4a7c15ull) + (hash << 6u) +
|
|
(hash >> 2u);
|
|
}
|
|
|
|
static void MixShaderId(std::size_t& hash, const ShaderId& id) {
|
|
Mix(hash, id.hash0);
|
|
Mix(hash, id.crc32);
|
|
Mix(hash, id.ids.size());
|
|
for (auto value: id.ids) {
|
|
Mix(hash, value);
|
|
}
|
|
}
|
|
|
|
static void MixStaticParams(std::size_t& hash, const PipelineStaticParameters& params) {
|
|
const auto* bytes = reinterpret_cast<const uint8_t*>(¶ms);
|
|
for (std::size_t i = 0; i < sizeof(params); i++) {
|
|
Mix(hash, bytes[i]);
|
|
}
|
|
}
|
|
|
|
static void MixRendering(std::size_t& hash, const PipelineRenderingState& rendering) {
|
|
Mix(hash, rendering.color_count);
|
|
for (uint32_t i = 0; i < rendering.color_count; i++) {
|
|
Mix(hash, static_cast<uint32_t>(rendering.color_formats[i]));
|
|
}
|
|
Mix(hash, static_cast<uint32_t>(rendering.depth_format));
|
|
Mix(hash, static_cast<uint32_t>(rendering.stencil_format));
|
|
}
|
|
};
|
|
|
|
struct GraphicsPipelineKeyHash {
|
|
std::size_t operator()(const GraphicsPipelineKey& key) const {
|
|
std::size_t hash = 0;
|
|
PipelineKeyHash::MixRendering(hash, key.rendering);
|
|
PipelineKeyHash::MixShaderId(hash, key.vs_shader_id);
|
|
PipelineKeyHash::MixShaderId(hash, key.ps_shader_id);
|
|
PipelineKeyHash::MixStaticParams(hash, key.static_params);
|
|
return hash;
|
|
}
|
|
};
|
|
|
|
struct ComputePipelineKeyHash {
|
|
std::size_t operator()(const ComputePipelineKey& key) const {
|
|
std::size_t hash = 0;
|
|
PipelineKeyHash::MixShaderId(hash, key.cs_shader_id);
|
|
return hash;
|
|
}
|
|
};
|
|
|
|
GraphicContext& m_graphics;
|
|
DescriptorCache& m_descriptor_cache;
|
|
std::unordered_map<GraphicsPipelineKey, std::unique_ptr<GraphicsPipeline>,
|
|
GraphicsPipelineKeyHash>
|
|
m_graphics_pipelines;
|
|
std::unordered_map<ComputePipelineKey, std::unique_ptr<ComputePipeline>, ComputePipelineKeyHash>
|
|
m_compute_pipelines;
|
|
Common::Mutex m_mutex;
|
|
};
|
|
|
|
void LogPipelineTrace(const char* phase, uint32_t vs_hash0, uint32_t vs_crc32, uint32_t ps_hash0,
|
|
uint32_t ps_crc32);
|
|
void CreatePipelineInternal(
|
|
GraphicContext& graphics, DescriptorCache& descriptor_cache,
|
|
PipelineCache::GraphicsPipeline& pipeline, const PipelineRenderingState& rendering,
|
|
const ShaderVertexInputInfo& vs_input_info, std::span<const uint32_t> vs_shader,
|
|
const ShaderPixelInputInfo* ps_input_info, std::span<const uint32_t> ps_shader,
|
|
const PipelineStaticParameters& static_params, uint32_t vs_hash0, uint32_t vs_crc32,
|
|
uint32_t ps_hash0, uint32_t ps_crc32, bool ps_active);
|
|
void CreatePipelineInternal(GraphicContext& graphics, DescriptorCache& descriptor_cache,
|
|
PipelineCache::ComputePipeline& pipeline,
|
|
const ShaderComputeInputInfo& input_info,
|
|
std::span<const uint32_t> cs_shader);
|
|
|
|
} // namespace Libs::Graphics
|
|
|
|
#endif // EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_PIPELINECACHE_H_
|