Commit 95f6cedd by Shahmeer Esmail Committed by Commit Bot

RenderstateCache and Clear11 Optimizations

- Unify DepthStencilState and BlendState caches in RenderStateCache with those in Clear11. This will increase cache hit rate and reduce memory usage. - Apply DepthStencilState and BlendState only when required to reduce state sets. BUG=angleproject:1632 Change-Id: I244e3ba189f82814638fa90e2617aa5441024d0f Reviewed-on: https://chromium-review.googlesource.com/453888 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent d0fcb90d
...@@ -99,11 +99,9 @@ Clear11::ClearShader::~ClearShader() ...@@ -99,11 +99,9 @@ Clear11::ClearShader::~ClearShader()
Clear11::Clear11(Renderer11 *renderer) Clear11::Clear11(Renderer11 *renderer)
: mRenderer(renderer), : mRenderer(renderer),
mClearBlendStates(StructLessThan<ClearBlendInfo>),
mFloatClearShader(nullptr), mFloatClearShader(nullptr),
mUintClearShader(nullptr), mUintClearShader(nullptr),
mIntClearShader(nullptr), mIntClearShader(nullptr),
mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>),
mVertexBuffer(nullptr), mVertexBuffer(nullptr),
mRasterizerState(nullptr) mRasterizerState(nullptr)
{ {
...@@ -166,28 +164,44 @@ Clear11::Clear11(Renderer11 *renderer) ...@@ -166,28 +164,44 @@ Clear11::Clear11(Renderer11 *renderer)
ArraySize(g_VS_ClearSint), "Clear11 SINT VS", g_PS_ClearSint, ArraySize(g_VS_ClearSint), "Clear11 SINT VS", g_PS_ClearSint,
ArraySize(g_PS_ClearSint), "Clear11 SINT PS"); ArraySize(g_PS_ClearSint), "Clear11 SINT PS");
} }
// Initialize DepthstencilStateKey with defaults
mDepthStencilStateKey.depthTest = false;
mDepthStencilStateKey.depthMask = false;
mDepthStencilStateKey.depthFunc = GL_ALWAYS;
mDepthStencilStateKey.stencilWritemask = static_cast<GLuint>(-1);
mDepthStencilStateKey.stencilBackWritemask = static_cast<GLuint>(-1);
mDepthStencilStateKey.stencilBackMask = static_cast<GLuint>(-1);
mDepthStencilStateKey.stencilTest = false;
mDepthStencilStateKey.stencilMask = static_cast<GLuint>(-1);
mDepthStencilStateKey.stencilFail = GL_REPLACE;
mDepthStencilStateKey.stencilPassDepthFail = GL_REPLACE;
mDepthStencilStateKey.stencilPassDepthPass = GL_REPLACE;
mDepthStencilStateKey.stencilFunc = GL_ALWAYS;
mDepthStencilStateKey.stencilBackFail = GL_REPLACE;
mDepthStencilStateKey.stencilBackPassDepthFail = GL_REPLACE;
mDepthStencilStateKey.stencilBackPassDepthPass = GL_REPLACE;
mDepthStencilStateKey.stencilBackFunc = GL_ALWAYS;
// Initialize BlendStateKey with defaults
mBlendStateKey.blendState.blend = false;
mBlendStateKey.blendState.sourceBlendRGB = GL_ONE;
mBlendStateKey.blendState.sourceBlendAlpha = GL_ONE;
mBlendStateKey.blendState.destBlendRGB = GL_ZERO;
mBlendStateKey.blendState.destBlendAlpha = GL_ZERO;
mBlendStateKey.blendState.blendEquationRGB = GL_FUNC_ADD;
mBlendStateKey.blendState.blendEquationAlpha = GL_FUNC_ADD;
mBlendStateKey.blendState.sampleAlphaToCoverage = false;
mBlendStateKey.blendState.dither = true;
mBlendStateKey.mrt = false;
memset(mBlendStateKey.rtvMasks, 0, sizeof(mBlendStateKey.rtvMasks));
} }
Clear11::~Clear11() Clear11::~Clear11()
{ {
for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end();
i++)
{
SafeRelease(i->second);
}
mClearBlendStates.clear();
SafeDelete(mFloatClearShader); SafeDelete(mFloatClearShader);
SafeDelete(mUintClearShader); SafeDelete(mUintClearShader);
SafeDelete(mIntClearShader); SafeDelete(mIntClearShader);
for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin();
i != mClearDepthStencilStates.end(); i++)
{
SafeRelease(i->second);
}
mClearDepthStencilStates.clear();
SafeRelease(mVertexBuffer); SafeRelease(mVertexBuffer);
SafeRelease(mRasterizerState); SafeRelease(mRasterizerState);
} }
...@@ -206,8 +220,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -206,8 +220,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
// cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView. // cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView.
// This requires: // This requires:
// 1) The render target is being cleared to a float value (will be cast to integer when clearing // 1) The render target is being cleared to a float value (will be cast to integer when clearing
// integer // integer render targets as expected but does not work the other way around)
// render targets as expected but does not work the other way around)
// 2) The format of the render target has no color channels that are currently masked out. // 2) The format of the render target has no color channels that are currently masked out.
// Clear the easy-to-clear buffers on the spot and accumulate the ones that require special // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special
// work. // work.
...@@ -261,13 +274,18 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -261,13 +274,18 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width ||
clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height);
std::vector<MaskedRenderTarget> maskedClearRenderTargets;
RenderTarget11 *maskedClearDepthStencil = nullptr;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
ID3D11Device *device = mRenderer->getDevice(); ID3D11Device *device = mRenderer->getDevice();
std::array<ID3D11RenderTargetView *, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvs;
std::array<uint8_t, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvMasks;
ID3D11DepthStencilView *dsv = nullptr;
uint32_t numRtvs = 0;
const uint8_t colorMask =
gl_d3d11::ConvertColorMask(clearParams.colorMaskRed, clearParams.colorMaskGreen,
clearParams.colorMaskBlue, clearParams.colorMaskAlpha);
for (size_t colorAttachmentIndex = 0; colorAttachmentIndex < colorAttachments.size(); for (size_t colorAttachmentIndex = 0; colorAttachmentIndex < colorAttachments.size();
colorAttachmentIndex++) colorAttachmentIndex++)
{ {
...@@ -301,37 +319,30 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -301,37 +319,30 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
// Every channel either does not exist in the render target or is masked out // Every channel either does not exist in the render target or is masked out
continue; continue;
} }
else if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) &&
needScissoredClear) || ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
clearParams.colorClearType != GL_FLOAT || if (!framebufferRTV)
(formatInfo.redBits > 0 && !clearParams.colorMaskRed) || {
(formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || return gl::OutOfMemory()
(formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || << "Clear11: Render target view pointer unexpectedly null.";
(formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) }
if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) && needScissoredClear) ||
clearParams.colorClearType != GL_FLOAT ||
(formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
(formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
(formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
(formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
{ {
// A masked clear is required, or a scissored clear is required and rtvs[numRtvs] = framebufferRTV;
// ID3D11DeviceContext1::ClearView is unavailable rtvMasks[numRtvs] = gl_d3d11::GetColorMask(&formatInfo) & colorMask;
MaskedRenderTarget maskAndRt; numRtvs++;
bool clearColor = clearParams.clearColor[colorAttachmentIndex];
maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed);
maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen);
maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue);
maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha);
maskAndRt.renderTarget = renderTarget;
maskedClearRenderTargets.push_back(maskAndRt);
} }
else else
{ {
// ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is
// possible // possible
ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
if (!framebufferRTV)
{
return gl::Error(GL_OUT_OF_MEMORY,
"Internal render target view pointer unexpectedly null.");
}
const auto &nativeFormat = renderTarget->getFormatSet().format(); const auto &nativeFormat = renderTarget->getFormatSet().format();
// Check if the actual format has a channel that the internal format does not and // Check if the actual format has a channel that the internal format does not and
...@@ -411,30 +422,27 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -411,30 +422,27 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
clearParams.clearStencil && clearParams.clearStencil &&
(clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
if (needScissoredClear || needMaskedStencilClear) dsv = renderTarget->getDepthStencilView();
if (!dsv)
{ {
maskedClearDepthStencil = renderTarget; return gl::OutOfMemory() << "Clear11: Depth stencil view pointer unexpectedly null.";
} }
else
{
ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
if (!framebufferDSV)
{
return gl::Error(GL_OUT_OF_MEMORY,
"Internal depth stencil view pointer unexpectedly null.");
}
if (!needScissoredClear && !needMaskedStencilClear)
{
UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) |
(clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0);
FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); FLOAT depthClear = gl::clamp01(clearParams.depthClearValue);
UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; UINT8 stencilClear = clearParams.stencilClearValue & 0xFF;
deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, deviceContext->ClearDepthStencilView(dsv, clearFlags, depthClear, stencilClear);
stencilClear);
dsv = nullptr;
} }
} }
if (maskedClearRenderTargets.empty() && !maskedClearDepthStencil) if (numRtvs == 0 && !dsv)
{ {
return gl::NoError(); return gl::NoError();
} }
...@@ -462,30 +470,42 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -462,30 +470,42 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
// glClearBuffer* calls only clear a single renderbuffer at a time which is verified to // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to
// be a compatible clear type. // be a compatible clear type.
// Bind all the render targets which need clearing ASSERT(numRtvs <= mRenderer->getNativeCaps().maxDrawBuffers);
ASSERT(maskedClearRenderTargets.size() <= mRenderer->getNativeCaps().maxDrawBuffers);
std::vector<ID3D11RenderTargetView *> rtvs(maskedClearRenderTargets.size());
for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++)
{
RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget;
ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView();
if (!rtv)
{
return gl::Error(GL_OUT_OF_MEMORY,
"Internal render target view pointer unexpectedly null.");
}
rtvs[i] = rtv; const UINT sampleMask = 0xFFFFFFFF;
const float blendFactors[4] = {1.0f, 1.0f, 1.0f, 1.0f};
ID3D11BlendState *blendState = nullptr;
if (numRtvs > 0)
{
// Setup BlendStateKey parameters
mBlendStateKey.blendState.colorMaskRed = clearParams.colorMaskRed;
mBlendStateKey.blendState.colorMaskGreen = clearParams.colorMaskGreen;
mBlendStateKey.blendState.colorMaskBlue = clearParams.colorMaskBlue;
mBlendStateKey.blendState.colorMaskAlpha = clearParams.colorMaskAlpha;
mBlendStateKey.mrt = numRtvs > 1;
memcpy(mBlendStateKey.rtvMasks, &rtvMasks[0], sizeof(mBlendStateKey.rtvMasks));
// Get BlendState
ANGLE_TRY(mRenderer->getStateCache().getBlendState(mBlendStateKey, &blendState));
} }
ID3D11DepthStencilView *dsv =
maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : nullptr;
ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); const UINT stencilValue = clearParams.stencilClearValue & 0xFF;
const FLOAT blendFactors[4] = {1.0f, 1.0f, 1.0f, 1.0f}; ID3D11DepthStencilState *dsState = nullptr;
const UINT sampleMask = 0xFFFFFFFF; const float *zValue = nullptr;
ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); if (dsv)
const UINT stencilClear = clearParams.stencilClearValue & 0xFF; {
// Setup DepthStencilStateKey
mDepthStencilStateKey.depthTest = clearParams.clearDepth;
mDepthStencilStateKey.depthMask = clearParams.clearDepth;
mDepthStencilStateKey.stencilWritemask = clearParams.stencilWriteMask;
mDepthStencilStateKey.stencilTest = clearParams.clearStencil;
// Get DepthStencilState
ANGLE_TRY(mRenderer->getStateCache().getDepthStencilState(mDepthStencilStateKey, &dsState));
zValue = clearParams.clearDepth ? &clearParams.depthClearValue : nullptr;
}
// Set the vertices // Set the vertices
UINT vertexStride = 0; UINT vertexStride = 0;
...@@ -496,9 +516,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -496,9 +516,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result)) if (FAILED(result))
{ {
return gl::Error(GL_OUT_OF_MEMORY, return gl::OutOfMemory() << "Clear11: Failed to map internal VB, " << result;
"Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.",
result);
} }
const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : nullptr; const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : nullptr;
...@@ -543,9 +561,9 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -543,9 +561,9 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
deviceContext->RSSetViewports(1, &viewport); deviceContext->RSSetViewports(1, &viewport);
// Apply state // Apply state
deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
deviceContext->OMSetDepthStencilState(dsState, stencilClear);
deviceContext->RSSetState(mRasterizerState); deviceContext->RSSetState(mRasterizerState);
deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
deviceContext->OMSetDepthStencilState(dsState, stencilValue);
// Apply shaders // Apply shaders
deviceContext->IASetInputLayout(shader->inputLayout->resolve(device)); deviceContext->IASetInputLayout(shader->inputLayout->resolve(device));
...@@ -558,7 +576,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -558,7 +576,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// Apply render targets // Apply render targets
mRenderer->getStateManager()->setOneTimeRenderTargets(rtvs, dsv); mRenderer->getStateManager()->setOneTimeRenderTargets(&rtvs[0], numRtvs, dsv);
// Draw the clear quad // Draw the clear quad
deviceContext->Draw(4, 0); deviceContext->Draw(4, 0);
...@@ -568,109 +586,4 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -568,109 +586,4 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
return gl::NoError(); return gl::NoError();
} }
ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget> &rts)
{
ClearBlendInfo blendKey = {};
for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
{
if (i < rts.size())
{
RenderTarget11 *rt = rts[i].renderTarget;
const gl::InternalFormat &formatInfo =
gl::GetInternalFormatInfo(rt->getInternalFormat());
blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && formatInfo.redBits > 0);
blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && formatInfo.greenBits > 0);
blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && formatInfo.blueBits > 0);
blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && formatInfo.alphaBits > 0);
}
else
{
blendKey.maskChannels[i][0] = false;
blendKey.maskChannels[i][1] = false;
blendKey.maskChannels[i][2] = false;
blendKey.maskChannels[i][3] = false;
}
}
ClearBlendStateMap::const_iterator i = mClearBlendStates.find(blendKey);
if (i != mClearBlendStates.end())
{
return i->second;
}
else
{
D3D11_BLEND_DESC blendDesc = {0};
blendDesc.AlphaToCoverageEnable = FALSE;
blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE;
for (unsigned int j = 0; j < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; j++)
{
blendDesc.RenderTarget[j].BlendEnable = FALSE;
blendDesc.RenderTarget[j].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(
blendKey.maskChannels[j][0], blendKey.maskChannels[j][1],
blendKey.maskChannels[j][2], blendKey.maskChannels[j][3]);
}
ID3D11Device *device = mRenderer->getDevice();
ID3D11BlendState *blendState = nullptr;
HRESULT result = device->CreateBlendState(&blendDesc, &blendState);
if (FAILED(result) || !blendState)
{
ERR() << "Unable to create a ID3D11BlendState, " << gl::FmtHR(result) << ".";
return nullptr;
}
mClearBlendStates[blendKey] = blendState;
return blendState;
}
}
ID3D11DepthStencilState *Clear11::getDepthStencilState(const ClearParameters &clearParams)
{
ClearDepthStencilInfo dsKey = {0};
dsKey.clearDepth = clearParams.clearDepth;
dsKey.clearStencil = clearParams.clearStencil;
dsKey.stencilWriteMask = clearParams.stencilWriteMask & 0xFF;
ClearDepthStencilStateMap::const_iterator i = mClearDepthStencilStates.find(dsKey);
if (i != mClearDepthStencilStates.end())
{
return i->second;
}
else
{
D3D11_DEPTH_STENCIL_DESC dsDesc = {0};
dsDesc.DepthEnable = dsKey.clearDepth ? TRUE : FALSE;
dsDesc.DepthWriteMask =
dsKey.clearDepth ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
dsDesc.StencilEnable = dsKey.clearStencil ? TRUE : FALSE;
dsDesc.StencilReadMask = 0;
dsDesc.StencilWriteMask = dsKey.stencilWriteMask;
dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE;
dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE;
dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
ID3D11Device *device = mRenderer->getDevice();
ID3D11DepthStencilState *dsState = nullptr;
HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState);
if (FAILED(result) || !dsState)
{
ERR() << "Unable to create a ID3D11DepthStencilState, " << gl::FmtHR(result) << ".";
return nullptr;
}
mClearDepthStencilStates[dsKey] = dsState;
return dsState;
}
}
} }
...@@ -60,35 +60,17 @@ class Clear11 : angle::NonCopyable ...@@ -60,35 +60,17 @@ class Clear11 : angle::NonCopyable
d3d11::LazyShader<ID3D11PixelShader> pixelShader; d3d11::LazyShader<ID3D11PixelShader> pixelShader;
}; };
template <unsigned int vsSize, unsigned int psSize>
static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE(&vsByteCode)[vsSize], const BYTE(&psByteCode)[psSize]);
struct ClearBlendInfo
{
bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4];
};
typedef bool(*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &);
typedef std::map<ClearBlendInfo, ID3D11BlendState*, ClearBlendInfoComparisonFunction> ClearBlendStateMap;
struct ClearDepthStencilInfo
{
bool clearDepth;
bool clearStencil;
UINT8 stencilWriteMask;
};
typedef bool(*ClearDepthStencilInfoComparisonFunction)(const ClearDepthStencilInfo&, const ClearDepthStencilInfo &);
typedef std::map<ClearDepthStencilInfo, ID3D11DepthStencilState*, ClearDepthStencilInfoComparisonFunction> ClearDepthStencilStateMap;
Renderer11 *mRenderer; Renderer11 *mRenderer;
ClearBlendStateMap mClearBlendStates; // Cached cache Keys
gl::DepthStencilState mDepthStencilStateKey;
d3d11::BlendStateKey mBlendStateKey;
ClearShader *mFloatClearShader; ClearShader *mFloatClearShader;
ClearShader *mUintClearShader; ClearShader *mUintClearShader;
ClearShader *mIntClearShader; ClearShader *mIntClearShader;
ClearDepthStencilStateMap mClearDepthStencilStates;
ID3D11Buffer *mVertexBuffer; ID3D11Buffer *mVertexBuffer;
ID3D11RasterizerState *mRasterizerState; ID3D11RasterizerState *mRasterizerState;
}; };
......
...@@ -46,10 +46,10 @@ const unsigned int RenderStateCache::kMaxSamplerStates = 2048; ...@@ -46,10 +46,10 @@ const unsigned int RenderStateCache::kMaxSamplerStates = 2048;
RenderStateCache::RenderStateCache(Renderer11 *renderer) RenderStateCache::RenderStateCache(Renderer11 *renderer)
: mRenderer(renderer), : mRenderer(renderer),
mCounter(0), mCounter(0),
mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates), mBlendStateCache(kMaxBlendStates, HashBlendState, CompareBlendStates),
mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates), mRasterizerStateCache(kMaxRasterizerStates, HashRasterizerState, CompareRasterizerStates),
mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates), mDepthStencilStateCache(kMaxDepthStencilStates, HashDepthStencilState, CompareDepthStencilStates),
mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates), mSamplerStateCache(kMaxSamplerStates, HashSamplerState, CompareSamplerStates),
mDevice(NULL) mDevice(NULL)
{ {
} }
...@@ -73,53 +73,71 @@ void RenderStateCache::clear() ...@@ -73,53 +73,71 @@ void RenderStateCache::clear()
ClearStateMap(mSamplerStateCache); ClearStateMap(mSamplerStateCache);
} }
std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState) // static
std::size_t RenderStateCache::HashBlendState(const d3d11::BlendStateKey &blendState)
{ {
static const unsigned int seed = 0xABCDEF98; static const unsigned int seed = 0xABCDEF98;
std::size_t hash = 0; std::size_t hash = 0;
MurmurHash3_x86_32(&blendState, sizeof(BlendStateKey), seed, &hash); MurmurHash3_x86_32(&blendState, sizeof(d3d11::BlendStateKey), seed, &hash);
return hash; return hash;
} }
bool RenderStateCache::compareBlendStates(const BlendStateKey &a, const BlendStateKey &b) // static
bool RenderStateCache::CompareBlendStates(const d3d11::BlendStateKey &a,
const d3d11::BlendStateKey &b)
{ {
return memcmp(&a, &b, sizeof(BlendStateKey)) == 0; return memcmp(&a, &b, sizeof(d3d11::BlendStateKey)) == 0;
} }
gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, // static
ID3D11BlendState **outBlendState) d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Framebuffer *framebuffer,
const gl::BlendState &blendState)
{ {
if (!mDevice) d3d11::BlendStateKey key;
{ const FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer);
return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
}
bool mrt = false;
const FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer);
const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(); const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender();
const UINT8 blendStateMask =
gl_d3d11::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
blendState.colorMaskBlue, blendState.colorMaskAlpha);
BlendStateKey key = {};
key.blendState = blendState; key.blendState = blendState;
for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) key.mrt = false;
{
const gl::FramebufferAttachment *attachment = colorbuffers[colorAttachment];
auto rtChannels = key.rtChannels[colorAttachment]; for (size_t i = 0; i < colorbuffers.size(); i++)
{
const gl::FramebufferAttachment *attachment = colorbuffers[i];
if (attachment) if (attachment)
{ {
if (colorAttachment > 0) if (i > 0)
{ {
mrt = true; key.mrt = true;
} }
rtChannels[0] = attachment->getRedSize() > 0; key.rtvMasks[i] =
rtChannels[1] = attachment->getGreenSize() > 0; (gl_d3d11::GetColorMask(attachment->getFormat().info)) & blendStateMask;
rtChannels[2] = attachment->getBlueSize() > 0;
rtChannels[3] = attachment->getAlphaSize() > 0;
} }
else
{
key.rtvMasks[i] = 0;
}
}
for (size_t i = colorbuffers.size(); i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
{
key.rtvMasks[i] = 0;
}
return key;
}
gl::Error RenderStateCache::getBlendState(const d3d11::BlendStateKey &key,
ID3D11BlendState **outBlendState)
{
if (!mDevice)
{
return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
} }
BlendStateMap::iterator keyIter = mBlendStateCache.find(key); BlendStateMap::iterator keyIter = mBlendStateCache.find(key);
...@@ -150,47 +168,46 @@ gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, co ...@@ -150,47 +168,46 @@ gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, co
} }
// Create a new blend state and insert it into the cache // Create a new blend state and insert it into the cache
D3D11_BLEND_DESC blendDesc = { 0 }; D3D11_BLEND_DESC blendDesc;
blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; D3D11_RENDER_TARGET_BLEND_DESC &rtDesc0 = blendDesc.RenderTarget[0];
blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE; rtDesc0 = {};
const gl::BlendState &blendState = key.blendState;
for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage;
blendDesc.IndependentBlendEnable = key.mrt ? TRUE : FALSE;
if (blendState.blend)
{ {
D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i]; rtDesc0.BlendEnable = true;
rtDesc0.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false);
rtBlend.BlendEnable = blendState.blend; rtDesc0.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false);
if (blendState.blend) rtDesc0.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB);
{ rtDesc0.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true);
rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false); rtDesc0.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true);
rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false); rtDesc0.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha);
rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB); }
rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true); rtDesc0.RenderTargetWriteMask = key.rtvMasks[0];
rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true);
rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha);
}
rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed, for (unsigned int i = 1; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
key.rtChannels[i][1] && blendState.colorMaskGreen, {
key.rtChannels[i][2] && blendState.colorMaskBlue, blendDesc.RenderTarget[i] = rtDesc0;
key.rtChannels[i][3] && blendState.colorMaskAlpha); blendDesc.RenderTarget[i].RenderTargetWriteMask = key.rtvMasks[i];
} }
ID3D11BlendState *dx11BlendState = NULL; HRESULT result = mDevice->CreateBlendState(&blendDesc, outBlendState);
HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState); if (FAILED(result) || !(*outBlendState))
if (FAILED(result) || !dx11BlendState)
{ {
return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
} }
mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++))); mBlendStateCache.insert(std::make_pair(key, std::make_pair(*outBlendState, mCounter++)));
*outBlendState = dx11BlendState;
return gl::NoError(); return gl::NoError();
} }
} }
std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState) // static
std::size_t RenderStateCache::HashRasterizerState(const RasterizerStateKey &rasterState)
{ {
static const unsigned int seed = 0xABCDEF98; static const unsigned int seed = 0xABCDEF98;
...@@ -199,7 +216,8 @@ std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rast ...@@ -199,7 +216,8 @@ std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rast
return hash; return hash;
} }
bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b) // static
bool RenderStateCache::CompareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b)
{ {
return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
} }
...@@ -286,7 +304,8 @@ gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &raster ...@@ -286,7 +304,8 @@ gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &raster
} }
} }
std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState) // static
std::size_t RenderStateCache::HashDepthStencilState(const gl::DepthStencilState &dsState)
{ {
static const unsigned int seed = 0xABCDEF98; static const unsigned int seed = 0xABCDEF98;
...@@ -295,14 +314,13 @@ std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState ...@@ -295,14 +314,13 @@ std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState
return hash; return hash;
} }
bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b) // static
bool RenderStateCache::CompareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b)
{ {
return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0; return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0;
} }
gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &originalState, gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &glState,
bool disableDepth,
bool disableStencil,
ID3D11DepthStencilState **outDSState) ID3D11DepthStencilState **outDSState)
{ {
if (!mDevice) if (!mDevice)
...@@ -310,20 +328,6 @@ gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &or ...@@ -310,20 +328,6 @@ gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &or
return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
} }
gl::DepthStencilState glState = originalState;
if (disableDepth)
{
glState.depthTest = false;
glState.depthMask = false;
}
if (disableStencil)
{
glState.stencilWritemask = 0;
glState.stencilBackWritemask = 0;
glState.stencilTest = false;
}
auto keyIter = mDepthStencilStateCache.find(glState); auto keyIter = mDepthStencilStateCache.find(glState);
if (keyIter != mDepthStencilStateCache.end()) if (keyIter != mDepthStencilStateCache.end())
{ {
...@@ -381,7 +385,8 @@ gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &or ...@@ -381,7 +385,8 @@ gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &or
return gl::NoError(); return gl::NoError();
} }
std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState) // static
std::size_t RenderStateCache::HashSamplerState(const gl::SamplerState &samplerState)
{ {
static const unsigned int seed = 0xABCDEF98; static const unsigned int seed = 0xABCDEF98;
...@@ -390,7 +395,8 @@ std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerSt ...@@ -390,7 +395,8 @@ std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerSt
return hash; return hash;
} }
bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b) // static
bool RenderStateCache::CompareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b)
{ {
return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0; return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0;
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include <unordered_map> #include <unordered_map>
...@@ -34,11 +35,11 @@ class RenderStateCache : angle::NonCopyable ...@@ -34,11 +35,11 @@ class RenderStateCache : angle::NonCopyable
void initialize(ID3D11Device *device); void initialize(ID3D11Device *device);
void clear(); void clear();
gl::Error getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, ID3D11BlendState **outBlendState); static d3d11::BlendStateKey GetBlendStateKey(const gl::Framebuffer *framebuffer,
const gl::BlendState &blendState);
gl::Error getBlendState(const d3d11::BlendStateKey &key, ID3D11BlendState **outBlendState);
gl::Error getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, ID3D11RasterizerState **outRasterizerState); gl::Error getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, ID3D11RasterizerState **outRasterizerState);
gl::Error getDepthStencilState(const gl::DepthStencilState &dsState, gl::Error getDepthStencilState(const gl::DepthStencilState &dsState,
bool disableDepth,
bool disableStencil,
ID3D11DepthStencilState **outDSState); ID3D11DepthStencilState **outDSState);
gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState); gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState);
...@@ -47,19 +48,19 @@ class RenderStateCache : angle::NonCopyable ...@@ -47,19 +48,19 @@ class RenderStateCache : angle::NonCopyable
unsigned long long mCounter; unsigned long long mCounter;
// Blend state cache // Blend state cache
struct BlendStateKey static std::size_t HashBlendState(const d3d11::BlendStateKey &blendState);
{ static bool CompareBlendStates(const d3d11::BlendStateKey &a, const d3d11::BlendStateKey &b);
gl::BlendState blendState;
bool rtChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4];
};
static std::size_t hashBlendState(const BlendStateKey &blendState);
static bool compareBlendStates(const BlendStateKey &a, const BlendStateKey &b);
static const unsigned int kMaxBlendStates; static const unsigned int kMaxBlendStates;
typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &); typedef std::size_t (*BlendStateHashFunction)(const d3d11::BlendStateKey &);
typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &); typedef bool (*BlendStateEqualityFunction)(const d3d11::BlendStateKey &,
const d3d11::BlendStateKey &);
typedef std::pair<ID3D11BlendState*, unsigned long long> BlendStateCounterPair; typedef std::pair<ID3D11BlendState*, unsigned long long> BlendStateCounterPair;
typedef std::unordered_map<BlendStateKey, BlendStateCounterPair, BlendStateHashFunction, BlendStateEqualityFunction> BlendStateMap; typedef std::unordered_map<d3d11::BlendStateKey,
BlendStateCounterPair,
BlendStateHashFunction,
BlendStateEqualityFunction>
BlendStateMap;
BlendStateMap mBlendStateCache; BlendStateMap mBlendStateCache;
// Rasterizer state cache // Rasterizer state cache
...@@ -68,8 +69,8 @@ class RenderStateCache : angle::NonCopyable ...@@ -68,8 +69,8 @@ class RenderStateCache : angle::NonCopyable
gl::RasterizerState rasterizerState; gl::RasterizerState rasterizerState;
bool scissorEnabled; bool scissorEnabled;
}; };
static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState); static std::size_t HashRasterizerState(const RasterizerStateKey &rasterState);
static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b); static bool CompareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b);
static const unsigned int kMaxRasterizerStates; static const unsigned int kMaxRasterizerStates;
typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &); typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &);
...@@ -79,8 +80,8 @@ class RenderStateCache : angle::NonCopyable ...@@ -79,8 +80,8 @@ class RenderStateCache : angle::NonCopyable
RasterizerStateMap mRasterizerStateCache; RasterizerStateMap mRasterizerStateCache;
// Depth stencil state cache // Depth stencil state cache
static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState); static std::size_t HashDepthStencilState(const gl::DepthStencilState &dsState);
static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b); static bool CompareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b);
static const unsigned int kMaxDepthStencilStates; static const unsigned int kMaxDepthStencilStates;
typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &); typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &);
...@@ -93,8 +94,8 @@ class RenderStateCache : angle::NonCopyable ...@@ -93,8 +94,8 @@ class RenderStateCache : angle::NonCopyable
DepthStencilStateMap mDepthStencilStateCache; DepthStencilStateMap mDepthStencilStateCache;
// Sample state cache // Sample state cache
static std::size_t hashSamplerState(const gl::SamplerState &samplerState); static std::size_t HashSamplerState(const gl::SamplerState &samplerState);
static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b); static bool CompareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b);
static const unsigned int kMaxSamplerStates; static const unsigned int kMaxSamplerStates;
typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &); typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &);
......
...@@ -496,7 +496,9 @@ gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer, ...@@ -496,7 +496,9 @@ gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer,
} }
ID3D11BlendState *dxBlendState = nullptr; ID3D11BlendState *dxBlendState = nullptr;
ANGLE_TRY(mRenderer->getStateCache().getBlendState(framebuffer, blendState, &dxBlendState)); const d3d11::BlendStateKey &key = RenderStateCache::GetBlendStateKey(framebuffer, blendState);
ANGLE_TRY(mRenderer->getStateCache().getBlendState(key, &dxBlendState));
ASSERT(dxBlendState != nullptr); ASSERT(dxBlendState != nullptr);
...@@ -550,25 +552,41 @@ gl::Error StateManager11::setDepthStencilState(const gl::State &glState) ...@@ -550,25 +552,41 @@ gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
return gl::NoError(); return gl::NoError();
} }
const auto &depthStencilState = glState.getDepthStencilState(); mCurDepthStencilState = glState.getDepthStencilState();
int stencilRef = glState.getStencilRef(); mCurStencilRef = glState.getStencilRef();
int stencilBackRef = glState.getStencilBackRef(); mCurStencilBackRef = glState.getStencilBackRef();
mCurDisableDepth = disableDepth;
mCurDisableStencil = disableStencil;
// get the maximum size of the stencil ref // get the maximum size of the stencil ref
unsigned int maxStencil = 0; unsigned int maxStencil = 0;
if (depthStencilState.stencilTest && mCurStencilSize > 0) if (mCurDepthStencilState.stencilTest && mCurStencilSize > 0)
{ {
maxStencil = (1 << mCurStencilSize) - 1; maxStencil = (1 << mCurStencilSize) - 1;
} }
ASSERT((depthStencilState.stencilWritemask & maxStencil) == ASSERT((mCurDepthStencilState.stencilWritemask & maxStencil) ==
(depthStencilState.stencilBackWritemask & maxStencil)); (mCurDepthStencilState.stencilBackWritemask & maxStencil));
ASSERT(stencilRef == stencilBackRef); ASSERT(mCurStencilRef == mCurStencilBackRef);
ASSERT((depthStencilState.stencilMask & maxStencil) == ASSERT((mCurDepthStencilState.stencilMask & maxStencil) ==
(depthStencilState.stencilBackMask & maxStencil)); (mCurDepthStencilState.stencilBackMask & maxStencil));
ID3D11DepthStencilState *dxDepthStencilState = NULL; ID3D11DepthStencilState *dxDepthStencilState = NULL;
ANGLE_TRY(mRenderer->getStateCache().getDepthStencilState( gl::DepthStencilState dsStateKey = glState.getDepthStencilState();
depthStencilState, disableDepth, disableStencil, &dxDepthStencilState));
if (disableDepth)
{
dsStateKey.depthTest = false;
dsStateKey.depthMask = false;
}
if (disableStencil)
{
dsStateKey.stencilWritemask = 0;
dsStateKey.stencilBackWritemask = 0;
dsStateKey.stencilTest = false;
}
ANGLE_TRY(mRenderer->getStateCache().getDepthStencilState(dsStateKey, &dxDepthStencilState));
ASSERT(dxDepthStencilState); ASSERT(dxDepthStencilState);
...@@ -580,16 +598,10 @@ gl::Error StateManager11::setDepthStencilState(const gl::State &glState) ...@@ -580,16 +598,10 @@ gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
"Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK"); "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF, static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF,
"Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK"); "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu); UINT dxStencilRef = std::min<UINT>(mCurStencilRef, 0xFFu);
mRenderer->getDeviceContext()->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); mRenderer->getDeviceContext()->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
mCurDepthStencilState = depthStencilState;
mCurStencilRef = stencilRef;
mCurStencilBackRef = stencilBackRef;
mCurDisableDepth = disableDepth;
mCurDisableStencil = disableStencil;
mDepthStencilStateIsDirty = false; mDepthStencilStateIsDirty = false;
return gl::NoError(); return gl::NoError();
...@@ -803,21 +815,18 @@ void StateManager11::invalidateEverything() ...@@ -803,21 +815,18 @@ void StateManager11::invalidateEverything()
invalidateBoundViews(); invalidateBoundViews();
} }
void StateManager11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTarget, void StateManager11::setOneTimeRenderTarget(ID3D11RenderTargetView *rtv,
ID3D11DepthStencilView *depthStencil) ID3D11DepthStencilView *dsv)
{ {
mRenderer->getDeviceContext()->OMSetRenderTargets(1, &renderTarget, depthStencil); mRenderer->getDeviceContext()->OMSetRenderTargets(1, &rtv, dsv);
mRenderTargetIsDirty = true; mRenderTargetIsDirty = true;
} }
void StateManager11::setOneTimeRenderTargets( void StateManager11::setOneTimeRenderTargets(ID3D11RenderTargetView **rtvs,
const std::vector<ID3D11RenderTargetView *> &renderTargets, UINT numRtvs,
ID3D11DepthStencilView *depthStencil) ID3D11DepthStencilView *dsv)
{ {
UINT count = static_cast<UINT>(renderTargets.size()); mRenderer->getDeviceContext()->OMSetRenderTargets(numRtvs, (numRtvs > 0) ? rtvs : nullptr, dsv);
auto renderTargetPointer = (!renderTargets.empty() ? renderTargets.data() : nullptr);
mRenderer->getDeviceContext()->OMSetRenderTargets(count, renderTargetPointer, depthStencil);
mRenderTargetIsDirty = true; mRenderTargetIsDirty = true;
} }
......
...@@ -83,10 +83,10 @@ class StateManager11 final : angle::NonCopyable ...@@ -83,10 +83,10 @@ class StateManager11 final : angle::NonCopyable
void invalidateBoundViews(); void invalidateBoundViews();
void invalidateEverything(); void invalidateEverything();
void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTarget, void setOneTimeRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv);
ID3D11DepthStencilView *depthStencil); void setOneTimeRenderTargets(ID3D11RenderTargetView **rtvs,
void setOneTimeRenderTargets(const std::vector<ID3D11RenderTargetView *> &renderTargets, UINT numRtvs,
ID3D11DepthStencilView *depthStencil); ID3D11DepthStencilView *dsv);
void onBeginQuery(Query11 *query); void onBeginQuery(Query11 *query);
void onDeleteQueryObject(Query11 *query); void onDeleteQueryObject(Query11 *query);
......
...@@ -1697,6 +1697,29 @@ D3D11_QUERY ConvertQueryType(GLenum queryType) ...@@ -1697,6 +1697,29 @@ D3D11_QUERY ConvertQueryType(GLenum queryType)
} }
} }
// Get the D3D11 write mask covering all color channels of a given format
UINT8 GetColorMask(const gl::InternalFormat *formatInfo)
{
UINT8 mask = 0;
if (formatInfo->redBits > 0)
{
mask |= D3D11_COLOR_WRITE_ENABLE_RED;
}
if (formatInfo->greenBits > 0)
{
mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
}
if (formatInfo->blueBits > 0)
{
mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
}
if (formatInfo->alphaBits > 0)
{
mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
}
return mask;
}
} // namespace gl_d3d11 } // namespace gl_d3d11
namespace d3d11 namespace d3d11
......
...@@ -55,6 +55,8 @@ UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel); ...@@ -55,6 +55,8 @@ UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel);
D3D11_QUERY ConvertQueryType(GLenum queryType); D3D11_QUERY ConvertQueryType(GLenum queryType);
UINT8 GetColorMask(const gl::InternalFormat *formatInfo);
} // namespace gl_d3d11 } // namespace gl_d3d11
namespace d3d11_gl namespace d3d11_gl
...@@ -132,6 +134,13 @@ void SetPositionDepthColorVertex(PositionDepthColorVertex<T>* vertex, float x, f ...@@ -132,6 +134,13 @@ void SetPositionDepthColorVertex(PositionDepthColorVertex<T>* vertex, float x, f
vertex->a = color.alpha; vertex->a = color.alpha;
} }
struct BlendStateKey
{
gl::BlendState blendState;
bool mrt;
uint8_t rtvMasks[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
};
HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name);
template <typename T> template <typename T>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment