[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.enableSampleShading = VK_FALSE;
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;
msState.sampleMask = sampleMask;
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(
const Rc<DxvkContext>& ctx,
uint32_t sampleMask) const;
UINT sampleMask) const;
private:
@ -41,6 +41,7 @@ namespace dxvk {
std::array<DxvkBlendMode, 8> m_blendModes;
DxvkMultisampleState m_msState;
DxvkLogicOpState m_loState;
static DxvkBlendMode DecodeBlendMode(
const D3D11_RENDER_TARGET_BLEND_DESC& blendDesc);

View File

@ -15,9 +15,30 @@ namespace dxvk {
m_context = m_device->createContext();
m_context->beginRecording(
m_device->createCommandList());
this->SetDefaultBlendState();
this->SetDefaultDepthStencilState();
this->SetDefaultRasterizerState();
// Create default state objects. We won't ever return them
// to the application, but we'll use them to apply state.
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,
const FLOAT BlendFactor[4],
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(
ID3D11DepthStencilState* pDepthStencilState,
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) {
m_state.rs.state = rasterizerState;
if (rasterizerState != nullptr)
rasterizerState->BindToContext(m_context);
else
this->SetDefaultRasterizerState();
if (rasterizerState == nullptr)
rasterizerState = m_defaultRasterizerState.ptr();
rasterizerState->BindToContext(m_context);
// In D3D11, the rasterizer state defines
// whether the scissor test is enabled, so
@ -1553,75 +1604,4 @@ namespace dxvk {
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<DxvkContext> m_context;
Com<D3D11BlendState> m_defaultBlendState;
Com<D3D11DepthStencilState> m_defaultDepthStencilState;
Com<D3D11RasterizerState> m_defaultRasterizerState;
D3D11ContextState m_state;
void BindConstantBuffers(
@ -572,14 +576,6 @@ namespace dxvk {
void ApplyViewportState();
void SetupIAStateObjects();
void SetDefaultBlendState();
void SetDefaultDepthStencilState();
void SetDefaultRasterizerState();
};
}

View File

@ -97,6 +97,13 @@ namespace dxvk {
struct D3D11ContextStateOM {
std::array<Com<D3D11RenderTargetView>, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> renderTargetViews;
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(
const Rc<DxvkContext>& ctx) {
const Rc<DxvkContext>& ctx) {
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(
uint32_t firstScissor,
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(
uint32_t firstViewport,
uint32_t viewportCount,

View File

@ -169,11 +169,18 @@ namespace dxvk {
VkDeviceSize dataSize,
const void* pData);
void cmdSetBlendConstants(
float blendConstants[4]);
void cmdSetScissor(
uint32_t firstScissor,
uint32_t scissorCount,
const VkRect2D* scissors);
void cmdSetStencilReference(
VkStencilFaceFlags faceMask,
uint32_t reference);
void cmdSetViewport(
uint32_t firstViewport,
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(
const DxvkInputAssemblyState& state) {
m_state.ia = state;
@ -785,6 +802,8 @@ namespace dxvk {
m_flags.clr(DxvkContextFlag::GpDirtyDynamicState);
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() {
if (m_flags.test(DxvkContextFlag::GpDirtyIndexBuffer)) {
m_flags.clr(DxvkContextFlag::GpDirtyIndexBuffer);

View File

@ -295,6 +295,26 @@ namespace dxvk {
const VkViewport* viewports,
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
* \param [in] state New state object
@ -377,6 +397,8 @@ namespace dxvk {
void updateDynamicState();
void updateViewports();
void updateBlendConstants();
void updateStencilReference();
void updateIndexBufferBinding();
void updateVertexBufferBindings();

View File

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