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

View File

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

View File

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

View File

@ -451,7 +451,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
u8 target6 : 3;
u8 target7 : 3;
size_t operator[](size_t index) {
size_t operator[](size_t index) const {
switch (index) {
case 0:
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},
.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},
.globalShaderConfigRegisters = {*registers.postVtgShaderAttributeSkipMask, *registers.bindlessTexture, *registers.apiMandatedEarlyZEnable}
.globalShaderConfigRegisters = {*registers.postVtgShaderAttributeSkipMask, *registers.bindlessTexture, *registers.apiMandatedEarlyZEnable},
.ctSelect = *registers.ctSelect
};
}