mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 08:13:05 +00:00
pipeline: look up draw programs and pipelines from the command buffer
This commit is contained in:
1 parent
269e411ef2
commit
dbc7b8b2ff
11 files changed
+301
-382
No files matched your search
@@ -9,10 +9,9 @@
|
||||
#include "common/threads.h"
|
||||
#include "graphics/guest_gpu/gpu_format.h"
|
||||
#include "graphics/guest_gpu/hardwareContext.h"
|
||||
#include "graphics/host_gpu/renderer/colorRenderTarget.h"
|
||||
#include "graphics/host_gpu/renderer/debug.h"
|
||||
#include "graphics/host_gpu/renderer/depthRenderTarget.h"
|
||||
#include "graphics/host_gpu/renderer/image/imageView.h"
|
||||
#include "graphics/host_gpu/renderer/image/textureCommon.h"
|
||||
#include "graphics/host_gpu/renderer/pipeline/blendMapping.h"
|
||||
#include "graphics/host_gpu/renderer/render.h"
|
||||
#include "graphics/host_gpu/renderer/renderContext.h"
|
||||
@@ -332,33 +331,47 @@ struct PipelineCache::ProgramCache {
|
||||
template <typename InputInfo>
|
||||
ShaderProgram Get(const ShaderParams& params, InputInfo& input_info,
|
||||
uint32_t& push_data_cursor) {
|
||||
ShaderType stage;
|
||||
if constexpr (std::is_same_v<InputInfo, ShaderVertexInputInfo>) {
|
||||
stage = input_info.logical_stage;
|
||||
} else if constexpr (std::is_same_v<InputInfo, ShaderPixelInputInfo>) {
|
||||
stage = ShaderType::Pixel;
|
||||
} else {
|
||||
static_assert(std::is_same_v<InputInfo, ShaderComputeInputInfo>);
|
||||
stage = ShaderType::Compute;
|
||||
}
|
||||
|
||||
const auto user_data = std::span(params.user_data).first(params.user_data_count);
|
||||
lookup_key.stage = stage;
|
||||
lookup_key.hash = params.hash;
|
||||
lookup_key.user_data_count = params.user_data_count;
|
||||
lookup_key.code_size = static_cast<uint32_t>(params.code.size());
|
||||
BuildStageStaticKey(input_info, lookup_key.static_state);
|
||||
auto entry = programs.find(lookup_key);
|
||||
ShaderRecompiler::IR::SrtRuntime runtime {
|
||||
ShaderRecompiler::IR::SrtRuntime runtime {
|
||||
.user_data = user_data,
|
||||
.shader_base = params.Base(),
|
||||
.read_specialization_memory = ReadShaderGuestMemory,
|
||||
.image_heap = image_heap,
|
||||
};
|
||||
if constexpr (std::is_same_v<InputInfo, ShaderComputeInputInfo>) {
|
||||
runtime.workgroup_counts = input_info.workgroup_counts;
|
||||
ShaderRecompiler::CompileOptions options {.wave_size = input_info.wave_size};
|
||||
if constexpr (std::is_same_v<InputInfo, ShaderVertexInputInfo>) {
|
||||
options.stage = input_info.logical_stage;
|
||||
options.input_info.vertex = &input_info;
|
||||
options.user_data_base = 8;
|
||||
if (options.stage == ShaderType::Mesh ||
|
||||
options.stage == ShaderType::TessellationControl) {
|
||||
options.user_data_base = 0;
|
||||
options.wave_size =
|
||||
options.stage == ShaderType::Mesh ? input_info.mesh.wave_size : 64u;
|
||||
}
|
||||
} else if constexpr (std::is_same_v<InputInfo, ShaderPixelInputInfo>) {
|
||||
options.stage = ShaderType::Pixel;
|
||||
options.input_info.pixel = &input_info;
|
||||
} else {
|
||||
static_assert(std::is_same_v<InputInfo, ShaderComputeInputInfo>);
|
||||
options.stage = ShaderType::Compute;
|
||||
options.input_info.compute = &input_info;
|
||||
runtime.workgroup_counts = input_info.workgroup_counts;
|
||||
runtime.indirect_args_address = input_info.indirect_args_address;
|
||||
}
|
||||
lookup_key.stage = options.stage;
|
||||
lookup_key.hash = params.hash;
|
||||
lookup_key.user_data_count = params.user_data_count;
|
||||
lookup_key.code_size = static_cast<uint32_t>(params.code.size());
|
||||
BuildStageStaticKey(input_info, lookup_key.static_state);
|
||||
auto entry = programs.find(lookup_key);
|
||||
const auto bind = [&](const Permutation& permutation) {
|
||||
input_info.stage = {.program = &permutation.program,
|
||||
.resources = &entry->second.resources,
|
||||
.handle = &permutation.handle};
|
||||
permutation.program.bindings.AdvancePushData(push_data_cursor);
|
||||
return permutation.handle;
|
||||
};
|
||||
bool source_changed = false;
|
||||
if (entry != programs.end()) {
|
||||
auto& cached = entry->second;
|
||||
@@ -370,24 +383,12 @@ struct PipelineCache::ProgramCache {
|
||||
} else {
|
||||
permutation = cached.FindPermutation<false>(runtime, push_data_cursor);
|
||||
}
|
||||
if (permutation != nullptr) {
|
||||
input_info.stage = {.program = &permutation->program, .resources = &entry->second.resources};
|
||||
permutation->program.bindings.AdvancePushData(push_data_cursor);
|
||||
return permutation->handle;
|
||||
}
|
||||
if (permutation != nullptr) return bind(*permutation);
|
||||
}
|
||||
|
||||
ShaderStageInputInfo stage_input {};
|
||||
if constexpr (std::is_same_v<InputInfo, ShaderVertexInputInfo>) {
|
||||
stage_input.vertex = &input_info;
|
||||
} else if constexpr (std::is_same_v<InputInfo, ShaderPixelInputInfo>) {
|
||||
stage_input.pixel = &input_info;
|
||||
} else {
|
||||
stage_input.compute = &input_info;
|
||||
}
|
||||
const char* label = nullptr;
|
||||
const char* stage_name = nullptr;
|
||||
switch (stage) {
|
||||
switch (options.stage) {
|
||||
case ShaderType::Vertex: label = "ShaderRecompiler VS"; stage_name = "vs"; break;
|
||||
case ShaderType::Mesh: label = "ShaderRecompiler MS"; stage_name = "ms"; break;
|
||||
case ShaderType::Local: label = "ShaderRecompiler LS"; stage_name = "ls"; break;
|
||||
@@ -397,8 +398,6 @@ struct PipelineCache::ProgramCache {
|
||||
case ShaderType::Compute: label = "ShaderRecompiler CS"; stage_name = "cs"; break;
|
||||
default: EXIT("invalid pipeline shader stage\n");
|
||||
}
|
||||
ShaderRecompiler::CompileOptions options;
|
||||
options.stage = stage;
|
||||
options.profile = &profile;
|
||||
options.shader_hash = params.hash;
|
||||
options.user_data = user_data;
|
||||
@@ -407,18 +406,6 @@ struct PipelineCache::ProgramCache {
|
||||
options.early_dump = options.dump_ir;
|
||||
options.emit_debug_info = Config::GraphicsDebugDumpEnabled();
|
||||
options.dump_label = label;
|
||||
options.input_info = stage_input;
|
||||
|
||||
if constexpr (std::is_same_v<InputInfo, ShaderVertexInputInfo>) {
|
||||
options.user_data_base = 8;
|
||||
options.wave_size = input_info.wave_size;
|
||||
if (stage == ShaderType::Mesh || stage == ShaderType::TessellationControl) {
|
||||
options.user_data_base = 0;
|
||||
options.wave_size = stage == ShaderType::Mesh ? input_info.mesh.wave_size : 64u;
|
||||
}
|
||||
} else {
|
||||
options.wave_size = input_info.wave_size;
|
||||
}
|
||||
DumpShaderOriginal(stage_name, options.shader_hash, params.code);
|
||||
ShaderRecompiler::ShaderSource source;
|
||||
if (entry == programs.end()) source = ShaderRecompiler::PrepareShaderSource(params.code, options);
|
||||
@@ -453,17 +440,12 @@ struct PipelineCache::ProgramCache {
|
||||
} else if (source_changed) {
|
||||
entry->second.resource_plan = ShaderRecompiler::IR::ExtractResourcePlan(translated.program);
|
||||
if (const auto* permutation = entry->second.FindPermutation<true>(runtime, push_data_cursor)) {
|
||||
input_info.stage = {.program = &permutation->program, .resources = &entry->second.resources};
|
||||
permutation->program.bindings.AdvancePushData(push_data_cursor);
|
||||
return permutation->handle;
|
||||
return bind(*permutation);
|
||||
}
|
||||
}
|
||||
entry->second.permutations.push_back(CompilePermutation(
|
||||
stage_name, options, std::move(translated), entry->second.specialization, push_data_cursor,
|
||||
entry->second.FunctionCode()));
|
||||
const auto& permutation = entry->second.permutations.back();
|
||||
input_info.stage = {.program = &permutation.program, .resources = &entry->second.resources};
|
||||
permutation.program.bindings.AdvancePushData(push_data_cursor);
|
||||
|
||||
std::array<size_t, static_cast<size_t>(ShaderType::TessellationEvaluation) + 1> counts {};
|
||||
for (const auto& [key, source]: programs) {
|
||||
@@ -478,7 +460,7 @@ struct PipelineCache::ProgramCache {
|
||||
counts[static_cast<size_t>(ShaderType::Local)],
|
||||
counts[static_cast<size_t>(ShaderType::TessellationControl)],
|
||||
counts[static_cast<size_t>(ShaderType::TessellationEvaluation)]);
|
||||
return permutation.handle;
|
||||
return bind(entry->second.permutations.back());
|
||||
}
|
||||
|
||||
ProgramCache(GraphicContext& graphics, ShaderRecompiler::IR::ImageHeapSource* image_heap)
|
||||
@@ -521,9 +503,9 @@ PipelineCache::~PipelineCache() {
|
||||
auto destroy = [this](const auto& pipelines) {
|
||||
for (const auto& [key, pipeline]: pipelines) {
|
||||
(void)key;
|
||||
m_graphics.device.destroyPipeline(pipeline->pipeline, nullptr);
|
||||
m_graphics.device.destroyPipelineLayout(pipeline->pipeline_layout, nullptr);
|
||||
m_graphics.device.destroyDescriptorSetLayout(pipeline->descriptor_set_layout, nullptr);
|
||||
m_graphics.device.destroyPipeline(pipeline.pipeline, nullptr);
|
||||
m_graphics.device.destroyPipelineLayout(pipeline.pipeline_layout, nullptr);
|
||||
m_graphics.device.destroyDescriptorSetLayout(pipeline.descriptor_set_layout, nullptr);
|
||||
}
|
||||
};
|
||||
destroy(m_graphics_pipelines);
|
||||
@@ -681,11 +663,34 @@ void PipelineCache::Save() {
|
||||
m_driver_cache_dirty = false;
|
||||
}
|
||||
|
||||
PipelineCache::GraphicsPrograms PipelineCache::GetGraphicsPrograms(
|
||||
const HW::VertexShaderInfo& vertex_regs, const HW::PixelShaderInfo& pixel_regs,
|
||||
const HW::ShaderRegisters& sh, const HW::Context& context, const HW::UserConfig& user_config,
|
||||
std::span<const Prospero::ColorComponentMapping, 8> target_export_mapping, bool pixel_active,
|
||||
std::array<ShaderVertexInputInfo, 3>& vertex_info, ShaderPixelInputInfo& pixel_info) {
|
||||
void PipelineCache::GetGraphicsPrograms(const CommandBuffer& command, DrawRenderState& state) {
|
||||
const auto& context = command.GetRegisters();
|
||||
const auto& user_config = command.GetUserConfig();
|
||||
const auto& sh = context.GetShaderRegisters();
|
||||
const auto& vertex_regs = command.GetShaders().GetVs();
|
||||
const auto& pixel_regs = command.GetShaders().GetPs();
|
||||
auto& vertex_info = state.vertex_info;
|
||||
auto& pixel_info = state.ps_input_info;
|
||||
const bool object_primitive_id = context.HasObjectPrimitiveIdOutput();
|
||||
const auto write_mask = context.GetRenderTargetMask() & sh.m_cbShaderMask;
|
||||
uint32_t color_output_mask = object_primitive_id ? 1u << 7u : 0;
|
||||
for (uint32_t index = 0; index < RENDER_COLOR_ATTACHMENTS_MAX; index++) {
|
||||
const auto slot = ShaderPixelExportTarget(sh.m_cbShaderMask, index);
|
||||
if (slot >= RENDER_COLOR_ATTACHMENTS_MAX) {
|
||||
break;
|
||||
}
|
||||
if (sh.target_output_mode[index] != 0 && render_target_mask_slot(write_mask, slot) != 0) {
|
||||
color_output_mask |= 1u << slot;
|
||||
}
|
||||
}
|
||||
const auto& db = sh.db_shader_control;
|
||||
// Without color outputs, a pixel shader still runs for its depth or coverage side effects.
|
||||
const bool pixel_active =
|
||||
pixel_regs.ps_regs.data_addr != 0 &&
|
||||
(color_output_mask != 0 || db.shader_kill_enable || db.shader_z_export_enable ||
|
||||
db.shader_mask_export_enable || db.shader_dual_export_enable ||
|
||||
db.shader_execute_on_noop || sh.AlphaToMask());
|
||||
state.ps_active = pixel_active;
|
||||
const bool tess_active = user_config.GetPrimType() == Prospero::PrimitiveType::kPatch;
|
||||
std::array<ShaderParams, 3> vertex_params;
|
||||
if (tess_active) {
|
||||
@@ -694,7 +699,6 @@ PipelineCache::GraphicsPrograms PipelineCache::GetGraphicsPrograms(
|
||||
vertex_params[0] = PrepareProgram(vertex_regs, context, user_config, vertex_info[0]);
|
||||
}
|
||||
const bool mesh_active = vertex_info[0].logical_stage == ShaderType::Mesh;
|
||||
const bool object_primitive_id = context.HasObjectPrimitiveIdOutput();
|
||||
if (object_primitive_id) {
|
||||
// CxObjectIdMode: register source plus a 32-bit pipelined primitive-ID addition.
|
||||
EXIT_NOT_IMPLEMENTED(sh.m_paClObjprimIdCntl != 2u || mesh_active || tess_active ||
|
||||
@@ -725,6 +729,17 @@ PipelineCache::GraphicsPrograms PipelineCache::GetGraphicsPrograms(
|
||||
}
|
||||
ShaderParams pixel_params;
|
||||
if (pixel_active) {
|
||||
std::array<Prospero::ColorComponentMapping, RENDER_COLOR_ATTACHMENTS_MAX>
|
||||
target_export_mapping {};
|
||||
for (uint32_t slot = 0; slot < RENDER_COLOR_ATTACHMENTS_MAX; slot++) {
|
||||
const auto& rt = context.GetRenderTarget(slot);
|
||||
if ((color_output_mask & (1u << slot)) != 0 && rt.base.addr != 0) {
|
||||
target_export_mapping[slot] =
|
||||
TextureGetRenderTargetFormat(rt.info.format, rt.info.channel_type,
|
||||
rt.info.channel_order)
|
||||
.export_mapping;
|
||||
}
|
||||
}
|
||||
pixel_params = PrepareProgram(pixel_regs, sh, target_export_mapping, pixel_info);
|
||||
pixel_info.object_primitive_id = object_primitive_id;
|
||||
for (uint32_t export_index = 0; export_index < 8u; export_index++) {
|
||||
@@ -816,21 +831,25 @@ PipelineCache::GraphicsPrograms PipelineCache::GetGraphicsPrograms(
|
||||
}
|
||||
uint32_t push_data_cursor = ShaderRecompiler::IR::PushData::GraphicsDrawDwords(
|
||||
mesh_active, object_primitive_id, last_stage.user_clip_planes);
|
||||
GraphicsPrograms result;
|
||||
if (pixel_active) {
|
||||
result.pixel = m_program_cache->Get(pixel_params, pixel_info, push_data_cursor);
|
||||
m_program_cache->Get(pixel_params, pixel_info, push_data_cursor);
|
||||
for (const auto& output: pixel_info.stage.program->info.outputs) {
|
||||
if (output.kind == ShaderRecompiler::IR::StageOutputKind::Mrt ||
|
||||
output.kind == ShaderRecompiler::IR::StageOutputKind::ObjectPrimitiveId) {
|
||||
state.mrt_mask |= 1u << output.location;
|
||||
}
|
||||
}
|
||||
state.mrt_mask &= color_output_mask;
|
||||
}
|
||||
for (uint32_t i = 0; i < (tess_active ? 3u : 1u); i++) {
|
||||
result.vertex[i] = m_program_cache->Get(vertex_params[i], vertex_info[i], push_data_cursor);
|
||||
m_program_cache->Get(vertex_params[i], vertex_info[i], push_data_cursor);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ShaderProgram PipelineCache::GetComputeProgram(const HW::ComputeShaderInfo& regs,
|
||||
const HW::ShaderRegisters& sh,
|
||||
ShaderComputeInputInfo& input_info) {
|
||||
input_info.host_subgroup_size = m_graphics.SupportsComputeWave64() ? 64u : 32u;
|
||||
const auto params = PrepareProgram(regs, sh, input_info);
|
||||
const auto params = PrepareProgram(regs, input_info);
|
||||
input_info.lds_storage = input_info.lds_size_dwords * 4u >
|
||||
m_graphics.GetPhysicalDeviceProperties().limits.maxComputeSharedMemorySize;
|
||||
uint32_t push_data_cursor = 0;
|
||||
@@ -841,32 +860,32 @@ bool PipelineStaticParameters::operator==(const PipelineStaticParameters& other)
|
||||
return std::memcmp(this, &other, sizeof(*this)) == 0;
|
||||
}
|
||||
|
||||
PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline(
|
||||
std::span<const RenderColorInfo> colors, const RenderDepthInfo& depth,
|
||||
std::span<const ShaderVertexInputInfo> vertex_info, CommandBuffer& command,
|
||||
const ShaderPixelInputInfo* ps_input_info, vk::PrimitiveTopology topology,
|
||||
bool primitive_restart_enable, const GraphicsPrograms& programs) {
|
||||
PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline(const CommandBuffer& command,
|
||||
const DrawRenderState& state) {
|
||||
const auto* colors = state.color_info;
|
||||
const auto& depth = state.depth_info;
|
||||
const auto vertex_info = state.VertexStages();
|
||||
const auto& ps_input_info = state.ps_input_info;
|
||||
const auto& vs_input_info = vertex_info.front();
|
||||
const auto& vertex_program = programs.vertex[0];
|
||||
const auto& pixel_program = programs.pixel;
|
||||
const auto* vertex_program = vs_input_info.stage.handle;
|
||||
const auto* pixel_program = state.ps_input_info.stage.handle;
|
||||
KYTY_PROFILER_BLOCK("PipelineCache::CreatePipeline(Gfx)", profiler::colors::DeepOrangeA200);
|
||||
|
||||
EXIT_IF(colors.size() > RENDER_COLOR_ATTACHMENTS_MAX);
|
||||
EXIT_IF(!vertex_program);
|
||||
const bool ps_active = ps_input_info != nullptr;
|
||||
EXIT_IF(ps_active && !pixel_program);
|
||||
const auto color_count = static_cast<uint32_t>(colors.size());
|
||||
EXIT_IF(vertex_program == nullptr);
|
||||
const bool ps_active = state.ps_active;
|
||||
EXIT_IF(ps_active && pixel_program == nullptr);
|
||||
const auto color_count = state.color_count;
|
||||
|
||||
auto& ctx = command.GetRegisters();
|
||||
|
||||
const HW::ModeControl& mc = ctx.GetModeControl();
|
||||
|
||||
const auto vs_id = vertex_program.id;
|
||||
const auto ps_id = ps_active ? pixel_program.id : 0;
|
||||
const auto vs_id = vertex_program->id;
|
||||
const auto ps_id = ps_active ? pixel_program->id : 0;
|
||||
|
||||
GraphicsPipelineKey key {};
|
||||
for (uint32_t i = 0; i < programs.vertex.size(); i++) {
|
||||
key.vertex_shader_ids[i] = programs.vertex[i].id;
|
||||
for (uint32_t i = 0; i < vertex_info.size(); i++) {
|
||||
key.vertex_shader_ids[i] = vertex_info[i].stage.handle->id;
|
||||
}
|
||||
key.ps_shader_id = ps_id;
|
||||
auto& static_params = key.static_params;
|
||||
@@ -893,8 +912,8 @@ PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline(
|
||||
const auto& rt = ctx.GetRenderTarget(colors[i].target_slot);
|
||||
const auto& bc = ctx.GetBlendControl(colors[i].target_slot);
|
||||
auto alpha_source = ShaderAlphaBlendSource::None;
|
||||
if (slot == 0 && ps_input_info != nullptr) {
|
||||
alpha_source = ps_input_info->alpha_blend_source;
|
||||
if (slot == 0 && ps_active) {
|
||||
alpha_source = ps_input_info.alpha_blend_source;
|
||||
}
|
||||
static_params.blend_enable[slot] = bc.enable && !rt.info.blend_bypass;
|
||||
if (static_params.blend_enable[slot] && alpha_source == ShaderAlphaBlendSource::None &&
|
||||
@@ -964,7 +983,7 @@ PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline(
|
||||
EXIT_IF(attachment_samples == 0 ||
|
||||
vulkan_sample_count(attachment_samples) == vk::SampleCountFlagBits {});
|
||||
|
||||
if (ps_active && depth.depth_test_enable && ps_input_info->ps_execute_on_noop) {
|
||||
if (ps_active && depth.depth_test_enable && ps_input_info.ps_execute_on_noop) {
|
||||
static std::atomic<uint32_t> log_count {0};
|
||||
if (log_count.fetch_add(1, std::memory_order_relaxed) < 16) {
|
||||
LOGF("Pipeline: temporary: accepting EXEC_ON_NOOP with depth test enabled\n");
|
||||
@@ -974,11 +993,11 @@ PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline(
|
||||
const auto& clip_control = ctx.GetClipControl();
|
||||
static_params.negative_one_to_one = !clip_control.dx_clip_space;
|
||||
static_params.depth_clip_enable = clip_control.IsZClipEnabled();
|
||||
static_params.topology = topology;
|
||||
static_params.primitive_restart_enable = primitive_restart_enable;
|
||||
static_params.topology = state.topology;
|
||||
static_params.primitive_restart_enable = state.primitive_restart_enable;
|
||||
static_params.samples = attachment_samples;
|
||||
static_params.sample_shading_enable =
|
||||
ps_active && attachment_samples > 1 && ps_input_info->ps_sample_shading;
|
||||
ps_active && attachment_samples > 1 && ps_input_info.ps_sample_shading;
|
||||
if (static_params.sample_shading_enable && !m_graphics.sample_rate_shading_enabled) {
|
||||
EXIT("Pipeline: sample-rate shading is required but unsupported by the host\n");
|
||||
}
|
||||
@@ -1014,73 +1033,67 @@ PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline(
|
||||
}
|
||||
}
|
||||
|
||||
if (auto iter = m_graphics_pipelines.find(key); iter != m_graphics_pipelines.end()) {
|
||||
return *iter->second;
|
||||
auto [iter, inserted] = m_graphics_pipelines.try_emplace(key);
|
||||
auto& pipeline = iter->second;
|
||||
if (!inserted) {
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
if (graphics_debug_dump_enabled()) {
|
||||
ShaderDbgDumpInputInfo(vs_input_info);
|
||||
if (ps_active) {
|
||||
ShaderDbgDumpInputInfo(*ps_input_info);
|
||||
ShaderDbgDumpInputInfo(ps_input_info);
|
||||
}
|
||||
LOGF("PipelineTrace: shader modules VS=%" PRIu64 " module=%p PS=%" PRIu64 " module=%p\n",
|
||||
vs_id, static_cast<void*>(vertex_program.module), ps_id,
|
||||
static_cast<void*>(pixel_program.module));
|
||||
vs_id, static_cast<void*>(vertex_program->module), ps_id,
|
||||
ps_active ? static_cast<void*>(pixel_program->module) : nullptr);
|
||||
}
|
||||
|
||||
auto cached = std::make_unique<Pipeline>();
|
||||
LogPipelineTrace("CreatePipelineInternal begin", vs_id, ps_id);
|
||||
{
|
||||
Common::DebugCounters::ScopedTimer timer(Common::DebugCounters::Counter::PipelinesCreated,
|
||||
Common::DebugCounters::Counter::PipelineCreateNs,
|
||||
Common::DebugCounters::Peak::PipelineCreateNs);
|
||||
CreatePipelineInternal(m_graphics, *cached, rendering, key.vertex_input, vertex_info,
|
||||
ps_input_info, programs, static_params, m_driver_cache);
|
||||
CreatePipelineInternal(m_graphics, pipeline, rendering, key.vertex_input, state,
|
||||
static_params, m_driver_cache);
|
||||
}
|
||||
LogPipelineTrace("CreatePipelineInternal done", vs_id, ps_id);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(cached->pipeline == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(cached->pipeline_layout == nullptr);
|
||||
|
||||
auto [iter, inserted] = m_graphics_pipelines.emplace(std::move(key), std::move(cached));
|
||||
EXIT_IF(!inserted);
|
||||
EXIT_NOT_IMPLEMENTED(pipeline.pipeline == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(pipeline.pipeline_layout == nullptr);
|
||||
CheckpointDriverCache();
|
||||
|
||||
return *iter->second;
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
PipelineCache::Pipeline&
|
||||
PipelineCache::GetComputePipeline(const ShaderComputeInputInfo& input_info,
|
||||
const ShaderProgram& compute_program) {
|
||||
PipelineCache::Pipeline& PipelineCache::GetComputePipeline(const ShaderComputeInputInfo& input_info) {
|
||||
KYTY_PROFILER_BLOCK("PipelineCache::CreatePipeline(Compute)", profiler::colors::RedA100);
|
||||
|
||||
EXIT_IF(!compute_program);
|
||||
EXIT_IF(input_info.stage.handle == nullptr);
|
||||
const auto& compute_program = *input_info.stage.handle;
|
||||
|
||||
if (auto iter = m_compute_pipelines.find(compute_program.id);
|
||||
iter != m_compute_pipelines.end()) {
|
||||
return *iter->second;
|
||||
auto [iter, inserted] = m_compute_pipelines.try_emplace(compute_program.id);
|
||||
auto& pipeline = iter->second;
|
||||
if (!inserted) {
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
if (graphics_debug_dump_enabled()) {
|
||||
ShaderDbgDumpInputInfo(input_info);
|
||||
}
|
||||
|
||||
auto cached = std::make_unique<Pipeline>();
|
||||
{
|
||||
Common::DebugCounters::ScopedTimer timer(Common::DebugCounters::Counter::PipelinesCreated,
|
||||
Common::DebugCounters::Counter::PipelineCreateNs,
|
||||
Common::DebugCounters::Peak::PipelineCreateNs);
|
||||
CreatePipelineInternal(m_graphics, *cached, input_info, compute_program.module,
|
||||
CreatePipelineInternal(m_graphics, pipeline, input_info, compute_program.module,
|
||||
m_driver_cache);
|
||||
}
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(cached->pipeline == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(cached->pipeline_layout == nullptr);
|
||||
|
||||
auto [iter, inserted] = m_compute_pipelines.emplace(compute_program.id, std::move(cached));
|
||||
EXIT_IF(!inserted);
|
||||
EXIT_NOT_IMPLEMENTED(pipeline.pipeline == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(pipeline.pipeline_layout == nullptr);
|
||||
CheckpointDriverCache();
|
||||
|
||||
return *iter->second;
|
||||
return pipeline;
|
||||
}
|
||||
} // namespace Libs::Graphics
|
||||
Reference in new issue
Block a user