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()
Clear11::Clear11(Renderer11 *renderer)
: mRenderer(renderer),
mClearBlendStates(StructLessThan<ClearBlendInfo>),
mFloatClearShader(nullptr),
mUintClearShader(nullptr),
mIntClearShader(nullptr),
mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>),
mVertexBuffer(nullptr),
mRasterizerState(nullptr)
{
......@@ -166,28 +164,44 @@ Clear11::Clear11(Renderer11 *renderer)
ArraySize(g_VS_ClearSint), "Clear11 SINT VS", g_PS_ClearSint,
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()
{
for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end();
i++)
{
SafeRelease(i->second);
}
mClearBlendStates.clear();
SafeDelete(mFloatClearShader);
SafeDelete(mUintClearShader);
SafeDelete(mIntClearShader);
for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin();
i != mClearDepthStencilStates.end(); i++)
{
SafeRelease(i->second);
}
mClearDepthStencilStates.clear();
SafeRelease(mVertexBuffer);
SafeRelease(mRasterizerState);
}
......@@ -206,8 +220,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
// cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView.
// This requires:
// 1) The render target is being cleared to a float value (will be cast to integer when clearing
// integer
// render targets as expected but does not work the other way around)
// integer 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.
// Clear the easy-to-clear buffers on the spot and accumulate the ones that require special
// work.
......@@ -261,13 +274,18 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width ||
clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height);
std::vector<MaskedRenderTarget> maskedClearRenderTargets;
RenderTarget11 *maskedClearDepthStencil = nullptr;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
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();
colorAttachmentIndex++)
{
......@@ -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
continue;
}
else 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))
ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
if (!framebufferRTV)
{
return gl::OutOfMemory()
<< "Clear11: Render target view pointer unexpectedly null.";
}
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
// ID3D11DeviceContext1::ClearView is unavailable
MaskedRenderTarget maskAndRt;
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);
rtvs[numRtvs] = framebufferRTV;
rtvMasks[numRtvs] = gl_d3d11::GetColorMask(&formatInfo) & colorMask;
numRtvs++;
}
else
{
// ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is
// 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();
// 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,
clearParams.clearStencil &&
(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) |
(clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0);
FLOAT depthClear = gl::clamp01(clearParams.depthClearValue);
UINT8 stencilClear = clearParams.stencilClearValue & 0xFF;
deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear,
stencilClear);
deviceContext->ClearDepthStencilView(dsv, clearFlags, depthClear, stencilClear);
dsv = nullptr;
}
}
if (maskedClearRenderTargets.empty() && !maskedClearDepthStencil)
if (numRtvs == 0 && !dsv)
{
return gl::NoError();
}
......@@ -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
// be a compatible clear type.
// Bind all the render targets which need clearing
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.");
}
ASSERT(numRtvs <= mRenderer->getNativeCaps().maxDrawBuffers);
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 FLOAT blendFactors[4] = {1.0f, 1.0f, 1.0f, 1.0f};
const UINT sampleMask = 0xFFFFFFFF;
const UINT stencilValue = clearParams.stencilClearValue & 0xFF;
ID3D11DepthStencilState *dsState = nullptr;
const float *zValue = nullptr;
ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams);
const UINT stencilClear = clearParams.stencilClearValue & 0xFF;
if (dsv)
{
// 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
UINT vertexStride = 0;
......@@ -496,9 +516,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY,
"Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.",
result);
return gl::OutOfMemory() << "Clear11: Failed to map internal VB, " << result;
}
const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : nullptr;
......@@ -543,9 +561,9 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
deviceContext->RSSetViewports(1, &viewport);
// Apply state
deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
deviceContext->OMSetDepthStencilState(dsState, stencilClear);
deviceContext->RSSetState(mRasterizerState);
deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
deviceContext->OMSetDepthStencilState(dsState, stencilValue);
// Apply shaders
deviceContext->IASetInputLayout(shader->inputLayout->resolve(device));
......@@ -558,7 +576,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// Apply render targets
mRenderer->getStateManager()->setOneTimeRenderTargets(rtvs, dsv);
mRenderer->getStateManager()->setOneTimeRenderTargets(&rtvs[0], numRtvs, dsv);
// Draw the clear quad
deviceContext->Draw(4, 0);
......@@ -568,109 +586,4 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
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
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;
ClearBlendStateMap mClearBlendStates;
// Cached cache Keys
gl::DepthStencilState mDepthStencilStateKey;
d3d11::BlendStateKey mBlendStateKey;
ClearShader *mFloatClearShader;
ClearShader *mUintClearShader;
ClearShader *mIntClearShader;
ClearDepthStencilStateMap mClearDepthStencilStates;
ID3D11Buffer *mVertexBuffer;
ID3D11RasterizerState *mRasterizerState;
};
......
......@@ -46,10 +46,10 @@ const unsigned int RenderStateCache::kMaxSamplerStates = 2048;
RenderStateCache::RenderStateCache(Renderer11 *renderer)
: mRenderer(renderer),
mCounter(0),
mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates),
mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates),
mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates),
mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates),
mBlendStateCache(kMaxBlendStates, HashBlendState, CompareBlendStates),
mRasterizerStateCache(kMaxRasterizerStates, HashRasterizerState, CompareRasterizerStates),
mDepthStencilStateCache(kMaxDepthStencilStates, HashDepthStencilState, CompareDepthStencilStates),
mSamplerStateCache(kMaxSamplerStates, HashSamplerState, CompareSamplerStates),
mDevice(NULL)
{
}
......@@ -73,53 +73,71 @@ void RenderStateCache::clear()
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;
std::size_t hash = 0;
MurmurHash3_x86_32(&blendState, sizeof(BlendStateKey), seed, &hash);
MurmurHash3_x86_32(&blendState, sizeof(d3d11::BlendStateKey), seed, &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,
ID3D11BlendState **outBlendState)
// static
d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Framebuffer *framebuffer,
const gl::BlendState &blendState)
{
if (!mDevice)
{
return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
}
bool mrt = false;
const FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer);
d3d11::BlendStateKey key;
const FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer);
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;
for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
{
const gl::FramebufferAttachment *attachment = colorbuffers[colorAttachment];
key.mrt = false;
auto rtChannels = key.rtChannels[colorAttachment];
for (size_t i = 0; i < colorbuffers.size(); i++)
{
const gl::FramebufferAttachment *attachment = colorbuffers[i];
if (attachment)
{
if (colorAttachment > 0)
if (i > 0)
{
mrt = true;
key.mrt = true;
}
rtChannels[0] = attachment->getRedSize() > 0;
rtChannels[1] = attachment->getGreenSize() > 0;
rtChannels[2] = attachment->getBlueSize() > 0;
rtChannels[3] = attachment->getAlphaSize() > 0;
key.rtvMasks[i] =
(gl_d3d11::GetColorMask(attachment->getFormat().info)) & blendStateMask;
}
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);
......@@ -150,47 +168,46 @@ gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, co
}
// Create a new blend state and insert it into the cache
D3D11_BLEND_DESC blendDesc = { 0 };
blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage;
blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE;
for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
D3D11_BLEND_DESC blendDesc;
D3D11_RENDER_TARGET_BLEND_DESC &rtDesc0 = blendDesc.RenderTarget[0];
rtDesc0 = {};
const gl::BlendState &blendState = key.blendState;
blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage;
blendDesc.IndependentBlendEnable = key.mrt ? TRUE : FALSE;
if (blendState.blend)
{
D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i];
rtBlend.BlendEnable = blendState.blend;
if (blendState.blend)
{
rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false);
rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false);
rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB);
rtDesc0.BlendEnable = true;
rtDesc0.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false);
rtDesc0.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false);
rtDesc0.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB);
rtDesc0.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true);
rtDesc0.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true);
rtDesc0.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha);
}
rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true);
rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true);
rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha);
}
rtDesc0.RenderTargetWriteMask = key.rtvMasks[0];
rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed,
key.rtChannels[i][1] && blendState.colorMaskGreen,
key.rtChannels[i][2] && blendState.colorMaskBlue,
key.rtChannels[i][3] && blendState.colorMaskAlpha);
for (unsigned int i = 1; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
{
blendDesc.RenderTarget[i] = rtDesc0;
blendDesc.RenderTarget[i].RenderTargetWriteMask = key.rtvMasks[i];
}
ID3D11BlendState *dx11BlendState = NULL;
HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState);
if (FAILED(result) || !dx11BlendState)
HRESULT result = mDevice->CreateBlendState(&blendDesc, outBlendState);
if (FAILED(result) || !(*outBlendState))
{
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();
}
}
std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState)
// static
std::size_t RenderStateCache::HashRasterizerState(const RasterizerStateKey &rasterState)
{
static const unsigned int seed = 0xABCDEF98;
......@@ -199,7 +216,8 @@ std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rast
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;
}
......@@ -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;
......@@ -295,14 +314,13 @@ std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState
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;
}
gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &originalState,
bool disableDepth,
bool disableStencil,
gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &glState,
ID3D11DepthStencilState **outDSState)
{
if (!mDevice)
......@@ -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.");
}
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);
if (keyIter != mDepthStencilStateCache.end())
{
......@@ -381,7 +385,8 @@ gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &or
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;
......@@ -390,7 +395,8 @@ std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerSt
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;
}
......
......@@ -13,6 +13,7 @@
#include "libANGLE/angletypes.h"
#include "libANGLE/Error.h"
#include "common/angleutils.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include <unordered_map>
......@@ -34,11 +35,11 @@ class RenderStateCache : angle::NonCopyable
void initialize(ID3D11Device *device);
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 getDepthStencilState(const gl::DepthStencilState &dsState,
bool disableDepth,
bool disableStencil,
ID3D11DepthStencilState **outDSState);
gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState);
......@@ -47,19 +48,19 @@ class RenderStateCache : angle::NonCopyable
unsigned long long mCounter;
// Blend state cache
struct BlendStateKey
{
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 std::size_t HashBlendState(const d3d11::BlendStateKey &blendState);
static bool CompareBlendStates(const d3d11::BlendStateKey &a, const d3d11::BlendStateKey &b);
static const unsigned int kMaxBlendStates;
typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &);
typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &);
typedef std::size_t (*BlendStateHashFunction)(const d3d11::BlendStateKey &);
typedef bool (*BlendStateEqualityFunction)(const d3d11::BlendStateKey &,
const d3d11::BlendStateKey &);
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;
// Rasterizer state cache
......@@ -68,8 +69,8 @@ class RenderStateCache : angle::NonCopyable
gl::RasterizerState rasterizerState;
bool scissorEnabled;
};
static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState);
static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b);
static std::size_t HashRasterizerState(const RasterizerStateKey &rasterState);
static bool CompareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b);
static const unsigned int kMaxRasterizerStates;
typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &);
......@@ -79,8 +80,8 @@ class RenderStateCache : angle::NonCopyable
RasterizerStateMap mRasterizerStateCache;
// Depth stencil state cache
static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState);
static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b);
static std::size_t HashDepthStencilState(const gl::DepthStencilState &dsState);
static bool CompareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b);
static const unsigned int kMaxDepthStencilStates;
typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &);
......@@ -93,8 +94,8 @@ class RenderStateCache : angle::NonCopyable
DepthStencilStateMap mDepthStencilStateCache;
// Sample state cache
static std::size_t hashSamplerState(const gl::SamplerState &samplerState);
static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b);
static std::size_t HashSamplerState(const gl::SamplerState &samplerState);
static bool CompareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b);
static const unsigned int kMaxSamplerStates;
typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &);
......
......@@ -496,7 +496,9 @@ gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer,
}
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);
......@@ -550,25 +552,41 @@ gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
return gl::NoError();
}
const auto &depthStencilState = glState.getDepthStencilState();
int stencilRef = glState.getStencilRef();
int stencilBackRef = glState.getStencilBackRef();
mCurDepthStencilState = glState.getDepthStencilState();
mCurStencilRef = glState.getStencilRef();
mCurStencilBackRef = glState.getStencilBackRef();
mCurDisableDepth = disableDepth;
mCurDisableStencil = disableStencil;
// get the maximum size of the stencil ref
unsigned int maxStencil = 0;
if (depthStencilState.stencilTest && mCurStencilSize > 0)
if (mCurDepthStencilState.stencilTest && mCurStencilSize > 0)
{
maxStencil = (1 << mCurStencilSize) - 1;
}
ASSERT((depthStencilState.stencilWritemask & maxStencil) ==
(depthStencilState.stencilBackWritemask & maxStencil));
ASSERT(stencilRef == stencilBackRef);
ASSERT((depthStencilState.stencilMask & maxStencil) ==
(depthStencilState.stencilBackMask & maxStencil));
ASSERT((mCurDepthStencilState.stencilWritemask & maxStencil) ==
(mCurDepthStencilState.stencilBackWritemask & maxStencil));
ASSERT(mCurStencilRef == mCurStencilBackRef);
ASSERT((mCurDepthStencilState.stencilMask & maxStencil) ==
(mCurDepthStencilState.stencilBackMask & maxStencil));
ID3D11DepthStencilState *dxDepthStencilState = NULL;
ANGLE_TRY(mRenderer->getStateCache().getDepthStencilState(
depthStencilState, disableDepth, disableStencil, &dxDepthStencilState));
gl::DepthStencilState dsStateKey = glState.getDepthStencilState();
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);
......@@ -580,16 +598,10 @@ gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
"Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF,
"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);
mCurDepthStencilState = depthStencilState;
mCurStencilRef = stencilRef;
mCurStencilBackRef = stencilBackRef;
mCurDisableDepth = disableDepth;
mCurDisableStencil = disableStencil;
mDepthStencilStateIsDirty = false;
return gl::NoError();
......@@ -803,21 +815,18 @@ void StateManager11::invalidateEverything()
invalidateBoundViews();
}
void StateManager11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTarget,
ID3D11DepthStencilView *depthStencil)
void StateManager11::setOneTimeRenderTarget(ID3D11RenderTargetView *rtv,
ID3D11DepthStencilView *dsv)
{
mRenderer->getDeviceContext()->OMSetRenderTargets(1, &renderTarget, depthStencil);
mRenderer->getDeviceContext()->OMSetRenderTargets(1, &rtv, dsv);
mRenderTargetIsDirty = true;
}
void StateManager11::setOneTimeRenderTargets(
const std::vector<ID3D11RenderTargetView *> &renderTargets,
ID3D11DepthStencilView *depthStencil)
void StateManager11::setOneTimeRenderTargets(ID3D11RenderTargetView **rtvs,
UINT numRtvs,
ID3D11DepthStencilView *dsv)
{
UINT count = static_cast<UINT>(renderTargets.size());
auto renderTargetPointer = (!renderTargets.empty() ? renderTargets.data() : nullptr);
mRenderer->getDeviceContext()->OMSetRenderTargets(count, renderTargetPointer, depthStencil);
mRenderer->getDeviceContext()->OMSetRenderTargets(numRtvs, (numRtvs > 0) ? rtvs : nullptr, dsv);
mRenderTargetIsDirty = true;
}
......
......@@ -83,10 +83,10 @@ class StateManager11 final : angle::NonCopyable
void invalidateBoundViews();
void invalidateEverything();
void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTarget,
ID3D11DepthStencilView *depthStencil);
void setOneTimeRenderTargets(const std::vector<ID3D11RenderTargetView *> &renderTargets,
ID3D11DepthStencilView *depthStencil);
void setOneTimeRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv);
void setOneTimeRenderTargets(ID3D11RenderTargetView **rtvs,
UINT numRtvs,
ID3D11DepthStencilView *dsv);
void onBeginQuery(Query11 *query);
void onDeleteQueryObject(Query11 *query);
......
......@@ -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 d3d11
......
......@@ -55,6 +55,8 @@ UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel);
D3D11_QUERY ConvertQueryType(GLenum queryType);
UINT8 GetColorMask(const gl::InternalFormat *formatInfo);
} // namespace gl_d3d11
namespace d3d11_gl
......@@ -132,6 +134,13 @@ void SetPositionDepthColorVertex(PositionDepthColorVertex<T>* vertex, float x, f
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);
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