renderer_vulkan: Implement logic ops

This commit is contained in:
IndecisiveTurtle 2025-07-14 01:34:01 +03:00
parent 23ebe5e0e9
commit 4cc2220f2f
7 changed files with 71 additions and 3 deletions

View File

@ -791,11 +791,29 @@ struct Liverpool {
Err = 4u,
FmaskDecompress = 5u,
};
enum class LogicOp : u32 {
Clear = 0x00,
Nor = 0x11,
AndInverted = 0x22,
CopyInverted = 0x33,
AndReverse = 0x44,
Invert = 0x55,
Xor = 0x66,
Nand = 0x77,
And = 0x88,
Equiv = 0x99,
Noop = 0xAA,
OrInverted = 0xBB,
Copy = 0xCC,
OrReverse = 0xDD,
Or = 0xEE,
Set = 0xFF,
};
BitField<0, 1, u32> disable_dual_quad;
BitField<3, 1, u32> degamma_enable;
BitField<4, 3, OperationMode> mode;
BitField<16, 8, u32> rop3;
BitField<16, 8, LogicOp> rop3;
};
struct ColorBuffer {

View File

@ -245,6 +245,46 @@ vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func) {
}
}
vk::LogicOp LogicOp(Liverpool::ColorControl::LogicOp logic_op) {
using LogicOp = Liverpool::ColorControl::LogicOp;
switch (logic_op) {
case LogicOp::Clear:
return vk::LogicOp::eClear;
case LogicOp::Nor:
return vk::LogicOp::eNor;
case LogicOp::AndInverted:
return vk::LogicOp::eAndInverted;
case LogicOp::CopyInverted:
return vk::LogicOp::eCopyInverted;
case LogicOp::AndReverse:
return vk::LogicOp::eAndReverse;
case LogicOp::Invert:
return vk::LogicOp::eInvert;
case LogicOp::Xor:
return vk::LogicOp::eXor;
case LogicOp::Nand:
return vk::LogicOp::eNand;
case LogicOp::And:
return vk::LogicOp::eAnd;
case LogicOp::Equiv:
return vk::LogicOp::eEquivalent;
case LogicOp::Noop:
return vk::LogicOp::eNoOp;
case LogicOp::OrInverted:
return vk::LogicOp::eOrInverted;
case LogicOp::Copy:
return vk::LogicOp::eCopy;
case LogicOp::OrReverse:
return vk::LogicOp::eOrReverse;
case LogicOp::Or:
return vk::LogicOp::eOr;
case LogicOp::Set:
return vk::LogicOp::eSet;
default:
UNREACHABLE_MSG("Unknown logic op {}", u32(logic_op));
}
}
// https://github.com/chaotic-cx/mesa-mirror/blob/0954afff5/src/amd/vulkan/radv_sampler.c#L21
vk::SamplerAddressMode ClampMode(AmdGpu::ClampMode mode) {
switch (mode) {

View File

@ -34,6 +34,8 @@ bool IsDualSourceBlendFactor(Liverpool::BlendControl::BlendFactor factor);
vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func);
vk::LogicOp LogicOp(Liverpool::ColorControl::LogicOp logic_op);
vk::SamplerAddressMode ClampMode(AmdGpu::ClampMode mode);
vk::CompareOp DepthCompare(AmdGpu::DepthCompare comp);

View File

@ -286,8 +286,9 @@ GraphicsPipeline::GraphicsPipeline(
}
const vk::PipelineColorBlendStateCreateInfo color_blending = {
.logicOpEnable = false,
.logicOp = vk::LogicOp::eCopy,
.logicOpEnable =
instance.IsLogicOpSupported() && key.logic_op != Liverpool::ColorControl::LogicOp::Copy,
.logicOp = LiverpoolToVK::LogicOp(key.logic_op),
.attachmentCount = key.num_color_attachments,
.pAttachments = attachments.data(),
.blendConstants = std::array{1.0f, 1.0f, 1.0f, 1.0f},

View File

@ -41,6 +41,7 @@ struct GraphicsPipelineKey {
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
std::array<vk::ColorComponentFlags, Liverpool::NumColorBuffers> write_masks;
Liverpool::ColorBufferMask cb_shader_mask;
Liverpool::ColorControl::LogicOp logic_op;
u32 num_samples;
u32 mrt_mask;
vk::Format depth_format;

View File

@ -356,6 +356,11 @@ public:
return driver_id != vk::DriverId::eMoltenvk;
}
/// Returns true if logic ops are supported by the device.
bool IsLogicOpSupported() const {
return features.logicOp;
}
/// Determines if a format is supported for a set of feature flags.
[[nodiscard]] bool IsFormatSupported(vk::Format format, vk::FormatFeatureFlags2 flags) const;

View File

@ -304,6 +304,7 @@ bool PipelineCache::RefreshGraphicsKey() {
key.polygon_mode = regs.polygon_control.PolyMode();
key.clip_space = regs.clipper_control.clip_space;
key.provoking_vtx_last = regs.polygon_control.provoking_vtx_last;
key.logic_op = regs.color_control.rop3;
key.num_samples = regs.NumSamples();
const bool skip_cb_binding =