Abstract out pipeline-compile-time GPU state accesses

Introduces the base abstractions that will be used for pipeline caching, with a 'PipelineStateBundle' that can be (de)serialised to/from disk and an abstract accessor class to allow switching between creating disk-cached pipelines and fresh ones.
This commit is contained in:
Billy Laws 2022-12-03 14:36:30 +00:00
parent 2e96248fb6
commit e849264028
10 changed files with 314 additions and 27 deletions

View File

@ -190,6 +190,7 @@ add_library(skyline SHARED
${source_DIR}/skyline/gpu/interconnect/inline2memory.cpp ${source_DIR}/skyline/gpu/interconnect/inline2memory.cpp
${source_DIR}/skyline/gpu/interconnect/maxwell_3d/active_state.cpp ${source_DIR}/skyline/gpu/interconnect/maxwell_3d/active_state.cpp
${source_DIR}/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp ${source_DIR}/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp
${source_DIR}/skyline/gpu/interconnect/maxwell_3d/graphics_pipeline_state_accessor.cpp
${source_DIR}/skyline/gpu/interconnect/maxwell_3d/packed_pipeline_state.cpp ${source_DIR}/skyline/gpu/interconnect/maxwell_3d/packed_pipeline_state.cpp
${source_DIR}/skyline/gpu/interconnect/maxwell_3d/pipeline_manager.cpp ${source_DIR}/skyline/gpu/interconnect/maxwell_3d/pipeline_manager.cpp
${source_DIR}/skyline/gpu/interconnect/maxwell_3d/constant_buffers.cpp ${source_DIR}/skyline/gpu/interconnect/maxwell_3d/constant_buffers.cpp
@ -205,6 +206,7 @@ add_library(skyline SHARED
${source_DIR}/skyline/gpu/interconnect/common/samplers.cpp ${source_DIR}/skyline/gpu/interconnect/common/samplers.cpp
${source_DIR}/skyline/gpu/interconnect/common/textures.cpp ${source_DIR}/skyline/gpu/interconnect/common/textures.cpp
${source_DIR}/skyline/gpu/interconnect/common/shader_cache.cpp ${source_DIR}/skyline/gpu/interconnect/common/shader_cache.cpp
${source_DIR}/skyline/gpu/interconnect/common/pipeline_state_bundle.cpp
${source_DIR}/skyline/gpu/shaders/helper_shaders.cpp ${source_DIR}/skyline/gpu/shaders/helper_shaders.cpp
${source_DIR}/skyline/soc/smmu.cpp ${source_DIR}/skyline/soc/smmu.cpp
${source_DIR}/skyline/soc/host1x/syncpoint.cpp ${source_DIR}/skyline/soc/host1x/syncpoint.cpp

View File

@ -0,0 +1,38 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <shader_compiler/shader_info.h>
#include "common.h"
#include "textures.h"
namespace skyline::gpu::interconnect {
/**
* @brief Provides an abstract interface for accessing pipeline state at creation time
*/
class PipelineStateAccessor {
public:
/**
* @return The texture type for the TIC entry at the given index
*/
virtual Shader::TextureType GetTextureType(u32 index) const = 0;
/**
* @return The value of the constant buffer at the given index, offset and stage
*/
virtual u32 GetConstantBufferValue(u32 shaderStage, u32 index, u32 offset) const = 0;
/**
* @return The raw binary for the given pipeline stage
*/
virtual ShaderBinary GetShaderBinary(u32 pipelineStage) const = 0;
/**
* @brief Marks that all Get* operations on the pipeline state has finished and the pipeline is build
*/
virtual void MarkComplete() const = 0;
virtual ~PipelineStateAccessor() = default;
};
}

View File

@ -0,0 +1,64 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <range/v3/algorithm.hpp>
#include "pipeline_state_bundle.h"
namespace skyline::gpu::interconnect {
void PipelineStateBundle::PipelineStage::Reset() {
binary.clear();
binaryBaseOffset = 0;
}
PipelineStateBundle::PipelineStateBundle() {}
void PipelineStateBundle::Reset(span<const u8> newKey) {
ranges::for_each(pipelineStages, [](auto &stage) { stage.Reset(); });
key.resize(newKey.size());
span(key).copy_from(newKey);
textureTypes.clear();
constantBufferValues.clear();
}
void PipelineStateBundle::SetShaderBinary(u32 pipelineStage, ShaderBinary bin) {
if (pipelineStages.size() <= pipelineStage)
pipelineStages.resize(pipelineStage + 1);
auto &stageInfo{pipelineStages[pipelineStage]};
stageInfo.binary.resize(bin.binary.size());
span(stageInfo.binary).copy_from(bin.binary);
stageInfo.binaryBaseOffset = bin.baseOffset;
}
void PipelineStateBundle::AddTextureType(u32 index, Shader::TextureType type) {
textureTypes.emplace_back(index, type);
}
void PipelineStateBundle::AddConstantBufferValue(u32 shaderStage, u32 index, u32 offset, u32 value) {
constantBufferValues.push_back({shaderStage, index, offset, value});
}
span<u8> PipelineStateBundle::GetKey() {
return span(key);
}
ShaderBinary PipelineStateBundle::GetShaderBinary(u32 pipelineStage) {
auto &stageInfo{pipelineStages[pipelineStage]};
return {stageInfo.binary, stageInfo.binaryBaseOffset};
}
Shader::TextureType PipelineStateBundle::LookupTextureType(u32 offset) {
auto it{ranges::find_if(textureTypes, [offset](auto &pair) { return pair.first == offset; })};
if (it == textureTypes.end())
throw exception("Failed to find texture type for offset: 0x{:X}", offset);
return it->second;
}
u32 PipelineStateBundle::LookupConstantBufferValue(u32 shaderStage, u32 index, u32 offset) {
auto it{ranges::find_if(constantBufferValues, [index, offset, shaderStage](auto &val) { return val.index == index && val.offset == offset && val.shaderStage == shaderStage; })};
if (it == constantBufferValues.end())
throw exception("Failed to find constant buffer value for offset: 0x{:X}", offset);
return it->value;
}
}

View File

@ -0,0 +1,95 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <shader_compiler/shader_info.h>
#include "common.h"
namespace skyline::gpu::interconnect {
/**
* @brief Stores both key and non-key state for a pipeline that is otherwise only accessible at creation time
*/
class PipelineStateBundle {
private:
std::vector<u8> key; //!< Byte array containing the pipeline key, this is interpreted by the the user and two different keys might refer to the same pipeline
/**
* @brief Holds the raw binary and associated info for a pipeline stage
*/
struct PipelineStage {
std::vector<u8> binary;
u32 binaryBaseOffset;
void Reset();
};
/**
* @brief Holds a value of a constant buffer read from memory at pipeline creation time
*/
struct ConstantBufferValue {
u32 shaderStage;
u32 index;
u32 offset;
u32 value;
};
boost::container::small_vector<ConstantBufferValue, 4> constantBufferValues;
boost::container::small_vector<std::pair<u32, Shader::TextureType>, 4> textureTypes;
std::vector<PipelineStage> pipelineStages{};
public:
PipelineStateBundle();
/**
* @brief Resets the bundle's state using the given key so it can be reused for a new pipeline
*/
void Reset(span<const u8> newKey);
template<typename T> requires std::is_trivially_copyable_v<T>
void Reset(const T &value) {
Reset(span<const u8>(reinterpret_cast<const u8 *>(&value), sizeof(T)));
}
/**
* @brief Sets the binary for a given pipeline stage
*/
void SetShaderBinary(u32 pipelineStage, ShaderBinary bin);
/**
* @brief Adds a texture type value for a given offset to the bundle
*/
void AddTextureType(u32 index, Shader::TextureType type);
/**
* @brief Adds a constant buffer value for a given offset and shader stage to the bundle
*/
void AddConstantBufferValue(u32 shaderStage, u32 index, u32 offset, u32 value);
/**
* @brief Returns the raw key data for the pipeline
*/
span<u8> GetKey();
template<typename T> requires std::is_trivially_copyable_v<T>
const T &GetKey() {
return *reinterpret_cast<const T *>(key.data());
}
/**
* @brief Returns the binary for a given pipeline stage
*/
ShaderBinary GetShaderBinary(u32 pipelineStage);
/**
* @brief Returns the texture type for a given offset
*/
Shader::TextureType LookupTextureType(u32 offset);
/**
* @brief Returns the constant buffer value for a given offset and shader stage
*/
u32 LookupConstantBufferValue(u32 shaderStage, u32 index, u32 offset);
};
}

View File

@ -0,0 +1,33 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include "graphics_pipeline_state_accessor.h"
namespace skyline::gpu::interconnect::maxwell3d {
RuntimeGraphicsPipelineStateAccessor::RuntimeGraphicsPipelineStateAccessor(PipelineStateBundle &bundle,
InterconnectContext &ctx,
Textures &textures, ConstantBufferSet &constantBuffers,
const std::array<ShaderBinary, engine::PipelineCount> &shaderBinaries)
: bundle{bundle}, ctx{ctx}, textures{textures}, constantBuffers{constantBuffers}, shaderBinaries{shaderBinaries} {}
Shader::TextureType RuntimeGraphicsPipelineStateAccessor::GetTextureType(u32 index) const {
Shader::TextureType type{textures.GetTextureType(ctx, index)};
bundle.AddTextureType(index, type);
return type;
}
u32 RuntimeGraphicsPipelineStateAccessor::GetConstantBufferValue(u32 shaderStage, u32 index, u32 offset) const {
u32 value{constantBuffers[shaderStage][index].Read<u32>(ctx.executor, offset)};
bundle.AddConstantBufferValue(shaderStage, index, offset, value);
return value;
}
ShaderBinary RuntimeGraphicsPipelineStateAccessor::GetShaderBinary(u32 pipelineStage) const {
ShaderBinary binary{shaderBinaries[pipelineStage]};
bundle.SetShaderBinary(pipelineStage, binary);
return binary;
}
void RuntimeGraphicsPipelineStateAccessor::MarkComplete() const {}
}

View File

@ -0,0 +1,38 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <gpu/interconnect/common/pipeline_state_accessor.h>
#include <gpu/interconnect/common/pipeline_state_bundle.h>
#include <gpu/interconnect/common/textures.h>
#include "constant_buffers.h"
namespace skyline::gpu::interconnect::maxwell3d {
/**
* @brief Implements the PipelineStateAccessor interface for pipelines created at emulator runtime
*/
class RuntimeGraphicsPipelineStateAccessor : public PipelineStateAccessor {
private:
PipelineStateBundle &bundle;
InterconnectContext &ctx;
Textures &textures;
ConstantBufferSet &constantBuffers;
std::array<ShaderBinary, engine::PipelineCount> shaderBinaries;
public:
RuntimeGraphicsPipelineStateAccessor(PipelineStateBundle &bundle,
InterconnectContext &ctx,
Textures &textures, ConstantBufferSet &constantBuffers,
const std::array<ShaderBinary, engine::PipelineCount> &shaderBinaries);
Shader::TextureType GetTextureType(u32 index) const override;
u32 GetConstantBufferValue(u32 shaderStage, u32 index, u32 offset) const override;
ShaderBinary GetShaderBinary(u32 pipelineStage) const override;
void MarkComplete() const override;
};
}

View File

@ -173,35 +173,36 @@ namespace skyline::gpu::interconnect::maxwell3d {
return info; return info;
} }
static std::array<Pipeline::ShaderStage, engine::ShaderStageCount> MakePipelineShaders(InterconnectContext &ctx, Textures &textures, ConstantBufferSet &constantBuffers, const PackedPipelineState &packedState, const std::array<ShaderBinary, engine::PipelineCount> &shaderBinaries) { static std::array<Pipeline::ShaderStage, engine::ShaderStageCount> MakePipelineShaders(InterconnectContext &ctx, const PipelineStateAccessor &accessor, const PackedPipelineState &packedState) {
ctx.gpu.shader.ResetPools(); ctx.gpu.shader.ResetPools();
using PipelineStage = engine::Pipeline::Shader::Type; using PipelineStage = engine::Pipeline::Shader::Type;
auto pipelineStage{[](size_t i) { return static_cast<PipelineStage>(i); }}; auto pipelineStage{[](u32 i) { return static_cast<PipelineStage>(i); }};
auto stageIdx{[](PipelineStage stage) { return static_cast<u8>(stage); }}; auto stageIdx{[](PipelineStage stage) { return static_cast<u8>(stage); }};
std::array<Shader::IR::Program, engine::PipelineCount> programs; std::array<Shader::IR::Program, engine::PipelineCount> programs;
bool ignoreVertexCullBeforeFetch{}; bool ignoreVertexCullBeforeFetch{};
for (size_t i{}; i < engine::PipelineCount; i++) { for (u32 i{}; i < engine::PipelineCount; i++) {
if (!packedState.shaderHashes[i]) if (!packedState.shaderHashes[i])
continue; continue;
auto binary{accessor.GetShaderBinary(i)};
auto program{ctx.gpu.shader.ParseGraphicsShader( auto program{ctx.gpu.shader.ParseGraphicsShader(
packedState.postVtgShaderAttributeSkipMask, packedState.postVtgShaderAttributeSkipMask,
ConvertCompilerShaderStage(static_cast<PipelineStage>(i)), ConvertCompilerShaderStage(static_cast<PipelineStage>(i)),
shaderBinaries[i].binary, shaderBinaries[i].baseOffset, binary.binary, binary.baseOffset,
packedState.bindlessTextureConstantBufferSlotSelect, packedState.bindlessTextureConstantBufferSlotSelect,
packedState.viewportTransformEnable, packedState.viewportTransformEnable,
[&](u32 index, u32 offset) { [&](u32 index, u32 offset) {
size_t shaderStage{i > 0 ? (i - 1) : 0}; u32 shaderStage{i > 0 ? (i - 1) : 0};
return constantBuffers[shaderStage][index].Read<int>(ctx.executor, offset); return accessor.GetConstantBufferValue(shaderStage, index, offset);
}, [&](u32 index) { }, [&](u32 index) {
return textures.GetTextureType(ctx, BindlessHandle{ .raw = index }.textureIndex); return accessor.GetTextureType(BindlessHandle{ .raw = index }.textureIndex);
})}; })};
if (i == stageIdx(PipelineStage::Vertex) && packedState.shaderHashes[stageIdx(PipelineStage::VertexCullBeforeFetch)]) { if (i == stageIdx(PipelineStage::Vertex) && packedState.shaderHashes[stageIdx(PipelineStage::VertexCullBeforeFetch)]) {
ignoreVertexCullBeforeFetch = true; ignoreVertexCullBeforeFetch = true;
programs[i] = ctx.gpu.shader.CombineVertexShaders(programs[stageIdx(PipelineStage::VertexCullBeforeFetch)], program, shaderBinaries[i].binary); programs[i] = ctx.gpu.shader.CombineVertexShaders(programs[stageIdx(PipelineStage::VertexCullBeforeFetch)], program, binary.binary);
} else { } else {
programs[i] = program; programs[i] = program;
} }
@ -213,7 +214,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
std::array<Pipeline::ShaderStage, engine::ShaderStageCount> shaderStages{}; std::array<Pipeline::ShaderStage, engine::ShaderStageCount> shaderStages{};
for (size_t i{stageIdx(ignoreVertexCullBeforeFetch ? PipelineStage::Vertex : PipelineStage::VertexCullBeforeFetch)}; i < engine::PipelineCount; i++) { for (u32 i{stageIdx(ignoreVertexCullBeforeFetch ? PipelineStage::Vertex : PipelineStage::VertexCullBeforeFetch)}; i < engine::PipelineCount; i++) {
if (!packedState.shaderHashes[i]) if (!packedState.shaderHashes[i])
continue; continue;
@ -424,8 +425,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
static cache::GraphicsPipelineCache::CompiledPipeline MakeCompiledPipeline(InterconnectContext &ctx, static cache::GraphicsPipelineCache::CompiledPipeline MakeCompiledPipeline(InterconnectContext &ctx,
const PackedPipelineState &packedState, const PackedPipelineState &packedState,
const std::array<Pipeline::ShaderStage, engine::ShaderStageCount> &shaderStages, const std::array<Pipeline::ShaderStage, engine::ShaderStageCount> &shaderStages,
span<vk::DescriptorSetLayoutBinding> layoutBindings, span<vk::DescriptorSetLayoutBinding> layoutBindings) {
span<TextureView *> colorAttachments, TextureView *depthAttachment) {
boost::container::static_vector<vk::PipelineShaderStageCreateInfo, engine::ShaderStageCount> shaderStageInfos; boost::container::static_vector<vk::PipelineShaderStageCreateInfo, engine::ShaderStageCount> shaderStageInfos;
for (const auto &stage : shaderStages) for (const auto &stage : shaderStages)
if (stage.module) if (stage.module)
@ -526,8 +526,13 @@ namespace skyline::gpu::interconnect::maxwell3d {
std::tie(depthStencilState.front, depthStencilState.back) = packedState.GetStencilOpsState(); std::tie(depthStencilState.front, depthStencilState.back) = packedState.GetStencilOpsState();
boost::container::static_vector<vk::PipelineColorBlendAttachmentState, engine::ColorTargetCount> attachmentBlendStates; boost::container::static_vector<vk::PipelineColorBlendAttachmentState, engine::ColorTargetCount> attachmentBlendStates;
for (u32 i{}; i < colorAttachments.size(); i++) boost::container::static_vector<vk::Format, engine::ColorTargetCount> colorAttachmentFormats;
for (u32 i{}; i < packedState.GetColorRenderTargetCount(); i++) {
attachmentBlendStates.push_back(packedState.GetAttachmentBlendState(i)); attachmentBlendStates.push_back(packedState.GetAttachmentBlendState(i));
texture::Format format{packedState.GetColorRenderTargetFormat(i)};
colorAttachmentFormats.push_back(format ? format->vkFormat : vk::Format::eUndefined);
}
vk::PipelineColorBlendStateCreateInfo colorBlendState{ vk::PipelineColorBlendStateCreateInfo colorBlendState{
.logicOpEnable = packedState.logicOpEnable, .logicOpEnable = packedState.logicOpEnable,
@ -536,7 +541,11 @@ namespace skyline::gpu::interconnect::maxwell3d {
.pAttachments = attachmentBlendStates.data() .pAttachments = attachmentBlendStates.data()
}; };
constexpr std::array<vk::DynamicState, 10> dynamicStates{
static constexpr u32 BaseDynamicStateCount{9};
static constexpr u32 ExtendedDynamicStateCount{BaseDynamicStateCount + 1};
constexpr std::array<vk::DynamicState, ExtendedDynamicStateCount> dynamicStates{
vk::DynamicState::eViewport, vk::DynamicState::eViewport,
vk::DynamicState::eScissor, vk::DynamicState::eScissor,
vk::DynamicState::eLineWidth, vk::DynamicState::eLineWidth,
@ -550,9 +559,6 @@ namespace skyline::gpu::interconnect::maxwell3d {
vk::DynamicState::eVertexInputBindingStrideEXT vk::DynamicState::eVertexInputBindingStrideEXT
}; };
static constexpr u32 BaseDynamicStateCount{9};
static constexpr u32 ExtendedDynamicStateCount{BaseDynamicStateCount + 1};
vk::PipelineDynamicStateCreateInfo dynamicState{ vk::PipelineDynamicStateCreateInfo dynamicState{
.dynamicStateCount = ctx.gpu.traits.supportsExtendedDynamicState ? ExtendedDynamicStateCount : BaseDynamicStateCount, .dynamicStateCount = ctx.gpu.traits.supportsExtendedDynamicState ? ExtendedDynamicStateCount : BaseDynamicStateCount,
.pDynamicStates = dynamicStates.data() .pDynamicStates = dynamicStates.data()
@ -569,6 +575,8 @@ namespace skyline::gpu::interconnect::maxwell3d {
.pScissors = emptyScissors.data(), .pScissors = emptyScissors.data(),
}; };
texture::Format depthStencilFormat{packedState.GetDepthRenderTargetFormat()};
return ctx.gpu.graphicsPipelineCache.GetCompiledPipeline(cache::GraphicsPipelineCache::PipelineState{ return ctx.gpu.graphicsPipelineCache.GetCompiledPipeline(cache::GraphicsPipelineCache::PipelineState{
.shaderStages = shaderStageInfos, .shaderStages = shaderStageInfos,
.vertexState = vertexInputState, .vertexState = vertexInputState,
@ -580,15 +588,16 @@ namespace skyline::gpu::interconnect::maxwell3d {
.depthStencilState = depthStencilState, .depthStencilState = depthStencilState,
.colorBlendState = colorBlendState, .colorBlendState = colorBlendState,
.dynamicState = dynamicState, .dynamicState = dynamicState,
.colorAttachments = colorAttachments, .colorFormats = colorAttachmentFormats,
.depthStencilAttachment = depthAttachment, .depthStencilFormat = depthStencilFormat ? depthStencilFormat->vkFormat : vk::Format::eUndefined,
.sampleCount = vk::SampleCountFlagBits::e1, //TODO: fix after MSAA support
}, layoutBindings); }, layoutBindings);
} }
Pipeline::Pipeline(InterconnectContext &ctx, Textures &textures, ConstantBufferSet &constantBuffers, const PackedPipelineState &packedState, const std::array<ShaderBinary, engine::PipelineCount> &shaderBinaries, span<TextureView *> colorAttachments, TextureView *depthAttachment) Pipeline::Pipeline(InterconnectContext &ctx, const PipelineStateAccessor &accessor, const PackedPipelineState &packedState)
: shaderStages{MakePipelineShaders(ctx, textures, constantBuffers, packedState, shaderBinaries)}, : shaderStages{MakePipelineShaders(ctx, accessor, packedState)},
descriptorInfo{MakePipelineDescriptorInfo(shaderStages, ctx.gpu.traits.quirks.needsIndividualTextureBindingWrites)}, descriptorInfo{MakePipelineDescriptorInfo(shaderStages, ctx.gpu.traits.quirks.needsIndividualTextureBindingWrites)},
compiledPipeline{MakeCompiledPipeline(ctx, packedState, shaderStages, descriptorInfo.descriptorSetLayoutBindings, colorAttachments, depthAttachment)}, compiledPipeline{MakeCompiledPipeline(ctx, packedState, shaderStages, descriptorInfo.descriptorSetLayoutBindings)},
sourcePackedState{packedState} { sourcePackedState{packedState} {
storageBufferViews.resize(descriptorInfo.totalStorageBufferCount); storageBufferViews.resize(descriptorInfo.totalStorageBufferCount);
} }

View File

@ -11,6 +11,7 @@
#include "common.h" #include "common.h"
#include "packed_pipeline_state.h" #include "packed_pipeline_state.h"
#include "constant_buffers.h" #include "constant_buffers.h"
#include "graphics_pipeline_state_accessor.h"
namespace skyline::gpu { namespace skyline::gpu {
class TextureView; class TextureView;
@ -100,7 +101,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
PackedPipelineState sourcePackedState; PackedPipelineState sourcePackedState;
Pipeline(InterconnectContext &ctx, Textures &textures, ConstantBufferSet &constantBuffers, const PackedPipelineState &packedState, const std::array<ShaderBinary, engine::PipelineCount> &shaderBinaries, span<TextureView *> colorAttachments, TextureView *depthAttachment); Pipeline(InterconnectContext &ctx, const PipelineStateAccessor &accessor, const PackedPipelineState &packedState);
Pipeline *LookupNext(const PackedPipelineState &packedState); Pipeline *LookupNext(const PackedPipelineState &packedState);
@ -123,17 +124,23 @@ namespace skyline::gpu::interconnect::maxwell3d {
DescriptorUpdateInfo *SyncDescriptorsQuickBind(InterconnectContext &ctx, ConstantBufferSet &constantBuffers, Samplers &samplers, Textures &textures, ConstantBuffers::QuickBind quickBind, span<TextureView *> sampledImages); DescriptorUpdateInfo *SyncDescriptorsQuickBind(InterconnectContext &ctx, ConstantBufferSet &constantBuffers, Samplers &samplers, Textures &textures, ConstantBuffers::QuickBind quickBind, span<TextureView *> sampledImages);
}; };
/**
* @brief Manages the caching and creation of pipelines
*/
class PipelineManager { class PipelineManager {
private: private:
PipelineStateBundle bundle;
tsl::robin_map<PackedPipelineState, std::unique_ptr<Pipeline>, PackedPipelineStateHash> map; tsl::robin_map<PackedPipelineState, std::unique_ptr<Pipeline>, PackedPipelineStateHash> map;
public: public:
Pipeline *FindOrCreate(InterconnectContext &ctx, Textures &textures, ConstantBufferSet &constantBuffers, const PackedPipelineState &packedState, const std::array<ShaderBinary, engine::PipelineCount> &shaderBinaries, span<TextureView *> colorAttachments, TextureView *depthAttachment) { Pipeline *FindOrCreate(InterconnectContext &ctx, Textures &textures, ConstantBufferSet &constantBuffers, const PackedPipelineState &packedState, const std::array<ShaderBinary, engine::PipelineCount> &shaderBinaries) {
auto it{map.find(packedState)}; auto it{map.find(packedState)};
if (it != map.end()) if (it != map.end())
return it->second.get(); return it->second.get();
return map.emplace(packedState, std::make_unique<Pipeline>(ctx, textures, constantBuffers, packedState, shaderBinaries, colorAttachments, depthAttachment)).first->second.get(); bundle.Reset(packedState);
auto accessor{RuntimeGraphicsPipelineStateAccessor{bundle, ctx, textures, constantBuffers, shaderBinaries}};
return map.emplace(packedState, std::make_unique<Pipeline>(ctx, accessor, packedState)).first->second.get();
} }
}; };
} }

View File

@ -432,7 +432,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
} }
} }
auto newPipeline{pipelineManager.FindOrCreate(ctx, textures, constantBuffers, packedState, shaderBinaries, colorAttachments, depthAttachment)}; auto newPipeline{pipelineManager.FindOrCreate(ctx, textures, constantBuffers, packedState, shaderBinaries)};
if (pipeline) if (pipeline)
pipeline->AddTransition(newPipeline); pipeline->AddTransition(newPipeline);
pipeline = newPipeline; pipeline = newPipeline;

View File

@ -136,6 +136,7 @@ namespace skyline::gpu {
.scissorCount = 1 .scissorCount = 1
}; };
std::array<vk::Format, 1> colorFormats{colorAttachment ? colorAttachment->format->vkFormat : vk::Format::eUndefined};
return gpu.graphicsPipelineCache.GetCompiledPipeline(cache::GraphicsPipelineCache::PipelineState{ return gpu.graphicsPipelineCache.GetCompiledPipeline(cache::GraphicsPipelineCache::PipelineState{
.shaderStages = shaderStages, .shaderStages = shaderStages,
.vertexState = vertexState, .vertexState = vertexState,
@ -147,8 +148,8 @@ namespace skyline::gpu {
.depthStencilState = depthStencilState, .depthStencilState = depthStencilState,
.colorBlendState = blendState, .colorBlendState = blendState,
.dynamicState = {}, .dynamicState = {},
.colorAttachments = span<TextureView *>{colorAttachment}, .colorFormats = colorFormats,
.depthStencilAttachment = depthStencilAttachment, .depthStencilFormat = depthStencilAttachment ? depthStencilAttachment->format->vkFormat : vk::Format::eUndefined,
}, layoutBindings, pushConstantRanges, true); }, layoutBindings, pushConstantRanges, true);
} }