mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-24 03:41:52 +01:00
Transition vertex input state to pipeline cache key
Also adds dirty tracking and removes it from direct state while we're at it. Since we no longer use Vulkan structs directly there's no benefit to it.
This commit is contained in:
parent
ffe24aa075
commit
3f9161fb74
@ -213,63 +213,23 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Vertex Input State */
|
/* Vertex Input State */
|
||||||
|
// TODO: check if better individually
|
||||||
void VertexInputState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
|
void VertexInputState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
|
||||||
ranges::for_each(vertexStreamRegisters, [&](const auto ®s) { manager.Bind(handle, regs.format, regs.frequency); });
|
ranges::for_each(vertexStreams, [&](const auto ®s) { manager.Bind(handle, regs.format, regs.frequency); });
|
||||||
|
|
||||||
auto bindFull{[&](const auto ®s) { manager.Bind(handle, regs); }};
|
auto bindFull{[&](const auto ®s) { manager.Bind(handle, regs); }};
|
||||||
ranges::for_each(vertexStreamInstanceRegisters, bindFull);
|
ranges::for_each(vertexStreamInstance, bindFull);
|
||||||
ranges::for_each(vertexAttributesRegisters, bindFull);
|
ranges::for_each(vertexAttributes, bindFull);
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::StructureChain<vk::PipelineVertexInputStateCreateInfo, vk::PipelineVertexInputDivisorStateCreateInfoEXT> VertexInputState::Build(InterconnectContext &ctx, const EngineRegisters &engine) {
|
VertexInputState::VertexInputState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine) : engine{manager, dirtyHandle, engine} {}
|
||||||
activeBindingDivisorDescs.clear();
|
|
||||||
activeAttributeDescs.clear();
|
|
||||||
|
|
||||||
for (size_t i{}; i < engine::VertexStreamCount; i++) {
|
void VertexInputState::Flush(Key &key) {
|
||||||
if (bindingDescs[i].inputRate == vk::VertexInputRate::eInstance) {
|
for (u32 i{}; i < engine::VertexStreamCount; i++)
|
||||||
if (!ctx.gpu.traits.supportsVertexAttributeDivisor) [[unlikely]]
|
key.SetVertexBinding(i, engine->vertexStreams[i], engine->vertexStreamInstance[i]);
|
||||||
Logger::Warn("Vertex attribute divisor used on guest without host support");
|
|
||||||
else if (!ctx.gpu.traits.supportsVertexAttributeZeroDivisor && bindingDivisorDescs[i].divisor == 0) [[unlikely]]
|
|
||||||
Logger::Warn("Vertex attribute zero divisor used on guest without host support");
|
|
||||||
else
|
|
||||||
activeBindingDivisorDescs.push_back(bindingDivisorDescs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: check shader inputs
|
for (u32 i{}; i < engine::VertexAttributeCount; i++)
|
||||||
for (size_t i{}; i < engine::VertexAttributeCount; i++)
|
key.vertexAttributes[i] = engine->vertexAttributes[i];
|
||||||
if (engine.vertexAttributesRegisters[i].source == engine::VertexAttribute::Source::Active)
|
|
||||||
activeAttributeDescs.push_back(attributeDescs[i]);
|
|
||||||
|
|
||||||
vk::StructureChain<vk::PipelineVertexInputStateCreateInfo, vk::PipelineVertexInputDivisorStateCreateInfoEXT> chain{
|
|
||||||
vk::PipelineVertexInputStateCreateInfo{
|
|
||||||
.vertexBindingDescriptionCount = static_cast<u32>(bindingDescs.size()),
|
|
||||||
.pVertexBindingDescriptions = bindingDescs.data(),
|
|
||||||
.vertexAttributeDescriptionCount = static_cast<u32>(activeAttributeDescs.size()),
|
|
||||||
.pVertexAttributeDescriptions = activeAttributeDescs.data(),
|
|
||||||
},
|
|
||||||
vk::PipelineVertexInputDivisorStateCreateInfoEXT{
|
|
||||||
.vertexBindingDivisorCount = static_cast<u32>(activeBindingDivisorDescs.size()),
|
|
||||||
.pVertexBindingDivisors = activeBindingDivisorDescs.data(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (activeBindingDivisorDescs.empty())
|
|
||||||
chain.unlink<vk::PipelineVertexInputDivisorStateCreateInfoEXT>();
|
|
||||||
|
|
||||||
return chain;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VertexInputState::SetStride(u32 index, u32 stride) {
|
|
||||||
bindingDescs[index].stride = stride;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VertexInputState::SetInputRate(u32 index, engine::VertexStreamInstance instance) {
|
|
||||||
bindingDescs[index].inputRate = instance.isInstanced ? vk::VertexInputRate::eInstance : vk::VertexInputRate::eVertex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VertexInputState::SetDivisor(u32 index, u32 divisor) {
|
|
||||||
bindingDivisorDescs[index].divisor = divisor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static vk::Format ConvertVertexInputAttributeFormat(engine::VertexAttribute::ComponentBitWidths componentBitWidths, engine::VertexAttribute::NumericalType numericalType) {
|
static vk::Format ConvertVertexInputAttributeFormat(engine::VertexAttribute::ComponentBitWidths componentBitWidths, engine::VertexAttribute::NumericalType numericalType) {
|
||||||
@ -355,20 +315,6 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexInputState::SetAttribute(u32 index, engine::VertexAttribute attribute) {
|
|
||||||
auto &vkAttribute{attributeDescs[index]};
|
|
||||||
if (attribute.source == engine::VertexAttribute::Source::Active) {
|
|
||||||
vkAttribute.binding = attribute.stream;
|
|
||||||
vkAttribute.format = ConvertVertexInputAttributeFormat(attribute.componentBitWidths, attribute.numericalType);
|
|
||||||
vkAttribute.offset = attribute.offset;
|
|
||||||
|
|
||||||
|
|
||||||
// UpdateRuntimeInformation(runtimeInfo.generic_input_types[index], ConvertShaderGenericInputType(attribute.numericalType), maxwell3d::PipelineStage::Vertex);
|
|
||||||
} else {
|
|
||||||
// UpdateRuntimeInformation(runtimeInfo.generic_input_types[index], Shader::AttributeType::Disabled, maxwell3d::PipelineStage::Vertex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Input Assembly State */
|
/* Input Assembly State */
|
||||||
void InputAssemblyState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
|
void InputAssemblyState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
|
||||||
manager.Bind(handle, primitiveRestartEnable);
|
manager.Bind(handle, primitiveRestartEnable);
|
||||||
@ -830,13 +776,12 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
: engine{manager, dirtyHandle, engine},
|
: engine{manager, dirtyHandle, engine},
|
||||||
colorRenderTargets{util::MergeInto<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount>(manager, engine.colorRenderTargetsRegisters, util::IncrementingT<size_t>{})},
|
colorRenderTargets{util::MergeInto<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount>(manager, engine.colorRenderTargetsRegisters, util::IncrementingT<size_t>{})},
|
||||||
depthRenderTarget{manager, engine.depthRenderTargetRegisters},
|
depthRenderTarget{manager, engine.depthRenderTargetRegisters},
|
||||||
|
vertexInput{manager, engine.vertexInputRegisters},
|
||||||
rasterization{manager, engine.rasterizationRegisters},
|
rasterization{manager, engine.rasterizationRegisters},
|
||||||
depthStencil{manager, engine.depthStencilRegisters},
|
depthStencil{manager, engine.depthStencilRegisters},
|
||||||
colorBlend{manager, engine.colorBlendRegisters} {}
|
colorBlend{manager, engine.colorBlendRegisters} {}
|
||||||
|
|
||||||
void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) {
|
void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) {
|
||||||
Key key;
|
|
||||||
|
|
||||||
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, key).view}; view)
|
||||||
@ -844,7 +789,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
|
|
||||||
TextureView *depthAttachment{depthRenderTarget.UpdateGet(ctx, key).view.get()};
|
TextureView *depthAttachment{depthRenderTarget.UpdateGet(ctx, key).view.get()};
|
||||||
|
|
||||||
auto vertexInputState{directState.vertexInput.Build(ctx, engine->vertexInputRegisters)};
|
vertexInput.Update(key);
|
||||||
const auto &inputAssemblyState{directState.inputAssembly.Build()};
|
const auto &inputAssemblyState{directState.inputAssembly.Build()};
|
||||||
const auto &tessellationState{directState.tessellation.Build()};
|
const auto &tessellationState{directState.tessellation.Build()};
|
||||||
const auto &rasterizationState{rasterization.UpdateGet().rasterizationState};
|
const auto &rasterizationState{rasterization.UpdateGet().rasterizationState};
|
||||||
|
@ -14,7 +14,17 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
u8 ztFormat : 5; // ZtFormat - 0xA as u8
|
u8 ztFormat : 5; // ZtFormat - 0xA as u8
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VertexBinding {
|
||||||
|
u16 stride : 12;
|
||||||
|
bool instanced : 1;
|
||||||
|
bool enable : 1;
|
||||||
|
u8 _pad_ : 2;
|
||||||
|
u32 divisor;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(VertexBinding) == 0x8);
|
||||||
|
|
||||||
std::array<u8, engine::ColorTargetCount> ctFormats; //!< ColorTarget::Format as u8
|
std::array<u8, engine::ColorTargetCount> ctFormats; //!< ColorTarget::Format as u8
|
||||||
|
std::array<VertexBinding, engine::VertexStreamCount> vertexBindings;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::array<engine::VertexAttribute, engine::VertexAttributeCount> vertexAttributes;
|
std::array<engine::VertexAttribute, engine::VertexAttributeCount> vertexAttributes;
|
||||||
@ -26,6 +36,13 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
void SetZtFormat(engine::ZtFormat format) {
|
void SetZtFormat(engine::ZtFormat format) {
|
||||||
ztFormat = static_cast<u8>(format) - static_cast<u8>(engine::ZtFormat::ZF32);
|
ztFormat = static_cast<u8>(format) - static_cast<u8>(engine::ZtFormat::ZF32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ColorRenderTargetState : dirty::ManualDirty {
|
class ColorRenderTargetState : dirty::ManualDirty {
|
||||||
@ -73,39 +90,23 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
void Flush(InterconnectContext &ctx, Key &key);
|
void Flush(InterconnectContext &ctx, Key &key);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VertexInputState {
|
class VertexInputState : dirty::ManualDirty {
|
||||||
private:
|
|
||||||
std::array<vk::VertexInputBindingDescription, engine::VertexStreamCount> bindingDescs{
|
|
||||||
util::MergeInto<vk::VertexInputBindingDescription, engine::VertexStreamCount>(util::IncrementingT<u32>{})
|
|
||||||
};
|
|
||||||
std::array<vk::VertexInputBindingDivisorDescriptionEXT, engine::VertexStreamCount> bindingDivisorDescs{
|
|
||||||
util::MergeInto<vk::VertexInputBindingDivisorDescriptionEXT, engine::VertexStreamCount>(util::IncrementingT<u32>{})
|
|
||||||
};
|
|
||||||
std::array<vk::VertexInputAttributeDescription, engine::VertexAttributeCount> attributeDescs{
|
|
||||||
util::MergeInto<vk::VertexInputAttributeDescription, engine::VertexAttributeCount>(util::IncrementingT<u32>{})
|
|
||||||
};
|
|
||||||
|
|
||||||
boost::container::static_vector<vk::VertexInputBindingDivisorDescriptionEXT, engine::VertexStreamCount> activeBindingDivisorDescs;
|
|
||||||
boost::container::static_vector<vk::VertexInputAttributeDescription, engine::VertexAttributeCount> activeAttributeDescs;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct EngineRegisters {
|
struct EngineRegisters {
|
||||||
const std::array<engine::VertexStream, engine::VertexStreamCount> &vertexStreamRegisters;
|
const std::array<engine::VertexStream, engine::VertexStreamCount> &vertexStreams;
|
||||||
const std::array<engine::VertexStreamInstance, engine::VertexStreamCount> &vertexStreamInstanceRegisters;
|
const std::array<engine::VertexStreamInstance, engine::VertexStreamCount> &vertexStreamInstance;
|
||||||
const std::array<engine::VertexAttribute, engine::VertexAttributeCount> &vertexAttributesRegisters;
|
const std::array<engine::VertexAttribute, engine::VertexAttributeCount> &vertexAttributes;
|
||||||
|
|
||||||
void DirtyBind(DirtyManager &manager, dirty::Handle handle) const;
|
void DirtyBind(DirtyManager &manager, dirty::Handle handle) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::StructureChain<vk::PipelineVertexInputStateCreateInfo, vk::PipelineVertexInputDivisorStateCreateInfoEXT> Build(InterconnectContext &ctx, const EngineRegisters &engine);
|
private:
|
||||||
|
dirty::BoundSubresource<EngineRegisters> engine;
|
||||||
|
|
||||||
void SetStride(u32 index, u32 stride);
|
public:
|
||||||
|
VertexInputState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine);
|
||||||
|
|
||||||
void SetInputRate(u32 index, engine::VertexStreamInstance instance);
|
void Flush(Key &key);
|
||||||
|
|
||||||
void SetDivisor(u32 index, u32 divisor);
|
|
||||||
|
|
||||||
void SetAttribute(u32 index, engine::VertexAttribute attribute);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InputAssemblyState {
|
struct InputAssemblyState {
|
||||||
@ -158,7 +159,6 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
* @brief Holds pipeline state that is directly written by the engine code, without using dirty tracking
|
* @brief Holds pipeline state that is directly written by the engine code, without using dirty tracking
|
||||||
*/
|
*/
|
||||||
struct DirectPipelineState {
|
struct DirectPipelineState {
|
||||||
VertexInputState vertexInput;
|
|
||||||
InputAssemblyState inputAssembly;
|
InputAssemblyState inputAssembly;
|
||||||
TessellationState tessellation;
|
TessellationState tessellation;
|
||||||
};
|
};
|
||||||
@ -269,6 +269,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
|
|
||||||
std::array<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount> colorRenderTargets;
|
std::array<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount> colorRenderTargets;
|
||||||
dirty::ManualDirtyState<DepthRenderTargetState> depthRenderTarget;
|
dirty::ManualDirtyState<DepthRenderTargetState> depthRenderTarget;
|
||||||
|
dirty::ManualDirtyState<VertexInputState> vertexInput;
|
||||||
dirty::ManualDirtyState<RasterizationState> rasterization;
|
dirty::ManualDirtyState<RasterizationState> rasterization;
|
||||||
dirty::ManualDirtyState<DepthStencilState> depthStencil;
|
dirty::ManualDirtyState<DepthStencilState> depthStencil;
|
||||||
dirty::ManualDirtyState<ColorBlendState> colorBlend;
|
dirty::ManualDirtyState<ColorBlendState> colorBlend;
|
||||||
|
@ -153,31 +153,6 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
dirtyManager.MarkDirty(method);
|
dirtyManager.MarkDirty(method);
|
||||||
|
|
||||||
switch (method) {
|
switch (method) {
|
||||||
#define VERTEX_STREAM_CALLBACKS(z, idx, data) \
|
|
||||||
ENGINE_ARRAY_STRUCT_CASE(vertexStreams, idx, format, { \
|
|
||||||
interconnect.directState.vertexInput.SetStride(idx, format.stride); \
|
|
||||||
}) \
|
|
||||||
ENGINE_ARRAY_STRUCT_CASE(vertexStreams, idx, frequency, { \
|
|
||||||
interconnect.directState.vertexInput.SetDivisor(idx, frequency); \
|
|
||||||
}) \
|
|
||||||
ENGINE_ARRAY_CASE(vertexStreamInstance, idx, { \
|
|
||||||
interconnect.directState.vertexInput.SetInputRate(idx, vertexStreamInstance); \
|
|
||||||
})
|
|
||||||
|
|
||||||
BOOST_PP_REPEAT(16, VERTEX_STREAM_CALLBACKS, 0)
|
|
||||||
static_assert(type::VertexStreamCount == 16 && type::VertexStreamCount < BOOST_PP_LIMIT_REPEAT);
|
|
||||||
#undef VERTEX_STREAM_CALLBACKS
|
|
||||||
|
|
||||||
|
|
||||||
#define VERTEX_ATTRIBUTE_CALLBACKS(z, idx, data) \
|
|
||||||
ENGINE_ARRAY_CASE(vertexAttributes, idx, { \
|
|
||||||
interconnect.directState.vertexInput.SetAttribute(idx, vertexAttributes); \
|
|
||||||
})
|
|
||||||
|
|
||||||
BOOST_PP_REPEAT(16, VERTEX_ATTRIBUTE_CALLBACKS, 0)
|
|
||||||
static_assert(type::VertexAttributeCount == 32 && type::VertexAttributeCount < BOOST_PP_LIMIT_REPEAT);
|
|
||||||
#undef VERTEX_ATTRIBUTE_CALLBACKS
|
|
||||||
|
|
||||||
|
|
||||||
ENGINE_CASE(primitiveRestartEnable, {
|
ENGINE_CASE(primitiveRestartEnable, {
|
||||||
interconnect.directState.inputAssembly.SetPrimitiveRestart(primitiveRestartEnable != 0);
|
interconnect.directState.inputAssembly.SetPrimitiveRestart(primitiveRestartEnable != 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user