Use ctSelect register for colour targets and impl null color attachments

Some games have invalid colour attachments sandwiched inbetween valid ones, these need to be skipped in Vulkan with UNUSED_ATTACHMENT
This commit is contained in:
Billy Laws 2022-09-29 20:32:52 +01:00
parent 38aad21d29
commit f42a0df72c
6 changed files with 62 additions and 31 deletions

View File

@ -36,8 +36,13 @@ namespace skyline::gpu::cache {
colorBlendState.pAttachments = colorBlendAttachments.data(); colorBlendState.pAttachments = colorBlendAttachments.data();
for (auto &colorAttachment : state.colorAttachments) for (auto &colorAttachment : state.colorAttachments) {
if (colorAttachment)
colorAttachments.emplace_back(AttachmentMetadata{colorAttachment->format->vkFormat, colorAttachment->texture->sampleCount}); colorAttachments.emplace_back(AttachmentMetadata{colorAttachment->format->vkFormat, colorAttachment->texture->sampleCount});
else
colorAttachments.emplace_back(AttachmentMetadata{vk::Format::eUndefined, vk::SampleCountFlagBits::e1});
}
if (state.depthStencilAttachment) if (state.depthStencilAttachment)
depthStencilAttachment.emplace(AttachmentMetadata{state.depthStencilAttachment->format->vkFormat, state.depthStencilAttachment->texture->sampleCount}); depthStencilAttachment.emplace(AttachmentMetadata{state.depthStencilAttachment->format->vkFormat, state.depthStencilAttachment->texture->sampleCount});
} }
@ -171,9 +176,11 @@ namespace skyline::gpu::cache {
HASH(key.colorAttachments.size()); HASH(key.colorAttachments.size());
for (const auto &attachment : key.colorAttachments) { for (const auto &attachment : key.colorAttachments) {
if (attachment) {
HASH(attachment->format->vkFormat); HASH(attachment->format->vkFormat);
HASH(attachment->texture->sampleCount); HASH(attachment->texture->sampleCount);
} }
}
HASH(key.depthStencilAttachment != nullptr); HASH(key.depthStencilAttachment != nullptr);
if (key.depthStencilAttachment != nullptr) { if (key.depthStencilAttachment != nullptr) {
@ -342,21 +349,28 @@ namespace skyline::gpu::cache {
boost::container::small_vector<vk::AttachmentDescription, 8> attachmentDescriptions; boost::container::small_vector<vk::AttachmentDescription, 8> attachmentDescriptions;
boost::container::small_vector<vk::AttachmentReference, 8> attachmentReferences; boost::container::small_vector<vk::AttachmentReference, 8> attachmentReferences;
auto pushAttachment{[&](const TextureView &view) { auto pushAttachment{[&](TextureView *view) {
if (view) {
attachmentDescriptions.push_back(vk::AttachmentDescription{ attachmentDescriptions.push_back(vk::AttachmentDescription{
.format = view.format->vkFormat, .format = view->format->vkFormat,
.samples = view.texture->sampleCount, .samples = view->texture->sampleCount,
.loadOp = vk::AttachmentLoadOp::eLoad, .loadOp = vk::AttachmentLoadOp::eLoad,
.storeOp = vk::AttachmentStoreOp::eStore, .storeOp = vk::AttachmentStoreOp::eStore,
.stencilLoadOp = vk::AttachmentLoadOp::eLoad, .stencilLoadOp = vk::AttachmentLoadOp::eLoad,
.stencilStoreOp = vk::AttachmentStoreOp::eStore, .stencilStoreOp = vk::AttachmentStoreOp::eStore,
.initialLayout = view.texture->layout, .initialLayout = view->texture->layout,
.finalLayout = view.texture->layout, .finalLayout = view->texture->layout,
}); });
attachmentReferences.push_back(vk::AttachmentReference{ attachmentReferences.push_back(vk::AttachmentReference{
.attachment = static_cast<u32>(attachmentDescriptions.size() - 1), .attachment = static_cast<u32>(attachmentDescriptions.size() - 1),
.layout = view.texture->layout, .layout = view->texture->layout,
}); });
} else {
attachmentReferences.push_back(vk::AttachmentReference{
.attachment = VK_ATTACHMENT_UNUSED,
.layout = vk::ImageLayout::eUndefined,
});
}
}}; }};
vk::SubpassDescription subpassDescription{ vk::SubpassDescription subpassDescription{
@ -364,10 +378,10 @@ namespace skyline::gpu::cache {
}; };
for (auto &colorAttachment : state.colorAttachments) for (auto &colorAttachment : state.colorAttachments)
pushAttachment(*colorAttachment); pushAttachment(colorAttachment);
if (state.depthStencilAttachment) { if (state.depthStencilAttachment) {
pushAttachment(*state.depthStencilAttachment); pushAttachment(state.depthStencilAttachment);
subpassDescription.pColorAttachments = attachmentReferences.data(); subpassDescription.pColorAttachments = attachmentReferences.data();
subpassDescription.colorAttachmentCount = static_cast<u32>(attachmentReferences.size() - 1); subpassDescription.colorAttachmentCount = static_cast<u32>(attachmentReferences.size() - 1);

View File

@ -128,10 +128,16 @@ namespace skyline::gpu::interconnect::node {
auto colorAttachmentsOffset{attachmentReferences.size() * sizeof(vk::AttachmentReference)}; // Calculate new base offset as it has changed since we pushed the input attachments auto colorAttachmentsOffset{attachmentReferences.size() * sizeof(vk::AttachmentReference)}; // Calculate new base offset as it has changed since we pushed the input attachments
for (auto &attachment : colorAttachments) { for (auto &attachment : colorAttachments) {
if (attachment)
attachmentReferences.push_back(vk::AttachmentReference{ attachmentReferences.push_back(vk::AttachmentReference{
.attachment = AddAttachment(attachment, gpu), .attachment = AddAttachment(attachment, gpu),
.layout = attachment->texture->layout, .layout = attachment->texture->layout,
}); });
else
attachmentReferences.push_back(vk::AttachmentReference{
.attachment = VK_ATTACHMENT_UNUSED,
.layout = vk::ImageLayout::eUndefined,
});
} }
auto depthStencilAttachmentOffset{attachmentReferences.size() * sizeof(vk::AttachmentReference)}; auto depthStencilAttachmentOffset{attachmentReferences.size() * sizeof(vk::AttachmentReference)};

View File

@ -470,6 +470,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
bindFunc(depthStencilRegisters); bindFunc(depthStencilRegisters);
bindFunc(colorBlendRegisters); bindFunc(colorBlendRegisters);
bindFunc(globalShaderConfigRegisters); bindFunc(globalShaderConfigRegisters);
manager.Bind(handle, ctSelect);
} }
PipelineState::PipelineState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine) PipelineState::PipelineState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine)
@ -483,7 +484,8 @@ namespace skyline::gpu::interconnect::maxwell3d {
depthStencil{manager, engine.depthStencilRegisters}, depthStencil{manager, engine.depthStencilRegisters},
colorBlend{manager, engine.colorBlendRegisters}, colorBlend{manager, engine.colorBlendRegisters},
directState{engine.inputAssemblyRegisters}, directState{engine.inputAssemblyRegisters},
globalShaderConfig{engine.globalShaderConfigRegisters} {} globalShaderConfig{engine.globalShaderConfigRegisters},
ctSelect{engine.ctSelect} {}
void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) { void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) {
std::array<ShaderBinary, engine::PipelineCount> shaderBinaries; std::array<ShaderBinary, engine::PipelineCount> shaderBinaries;
@ -494,11 +496,17 @@ namespace skyline::gpu::interconnect::maxwell3d {
} }
colorAttachments.clear(); colorAttachments.clear();
for (auto &colorRenderTarget : colorRenderTargets) for (size_t i{}; i < ctSelect.count; i++) {
if (auto view{colorRenderTarget.UpdateGet(ctx, packedState).view}) const auto &view{colorRenderTargets[ctSelect[i]].UpdateGet(ctx, packedState).view.get()};
colorAttachments.push_back(view.get()); colorAttachments.push_back(view);
if (view)
ctx.executor.AttachTexture(view);
}
depthAttachment = depthRenderTarget.UpdateGet(ctx, packedState).view.get(); depthAttachment = depthRenderTarget.UpdateGet(ctx, packedState).view.get();
if (depthAttachment)
ctx.executor.AttachTexture(depthAttachment);
vertexInput.Update(packedState); vertexInput.Update(packedState);
directState.inputAssembly.Update(packedState); directState.inputAssembly.Update(packedState);

View File

@ -284,6 +284,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
DepthStencilState::EngineRegisters depthStencilRegisters; DepthStencilState::EngineRegisters depthStencilRegisters;
ColorBlendState::EngineRegisters colorBlendRegisters; ColorBlendState::EngineRegisters colorBlendRegisters;
GlobalShaderConfigState::EngineRegisters globalShaderConfigRegisters; GlobalShaderConfigState::EngineRegisters globalShaderConfigRegisters;
const engine::CtSelect &ctSelect;
void DirtyBind(DirtyManager &manager, dirty::Handle handle) const; void DirtyBind(DirtyManager &manager, dirty::Handle handle) const;
}; };
@ -304,6 +305,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
dirty::ManualDirtyState<DepthStencilState> depthStencil; dirty::ManualDirtyState<DepthStencilState> depthStencil;
dirty::ManualDirtyState<ColorBlendState> colorBlend; dirty::ManualDirtyState<ColorBlendState> colorBlend;
GlobalShaderConfigState globalShaderConfig; GlobalShaderConfigState globalShaderConfig;
const engine::CtSelect &ctSelect;
public: public:
DirectPipelineState directState; DirectPipelineState directState;

View File

@ -451,7 +451,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
u8 target6 : 3; u8 target6 : 3;
u8 target7 : 3; u8 target7 : 3;
size_t operator[](size_t index) { size_t operator[](size_t index) const {
switch (index) { switch (index) {
case 0: case 0:
return target0; return target0;

View File

@ -23,7 +23,8 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
.rasterizationRegisters = {*registers.rasterEnable, *registers.frontPolygonMode, *registers.backPolygonMode, *registers.oglCullEnable, *registers.oglCullFace, *registers.windowOrigin, *registers.oglFrontFace, *registers.viewportClipControl, *registers.polyOffset, *registers.provokingVertex, *registers.pointSize, *registers.zClipRange}, .rasterizationRegisters = {*registers.rasterEnable, *registers.frontPolygonMode, *registers.backPolygonMode, *registers.oglCullEnable, *registers.oglCullFace, *registers.windowOrigin, *registers.oglFrontFace, *registers.viewportClipControl, *registers.polyOffset, *registers.provokingVertex, *registers.pointSize, *registers.zClipRange},
.depthStencilRegisters = {*registers.depthTestEnable, *registers.depthWriteEnable, *registers.depthFunc, *registers.depthBoundsTestEnable, *registers.stencilTestEnable, *registers.twoSidedStencilTestEnable, *registers.stencilOps, *registers.stencilBack}, .depthStencilRegisters = {*registers.depthTestEnable, *registers.depthWriteEnable, *registers.depthFunc, *registers.depthBoundsTestEnable, *registers.stencilTestEnable, *registers.twoSidedStencilTestEnable, *registers.stencilOps, *registers.stencilBack},
.colorBlendRegisters = {*registers.logicOp, *registers.singleCtWriteControl, *registers.ctWrites, *registers.blendStatePerTargetEnable, *registers.blendPerTargets, *registers.blend}, .colorBlendRegisters = {*registers.logicOp, *registers.singleCtWriteControl, *registers.ctWrites, *registers.blendStatePerTargetEnable, *registers.blendPerTargets, *registers.blend},
.globalShaderConfigRegisters = {*registers.postVtgShaderAttributeSkipMask, *registers.bindlessTexture, *registers.apiMandatedEarlyZEnable} .globalShaderConfigRegisters = {*registers.postVtgShaderAttributeSkipMask, *registers.bindlessTexture, *registers.apiMandatedEarlyZEnable},
.ctSelect = *registers.ctSelect
}; };
} }