D3D11: implement support for logic op blending when available

This commit is contained in:
Henrik Rydgard 2017-02-18 02:14:10 +01:00
parent d41a7083fb
commit 3713f4e6e6
4 changed files with 56 additions and 24 deletions

View File

@ -83,6 +83,8 @@ DrawEngineD3D11::DrawEngineD3D11(Draw::DrawContext *draw, ID3D11Device *device,
vertexCountInDrawCalls(0),
decodeCounter_(0),
dcid_(0) {
device1_ = (ID3D11Device1 *)draw->GetNativeObject(Draw::NativeObject::DEVICE_EX);
context1_ = (ID3D11DeviceContext1 *)draw->GetNativeObject(Draw::NativeObject::CONTEXT_EX);
decOptions_.expandAllWeightsToFloat = true;
decOptions_.expand8BitNormalsToFloat = true;

View File

@ -20,6 +20,7 @@
#include <unordered_map>
#include <d3d11.h>
#include <d3d11_1.h>
#include "GPU/GPUState.h"
#include "GPU/Common/GPUDebugInterface.h"
@ -172,7 +173,9 @@ private:
Draw::DrawContext *draw_; // Used for framebuffer related things exclusively.
ID3D11Device *device_;
ID3D11Device1 *device1_;
ID3D11DeviceContext *context_;
ID3D11DeviceContext1 *context1_;
// Defer all vertex decoding to a Flush, so that we can hash and cache the
// generated buffers without having to redecode them every time.
@ -236,13 +239,15 @@ private:
// D3D11 state object caches
std::map<uint64_t, ID3D11BlendState *> blendCache_;
std::map<uint64_t, ID3D11BlendState1 *> blendCache1_;
std::map<uint64_t, ID3D11DepthStencilState *> depthStencilCache_;
std::map<uint32_t, ID3D11RasterizerState *> rasterCache_;
// Keep the depth state between ApplyDrawState and ApplyDrawStateLate
ID3D11RasterizerState *rasterState_;
ID3D11BlendState *blendState_;
ID3D11DepthStencilState *depthStencilState_;
ID3D11RasterizerState *rasterState_ = nullptr;
ID3D11BlendState *blendState_ = nullptr;
ID3D11BlendState1 *blendState1_ = nullptr;
ID3D11DepthStencilState *depthStencilState_ = nullptr;
// State keys
D3D11StateKeys keys_{};

View File

@ -517,8 +517,7 @@ void GPU_D3D11::CheckGPUFeatures() {
}
if (draw_->GetDeviceCaps().logicOpSupported) {
// This requires a little bit more code in statemapping, and passing in a device1_ object.
// features |= GPU_SUPPORTS_LOGIC_OP;
features |= GPU_SUPPORTS_LOGIC_OP;
}
if (!g_Config.bHighQualityDepth) {

View File

@ -355,30 +355,52 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
}
ID3D11BlendState *bs = nullptr;
ID3D11BlendState1 *bs1 = nullptr;
ID3D11DepthStencilState *ds = nullptr;
ID3D11RasterizerState *rs = nullptr;
auto blendIter = blendCache_.find(keys_.blend.value);
if (blendIter == blendCache_.end()) {
D3D11_BLEND_DESC desc{};
D3D11_RENDER_TARGET_BLEND_DESC &rt = desc.RenderTarget[0];
rt.BlendEnable = keys_.blend.blendEnable;
rt.BlendOp = (D3D11_BLEND_OP)keys_.blend.blendOpColor;
rt.BlendOpAlpha = (D3D11_BLEND_OP)keys_.blend.blendOpAlpha;
rt.SrcBlend = (D3D11_BLEND)keys_.blend.srcColor;
rt.DestBlend = (D3D11_BLEND)keys_.blend.destColor;
rt.SrcBlendAlpha = (D3D11_BLEND)keys_.blend.srcAlpha;
rt.DestBlendAlpha = (D3D11_BLEND)keys_.blend.destAlpha;
rt.RenderTargetWriteMask = keys_.blend.colorWriteMask;
// TODO: Add logic op support, requires a device1_ and CreateBlendState1
device_->CreateBlendState(&desc, &bs);
blendCache_.insert(std::pair<uint64_t, ID3D11BlendState *>(keys_.blend.value, bs));
if (!device1_) {
auto blendIter = blendCache_.find(keys_.blend.value);
if (blendIter == blendCache_.end()) {
D3D11_BLEND_DESC desc{};
D3D11_RENDER_TARGET_BLEND_DESC &rt = desc.RenderTarget[0];
rt.BlendEnable = keys_.blend.blendEnable;
rt.BlendOp = (D3D11_BLEND_OP)keys_.blend.blendOpColor;
rt.BlendOpAlpha = (D3D11_BLEND_OP)keys_.blend.blendOpAlpha;
rt.SrcBlend = (D3D11_BLEND)keys_.blend.srcColor;
rt.DestBlend = (D3D11_BLEND)keys_.blend.destColor;
rt.SrcBlendAlpha = (D3D11_BLEND)keys_.blend.srcAlpha;
rt.DestBlendAlpha = (D3D11_BLEND)keys_.blend.destAlpha;
rt.RenderTargetWriteMask = keys_.blend.colorWriteMask;
device_->CreateBlendState(&desc, &bs);
blendCache_.insert(std::pair<uint64_t, ID3D11BlendState *>(keys_.blend.value, bs));
} else {
bs = blendIter->second;
}
blendState_ = bs;
} else {
bs = blendIter->second;
auto blendIter = blendCache1_.find(keys_.blend.value);
if (blendIter == blendCache1_.end()) {
D3D11_BLEND_DESC1 desc1{};
D3D11_RENDER_TARGET_BLEND_DESC1 &rt = desc1.RenderTarget[0];
rt.BlendEnable = keys_.blend.blendEnable;
rt.BlendOp = (D3D11_BLEND_OP)keys_.blend.blendOpColor;
rt.BlendOpAlpha = (D3D11_BLEND_OP)keys_.blend.blendOpAlpha;
rt.SrcBlend = (D3D11_BLEND)keys_.blend.srcColor;
rt.DestBlend = (D3D11_BLEND)keys_.blend.destColor;
rt.SrcBlendAlpha = (D3D11_BLEND)keys_.blend.srcAlpha;
rt.DestBlendAlpha = (D3D11_BLEND)keys_.blend.destAlpha;
rt.RenderTargetWriteMask = keys_.blend.colorWriteMask;
rt.LogicOpEnable = keys_.blend.logicOpEnable;
rt.LogicOp = (D3D11_LOGIC_OP)keys_.blend.logicOp;
device1_->CreateBlendState1(&desc1, &bs1);
blendCache1_.insert(std::pair<uint64_t, ID3D11BlendState1 *>(keys_.blend.value, bs1));
} else {
bs1 = blendIter->second;
}
blendState1_ = bs1;
}
blendState_ = bs;
auto depthIter = depthStencilCache_.find(keys_.depthStencil.value);
if (depthIter == depthStencilCache_.end()) {
D3D11_DEPTH_STENCIL_DESC desc{};
@ -433,6 +455,10 @@ void DrawEngineD3D11::ApplyDrawStateLate(bool applyStencilRef, uint8_t stencilRe
context_->RSSetViewports(1, &dynState_.viewport);
context_->RSSetScissorRects(1, &dynState_.scissor);
context_->RSSetState(rasterState_);
context_->OMSetBlendState(blendState_, blendColor, 0xFFFFFFFF);
if (device1_) {
context1_->OMSetBlendState(blendState1_, blendColor, 0xFFFFFFFF);
} else {
context_->OMSetBlendState(blendState_, blendColor, 0xFFFFFFFF);
}
context_->OMSetDepthStencilState(depthStencilState_, applyStencilRef ? stencilRef : dynState_.stencilRef);
}