mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-23 12:21:51 +01:00
Implement Maxwell3D Color Logic Operations
Implements a basic part of Vulkan blending state which are color logic operations applied on the framebuffer after running the fragment shader. It is an optional feature in Vulkan and not supported on any mobile GPU vendor aside from ImgTec/NVIDIA by default.
This commit is contained in:
parent
662935c35d
commit
01eb16e59a
@ -479,5 +479,57 @@ namespace skyline::gpu::interconnect {
|
||||
void SetDepthBiasSlopeFactor(float factor) {
|
||||
rasterizerState.get<vk::PipelineRasterizationStateCreateInfo>().depthBiasSlopeFactor = factor;
|
||||
}
|
||||
|
||||
/* Color Blending */
|
||||
private:
|
||||
vk::PipelineColorBlendStateCreateInfo blendState{};
|
||||
|
||||
public:
|
||||
void SetBlendLogicOpEnable(bool enabled) {
|
||||
if (!gpu.quirks.supportsLogicOp && enabled) {
|
||||
Logger::Warn("Cannot enable framebuffer logical operation without host GPU support");
|
||||
return;
|
||||
}
|
||||
blendState.logicOpEnable = enabled;
|
||||
}
|
||||
|
||||
void SetBlendLogicOpType(maxwell3d::ColorLogicOp logicOp) {
|
||||
blendState.logicOp = [logicOp]() {
|
||||
switch (logicOp) {
|
||||
case maxwell3d::ColorLogicOp::Clear:
|
||||
return vk::LogicOp::eClear;
|
||||
case maxwell3d::ColorLogicOp::And:
|
||||
return vk::LogicOp::eAnd;
|
||||
case maxwell3d::ColorLogicOp::AndReverse:
|
||||
return vk::LogicOp::eAndReverse;
|
||||
case maxwell3d::ColorLogicOp::Copy:
|
||||
return vk::LogicOp::eCopy;
|
||||
case maxwell3d::ColorLogicOp::AndInverted:
|
||||
return vk::LogicOp::eAndInverted;
|
||||
case maxwell3d::ColorLogicOp::Noop:
|
||||
return vk::LogicOp::eNoOp;
|
||||
case maxwell3d::ColorLogicOp::Xor:
|
||||
return vk::LogicOp::eXor;
|
||||
case maxwell3d::ColorLogicOp::Or:
|
||||
return vk::LogicOp::eOr;
|
||||
case maxwell3d::ColorLogicOp::Nor:
|
||||
return vk::LogicOp::eNor;
|
||||
case maxwell3d::ColorLogicOp::Equiv:
|
||||
return vk::LogicOp::eEquivalent;
|
||||
case maxwell3d::ColorLogicOp::Invert:
|
||||
return vk::LogicOp::eInvert;
|
||||
case maxwell3d::ColorLogicOp::OrReverse:
|
||||
return vk::LogicOp::eOrReverse;
|
||||
case maxwell3d::ColorLogicOp::CopyInverted:
|
||||
return vk::LogicOp::eCopyInverted;
|
||||
case maxwell3d::ColorLogicOp::OrInverted:
|
||||
return vk::LogicOp::eOrInverted;
|
||||
case maxwell3d::ColorLogicOp::Nand:
|
||||
return vk::LogicOp::eNand;
|
||||
case maxwell3d::ColorLogicOp::Set:
|
||||
return vk::LogicOp::eSet;
|
||||
}
|
||||
}();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "quirk_manager.h"
|
||||
|
||||
namespace skyline {
|
||||
QuirkManager::QuirkManager(vk::PhysicalDeviceProperties properties, vk::PhysicalDeviceFeatures2 features, const std::vector<vk::ExtensionProperties> &extensions) {
|
||||
QuirkManager::QuirkManager(vk::PhysicalDeviceProperties properties, vk::PhysicalDeviceFeatures2 features2, const std::vector<vk::ExtensionProperties> &extensions) {
|
||||
for (auto &extension : extensions) {
|
||||
#define EXT_SET(name, property) \
|
||||
case util::Hash(name): \
|
||||
@ -27,5 +27,7 @@ namespace skyline {
|
||||
#undef EXT_SET
|
||||
#undef EXT_SET_V
|
||||
}
|
||||
|
||||
supportsLogicOp = features2.features.logicOp;
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace skyline {
|
||||
class QuirkManager {
|
||||
public:
|
||||
bool supportsLastProvokingVertex{}; //!< If the device supports setting the last vertex as the provoking vertex (with VK_EXT_provoking_vertex)
|
||||
bool supportsLogicOp{}; //!< If the device supports framebuffer logical operations during blending
|
||||
|
||||
QuirkManager() = default;
|
||||
|
||||
|
@ -540,6 +540,28 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
|
||||
};
|
||||
static_assert(sizeof(SemaphoreInfo) == sizeof(u32));
|
||||
|
||||
/**
|
||||
* @brief The logical operations that can be performed on the framebuffer after the fragment shader
|
||||
*/
|
||||
enum class ColorLogicOp : u32 {
|
||||
Clear = 0x1500,
|
||||
And = 0x1501,
|
||||
AndReverse = 0x1502,
|
||||
Copy = 0x1503,
|
||||
AndInverted = 0x1504,
|
||||
Noop = 0x1505,
|
||||
Xor = 0x1506,
|
||||
Or = 0x1507,
|
||||
Nor = 0x1508,
|
||||
Equiv = 0x1509,
|
||||
Invert = 0x150A,
|
||||
OrReverse = 0x150B,
|
||||
CopyInverted = 0x150C,
|
||||
OrInverted = 0x150D,
|
||||
Nand = 0x150E,
|
||||
Set = 0x150F,
|
||||
};
|
||||
|
||||
constexpr static size_t StageCount{6}; //!< Amount of pipeline stages on Maxwell 3D
|
||||
|
||||
/**
|
||||
|
@ -237,6 +237,14 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
context.SetDepthClampEnabled(!viewVolumeClipControl.depthClampDisable);
|
||||
})
|
||||
|
||||
MAXWELL3D_STRUCT_CASE(colorLogicOp, enable, {
|
||||
context.SetBlendLogicOpEnable(enable);
|
||||
})
|
||||
|
||||
MAXWELL3D_STRUCT_CASE(colorLogicOp, type, {
|
||||
context.SetBlendLogicOpType(type);
|
||||
})
|
||||
|
||||
#define SET_SHADER_ENABLE_CALLBACK(z, index, data) \
|
||||
MAXWELL3D_ARRAY_STRUCT_CASE(setProgram, index, info, { \
|
||||
context.SetShaderEnabled(info.stage, info.enable); \
|
||||
|
@ -219,6 +219,12 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
};
|
||||
Register<0x6C0, Semaphore> semaphore;
|
||||
|
||||
struct ColorLogicOp {
|
||||
u32 enable;
|
||||
type::ColorLogicOp type;
|
||||
};
|
||||
Register<0x671, ColorLogicOp> colorLogicOp;
|
||||
|
||||
Register<0x780, std::array<type::Blend, type::RenderTargetCount>> independentBlend;
|
||||
|
||||
Register<0x800, std::array<type::SetProgramInfo, type::StageCount>> setProgram;
|
||||
|
Loading…
Reference in New Issue
Block a user