diff --git a/src/backend/d3d12/BlendStateD3D12.cpp b/src/backend/d3d12/BlendStateD3D12.cpp index bd58f9c132..da1e1fd9a8 100644 --- a/src/backend/d3d12/BlendStateD3D12.cpp +++ b/src/backend/d3d12/BlendStateD3D12.cpp @@ -15,11 +15,95 @@ #include "backend/d3d12/BlendStateD3D12.h" #include "backend/d3d12/D3D12Backend.h" +#include "common/Assert.h" namespace backend { namespace d3d12 { + namespace { + D3D12_BLEND D3D12Blend(nxt::BlendFactor factor) { + switch(factor) { + case nxt::BlendFactor::Zero: + return D3D12_BLEND_ZERO; + case nxt::BlendFactor::One: + return D3D12_BLEND_ONE; + case nxt::BlendFactor::SrcColor: + return D3D12_BLEND_SRC_COLOR; + case nxt::BlendFactor::OneMinusSrcColor: + return D3D12_BLEND_INV_SRC_COLOR; + case nxt::BlendFactor::SrcAlpha: + return D3D12_BLEND_SRC_ALPHA; + case nxt::BlendFactor::OneMinusSrcAlpha: + return D3D12_BLEND_INV_SRC_ALPHA; + case nxt::BlendFactor::DstColor: + return D3D12_BLEND_DEST_COLOR; + case nxt::BlendFactor::OneMinusDstColor: + return D3D12_BLEND_INV_DEST_COLOR; + case nxt::BlendFactor::DstAlpha: + return D3D12_BLEND_DEST_ALPHA; + case nxt::BlendFactor::OneMinusDstAlpha: + return D3D12_BLEND_INV_DEST_ALPHA; + case nxt::BlendFactor::SrcAlphaSaturated: + return D3D12_BLEND_SRC_ALPHA_SAT; + case nxt::BlendFactor::BlendColor: + return D3D12_BLEND_BLEND_FACTOR; + case nxt::BlendFactor::OneMinusBlendColor: + return D3D12_BLEND_INV_BLEND_FACTOR; + case nxt::BlendFactor::Src1Color: + return D3D12_BLEND_SRC1_COLOR; + case nxt::BlendFactor::OneMinusSrc1Color: + return D3D12_BLEND_INV_SRC1_COLOR; + case nxt::BlendFactor::Src1Alpha: + return D3D12_BLEND_SRC1_ALPHA; + case nxt::BlendFactor::OneMinusSrc1Alpha: + return D3D12_BLEND_INV_SRC1_ALPHA; + default: + UNREACHABLE(); + } + } + + D3D12_BLEND_OP D3D12BlendOperation(nxt::BlendOperation operation) { + switch(operation) { + case nxt::BlendOperation::Add: + return D3D12_BLEND_OP_ADD; + case nxt::BlendOperation::Subtract: + return D3D12_BLEND_OP_SUBTRACT; + case nxt::BlendOperation::ReverseSubtract: + return D3D12_BLEND_OP_REV_SUBTRACT; + case nxt::BlendOperation::Min: + return D3D12_BLEND_OP_MIN; + case nxt::BlendOperation::Max: + return D3D12_BLEND_OP_MAX; + default: + UNREACHABLE(); + } + } + + uint8_t D3D12RenderTargetWriteMask(nxt::ColorWriteMask colorWriteMask) { + static_assert(static_cast(nxt::ColorWriteMask::Red) == D3D12_COLOR_WRITE_ENABLE_RED, "ColorWriteMask values must match"); + static_assert(static_cast(nxt::ColorWriteMask::Green) == D3D12_COLOR_WRITE_ENABLE_GREEN, "ColorWriteMask values must match"); + static_assert(static_cast(nxt::ColorWriteMask::Blue) == D3D12_COLOR_WRITE_ENABLE_BLUE, "ColorWriteMask values must match"); + static_assert(static_cast(nxt::ColorWriteMask::Alpha) == D3D12_COLOR_WRITE_ENABLE_ALPHA, "ColorWriteMask values must match"); + return static_cast(colorWriteMask); + } + } + BlendState::BlendState(BlendStateBuilder* builder) : BlendStateBase(builder) { + auto& info = GetBlendInfo(); + blendDesc.BlendEnable = info.blendEnabled; + blendDesc.SrcBlend = D3D12Blend(info.colorBlend.srcFactor); + blendDesc.DestBlend = D3D12Blend(info.colorBlend.dstFactor); + blendDesc.BlendOp = D3D12BlendOperation(info.colorBlend.operation); + blendDesc.SrcBlendAlpha = D3D12Blend(info.alphaBlend.srcFactor); + blendDesc.DestBlendAlpha = D3D12Blend(info.alphaBlend.dstFactor); + blendDesc.BlendOpAlpha = D3D12BlendOperation(info.alphaBlend.operation); + blendDesc.RenderTargetWriteMask = D3D12RenderTargetWriteMask(info.colorWriteMask); + blendDesc.LogicOpEnable = false; + blendDesc.LogicOp = D3D12_LOGIC_OP_NOOP; + } + + const D3D12_RENDER_TARGET_BLEND_DESC& BlendState::GetD3D12BlendDesc() const { + return blendDesc; } } diff --git a/src/backend/d3d12/BlendStateD3D12.h b/src/backend/d3d12/BlendStateD3D12.h index 57eab15dcf..315cb6f34a 100644 --- a/src/backend/d3d12/BlendStateD3D12.h +++ b/src/backend/d3d12/BlendStateD3D12.h @@ -17,12 +17,19 @@ #include "backend/BlendState.h" +#include "backend/d3d12/d3d12_platform.h" + namespace backend { namespace d3d12 { class BlendState : public BlendStateBase { public: BlendState(BlendStateBuilder* builder); + + const D3D12_RENDER_TARGET_BLEND_DESC& GetD3D12BlendDesc() const; + + private: + D3D12_RENDER_TARGET_BLEND_DESC blendDesc; }; } diff --git a/src/backend/metal/BlendStateMTL.h b/src/backend/metal/BlendStateMTL.h index 27c3e4358d..cef5ad6aec 100644 --- a/src/backend/metal/BlendStateMTL.h +++ b/src/backend/metal/BlendStateMTL.h @@ -17,12 +17,15 @@ #include "backend/BlendState.h" +#import namespace backend { namespace metal { class BlendState : public BlendStateBase { public: BlendState(BlendStateBuilder* builder); + + void ApplyBlendState(MTLRenderPipelineColorAttachmentDescriptor* descriptor) const; }; } diff --git a/src/backend/metal/BlendStateMTL.mm b/src/backend/metal/BlendStateMTL.mm index d0aaece97d..ade6ed8037 100644 --- a/src/backend/metal/BlendStateMTL.mm +++ b/src/backend/metal/BlendStateMTL.mm @@ -19,8 +19,86 @@ namespace backend { namespace metal { + namespace { + + MTLBlendFactor MetalBlendFactor(nxt::BlendFactor factor, bool alpha) { + switch(factor) { + case nxt::BlendFactor::Zero: + return MTLBlendFactorZero; + case nxt::BlendFactor::One: + return MTLBlendFactorOne; + case nxt::BlendFactor::SrcColor: + return MTLBlendFactorSourceColor; + case nxt::BlendFactor::OneMinusSrcColor: + return MTLBlendFactorOneMinusSourceColor; + case nxt::BlendFactor::SrcAlpha: + return MTLBlendFactorSourceAlpha; + case nxt::BlendFactor::OneMinusSrcAlpha: + return MTLBlendFactorOneMinusSourceAlpha; + case nxt::BlendFactor::DstColor: + return MTLBlendFactorDestinationColor; + case nxt::BlendFactor::OneMinusDstColor: + return MTLBlendFactorOneMinusDestinationColor; + case nxt::BlendFactor::DstAlpha: + return MTLBlendFactorDestinationAlpha; + case nxt::BlendFactor::OneMinusDstAlpha: + return MTLBlendFactorOneMinusDestinationAlpha; + case nxt::BlendFactor::SrcAlphaSaturated: + return MTLBlendFactorSourceAlphaSaturated; + case nxt::BlendFactor::BlendColor: + return alpha ? MTLBlendFactorBlendAlpha : MTLBlendFactorBlendColor; + case nxt::BlendFactor::OneMinusBlendColor: + return alpha ? MTLBlendFactorOneMinusBlendAlpha : MTLBlendFactorOneMinusBlendColor; + case nxt::BlendFactor::Src1Color: + return MTLBlendFactorSource1Color; + case nxt::BlendFactor::OneMinusSrc1Color: + return MTLBlendFactorOneMinusSource1Color; + case nxt::BlendFactor::Src1Alpha: + return MTLBlendFactorSource1Alpha; + case nxt::BlendFactor::OneMinusSrc1Alpha: + return MTLBlendFactorOneMinusSource1Alpha; + } + } + + MTLBlendOperation MetalBlendOperation(nxt::BlendOperation operation) { + switch(operation) { + case nxt::BlendOperation::Add: + return MTLBlendOperationAdd; + case nxt::BlendOperation::Subtract: + return MTLBlendOperationSubtract; + case nxt::BlendOperation::ReverseSubtract: + return MTLBlendOperationReverseSubtract; + case nxt::BlendOperation::Min: + return MTLBlendOperationMin; + case nxt::BlendOperation::Max: + return MTLBlendOperationMax; + } + } + + MTLColorWriteMask MetalColorWriteMask(nxt::ColorWriteMask colorWriteMask) { + return ( + ((colorWriteMask & nxt::ColorWriteMask::Red) != nxt::ColorWriteMask::None ? MTLColorWriteMaskRed : MTLColorWriteMaskNone) | + ((colorWriteMask & nxt::ColorWriteMask::Green) != nxt::ColorWriteMask::None ? MTLColorWriteMaskGreen : MTLColorWriteMaskNone) | + ((colorWriteMask & nxt::ColorWriteMask::Blue) != nxt::ColorWriteMask::None ? MTLColorWriteMaskBlue : MTLColorWriteMaskNone) | + ((colorWriteMask & nxt::ColorWriteMask::Alpha) != nxt::ColorWriteMask::None ? MTLColorWriteMaskAlpha : MTLColorWriteMaskNone) + ); + } + + } + BlendState::BlendState(BlendStateBuilder* builder) : BlendStateBase(builder) { } + void BlendState::ApplyBlendState(MTLRenderPipelineColorAttachmentDescriptor* descriptor) const { + auto& info = GetBlendInfo(); + descriptor.blendingEnabled = info.blendEnabled; + descriptor.sourceRGBBlendFactor = MetalBlendFactor(info.colorBlend.srcFactor, false); + descriptor.destinationRGBBlendFactor = MetalBlendFactor(info.colorBlend.dstFactor, false); + descriptor.rgbBlendOperation = MetalBlendOperation(info.colorBlend.operation); + descriptor.sourceAlphaBlendFactor = MetalBlendFactor(info.alphaBlend.srcFactor, true); + descriptor.destinationAlphaBlendFactor = MetalBlendFactor(info.alphaBlend.dstFactor, true); + descriptor.alphaBlendOperation = MetalBlendOperation(info.alphaBlend.operation); + descriptor.writeMask = MetalColorWriteMask(info.colorWriteMask); + } } }