diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VKRBase.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VKRBase.h index 1c91207e..f79bd2dc 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VKRBase.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VKRBase.h @@ -1,4 +1,5 @@ #pragma once +#include "Cafe/HW/Latte/ISA/LatteReg.h" #include "util/math/vector2.h" class VKRMoveableRefCounterRef @@ -150,14 +151,28 @@ public: struct AttachmentInfo_t { - AttachmentEntryColor_t colorAttachment[8]; + AttachmentEntryColor_t colorAttachment[Latte::GPU_LIMITS::NUM_COLOR_ATTACHMENTS]; AttachmentEntryDepth_t depthAttachment; }; + VkFormat GetColorFormat(size_t index) + { + if (index >= Latte::GPU_LIMITS::NUM_COLOR_ATTACHMENTS) + return VK_FORMAT_UNDEFINED; + return m_colorAttachmentFormat[index]; + } + + VkFormat GetDepthFormat() + { + return m_depthAttachmentFormat; + } + public: - VKRObjectRenderPass(AttachmentInfo_t& attachmentInfo, sint32 colorAttachmentCount = 8); + VKRObjectRenderPass(AttachmentInfo_t& attachmentInfo, sint32 colorAttachmentCount = Latte::GPU_LIMITS::NUM_COLOR_ATTACHMENTS); ~VKRObjectRenderPass() override; VkRenderPass m_renderPass{ VK_NULL_HANDLE }; + VkFormat m_colorAttachmentFormat[Latte::GPU_LIMITS::NUM_COLOR_ATTACHMENTS]; + VkFormat m_depthAttachmentFormat; uint64 m_hashForPipeline; // helper var. Holds hash of all the renderpass creation parameters (mainly the formats) that affect the pipeline state }; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp index 7fb506b7..0deacddd 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp @@ -609,7 +609,29 @@ void PipelineCompiler::InitRasterizerState(const LatteContextRegister& latteRegi multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; } -void PipelineCompiler::InitBlendState(const LatteContextRegister& latteRegister, PipelineInfo* pipelineInfo, bool& usesBlendConstants) +bool _IsVkIntegerFormat(VkFormat fmt) +{ + return + // 8bit integer formats + fmt == VK_FORMAT_R8_UINT || fmt == VK_FORMAT_R8_SINT || + fmt == VK_FORMAT_R8G8_UINT || fmt == VK_FORMAT_R8G8_SINT || + fmt == VK_FORMAT_R8G8B8_UINT || fmt == VK_FORMAT_R8G8B8_SINT || + fmt == VK_FORMAT_R8G8B8A8_UINT || fmt == VK_FORMAT_R8G8B8A8_SINT || + fmt == VK_FORMAT_B8G8R8A8_UINT || fmt == VK_FORMAT_B8G8R8A8_SINT || + // 16bit integer formats + fmt == VK_FORMAT_R16_UINT || fmt == VK_FORMAT_R16_SINT || + fmt == VK_FORMAT_R16G16_UINT || fmt == VK_FORMAT_R16G16_SINT || + fmt == VK_FORMAT_R16G16B16_UINT || fmt == VK_FORMAT_R16G16B16_SINT || + fmt == VK_FORMAT_R16G16B16A16_UINT || fmt == VK_FORMAT_R16G16B16A16_SINT || + // 32bit integer formats + fmt == VK_FORMAT_R32_UINT || fmt == VK_FORMAT_R32_SINT || + fmt == VK_FORMAT_R32G32_UINT || fmt == VK_FORMAT_R32G32_SINT || + fmt == VK_FORMAT_R32G32B32_UINT || fmt == VK_FORMAT_R32G32B32_SINT || + fmt == VK_FORMAT_R32G32B32A32_UINT || fmt == VK_FORMAT_R32G32B32A32_SINT; +} + + +void PipelineCompiler::InitBlendState(const LatteContextRegister& latteRegister, PipelineInfo* pipelineInfo, bool& usesBlendConstants, VKRObjectRenderPass* renderPassObj) { const Latte::LATTE_CB_COLOR_CONTROL& colorControlReg = latteRegister.CB_COLOR_CONTROL; uint32 blendEnableMask = colorControlReg.get_BLEND_MASK(); @@ -625,6 +647,12 @@ void PipelineCompiler::InitBlendState(const LatteContextRegister& latteRegister, else entry.blendEnable = VK_FALSE; + if (entry.blendEnable != VK_FALSE && _IsVkIntegerFormat(renderPassObj->GetColorFormat(i))) + { + // force-disable blending for integer formats + entry.blendEnable = VK_FALSE; + } + const auto& blendControlReg = latteRegister.CB_BLENDN_CONTROL[i]; entry.colorWriteMask = (renderTargetMask >> (i * 4)) & 0xF; @@ -873,7 +901,7 @@ bool PipelineCompiler::InitFromCurrentGPUState(PipelineInfo* pipelineInfo, const bool usesDepthBias = false; InitRasterizerState(latteRegister, vkRenderer, isPrimitiveRect, usesDepthBias); bool usesBlendConstants = false; - InitBlendState(latteRegister, pipelineInfo, usesBlendConstants); + InitBlendState(latteRegister, pipelineInfo, usesBlendConstants, renderPassObj); InitDescriptorSetLayouts(vkRenderer, pipelineInfo, pipelineInfo->vertexShader, pipelineInfo->pixelShader, pipelineInfo->geometryShader); // ########################################################################################################################################## diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.h index 4020b27e..304a7b31 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.h @@ -23,7 +23,7 @@ private: void InitInputAssemblyState(const Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE primitiveMode); void InitViewportState(); void InitRasterizerState(const LatteContextRegister& latteRegister, VulkanRenderer* vkRenderer, bool isPrimitiveRect, bool& usesDepthBias); - void InitBlendState(const LatteContextRegister& latteRegister, PipelineInfo* pipelineInfo, bool& usesBlendConstants); + void InitBlendState(const LatteContextRegister& latteRegister, PipelineInfo* pipelineInfo, bool& usesBlendConstants, VKRObjectRenderPass* renderPassObj); void InitDescriptorSetLayouts(VulkanRenderer* vkRenderer, PipelineInfo* vkrPipelineInfo, LatteDecompilerShader* vertexShader, LatteDecompilerShader* pixelShader, LatteDecompilerShader* geometryShader); void InitDepthStencilState(); void InitDynamicState(PipelineInfo* pipelineInfo, bool usesBlendConstants, bool usesDepthBias); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index 03ffb7f5..8d352654 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -4085,7 +4085,7 @@ VKRObjectRenderPass::VKRObjectRenderPass(AttachmentInfo_t& attachmentInfo, sint3 { // generate helper hash for pipeline state uint64 stateHash = 0; - for (int i = 0; i < 8; ++i) + for (int i = 0; i < Latte::GPU_LIMITS::NUM_COLOR_ATTACHMENTS; ++i) { if (attachmentInfo.colorAttachment[i].isPresent || attachmentInfo.colorAttachment[i].viewObj) { @@ -4102,7 +4102,7 @@ VKRObjectRenderPass::VKRObjectRenderPass(AttachmentInfo_t& attachmentInfo, sint3 // setup Vulkan renderpass std::vector attachments_descriptions; - std::array color_attachments_references{}; + std::array color_attachments_references{}; cemu_assert(colorAttachmentCount <= color_attachments_references.size()); sint32 numColorAttachments = 0; for (int i = 0; i < 8; ++i) @@ -4110,8 +4110,10 @@ VKRObjectRenderPass::VKRObjectRenderPass(AttachmentInfo_t& attachmentInfo, sint3 if (attachmentInfo.colorAttachment[i].viewObj == nullptr && attachmentInfo.colorAttachment[i].isPresent == false) { color_attachments_references[i].attachment = VK_ATTACHMENT_UNUSED; + m_colorAttachmentFormat[i] = VK_FORMAT_UNDEFINED; continue; } + m_colorAttachmentFormat[i] = attachmentInfo.colorAttachment[i].format; color_attachments_references[i].attachment = (uint32)attachments_descriptions.size(); color_attachments_references[i].layout = VK_IMAGE_LAYOUT_GENERAL; @@ -4135,12 +4137,14 @@ VKRObjectRenderPass::VKRObjectRenderPass(AttachmentInfo_t& attachmentInfo, sint3 if (attachmentInfo.depthAttachment.viewObj == nullptr && attachmentInfo.depthAttachment.isPresent == false) { depth_stencil_attachments_references.attachment = VK_ATTACHMENT_UNUSED; + m_depthAttachmentFormat = VK_FORMAT_UNDEFINED; } else { hasDepthStencilAttachment = true; depth_stencil_attachments_references.attachment = (uint32)attachments_descriptions.size(); depth_stencil_attachments_references.layout = VK_IMAGE_LAYOUT_GENERAL; + m_depthAttachmentFormat = attachmentInfo.depthAttachment.format; VkAttachmentDescription entry{}; entry.format = attachmentInfo.depthAttachment.format;