Move pipeline cache Key to cpp file and rename to PackedPipelineState

The new name is more indicative of what the struct contains and how it will be used as more than just a key.
This commit is contained in:
Billy Laws 2022-09-06 20:09:23 +01:00
parent e1512c91a0
commit effeb074b6
2 changed files with 143 additions and 122 deletions

View File

@ -13,6 +13,89 @@
#include "pipeline_state.h" #include "pipeline_state.h"
namespace skyline::gpu::interconnect::maxwell3d { namespace skyline::gpu::interconnect::maxwell3d {
/* Packed State */
void PackedPipelineState::SetCtFormat(size_t index, engine::ColorTarget::Format format) {
ctFormats[index] = static_cast<u8>(format);
}
void PackedPipelineState::SetZtFormat(engine::ZtFormat format) {
ztFormat = static_cast<u8>(format) - static_cast<u8>(engine::ZtFormat::ZF32);
}
void PackedPipelineState::SetVertexBinding(u32 index, engine::VertexStream stream, engine::VertexStreamInstance instance) {
vertexBindings[index].stride = stream.format.stride;
vertexBindings[index].instanced = instance.isInstanced;
vertexBindings[index].enable = stream.format.enable;
vertexBindings[index].divisor = stream.frequency;
}
void PackedPipelineState::SetTessellationParameters(engine::TessellationParameters parameters) {
domainType = parameters.domainType;
spacing = parameters.spacing;
outputPrimitives = parameters.outputPrimitives;
}
void PackedPipelineState::SetPolygonMode(engine::PolygonMode mode) {
polygonMode = static_cast<u8>(static_cast<u32>(mode) - 0x1B00);
}
static u8 PackCompareFunc(engine::CompareFunc func) {
// OpenGL enums go from 0x200 to 0x207 and the others from 1 to 8, subtract 0x200 from OpenGL enums and 1 from the others we get a 0-7 range (method from yuzu)
u32 val{static_cast<u32>(func)};
return static_cast<u8>(val >= 0x200 ? (val - 0x200) : (val - 1));
}
void PackedPipelineState::SetDepthFunc(engine::CompareFunc func) {
depthFunc = PackCompareFunc(func);
}
static u8 PackStencilOp(engine::StencilOps::Op op) {
switch (op) {
case engine::StencilOps::Op::OglZero:
op = engine::StencilOps::Op::D3DZero;
break;
case engine::StencilOps::Op::OglKeep:
op = engine::StencilOps::Op::D3DKeep;
break;
case engine::StencilOps::Op::OglReplace:
op = engine::StencilOps::Op::D3DReplace;
break;
case engine::StencilOps::Op::OglIncrSat:
op = engine::StencilOps::Op::D3DIncrSat;
break;
case engine::StencilOps::Op::OglDecrSat:
op = engine::StencilOps::Op::D3DDecrSat;
break;
case engine::StencilOps::Op::OglInvert:
op = engine::StencilOps::Op::D3DInvert;
break;
case engine::StencilOps::Op::OglIncr:
op = engine::StencilOps::Op::D3DIncr;
break;
case engine::StencilOps::Op::OglDecr:
op = engine::StencilOps::Op::D3DDecr;
break;
default:
break;
}
return static_cast<u8>(op) - 1;
}
static PackedPipelineState::StencilOps PackStencilOps(engine::StencilOps ops) {
return {
.zPass = PackStencilOp(ops.zPass),
.fail = PackStencilOp(ops.fail),
.zFail = PackStencilOp(ops.zFail),
.func = PackCompareFunc(ops.func),
};
}
void PackedPipelineState::SetStencilOps(engine::StencilOps front, engine::StencilOps back) {
stencilFront = PackStencilOps(front);
stencilBack = PackStencilOps(back);
}
/* Colour Render Target */ /* Colour Render Target */
void ColorRenderTargetState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const { void ColorRenderTargetState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
manager.Bind(handle, colorTarget); manager.Bind(handle, colorTarget);
@ -107,9 +190,9 @@ namespace skyline::gpu::interconnect::maxwell3d {
#undef FORMAT_CASE_BASE #undef FORMAT_CASE_BASE
} }
void ColorRenderTargetState::Flush(InterconnectContext &ctx, Key &key) { void ColorRenderTargetState::Flush(InterconnectContext &ctx, PackedPipelineState &packedState) {
auto &target{engine->colorTarget}; auto &target{engine->colorTarget};
key.SetCtFormat(index, target.format); packedState.SetCtFormat(index, target.format);
if (target.format == engine::ColorTarget::Format::Disabled) { if (target.format == engine::ColorTarget::Format::Disabled) {
view = {}; view = {};
@ -175,8 +258,8 @@ namespace skyline::gpu::interconnect::maxwell3d {
#undef FORMAT_CASE #undef FORMAT_CASE
} }
void DepthRenderTargetState::Flush(InterconnectContext &ctx, Key &key) { void DepthRenderTargetState::Flush(InterconnectContext &ctx, PackedPipelineState &packedState) {
key.SetZtFormat(engine->ztFormat); packedState.SetZtFormat(engine->ztFormat);
if (!engine->ztSelect.targetCount) { if (!engine->ztSelect.targetCount) {
view = {}; view = {};
@ -224,12 +307,12 @@ namespace skyline::gpu::interconnect::maxwell3d {
VertexInputState::VertexInputState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine) : engine{manager, dirtyHandle, engine} {} VertexInputState::VertexInputState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine) : engine{manager, dirtyHandle, engine} {}
void VertexInputState::Flush(Key &key) { void VertexInputState::Flush(PackedPipelineState &packedState) {
for (u32 i{}; i < engine::VertexStreamCount; i++) for (u32 i{}; i < engine::VertexStreamCount; i++)
key.SetVertexBinding(i, engine->vertexStreams[i], engine->vertexStreamInstance[i]); packedState.SetVertexBinding(i, engine->vertexStreams[i], engine->vertexStreamInstance[i]);
for (u32 i{}; i < engine::VertexAttributeCount; i++) for (u32 i{}; i < engine::VertexAttributeCount; i++)
key.vertexAttributes[i] = engine->vertexAttributes[i]; packedState.vertexAttributes[i] = engine->vertexAttributes[i];
} }
static vk::Format ConvertVertexInputAttributeFormat(engine::VertexAttribute::ComponentBitWidths componentBitWidths, engine::VertexAttribute::NumericalType numericalType) { static vk::Format ConvertVertexInputAttributeFormat(engine::VertexAttribute::ComponentBitWidths componentBitWidths, engine::VertexAttribute::NumericalType numericalType) {
@ -322,9 +405,9 @@ namespace skyline::gpu::interconnect::maxwell3d {
InputAssemblyState::InputAssemblyState(const EngineRegisters &engine) : engine{engine} {} InputAssemblyState::InputAssemblyState(const EngineRegisters &engine) : engine{engine} {}
void InputAssemblyState::Update(Key &key) { void InputAssemblyState::Update(PackedPipelineState &packedState) {
key.topology = currentEngineTopology; packedState.topology = currentEngineTopology;
key.primitiveRestartEnabled = engine.primitiveRestartEnable & 1; packedState.primitiveRestartEnabled = engine.primitiveRestartEnable & 1;
} }
static std::pair<vk::PrimitiveTopology, Shader::InputTopology> ConvertPrimitiveTopology(engine::DrawTopology topology) { static std::pair<vk::PrimitiveTopology, Shader::InputTopology> ConvertPrimitiveTopology(engine::DrawTopology topology) {
@ -388,9 +471,9 @@ namespace skyline::gpu::interconnect::maxwell3d {
TessellationState::TessellationState(const EngineRegisters &engine) : engine{engine} {} TessellationState::TessellationState(const EngineRegisters &engine) : engine{engine} {}
void TessellationState::Update(Key &key) { void TessellationState::Update(PackedPipelineState &packedState) {
key.patchSize = engine.patchSize; packedState.patchSize = engine.patchSize;
key.SetTessellationParameters(engine.tessellationParameters); packedState.SetTessellationParameters(engine.tessellationParameters);
} }
Shader::TessPrimitive ConvertShaderTessPrimitive(engine::TessellationParameters::DomainType domainType) { Shader::TessPrimitive ConvertShaderTessPrimitive(engine::TessellationParameters::DomainType domainType) {
@ -477,27 +560,27 @@ namespace skyline::gpu::interconnect::maxwell3d {
} }
} }
void RasterizationState::Flush(Key &key) { void RasterizationState::Flush(PackedPipelineState &packedState) {
key.rasterizerDiscardEnable = !engine->rasterEnable; packedState.rasterizerDiscardEnable = !engine->rasterEnable;
key.SetPolygonMode(engine->frontPolygonMode); packedState.SetPolygonMode(engine->frontPolygonMode);
if (engine->backPolygonMode != engine->frontPolygonMode) if (engine->backPolygonMode != engine->frontPolygonMode)
Logger::Warn("Non-matching polygon modes!"); Logger::Warn("Non-matching polygon modes!");
if (engine->oglCullEnable) { if (engine->oglCullEnable) {
key.cullModeFront = engine->oglCullFace == engine::CullFace::Front || engine->oglCullFace == engine::CullFace::FrontAndBack; packedState.cullModeFront = engine->oglCullFace == engine::CullFace::Front || engine->oglCullFace == engine::CullFace::FrontAndBack;
key.cullModeBack = engine->oglCullFace == engine::CullFace::Back || engine->oglCullFace == engine::CullFace::FrontAndBack; packedState.cullModeBack = engine->oglCullFace == engine::CullFace::Back || engine->oglCullFace == engine::CullFace::FrontAndBack;
} else { } else {
key.cullModeFront = key.cullModeBack = false; packedState.cullModeFront = packedState.cullModeBack = false;
} }
// UpdateRuntimeInformation(runtimeInfo.y_negate, enabled, maxwell3d::PipelineStage::Vertex, maxwell3d::PipelineStage::Fragment); // UpdateRuntimeInformation(runtimeInfo.y_negate, enabled, maxwell3d::PipelineStage::Vertex, maxwell3d::PipelineStage::Fragment);
key.flipYEnable = engine->windowOrigin.flipY; packedState.flipYEnable = engine->windowOrigin.flipY;
bool origFrontFaceClockwise{engine->oglFrontFace == engine::FrontFace::CW}; bool origFrontFaceClockwise{engine->oglFrontFace == engine::FrontFace::CW};
key.frontFaceClockwise = (key.flipYEnable != origFrontFaceClockwise); packedState.frontFaceClockwise = (packedState.flipYEnable != origFrontFaceClockwise);
key.depthBiasEnable = ConvertDepthBiasEnable(engine->polyOffset, engine->frontPolygonMode); packedState.depthBiasEnable = ConvertDepthBiasEnable(engine->polyOffset, engine->frontPolygonMode);
key.provokingVertex = engine->provokingVertex.value; packedState.provokingVertex = engine->provokingVertex.value;
} }
/* Depth Stencil State */ /* Depth Stencil State */
@ -578,15 +661,15 @@ namespace skyline::gpu::interconnect::maxwell3d {
}; };
} }
void DepthStencilState::Flush(Key &key) { void DepthStencilState::Flush(PackedPipelineState &packedState) {
key.depthTestEnable = engine->depthTestEnable; packedState.depthTestEnable = engine->depthTestEnable;
key.depthWriteEnable = engine->depthWriteEnable; packedState.depthWriteEnable = engine->depthWriteEnable;
key.SetDepthFunc(engine->depthFunc); packedState.SetDepthFunc(engine->depthFunc);
key.depthBoundsTestEnable = engine->depthBoundsTestEnable; packedState.depthBoundsTestEnable = engine->depthBoundsTestEnable;
key.stencilTestEnable = engine->stencilTestEnable; packedState.stencilTestEnable = engine->stencilTestEnable;
auto stencilBack{engine->twoSidedStencilTestEnable ? engine->stencilBack : engine->stencilOps}; auto stencilBack{engine->twoSidedStencilTestEnable ? engine->stencilBack : engine->stencilOps};
key.SetStencilOps(engine->stencilOps, engine->stencilOps); packedState.SetStencilOps(engine->stencilOps, engine->stencilOps);
}; };
/* Color Blend State */ /* Color Blend State */
@ -788,19 +871,19 @@ namespace skyline::gpu::interconnect::maxwell3d {
void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) { void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) {
boost::container::static_vector<TextureView *, engine::ColorTargetCount> colorAttachments; boost::container::static_vector<TextureView *, engine::ColorTargetCount> colorAttachments;
for (auto &colorRenderTarget : colorRenderTargets) for (auto &colorRenderTarget : colorRenderTargets)
if (auto view{colorRenderTarget.UpdateGet(ctx, key).view}; view) if (auto view{colorRenderTarget.UpdateGet(ctx, packedState).view}; view)
colorAttachments.push_back(view.get()); colorAttachments.push_back(view.get());
TextureView *depthAttachment{depthRenderTarget.UpdateGet(ctx, key).view.get()}; TextureView *depthAttachment{depthRenderTarget.UpdateGet(ctx, packedState).view.get()};
vertexInput.Update(key); vertexInput.Update(packedState);
directState.inputAssembly.Update(key); directState.inputAssembly.Update(packedState);
tessellation.Update(key); tessellation.Update(packedState);
rasterization.Update(key); rasterization.Update(packedState);
/* vk::PipelineMultisampleStateCreateInfo multisampleState{ /* vk::PipelineMultisampleStateCreateInfo multisampleState{
.rasterizationSamples = vk::SampleCountFlagBits::e1 .rasterizationSamples = vk::SampleCountFlagBits::e1
}; */ }; */
depthStencil.Update(key); depthStencil.Update(packedState);
const auto &colorBlendState{colorBlend.UpdateGet(ctx, colorAttachments.size()).colorBlendState}; const auto &colorBlendState{colorBlend.UpdateGet(ctx, colorAttachments.size()).colorBlendState};
constexpr std::array<vk::DynamicState, 9> dynamicStates{ constexpr std::array<vk::DynamicState, 9> dynamicStates{
@ -822,10 +905,10 @@ namespace skyline::gpu::interconnect::maxwell3d {
} }
std::shared_ptr<TextureView> PipelineState::GetColorRenderTargetForClear(InterconnectContext &ctx, size_t index) { std::shared_ptr<TextureView> PipelineState::GetColorRenderTargetForClear(InterconnectContext &ctx, size_t index) {
return colorRenderTargets[index].UpdateGet(ctx, key).view; return colorRenderTargets[index].UpdateGet(ctx, packedState).view;
} }
std::shared_ptr<TextureView> PipelineState::GetDepthRenderTargetForClear(InterconnectContext &ctx) { std::shared_ptr<TextureView> PipelineState::GetDepthRenderTargetForClear(InterconnectContext &ctx) {
return depthRenderTarget.UpdateGet(ctx, key).view; return depthRenderTarget.UpdateGet(ctx, packedState).view;
} }
} }

View File

@ -9,7 +9,12 @@
#include "soc/gm20b/engines/maxwell/types.h" #include "soc/gm20b/engines/maxwell/types.h"
namespace skyline::gpu::interconnect::maxwell3d { namespace skyline::gpu::interconnect::maxwell3d {
struct Key { /**
* @brief Packed struct of pipeline state suitable for use as a map key
* @note This is heavily based around yuzu's pipeline key with some packing modifications
* @url https://github.com/yuzu-emu/yuzu/blob/9c701774562ea490296b9cbea3dbd8c096bc4483/src/video_core/renderer_vulkan/fixed_pipeline_state.h#L20
*/
struct PackedPipelineState {
struct StencilOps { struct StencilOps {
u8 zPass : 3; u8 zPass : 3;
u8 fail : 3; u8 fail : 3;
@ -57,86 +62,19 @@ namespace skyline::gpu::interconnect::maxwell3d {
std::array<VertexBinding, engine::VertexStreamCount> vertexBindings; //!< Use {Set, Get}VertexBinding std::array<VertexBinding, engine::VertexStreamCount> vertexBindings; //!< Use {Set, Get}VertexBinding
std::array<engine::VertexAttribute, engine::VertexAttributeCount> vertexAttributes; std::array<engine::VertexAttribute, engine::VertexAttributeCount> vertexAttributes;
void SetCtFormat(size_t index, engine::ColorTarget::Format format) { void SetCtFormat(size_t index, engine::ColorTarget::Format format);
ctFormats[index] = static_cast<u8>(format);
}
void SetZtFormat(engine::ZtFormat format) { void SetZtFormat(engine::ZtFormat format);
ztFormat = static_cast<u8>(format) - static_cast<u8>(engine::ZtFormat::ZF32);
}
void SetVertexBinding(u32 index, engine::VertexStream stream, engine::VertexStreamInstance instance) { void SetVertexBinding(u32 index, engine::VertexStream stream, engine::VertexStreamInstance instance);
vertexBindings[index].stride = stream.format.stride;
vertexBindings[index].instanced = instance.isInstanced;
vertexBindings[index].enable = stream.format.enable;
vertexBindings[index].divisor = stream.frequency;
}
void SetTessellationParameters(engine::TessellationParameters parameters) { void SetTessellationParameters(engine::TessellationParameters parameters);
domainType = parameters.domainType;
spacing = parameters.spacing;
outputPrimitives = parameters.outputPrimitives;
}
void SetPolygonMode(engine::PolygonMode mode) { void SetPolygonMode(engine::PolygonMode mode);
polygonMode = static_cast<u8>(static_cast<u32>(mode) - 0x1B00);
}
u8 PackCompareFunc(engine::CompareFunc func) { void SetDepthFunc(engine::CompareFunc func);
u32 val{static_cast<u32>(func)};
return static_cast<u8>(val >= 0x200 ? (val - 0x200) : (val - 1));
}
void SetDepthFunc(engine::CompareFunc func) { void SetStencilOps(engine::StencilOps front, engine::StencilOps back);
depthFunc = PackCompareFunc(func);
}
u8 PackStencilOp(engine::StencilOps::Op op) {
switch (op) {
case engine::StencilOps::Op::OglZero:
op = engine::StencilOps::Op::D3DZero;
break;
case engine::StencilOps::Op::OglKeep:
op = engine::StencilOps::Op::D3DKeep;
break;
case engine::StencilOps::Op::OglReplace:
op = engine::StencilOps::Op::D3DReplace;
break;
case engine::StencilOps::Op::OglIncrSat:
op = engine::StencilOps::Op::D3DIncrSat;
break;
case engine::StencilOps::Op::OglDecrSat:
op = engine::StencilOps::Op::D3DDecrSat;
break;
case engine::StencilOps::Op::OglInvert:
op = engine::StencilOps::Op::D3DInvert;
break;
case engine::StencilOps::Op::OglIncr:
op = engine::StencilOps::Op::D3DIncr;
break;
case engine::StencilOps::Op::OglDecr:
op = engine::StencilOps::Op::D3DDecr;
break;
default:
break;
}
return static_cast<u8>(op) - 1;
}
StencilOps PackStencilOps(engine::StencilOps ops) {
return {
.zPass = PackStencilOp(ops.zPass),
.fail = PackStencilOp(ops.fail),
.zFail = PackStencilOp(ops.zFail),
.func = PackCompareFunc(ops.func),
};
}
void SetStencilOps(engine::StencilOps front, engine::StencilOps back) {
stencilFront = PackStencilOps(front);
stencilBack = PackStencilOps(back);
}
}; };
class ColorRenderTargetState : dirty::ManualDirty { class ColorRenderTargetState : dirty::ManualDirty {
@ -156,7 +94,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
std::shared_ptr<TextureView> view; std::shared_ptr<TextureView> view;
void Flush(InterconnectContext &ctx, Key &key); void Flush(InterconnectContext &ctx, PackedPipelineState &packedState);
}; };
class DepthRenderTargetState : dirty::ManualDirty { class DepthRenderTargetState : dirty::ManualDirty {
@ -181,7 +119,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
std::shared_ptr<TextureView> view; std::shared_ptr<TextureView> view;
void Flush(InterconnectContext &ctx, Key &key); void Flush(InterconnectContext &ctx, PackedPipelineState &packedState);
}; };
class VertexInputState : dirty::ManualDirty { class VertexInputState : dirty::ManualDirty {
@ -200,7 +138,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
public: public:
VertexInputState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine); VertexInputState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine);
void Flush(Key &key); void Flush(PackedPipelineState &packedState);
}; };
class InputAssemblyState { class InputAssemblyState {
@ -219,7 +157,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
public: public:
InputAssemblyState(const EngineRegisters &engine); InputAssemblyState(const EngineRegisters &engine);
void Update(Key &key); void Update(PackedPipelineState &packedState);
void SetPrimitiveTopology(engine::DrawTopology topology); void SetPrimitiveTopology(engine::DrawTopology topology);
@ -243,7 +181,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
public: public:
TessellationState(const EngineRegisters &engine); TessellationState(const EngineRegisters &engine);
void Update(Key &key); void Update(PackedPipelineState &packedState);
}; };
/** /**
@ -278,7 +216,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
RasterizationState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine); RasterizationState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine);
void Flush(Key &key); void Flush(PackedPipelineState &packedState);
}; };
class DepthStencilState : dirty::ManualDirty { class DepthStencilState : dirty::ManualDirty {
@ -302,7 +240,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
public: public:
DepthStencilState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine); DepthStencilState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine);
void Flush(Key &key); void Flush(PackedPipelineState &packedState);
}; };
class ColorBlendState : dirty::RefreshableManualDirty { class ColorBlendState : dirty::RefreshableManualDirty {
@ -351,7 +289,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
}; };
private: private:
Key key{}; PackedPipelineState packedState{};
dirty::BoundSubresource<EngineRegisters> engine; dirty::BoundSubresource<EngineRegisters> engine;