1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-18 20:52:10 +01:00

[d3d11] Implemented blend state and depth-stencil state binding

This commit is contained in:
Philip Rebohle 2017-12-11 14:11:18 +01:00
parent 352b46fe80
commit 50b7293b8f
11 changed files with 162 additions and 91 deletions

View File

@ -23,6 +23,11 @@ namespace dxvk {
m_msState.enableAlphaToOne = VK_FALSE; m_msState.enableAlphaToOne = VK_FALSE;
m_msState.enableSampleShading = VK_FALSE; m_msState.enableSampleShading = VK_FALSE;
m_msState.minSampleShading = 0.0f; m_msState.minSampleShading = 0.0f;
// In 11_0, there is no logic op state. Later versions
// of D3D11 however put it into the blend state object.
m_loState.enableLogicOp = VK_FALSE;
m_loState.logicOp = VK_LOGIC_OP_NO_OP;
} }
@ -64,6 +69,11 @@ namespace dxvk {
DxvkMultisampleState msState = m_msState; DxvkMultisampleState msState = m_msState;
msState.sampleMask = sampleMask; msState.sampleMask = sampleMask;
ctx->setMultisampleState(msState); ctx->setMultisampleState(msState);
// Set up logic op state as well
ctx->setLogicOpState(m_loState);
// TODO set blend factor
} }

View File

@ -32,7 +32,7 @@ namespace dxvk {
void BindToContext( void BindToContext(
const Rc<DxvkContext>& ctx, const Rc<DxvkContext>& ctx,
uint32_t sampleMask) const; UINT sampleMask) const;
private: private:
@ -41,6 +41,7 @@ namespace dxvk {
std::array<DxvkBlendMode, 8> m_blendModes; std::array<DxvkBlendMode, 8> m_blendModes;
DxvkMultisampleState m_msState; DxvkMultisampleState m_msState;
DxvkLogicOpState m_loState;
static DxvkBlendMode DecodeBlendMode( static DxvkBlendMode DecodeBlendMode(
const D3D11_RENDER_TARGET_BLEND_DESC& blendDesc); const D3D11_RENDER_TARGET_BLEND_DESC& blendDesc);

View File

@ -15,9 +15,30 @@ namespace dxvk {
m_context = m_device->createContext(); m_context = m_device->createContext();
m_context->beginRecording( m_context->beginRecording(
m_device->createCommandList()); m_device->createCommandList());
this->SetDefaultBlendState(); // Create default state objects. We won't ever return them
this->SetDefaultDepthStencilState(); // to the application, but we'll use them to apply state.
this->SetDefaultRasterizerState(); Com<ID3D11BlendState> defaultBlendState;
Com<ID3D11DepthStencilState> defaultDepthStencilState;
Com<ID3D11RasterizerState> defaultRasterizerState;
if (FAILED(m_parent->CreateBlendState (nullptr, &defaultBlendState))
|| FAILED(m_parent->CreateDepthStencilState(nullptr, &defaultDepthStencilState))
|| FAILED(m_parent->CreateRasterizerState (nullptr, &defaultRasterizerState)))
throw DxvkError("D3D11DeviceContext: Failed to create default state objects");
// Apply default state to the context. This is required
// in order to initialize the DXVK contex properly.
m_defaultBlendState = static_cast<D3D11BlendState*>(defaultBlendState.ptr());
m_defaultBlendState->BindToContext(m_context, 0xFFFFFFFF);
m_defaultDepthStencilState = static_cast<D3D11DepthStencilState*>(defaultDepthStencilState.ptr());
m_defaultDepthStencilState->BindToContext(m_context);
m_defaultRasterizerState = static_cast<D3D11RasterizerState*>(defaultRasterizerState.ptr());
m_defaultRasterizerState->BindToContext(m_context);
m_context->setBlendConstants(m_state.om.blendFactor);
m_context->setStencilReference(m_state.om.stencilRef);
} }
@ -1201,14 +1222,44 @@ namespace dxvk {
ID3D11BlendState* pBlendState, ID3D11BlendState* pBlendState,
const FLOAT BlendFactor[4], const FLOAT BlendFactor[4],
UINT SampleMask) { UINT SampleMask) {
Logger::err("D3D11DeviceContext::OMSetBlendState: Not implemented"); auto blendState = static_cast<D3D11BlendState*>(pBlendState);
if (m_state.om.cbState != blendState
|| m_state.om.sampleMask != SampleMask) {
m_state.om.cbState = blendState;
m_state.om.sampleMask = SampleMask;
if (blendState == nullptr)
blendState = m_defaultBlendState.ptr();
blendState->BindToContext(m_context, SampleMask);
}
if ((BlendFactor != nullptr) && (!std::memcmp(m_state.om.blendFactor, BlendFactor, 4 * sizeof(FLOAT)))) {
std::memcpy(m_state.om.blendFactor, BlendFactor, 4 * sizeof(FLOAT));
m_context->setBlendConstants(BlendFactor);
}
} }
void D3D11DeviceContext::OMSetDepthStencilState( void D3D11DeviceContext::OMSetDepthStencilState(
ID3D11DepthStencilState* pDepthStencilState, ID3D11DepthStencilState* pDepthStencilState,
UINT StencilRef) { UINT StencilRef) {
Logger::err("D3D11DeviceContext::OMSetDepthStencilState: Not implemented"); auto depthStencilState = static_cast<D3D11DepthStencilState*>(pDepthStencilState);
if (m_state.om.dsState != depthStencilState) {
m_state.om.dsState = depthStencilState;
if (depthStencilState == nullptr)
depthStencilState = m_defaultDepthStencilState.ptr();
depthStencilState->BindToContext(m_context);
}
if (m_state.om.stencilRef != StencilRef) {
m_state.om.stencilRef = StencilRef;
m_context->setStencilReference(StencilRef);
}
} }
@ -1262,10 +1313,10 @@ namespace dxvk {
if (m_state.rs.state != rasterizerState) { if (m_state.rs.state != rasterizerState) {
m_state.rs.state = rasterizerState; m_state.rs.state = rasterizerState;
if (rasterizerState != nullptr) if (rasterizerState == nullptr)
rasterizerState->BindToContext(m_context); rasterizerState = m_defaultRasterizerState.ptr();
else
this->SetDefaultRasterizerState(); rasterizerState->BindToContext(m_context);
// In D3D11, the rasterizer state defines // In D3D11, the rasterizer state defines
// whether the scissor test is enabled, so // whether the scissor test is enabled, so
@ -1553,75 +1604,4 @@ namespace dxvk {
scissors.data()); scissors.data());
} }
void D3D11DeviceContext::SetDefaultBlendState() {
DxvkMultisampleState msState;
msState.sampleMask = 0xffffffff;
msState.enableAlphaToCoverage = VK_FALSE;
msState.enableAlphaToOne = VK_FALSE;
msState.enableSampleShading = VK_FALSE;
msState.minSampleShading = 0.0f;
m_context->setMultisampleState(msState);
DxvkLogicOpState loState;
loState.enableLogicOp = VK_FALSE;
loState.logicOp = VK_LOGIC_OP_CLEAR;
m_context->setLogicOpState(loState);
DxvkBlendMode blendMode;
blendMode.enableBlending = VK_FALSE;
blendMode.colorSrcFactor = VK_BLEND_FACTOR_ONE;
blendMode.colorDstFactor = VK_BLEND_FACTOR_ZERO;
blendMode.colorBlendOp = VK_BLEND_OP_ADD;
blendMode.alphaSrcFactor = VK_BLEND_FACTOR_ONE;
blendMode.alphaDstFactor = VK_BLEND_FACTOR_ZERO;
blendMode.alphaBlendOp = VK_BLEND_OP_ADD;
blendMode.writeMask = VK_COLOR_COMPONENT_R_BIT
| VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT
| VK_COLOR_COMPONENT_A_BIT;
for (uint32_t i = 0; i < DxvkLimits::MaxNumRenderTargets; i++)
m_context->setBlendMode(i, blendMode);
}
void D3D11DeviceContext::SetDefaultDepthStencilState() {
VkStencilOpState stencilOp;
stencilOp.failOp = VK_STENCIL_OP_KEEP;
stencilOp.passOp = VK_STENCIL_OP_KEEP;
stencilOp.depthFailOp = VK_STENCIL_OP_KEEP;
stencilOp.compareOp = VK_COMPARE_OP_ALWAYS;
stencilOp.compareMask = D3D11_DEFAULT_STENCIL_READ_MASK;
stencilOp.writeMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
stencilOp.reference = 0;
DxvkDepthStencilState dsState;
dsState.enableDepthTest = VK_TRUE;
dsState.enableDepthWrite = VK_TRUE;
dsState.enableDepthBounds = VK_FALSE;
dsState.enableStencilTest = VK_FALSE;
dsState.depthCompareOp = VK_COMPARE_OP_LESS;
dsState.stencilOpFront = stencilOp;
dsState.stencilOpBack = stencilOp;
dsState.depthBoundsMin = 0.0f;
dsState.depthBoundsMax = 1.0f;
m_context->setDepthStencilState(dsState);
}
void D3D11DeviceContext::SetDefaultRasterizerState() {
DxvkRasterizerState rsState;
rsState.enableDepthClamp = VK_FALSE;
rsState.enableDiscard = VK_FALSE;
rsState.polygonMode = VK_POLYGON_MODE_FILL;
rsState.cullMode = VK_CULL_MODE_BACK_BIT;
rsState.frontFace = VK_FRONT_FACE_CLOCKWISE;
rsState.depthBiasEnable = VK_FALSE;
rsState.depthBiasConstant = 0.0f;
rsState.depthBiasClamp = 0.0f;
rsState.depthBiasSlope = 0.0f;
m_context->setRasterizerState(rsState);
}
} }

View File

@ -547,6 +547,10 @@ namespace dxvk {
Rc<DxvkDevice> m_device; Rc<DxvkDevice> m_device;
Rc<DxvkContext> m_context; Rc<DxvkContext> m_context;
Com<D3D11BlendState> m_defaultBlendState;
Com<D3D11DepthStencilState> m_defaultDepthStencilState;
Com<D3D11RasterizerState> m_defaultRasterizerState;
D3D11ContextState m_state; D3D11ContextState m_state;
void BindConstantBuffers( void BindConstantBuffers(
@ -572,14 +576,6 @@ namespace dxvk {
void ApplyViewportState(); void ApplyViewportState();
void SetupIAStateObjects();
void SetDefaultBlendState();
void SetDefaultDepthStencilState();
void SetDefaultRasterizerState();
}; };
} }

View File

@ -97,6 +97,13 @@ namespace dxvk {
struct D3D11ContextStateOM { struct D3D11ContextStateOM {
std::array<Com<D3D11RenderTargetView>, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> renderTargetViews; std::array<Com<D3D11RenderTargetView>, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> renderTargetViews;
Com<D3D11DepthStencilView> depthStencilView; Com<D3D11DepthStencilView> depthStencilView;
Com<D3D11BlendState> cbState = nullptr;
Com<D3D11DepthStencilState> dsState = nullptr;
FLOAT blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
UINT sampleMask = 0xFFFFFFFFu;
UINT stencilRef = 0u;
}; };

View File

@ -48,7 +48,7 @@ namespace dxvk {
void D3D11DepthStencilState::BindToContext( void D3D11DepthStencilState::BindToContext(
const Rc<DxvkContext>& ctx) { const Rc<DxvkContext>& ctx) {
ctx->setDepthStencilState(m_state); ctx->setDepthStencilState(m_state);
} }

View File

@ -284,6 +284,12 @@ namespace dxvk {
} }
void DxvkCommandList::cmdSetBlendConstants(
float blendConstants[4]) {
m_vkd->vkCmdSetBlendConstants(m_buffer, blendConstants);
}
void DxvkCommandList::cmdSetScissor( void DxvkCommandList::cmdSetScissor(
uint32_t firstScissor, uint32_t firstScissor,
uint32_t scissorCount, uint32_t scissorCount,
@ -293,6 +299,14 @@ namespace dxvk {
} }
void DxvkCommandList::cmdSetStencilReference(
VkStencilFaceFlags faceMask,
uint32_t reference) {
m_vkd->vkCmdSetStencilReference(m_buffer,
faceMask, reference);
}
void DxvkCommandList::cmdSetViewport( void DxvkCommandList::cmdSetViewport(
uint32_t firstViewport, uint32_t firstViewport,
uint32_t viewportCount, uint32_t viewportCount,

View File

@ -169,11 +169,18 @@ namespace dxvk {
VkDeviceSize dataSize, VkDeviceSize dataSize,
const void* pData); const void* pData);
void cmdSetBlendConstants(
float blendConstants[4]);
void cmdSetScissor( void cmdSetScissor(
uint32_t firstScissor, uint32_t firstScissor,
uint32_t scissorCount, uint32_t scissorCount,
const VkRect2D* scissors); const VkRect2D* scissors);
void cmdSetStencilReference(
VkStencilFaceFlags faceMask,
uint32_t reference);
void cmdSetViewport( void cmdSetViewport(
uint32_t firstViewport, uint32_t firstViewport,
uint32_t viewportCount, uint32_t viewportCount,

View File

@ -538,6 +538,23 @@ namespace dxvk {
} }
void DxvkContext::setBlendConstants(
const float blendConstants[4]) {
for (uint32_t i = 0; i < 4; i++)
m_state.om.blendConstants[i] = blendConstants[i];
this->updateBlendConstants();
}
void DxvkContext::setStencilReference(
const uint32_t reference) {
m_state.om.stencilReference = reference;
this->updateStencilReference();
}
void DxvkContext::setInputAssemblyState( void DxvkContext::setInputAssemblyState(
const DxvkInputAssemblyState& state) { const DxvkInputAssemblyState& state) {
m_state.ia = state; m_state.ia = state;
@ -785,6 +802,8 @@ namespace dxvk {
m_flags.clr(DxvkContextFlag::GpDirtyDynamicState); m_flags.clr(DxvkContextFlag::GpDirtyDynamicState);
this->updateViewports(); this->updateViewports();
this->updateBlendConstants();
this->updateStencilReference();
} }
} }
@ -795,6 +814,18 @@ namespace dxvk {
} }
void DxvkContext::updateBlendConstants() {
m_cmd->cmdSetBlendConstants(m_state.om.blendConstants);
}
void DxvkContext::updateStencilReference() {
m_cmd->cmdSetStencilReference(
VK_STENCIL_FRONT_AND_BACK,
m_state.om.stencilReference);
}
void DxvkContext::updateIndexBufferBinding() { void DxvkContext::updateIndexBufferBinding() {
if (m_flags.test(DxvkContextFlag::GpDirtyIndexBuffer)) { if (m_flags.test(DxvkContextFlag::GpDirtyIndexBuffer)) {
m_flags.clr(DxvkContextFlag::GpDirtyIndexBuffer); m_flags.clr(DxvkContextFlag::GpDirtyIndexBuffer);

View File

@ -295,6 +295,26 @@ namespace dxvk {
const VkViewport* viewports, const VkViewport* viewports,
const VkRect2D* scissorRects); const VkRect2D* scissorRects);
/**
* \brief Sets blend constants
*
* Blend constants are a set of four floating
* point numbers that may be used as an input
* for blending operations.
* \param [in] blendConstants Blend constants
*/
void setBlendConstants(
const float blendConstants[4]);
/**
* \brief Sets stencil reference
*
* Sets the reference value for stencil compare operations.
* \param [in] reference Reference value
*/
void setStencilReference(
const uint32_t reference);
/** /**
* \brief Sets input assembly state * \brief Sets input assembly state
* \param [in] state New state object * \param [in] state New state object
@ -377,6 +397,8 @@ namespace dxvk {
void updateDynamicState(); void updateDynamicState();
void updateViewports(); void updateViewports();
void updateBlendConstants();
void updateStencilReference();
void updateIndexBufferBinding(); void updateIndexBufferBinding();
void updateVertexBufferBindings(); void updateVertexBufferBindings();

View File

@ -57,7 +57,10 @@ namespace dxvk {
struct DxvkOutputMergerState { struct DxvkOutputMergerState {
Rc<DxvkFramebuffer> framebuffer; Rc<DxvkFramebuffer> framebuffer;
std::array<DxvkBlendMode, DxvkLimits::MaxNumRenderTargets> blendModes; std::array<DxvkBlendMode,
DxvkLimits::MaxNumRenderTargets> blendModes;
float blendConstants[4];
uint32_t stencilReference;
}; };