1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-02 01:24:11 +01:00
This commit is contained in:
Philip Rebohle 2018-04-30 15:56:32 +02:00
commit 16a25db846
7 changed files with 286 additions and 26 deletions

View File

@ -148,8 +148,63 @@ namespace dxvk {
HRESULT D3D11BlendState::NormalizeDesc(D3D11_BLEND_DESC1* pDesc) {
// TODO validate
// TODO clear unused values
const D3D11_BLEND_DESC1 defaultDesc = DefaultDesc();
if (pDesc->AlphaToCoverageEnable)
pDesc->AlphaToCoverageEnable = TRUE;
if (pDesc->IndependentBlendEnable)
pDesc->IndependentBlendEnable = TRUE;
const uint32_t numRenderTargets = pDesc->IndependentBlendEnable ? 8 : 1;
for (uint32_t i = 0; i < numRenderTargets; i++) {
D3D11_RENDER_TARGET_BLEND_DESC1* rt = &pDesc->RenderTarget[i];
if (rt->BlendEnable) {
rt->BlendEnable = TRUE;
if (rt->LogicOpEnable)
return E_INVALIDARG;
if (!ValidateBlendOperations(
rt->SrcBlend, rt->SrcBlendAlpha,
rt->DestBlend, rt->DestBlendAlpha,
rt->BlendOp, rt->BlendOpAlpha))
return E_INVALIDARG;
} else {
rt->SrcBlend = defaultDesc.RenderTarget[0].SrcBlend;
rt->DestBlend = defaultDesc.RenderTarget[0].DestBlend;
rt->BlendOp = defaultDesc.RenderTarget[0].BlendOp;
rt->SrcBlendAlpha = defaultDesc.RenderTarget[0].SrcBlendAlpha;
rt->DestBlendAlpha = defaultDesc.RenderTarget[0].DestBlendAlpha;
rt->BlendOpAlpha = defaultDesc.RenderTarget[0].BlendOpAlpha;
}
if (rt->LogicOpEnable) {
rt->LogicOpEnable = TRUE;
// Blending must be disabled
// if the logic op is enabled
if (rt->BlendEnable
|| pDesc->IndependentBlendEnable
|| !ValidateLogicOp(rt->LogicOp))
return E_INVALIDARG;
} else {
rt->LogicOp = defaultDesc.RenderTarget[0].LogicOp;
}
if (rt->RenderTargetWriteMask > D3D11_COLOR_WRITE_ENABLE_ALL)
return E_INVALIDARG;
}
for (uint32_t i = numRenderTargets; i < 8; i++) {
// Render targets blend operations are the same
// across all render targets when blend is enabled
// on rendertarget[0] with independent blend disabled
pDesc->RenderTarget[i] = pDesc->RenderTarget[0];
}
return S_OK;
}
@ -188,11 +243,8 @@ namespace dxvk {
case D3D11_BLEND_INV_SRC1_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
case D3D11_BLEND_SRC1_ALPHA: return VK_BLEND_FACTOR_SRC1_ALPHA;
case D3D11_BLEND_INV_SRC1_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
default: return VK_BLEND_FACTOR_ZERO;
}
if (BlendFactor != 0) // prevent log spamming when apps use ZeroMemory
Logger::err(str::format("D3D11: Invalid blend factor: ", BlendFactor));
return VK_BLEND_FACTOR_ZERO;
}
@ -203,11 +255,8 @@ namespace dxvk {
case D3D11_BLEND_OP_REV_SUBTRACT: return VK_BLEND_OP_REVERSE_SUBTRACT;
case D3D11_BLEND_OP_MIN: return VK_BLEND_OP_MIN;
case D3D11_BLEND_OP_MAX: return VK_BLEND_OP_MAX;
default: return VK_BLEND_OP_ADD;
}
if (BlendOp != 0) // prevent log spamming when apps use ZeroMemory
Logger::err(str::format("D3D11: Invalid blend op: ", BlendOp));
return VK_BLEND_OP_ADD;
}
@ -229,11 +278,54 @@ namespace dxvk {
case D3D11_LOGIC_OP_AND_INVERTED: return VK_LOGIC_OP_AND_INVERTED;
case D3D11_LOGIC_OP_OR_REVERSE: return VK_LOGIC_OP_OR_REVERSE;
case D3D11_LOGIC_OP_OR_INVERTED: return VK_LOGIC_OP_OR_INVERTED;
default: return VK_LOGIC_OP_NO_OP;
}
if (LogicOp != 0)
Logger::err(str::format("D3D11: Invalid logic op: ", LogicOp));
return VK_LOGIC_OP_NO_OP;
}
bool D3D11BlendState::ValidateBlendFactor(D3D11_BLEND Blend) {
return Blend >= D3D11_BLEND_ZERO
&& Blend <= D3D11_BLEND_INV_SRC1_ALPHA;
}
bool D3D11BlendState::ValidateBlendFactorAlpha(D3D11_BLEND BlendAlpha) {
return BlendAlpha >= D3D11_BLEND_ZERO
&& BlendAlpha <= D3D11_BLEND_INV_SRC1_ALPHA
&& BlendAlpha != D3D11_BLEND_SRC_COLOR
&& BlendAlpha != D3D11_BLEND_INV_SRC_COLOR
&& BlendAlpha != D3D11_BLEND_DEST_COLOR
&& BlendAlpha != D3D11_BLEND_INV_DEST_COLOR
&& BlendAlpha != D3D11_BLEND_SRC1_COLOR
&& BlendAlpha != D3D11_BLEND_INV_SRC1_COLOR;
}
bool D3D11BlendState::ValidateBlendOp(D3D11_BLEND_OP BlendOp) {
return BlendOp >= D3D11_BLEND_OP_ADD
&& BlendOp <= D3D11_BLEND_OP_MAX;
}
bool D3D11BlendState::ValidateLogicOp(D3D11_LOGIC_OP LogicOp) {
return LogicOp >= D3D11_LOGIC_OP_CLEAR
&& LogicOp <= D3D11_LOGIC_OP_OR_INVERTED;
}
bool D3D11BlendState::ValidateBlendOperations(
D3D11_BLEND SrcBlend,
D3D11_BLEND SrcBlendAlpha,
D3D11_BLEND DestBlend,
D3D11_BLEND DestBlendAlpha,
D3D11_BLEND_OP BlendOp,
D3D11_BLEND_OP BlendOpAlpha) {
return ValidateBlendOp(BlendOp)
&& ValidateBlendOp(BlendOpAlpha)
&& ValidateBlendFactor(SrcBlend)
&& ValidateBlendFactor(DestBlend)
&& ValidateBlendFactorAlpha(SrcBlendAlpha)
&& ValidateBlendFactorAlpha(DestBlendAlpha);
}
}

View File

@ -44,6 +44,8 @@ namespace dxvk {
static HRESULT NormalizeDesc(
D3D11_BLEND_DESC1* pDesc);
private:
@ -66,7 +68,26 @@ namespace dxvk {
static VkLogicOp DecodeLogicOp(
D3D11_LOGIC_OP LogicOp);
static bool ValidateBlendFactor(
D3D11_BLEND Blend);
static bool ValidateBlendFactorAlpha(
D3D11_BLEND BlendAlpha);
static bool ValidateBlendOp(
D3D11_BLEND_OP BlendOp);
static bool ValidateLogicOp(
D3D11_LOGIC_OP LogicOp);
static bool ValidateBlendOperations(
D3D11_BLEND SrcBlend,
D3D11_BLEND SrcBlendAlpha,
D3D11_BLEND SestBlend,
D3D11_BLEND DestBlendAlpha,
D3D11_BLEND_OP BlendOp,
D3D11_BLEND_OP BlendOpAlpha);
};
}

View File

@ -50,8 +50,7 @@ namespace dxvk {
}
void D3D11DepthStencilState::BindToContext(
const Rc<DxvkContext>& ctx) {
void D3D11DepthStencilState::BindToContext(const Rc<DxvkContext>& ctx) {
ctx->setDepthStencilState(m_state);
}
@ -77,8 +76,42 @@ namespace dxvk {
HRESULT D3D11DepthStencilState::NormalizeDesc(D3D11_DEPTH_STENCIL_DESC* pDesc) {
// TODO validate
// TODO clear unused values
const D3D11_DEPTH_STENCIL_DESC defaultDesc = DefaultDesc();
if (pDesc->DepthEnable) {
pDesc->DepthEnable = TRUE;
if (!ValidateDepthFunc(pDesc->DepthFunc))
return E_INVALIDARG;
} else {
pDesc->DepthFunc = defaultDesc.DepthFunc;
pDesc->DepthWriteMask = defaultDesc.DepthWriteMask;
}
if (!ValidateDepthWriteMask(pDesc->DepthWriteMask))
return E_INVALIDARG;
if (pDesc->StencilEnable) {
pDesc->StencilEnable = TRUE;
if (!ValidateStencilFunc(pDesc->FrontFace.StencilFunc)
|| !ValidateStencilOp(pDesc->FrontFace.StencilFailOp)
|| !ValidateStencilOp(pDesc->FrontFace.StencilDepthFailOp)
|| !ValidateStencilOp(pDesc->FrontFace.StencilPassOp))
return E_INVALIDARG;
if (!ValidateStencilFunc(pDesc->BackFace.StencilFunc)
|| !ValidateStencilOp(pDesc->BackFace.StencilFailOp)
|| !ValidateStencilOp(pDesc->BackFace.StencilDepthFailOp)
|| !ValidateStencilOp(pDesc->BackFace.StencilPassOp))
return E_INVALIDARG;
} else {
pDesc->FrontFace = defaultDesc.FrontFace;
pDesc->BackFace = defaultDesc.BackFace;
pDesc->StencilReadMask = defaultDesc.StencilReadMask;
pDesc->StencilWriteMask = defaultDesc.StencilWriteMask;
}
return S_OK;
}
@ -116,11 +149,32 @@ namespace dxvk {
case D3D11_STENCIL_OP_INVERT: return VK_STENCIL_OP_INVERT;
case D3D11_STENCIL_OP_INCR: return VK_STENCIL_OP_INCREMENT_AND_WRAP;
case D3D11_STENCIL_OP_DECR: return VK_STENCIL_OP_DECREMENT_AND_WRAP;
default: return VK_STENCIL_OP_KEEP;
}
if (Op != 0)
Logger::err(str::format("D3D11: Invalid stencil op: ", Op));
return VK_STENCIL_OP_KEEP;
}
bool D3D11DepthStencilState::ValidateDepthFunc(D3D11_COMPARISON_FUNC Comparison) {
return Comparison >= D3D11_COMPARISON_NEVER
&& Comparison <= D3D11_COMPARISON_ALWAYS;
}
bool D3D11DepthStencilState::ValidateStencilFunc(D3D11_COMPARISON_FUNC Comparison) {
return Comparison >= D3D11_COMPARISON_NEVER
&& Comparison <= D3D11_COMPARISON_ALWAYS;
}
bool D3D11DepthStencilState::ValidateStencilOp(D3D11_STENCIL_OP StencilOp) {
return StencilOp >= D3D11_STENCIL_OP_KEEP
&& StencilOp <= D3D11_STENCIL_OP_DECR;
}
bool D3D11DepthStencilState::ValidateDepthWriteMask(D3D11_DEPTH_WRITE_MASK Mask) {
return Mask == D3D11_DEPTH_WRITE_MASK_ZERO
|| Mask == D3D11_DEPTH_WRITE_MASK_ALL;
}
}

View File

@ -37,6 +37,8 @@ namespace dxvk {
static HRESULT NormalizeDesc(
D3D11_DEPTH_STENCIL_DESC* pDesc);
private:
@ -51,6 +53,17 @@ namespace dxvk {
VkStencilOp DecodeStencilOp(
D3D11_STENCIL_OP Op) const;
static bool ValidateDepthFunc(
D3D11_COMPARISON_FUNC Comparison);
static bool ValidateStencilFunc(
D3D11_COMPARISON_FUNC Comparison);
static bool ValidateStencilOp(
D3D11_STENCIL_OP StencilOp);
static bool ValidateDepthWriteMask(
D3D11_DEPTH_WRITE_MASK Mask);
};
}

View File

@ -9,7 +9,7 @@ namespace dxvk {
: m_device(device), m_desc(desc) {
// State that is not supported in D3D11
m_state.enableDiscard = VK_FALSE;
m_state.enableDiscard = VK_FALSE;
// Polygon mode. Determines whether the rasterizer fills
// a polygon or renders lines connecting the vertices.
@ -151,7 +151,34 @@ namespace dxvk {
HRESULT D3D11RasterizerState::NormalizeDesc(
D3D11_RASTERIZER_DESC1* pDesc) {
// TODO validate
if (pDesc->FillMode < D3D11_FILL_WIREFRAME
|| pDesc->FillMode > D3D11_FILL_SOLID)
return E_INVALIDARG;
if (pDesc->CullMode < D3D11_CULL_NONE
|| pDesc->CullMode > D3D11_CULL_BACK)
return E_INVALIDARG;
if (pDesc->FrontCounterClockwise)
pDesc->FrontCounterClockwise = TRUE;
if (pDesc->DepthClipEnable)
pDesc->DepthClipEnable = TRUE;
if (pDesc->ScissorEnable)
pDesc->ScissorEnable = TRUE;
if (pDesc->MultisampleEnable)
pDesc->MultisampleEnable = TRUE;
if (pDesc->AntialiasedLineEnable)
pDesc->AntialiasedLineEnable = TRUE;
if (pDesc->ForcedSampleCount != 0) {
if (FAILED(DecodeSampleCount(pDesc->ForcedSampleCount, nullptr)))
return E_INVALIDARG;
}
return S_OK;
}

View File

@ -82,11 +82,58 @@ namespace dxvk {
const uint32_t filterBits = static_cast<uint32_t>(pDesc->Filter);
if (filterBits & 0xFFFFFF2A) {
Logger::err(str::format("D3D11SamplerState: Unhandled filter: ", filterBits));
Logger::err(str::format(
"D3D11SamplerState: Unhandled filter: ", filterBits));
return E_INVALIDARG;
}
if (filterBits & 0x40 /* anisotropic */) {
if (pDesc->MaxAnisotropy < 1
|| pDesc->MaxAnisotropy > 16)
return E_INVALIDARG;
} else if (pDesc->MaxAnisotropy < 0
|| pDesc->MaxAnisotropy > 16) {
return E_INVALIDARG;
} else {
// Reset anisotropy if it is not used
pDesc->MaxAnisotropy = 0;
}
if (filterBits & 0x80 /* compare-to-depth */) {
if (!ValidateComparisonFunc(pDesc->ComparisonFunc))
return E_INVALIDARG;
} else {
// Reset compare func if it is not used
pDesc->ComparisonFunc = D3D11_COMPARISON_NEVER;
}
if (!ValidateAddressMode(pDesc->AddressU)
|| !ValidateAddressMode(pDesc->AddressV)
|| !ValidateAddressMode(pDesc->AddressW))
return E_INVALIDARG;
// Clear BorderColor to 0 if none of the address
// modes are D3D11_TEXTURE_ADDRESS_BORDER
if (pDesc->AddressU != D3D11_TEXTURE_ADDRESS_BORDER
&& pDesc->AddressV != D3D11_TEXTURE_ADDRESS_BORDER
&& pDesc->AddressW != D3D11_TEXTURE_ADDRESS_BORDER) {
for (int i = 0; i < 4; i++)
pDesc->BorderColor[i] = 0.0f;
}
return S_OK;
}
bool D3D11SamplerState::ValidateAddressMode(D3D11_TEXTURE_ADDRESS_MODE Mode) {
return Mode >= D3D11_TEXTURE_ADDRESS_WRAP
&& Mode <= D3D11_TEXTURE_ADDRESS_MIRROR_ONCE;
}
bool D3D11SamplerState::ValidateComparisonFunc(D3D11_COMPARISON_FUNC Comparison) {
return Comparison >= D3D11_COMPARISON_NEVER
&& Comparison <= D3D11_COMPARISON_ALWAYS;
}
}

View File

@ -41,6 +41,12 @@ namespace dxvk {
D3D11Device* const m_device;
D3D11_SAMPLER_DESC m_desc;
Rc<DxvkSampler> m_sampler;
static bool ValidateAddressMode(
D3D11_TEXTURE_ADDRESS_MODE Mode);
static bool ValidateComparisonFunc(
D3D11_COMPARISON_FUNC Comparison);
};