mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-26 13:44:18 +01:00
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:
parent
2e96248fb6
commit
e849264028
@ -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
|
||||||
|
@ -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;
|
||||||
|
};
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
};
|
||||||
|
}
|
@ -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 {}
|
||||||
|
}
|
@ -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;
|
||||||
|
};
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user