mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-23 21:11:53 +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 */
|
||||
// TODO: check if better individually
|
||||
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); }};
|
||||
ranges::for_each(vertexStreamInstanceRegisters, bindFull);
|
||||
ranges::for_each(vertexAttributesRegisters, bindFull);
|
||||
ranges::for_each(vertexStreamInstance, bindFull);
|
||||
ranges::for_each(vertexAttributes, bindFull);
|
||||
}
|
||||
|
||||
vk::StructureChain<vk::PipelineVertexInputStateCreateInfo, vk::PipelineVertexInputDivisorStateCreateInfoEXT> VertexInputState::Build(InterconnectContext &ctx, const EngineRegisters &engine) {
|
||||
activeBindingDivisorDescs.clear();
|
||||
activeAttributeDescs.clear();
|
||||
VertexInputState::VertexInputState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine) : engine{manager, dirtyHandle, engine} {}
|
||||
|
||||
for (size_t i{}; i < engine::VertexStreamCount; i++) {
|
||||
if (bindingDescs[i].inputRate == vk::VertexInputRate::eInstance) {
|
||||
if (!ctx.gpu.traits.supportsVertexAttributeDivisor) [[unlikely]]
|
||||
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]);
|
||||
}
|
||||
}
|
||||
void VertexInputState::Flush(Key &key) {
|
||||
for (u32 i{}; i < engine::VertexStreamCount; i++)
|
||||
key.SetVertexBinding(i, engine->vertexStreams[i], engine->vertexStreamInstance[i]);
|
||||
|
||||
// TODO: check shader inputs
|
||||
for (size_t i{}; i < engine::VertexAttributeCount; 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;
|
||||
for (u32 i{}; i < engine::VertexAttributeCount; i++)
|
||||
key.vertexAttributes[i] = engine->vertexAttributes[i];
|
||||
}
|
||||
|
||||
static vk::Format ConvertVertexInputAttributeFormat(engine::VertexAttribute::ComponentBitWidths componentBitWidths, engine::VertexAttribute::NumericalType numericalType) {
|
||||
@ -354,20 +314,6 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
||||
return Shader::AttributeType::Disabled;
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
void InputAssemblyState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
|
||||
@ -830,13 +776,12 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
||||
: engine{manager, dirtyHandle, engine},
|
||||
colorRenderTargets{util::MergeInto<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount>(manager, engine.colorRenderTargetsRegisters, util::IncrementingT<size_t>{})},
|
||||
depthRenderTarget{manager, engine.depthRenderTargetRegisters},
|
||||
vertexInput{manager, engine.vertexInputRegisters},
|
||||
rasterization{manager, engine.rasterizationRegisters},
|
||||
depthStencil{manager, engine.depthStencilRegisters},
|
||||
colorBlend{manager, engine.colorBlendRegisters} {}
|
||||
|
||||
void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) {
|
||||
Key key;
|
||||
|
||||
boost::container::static_vector<TextureView *, engine::ColorTargetCount> colorAttachments;
|
||||
for (auto &colorRenderTarget : colorRenderTargets)
|
||||
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()};
|
||||
|
||||
auto vertexInputState{directState.vertexInput.Build(ctx, engine->vertexInputRegisters)};
|
||||
vertexInput.Update(key);
|
||||
const auto &inputAssemblyState{directState.inputAssembly.Build()};
|
||||
const auto &tessellationState{directState.tessellation.Build()};
|
||||
const auto &rasterizationState{rasterization.UpdateGet().rasterizationState};
|
||||
|
@ -14,7 +14,17 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
||||
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<VertexBinding, engine::VertexStreamCount> vertexBindings;
|
||||
|
||||
public:
|
||||
std::array<engine::VertexAttribute, engine::VertexAttributeCount> vertexAttributes;
|
||||
@ -26,6 +36,13 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
||||
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) {
|
||||
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 {
|
||||
@ -73,39 +90,23 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
||||
void Flush(InterconnectContext &ctx, Key &key);
|
||||
};
|
||||
|
||||
struct VertexInputState {
|
||||
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;
|
||||
|
||||
class VertexInputState : dirty::ManualDirty {
|
||||
public:
|
||||
struct EngineRegisters {
|
||||
const std::array<engine::VertexStream, engine::VertexStreamCount> &vertexStreamRegisters;
|
||||
const std::array<engine::VertexStreamInstance, engine::VertexStreamCount> &vertexStreamInstanceRegisters;
|
||||
const std::array<engine::VertexAttribute, engine::VertexAttributeCount> &vertexAttributesRegisters;
|
||||
const std::array<engine::VertexStream, engine::VertexStreamCount> &vertexStreams;
|
||||
const std::array<engine::VertexStreamInstance, engine::VertexStreamCount> &vertexStreamInstance;
|
||||
const std::array<engine::VertexAttribute, engine::VertexAttributeCount> &vertexAttributes;
|
||||
|
||||
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 SetDivisor(u32 index, u32 divisor);
|
||||
|
||||
void SetAttribute(u32 index, engine::VertexAttribute attribute);
|
||||
void Flush(Key &key);
|
||||
};
|
||||
|
||||
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
|
||||
*/
|
||||
struct DirectPipelineState {
|
||||
VertexInputState vertexInput;
|
||||
InputAssemblyState inputAssembly;
|
||||
TessellationState tessellation;
|
||||
};
|
||||
@ -269,6 +269,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
||||
|
||||
std::array<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount> colorRenderTargets;
|
||||
dirty::ManualDirtyState<DepthRenderTargetState> depthRenderTarget;
|
||||
dirty::ManualDirtyState<VertexInputState> vertexInput;
|
||||
dirty::ManualDirtyState<RasterizationState> rasterization;
|
||||
dirty::ManualDirtyState<DepthStencilState> depthStencil;
|
||||
dirty::ManualDirtyState<ColorBlendState> colorBlend;
|
||||
|
@ -153,31 +153,6 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
dirtyManager.MarkDirty(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, {
|
||||
interconnect.directState.inputAssembly.SetPrimitiveRestart(primitiveRestartEnable != 0);
|
||||
|
Loading…
Reference in New Issue
Block a user