Commit c9bdeff4 by Jamie Madill Committed by Commit Bot

D3D11: Refactor RenderTarget apply into StateManager11.

This is a refactoring patch only, and doesn't change the behaviour. The intent is to make it easy to turn on the Framebuffer dirty bits in a subsequent patch, once we can cleanly handle textures and renderbuffers getting recreated. BUG=angleproject:1260 Change-Id: Iaa5cfe222b020724e088eee5f1ae909b6f981a08 Reviewed-on: https://chromium-review.googlesource.com/325423Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 570f67d7
......@@ -8,8 +8,15 @@
#include "common/debug.h"
#include <stdio.h>
#include <limits>
#include <vector>
namespace angle
{
const uintptr_t DirtyPointer = std::numeric_limits<uintptr_t>::max();
}
size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& outBuffer)
{
// Attempt to just print to the current buffer
......
......@@ -33,6 +33,7 @@ class NonCopyable
void operator=(const NonCopyable&) = delete;
};
extern const uintptr_t DirtyPointer;
}
template <typename T, size_t N>
......
......@@ -37,8 +37,6 @@ const int ScratchMemoryBufferLifetime = 1000;
} // anonymous namespace
const uintptr_t RendererD3D::DirtyPointer = std::numeric_limits<uintptr_t>::max();
RendererD3D::RendererD3D(egl::Display *display)
: mDisplay(display),
mDeviceLost(false),
......
......@@ -172,8 +172,6 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
SourceIndexData *sourceIndexInfo) = 0;
virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0;
virtual void markAllStateDirty() = 0;
virtual unsigned int getReservedVertexUniformVectors() const = 0;
virtual unsigned int getReservedFragmentUniformVectors() const = 0;
virtual unsigned int getReservedVertexUniformBuffers() const = 0;
......@@ -263,7 +261,6 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
static unsigned int GetBlendSampleMask(const gl::Data &data, int samples);
// dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state.
static const uintptr_t DirtyPointer;
egl::Display *mDisplay;
bool mDeviceLost;
......
......@@ -709,7 +709,8 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source,
deviceContext->GSSetShader(support.geometryShader, nullptr, 0);
// Unset the currently bound shader resource to avoid conflicts
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
auto stateManager = mRenderer->getStateManager();
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
// Apply render target
mRenderer->setOneTimeRenderTarget(dest);
......@@ -725,7 +726,7 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source,
deviceContext->RSSetViewports(1, &viewport);
// Apply textures
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
// Apply samplers
deviceContext->PSSetSamplers(0, 1, &mPointSampler);
......@@ -734,7 +735,7 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source,
deviceContext->Draw(drawCount, 0);
// Unbind textures and render targets and vertex buffer
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
mRenderer->unapplyRenderTargets();
......@@ -846,7 +847,8 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source,
deviceContext->GSSetShader(support.geometryShader, nullptr, 0);
// Unset the currently bound shader resource to avoid conflicts
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
auto stateManager = mRenderer->getStateManager();
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
// Apply render target
mRenderer->setOneTimeRenderTarget(dest);
......@@ -862,7 +864,7 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source,
deviceContext->RSSetViewports(1, &viewport);
// Apply textures
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
// Apply samplers
ID3D11SamplerState *sampler = nullptr;
......@@ -881,7 +883,7 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source,
deviceContext->Draw(drawCount, 0);
// Unbind textures and render targets and vertex buffer
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
mRenderer->unapplyRenderTargets();
......@@ -973,7 +975,8 @@ gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sou
deviceContext->GSSetShader(nullptr, nullptr, 0);
// Unset the currently bound shader resource to avoid conflicts
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
auto stateManager = mRenderer->getStateManager();
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
// Apply render target
deviceContext->OMSetRenderTargets(0, nullptr, dest);
......@@ -989,7 +992,7 @@ gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sou
deviceContext->RSSetViewports(1, &viewport);
// Apply textures
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
// Apply samplers
deviceContext->PSSetSamplers(0, 1, &mPointSampler);
......@@ -998,7 +1001,7 @@ gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sou
deviceContext->Draw(drawCount, 0);
// Unbind textures and render targets and vertex buffer
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
mRenderer->unapplyRenderTargets();
......
......@@ -224,11 +224,12 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac
// Are we doing a 2D or 3D copy?
ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL);
auto stateManager = mRenderer->getStateManager();
deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0);
deviceContext->GSSetShader(geometryShader, NULL, 0);
deviceContext->PSSetShader(pixelShader, NULL, 0);
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV);
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV);
deviceContext->IASetInputLayout(NULL);
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
......@@ -261,7 +262,7 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac
deviceContext->Draw(numPixels, 0);
// Unbind textures and render targets and vertex buffer
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer);
mRenderer->markAllStateDirty();
......
......@@ -87,73 +87,6 @@ enum
MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
};
bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
{
unsigned mipLevel = index.mipIndex;
unsigned layerIndex = index.layerIndex;
GLenum type = index.type;
switch (desc.ViewDimension)
{
case D3D11_SRV_DIMENSION_TEXTURE2D:
{
unsigned maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
maxSrvMip = (desc.Texture2D.MipLevels == -1) ? INT_MAX : maxSrvMip;
unsigned mipMin = index.mipIndex;
unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex;
return type == GL_TEXTURE_2D && gl::RangeUI(mipMin, mipMax).intersects(gl::RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip));
}
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
{
unsigned maxSrvMip = desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip;
maxSrvMip = (desc.Texture2DArray.MipLevels == -1) ? INT_MAX : maxSrvMip;
unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize;
// Cube maps can be mapped to Texture2DArray SRVs
return (type == GL_TEXTURE_2D_ARRAY || gl::IsCubeMapTextureTarget(type)) &&
desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip &&
desc.Texture2DArray.FirstArraySlice <= layerIndex && layerIndex < maxSlice;
}
case D3D11_SRV_DIMENSION_TEXTURECUBE:
{
unsigned maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip;
maxSrvMip = (desc.TextureCube.MipLevels == -1) ? INT_MAX : maxSrvMip;
return gl::IsCubeMapTextureTarget(type) &&
desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
}
case D3D11_SRV_DIMENSION_TEXTURE3D:
{
unsigned maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip;
maxSrvMip = (desc.Texture3D.MipLevels == -1) ? INT_MAX : maxSrvMip;
return type == GL_TEXTURE_3D &&
desc.Texture3D.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
}
default:
// We only handle the cases corresponding to valid image indexes
UNIMPLEMENTED();
}
return false;
}
// Does *not* increment the resource ref count!!
ID3D11Resource *GetViewResource(ID3D11View *view)
{
ID3D11Resource *resource = NULL;
ASSERT(view);
view->GetResource(&resource);
resource->Release();
return resource;
}
void CalculateConstantBufferParams(GLintptr offset, GLsizeiptr size, UINT *outFirstConstant, UINT *outNumConstants)
{
// The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange).
......@@ -430,49 +363,10 @@ void GetTriFanIndices(const GLvoid *indices,
} // anonymous namespace
void Renderer11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv)
{
ASSERT(resourceIndex < mCurrentSRVs.size());
SRVRecord *record = &mCurrentSRVs[resourceIndex];
record->srv = reinterpret_cast<uintptr_t>(srv);
if (srv)
{
record->resource = reinterpret_cast<uintptr_t>(GetViewResource(srv));
srv->GetDesc(&record->desc);
mHighestUsedSRV = std::max(resourceIndex + 1, mHighestUsedSRV);
}
else
{
record->resource = 0;
if (resourceIndex + 1 == mHighestUsedSRV)
{
do
{
--mHighestUsedSRV;
}
while (mHighestUsedSRV > 0 &&
mCurrentSRVs[mHighestUsedSRV].srv == 0);
}
}
}
void Renderer11::SRVCache::clear()
{
if (mCurrentSRVs.empty())
{
return;
}
memset(&mCurrentSRVs[0], 0, sizeof(SRVRecord) * mCurrentSRVs.size());
mHighestUsedSRV = 0;
}
Renderer11::Renderer11(egl::Display *display)
: RendererD3D(display),
mStateCache(this),
mStateManager(),
mStateManager(this),
mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime()),
mDebug(nullptr)
{
......@@ -901,18 +795,17 @@ void Renderer11::initializeDevice()
ASSERT(!mPixelTransfer);
mPixelTransfer = new PixelTransfer11(this);
mStateManager.initialize(mDeviceContext, &mStateCache, &mRenderer11DeviceCaps);
const gl::Caps &rendererCaps = getRendererCaps();
mStateManager.initialize(rendererCaps);
mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
mCurVertexSRVs.initialize(rendererCaps.maxVertexTextureImageUnits);
mCurPixelSRVs.initialize(rendererCaps.maxTextureImageUnits);
mStateManager.initialize(rendererCaps);
markAllStateDirty();
......@@ -930,9 +823,6 @@ void Renderer11::initializeDevice()
angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1;
}
// Initialize cached NULL SRV block
mNullSRVs.resize(getRendererCaps().maxTextureImageUnits, nullptr);
ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel",
angleFeatureLevel,
NUM_ANGLE_FEATURE_LEVELS);
......@@ -1316,7 +1206,7 @@ gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *t
ASSERT((type == gl::SAMPLER_PIXEL && static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits) ||
(type == gl::SAMPLER_VERTEX && static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits));
setShaderResource(type, index, textureSRV);
mStateManager.setShaderResource(type, index, textureSRV);
return gl::Error(GL_NO_ERROR);
}
......@@ -1538,152 +1428,9 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi
return count >= minCount;
}
void Renderer11::unsetConflictingSRVs(gl::SamplerType samplerType, uintptr_t resource, const gl::ImageIndex &index)
{
auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex)
{
auto &record = currentSRVs[resourceIndex];
if (record.srv && record.resource == resource && ImageIndexConflictsWithSRV(index, record.desc))
{
setShaderResource(samplerType, static_cast<UINT>(resourceIndex), NULL);
}
}
}
gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
{
// Get the color render buffer and serial
// Also extract the render target dimensions and view
unsigned int renderTargetWidth = 0;
unsigned int renderTargetHeight = 0;
ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
bool missingColorRenderTarget = true;
const FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer);
const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender();
for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
{
const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
if (colorbuffer)
{
// the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order)
// check for zero-sized default framebuffer, which is a special case.
// in this case we do not wish to modify any state and just silently return false.
// this will not report any gl error but will cause the calling method to return.
const gl::Extents &size = colorbuffer->getSize();
if (size.width == 0 || size.height == 0)
{
return gl::Error(GL_NO_ERROR);
}
// Extract the render target dimensions and view
RenderTarget11 *renderTarget = NULL;
gl::Error error = colorbuffer->getRenderTarget(&renderTarget);
if (error.isError())
{
return error;
}
ASSERT(renderTarget);
framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
ASSERT(framebufferRTVs[colorAttachment]);
if (missingColorRenderTarget)
{
renderTargetWidth = renderTarget->getWidth();
renderTargetHeight = renderTarget->getHeight();
missingColorRenderTarget = false;
}
// Unbind render target SRVs from the shader here to prevent D3D11 warnings.
if (colorbuffer->type() == GL_TEXTURE)
{
uintptr_t rtResource = reinterpret_cast<uintptr_t>(GetViewResource(framebufferRTVs[colorAttachment]));
const gl::ImageIndex &index = colorbuffer->getTextureImageIndex();
// The index doesn't need to be corrected for the small compressed texture workaround
// because a rendertarget is never compressed.
unsetConflictingSRVs(gl::SAMPLER_VERTEX, rtResource, index);
unsetConflictingSRVs(gl::SAMPLER_PIXEL, rtResource, index);
}
}
}
// Get the depth stencil buffers
ID3D11DepthStencilView* framebufferDSV = NULL;
const gl::FramebufferAttachment *depthStencil = framebuffer->getDepthOrStencilbuffer();
if (depthStencil)
{
RenderTarget11 *depthStencilRenderTarget = NULL;
gl::Error error = depthStencil->getRenderTarget(&depthStencilRenderTarget);
if (error.isError())
{
SafeRelease(framebufferRTVs);
return error;
}
ASSERT(depthStencilRenderTarget);
framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
ASSERT(framebufferDSV);
// If there is no render buffer, the width, height and format values come from
// the depth stencil
if (missingColorRenderTarget)
{
renderTargetWidth = depthStencilRenderTarget->getWidth();
renderTargetHeight = depthStencilRenderTarget->getHeight();
}
// Unbind render target SRVs from the shader here to prevent D3D11 warnings.
if (depthStencil->type() == GL_TEXTURE)
{
uintptr_t depthStencilResource = reinterpret_cast<uintptr_t>(GetViewResource(framebufferDSV));
const gl::ImageIndex &index = depthStencil->getTextureImageIndex();
// The index doesn't need to be corrected for the small compressed texture workaround
// because a rendertarget is never compressed.
unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index);
unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index);
}
unsigned int stencilSize = depthStencil->getStencilSize();
mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize);
}
// Apply the render target and depth stencil
if (!mDepthStencilInitialized ||
memcmp(framebufferRTVs, mAppliedRTVs, sizeof(framebufferRTVs)) != 0 ||
reinterpret_cast<uintptr_t>(framebufferDSV) != mAppliedDSV)
{
mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV);
mStateManager.setViewportBounds(renderTargetWidth, renderTargetHeight);
mStateManager.forceSetBlendState();
if (!mDepthStencilInitialized)
{
mStateManager.forceSetRasterState();
}
for (size_t rtIndex = 0; rtIndex < ArraySize(framebufferRTVs); rtIndex++)
{
mAppliedRTVs[rtIndex] = reinterpret_cast<uintptr_t>(framebufferRTVs[rtIndex]);
}
mAppliedDSV = reinterpret_cast<uintptr_t>(framebufferDSV);
mDepthStencilInitialized = true;
}
const Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
gl::Error error = framebuffer11->invalidateSwizzles();
if (error.isError())
{
return error;
}
return gl::Error(GL_NO_ERROR);
return mStateManager.syncFramebuffer(framebuffer);
}
gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceInfo)
......@@ -2431,39 +2178,25 @@ void Renderer11::markAllStateDirty()
{
TRACE_EVENT0("gpu.angle", "Renderer11::markAllStateDirty");
markRenderTargetStateDirty();
// We reset the current SRV data because it might not be in sync with D3D's state
// anymore. For example when a currently used SRV is used as an RTV, D3D silently
// remove it from its state.
mCurVertexSRVs.clear();
mCurPixelSRVs.clear();
ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexSRVs.size());
for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId)
{
mForceSetVertexSamplerStates[vsamplerId] = true;
}
ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelSRVs.size());
for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId)
{
mForceSetPixelSamplerStates[fsamplerId] = true;
}
mStateManager.forceSetBlendState();
mStateManager.forceSetDepthStencilState();
mStateManager.forceSetRasterState();
mStateManager.forceSetScissorState();
mStateManager.forceSetViewportState();
mStateManager.invalidateEverything();
mAppliedIB = NULL;
mAppliedIBFormat = DXGI_FORMAT_UNKNOWN;
mAppliedIBOffset = 0;
mAppliedVertexShader = DirtyPointer;
mAppliedGeometryShader = DirtyPointer;
mAppliedPixelShader = DirtyPointer;
mAppliedVertexShader = angle::DirtyPointer;
mAppliedGeometryShader = angle::DirtyPointer;
mAppliedPixelShader = angle::DirtyPointer;
mAppliedNumXFBBindings = static_cast<size_t>(-1);
......@@ -2495,16 +2228,6 @@ void Renderer11::markAllStateDirty()
mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
}
void Renderer11::markRenderTargetStateDirty()
{
for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++)
{
mAppliedRTVs[rtIndex] = DirtyPointer;
}
mAppliedDSV = DirtyPointer;
mDepthStencilInitialized = false;
}
void Renderer11::releaseDeviceResources()
{
mStateCache.clear();
......@@ -3069,9 +2792,9 @@ void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView
// Do not preserve the serial for this one-time-use render target
for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++)
{
mAppliedRTVs[rtIndex] = DirtyPointer;
mAppliedRTVs[rtIndex] = angle::DirtyPointer;
}
mAppliedDSV = DirtyPointer;
mAppliedDSV = angle::DirtyPointer;
}
gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT)
......@@ -4185,28 +3908,6 @@ WorkaroundsD3D Renderer11::generateWorkarounds() const
return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps.featureLevel);
}
void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv)
{
auto &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size());
const SRVRecord &record = currentSRVs[resourceSlot];
if (record.srv != reinterpret_cast<uintptr_t>(srv))
{
if (shaderType == gl::SAMPLER_VERTEX)
{
mDeviceContext->VSSetShaderResources(resourceSlot, 1, &srv);
}
else
{
mDeviceContext->PSSetShaderResources(resourceSlot, 1, &srv);
}
currentSRVs.update(resourceSlot, srv);
}
}
void Renderer11::createAnnotator()
{
// The D3D11 renderer must choose the D3D9 debug annotator because the D3D11 interface
......@@ -4223,40 +3924,7 @@ void Renderer11::createAnnotator()
gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd)
{
if (rangeStart == rangeEnd)
{
return gl::Error(GL_NO_ERROR);
}
auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
gl::Range<size_t> clearRange(rangeStart, rangeStart);
clearRange.extend(std::min(rangeEnd, currentSRVs.highestUsed()));
if (clearRange.empty())
{
return gl::Error(GL_NO_ERROR);
}
if (samplerType == gl::SAMPLER_VERTEX)
{
mDeviceContext->VSSetShaderResources(static_cast<unsigned int>(rangeStart),
static_cast<unsigned int>(rangeEnd - rangeStart),
&mNullSRVs[0]);
}
else
{
mDeviceContext->PSSetShaderResources(static_cast<unsigned int>(rangeStart),
static_cast<unsigned int>(rangeEnd - rangeStart),
&mNullSRVs[0]);
}
for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; ++samplerIndex)
{
currentSRVs.update(samplerIndex, nullptr);
}
return gl::Error(GL_NO_ERROR);
return mStateManager.clearTextures(samplerType, rangeStart, rangeEnd);
}
egl::Error Renderer11::getEGLDevice(DeviceImpl **device)
......
......@@ -145,9 +145,6 @@ class Renderer11 : public RendererD3D
SourceIndexData *sourceIndexInfo) override;
void applyTransformFeedbackBuffers(const gl::State &state) override;
virtual void markAllStateDirty();
void markRenderTargetStateDirty();
// lost device
bool testDeviceLost() override;
bool testDeviceResettable() override;
......@@ -254,6 +251,7 @@ class Renderer11 : public RendererD3D
virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
void markAllStateDirty();
void unapplyRenderTargets();
void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView);
gl::Error packPixels(const TextureHelper11 &textureHelper,
......@@ -272,8 +270,6 @@ class Renderer11 : public RendererD3D
const gl::PixelPackState &pack,
uint8_t *pixels);
void setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv);
gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget,
RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
bool colorBlit, bool depthBlit, bool stencilBlit);
......@@ -283,6 +279,7 @@ class Renderer11 : public RendererD3D
RendererClass getRendererClass() const override { return RENDERER_D3D11; }
InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; }
StateManager11 *getStateManager() { return &mStateManager; }
void onSwap();
void onBufferDelete(const Buffer11 *deleted);
......@@ -329,7 +326,6 @@ class Renderer11 : public RendererD3D
int instances);
ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
void unsetConflictingSRVs(gl::SamplerType shaderType, uintptr_t resource, const gl::ImageIndex &index);
void populateRenderer11DeviceCaps();
......@@ -366,49 +362,6 @@ class Renderer11 : public RendererD3D
std::vector<bool> mForceSetPixelSamplerStates;
std::vector<gl::SamplerState> mCurPixelSamplerStates;
// Currently applied textures
struct SRVRecord
{
uintptr_t srv;
uintptr_t resource;
D3D11_SHADER_RESOURCE_VIEW_DESC desc;
};
// A cache of current SRVs that also tracks the highest 'used' (non-NULL) SRV
// We might want to investigate a more robust approach that is also fast when there's
// a large gap between used SRVs (e.g. if SRV 0 and 7 are non-NULL, this approach will
// waste time on SRVs 1-6.)
class SRVCache : angle::NonCopyable
{
public:
SRVCache()
: mHighestUsedSRV(0)
{
}
void initialize(size_t size)
{
mCurrentSRVs.resize(size);
}
size_t size() const { return mCurrentSRVs.size(); }
size_t highestUsed() const { return mHighestUsedSRV; }
const SRVRecord &operator[](size_t index) const { return mCurrentSRVs[index]; }
void clear();
void update(size_t resourceIndex, ID3D11ShaderResourceView *srv);
private:
std::vector<SRVRecord> mCurrentSRVs;
size_t mHighestUsedSRV;
};
SRVCache mCurVertexSRVs;
SRVCache mCurPixelSRVs;
// A block of NULL pointers, cached so we don't re-allocate every draw call
std::vector<ID3D11ShaderResourceView*> mNullSRVs;
StateManager11 mStateManager;
// Currently applied primitive topology
......
......@@ -9,13 +9,128 @@
#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
#include "common/BitSetIterator.h"
#include "common/utilities.h"
#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
namespace rx
{
StateManager11::StateManager11()
: mBlendStateIsDirty(false),
namespace
{
bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
{
unsigned mipLevel = index.mipIndex;
unsigned layerIndex = index.layerIndex;
GLenum type = index.type;
switch (desc.ViewDimension)
{
case D3D11_SRV_DIMENSION_TEXTURE2D:
{
unsigned maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
maxSrvMip = (desc.Texture2D.MipLevels == -1) ? INT_MAX : maxSrvMip;
unsigned mipMin = index.mipIndex;
unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex;
return type == GL_TEXTURE_2D &&
gl::RangeUI(mipMin, mipMax)
.intersects(gl::RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip));
}
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
{
unsigned maxSrvMip =
desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip;
maxSrvMip = (desc.Texture2DArray.MipLevels == -1) ? INT_MAX : maxSrvMip;
unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize;
// Cube maps can be mapped to Texture2DArray SRVs
return (type == GL_TEXTURE_2D_ARRAY || gl::IsCubeMapTextureTarget(type)) &&
desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip &&
desc.Texture2DArray.FirstArraySlice <= layerIndex && layerIndex < maxSlice;
}
case D3D11_SRV_DIMENSION_TEXTURECUBE:
{
unsigned maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip;
maxSrvMip = (desc.TextureCube.MipLevels == -1) ? INT_MAX : maxSrvMip;
return gl::IsCubeMapTextureTarget(type) &&
desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
}
case D3D11_SRV_DIMENSION_TEXTURE3D:
{
unsigned maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip;
maxSrvMip = (desc.Texture3D.MipLevels == -1) ? INT_MAX : maxSrvMip;
return type == GL_TEXTURE_3D && desc.Texture3D.MostDetailedMip <= mipLevel &&
mipLevel < maxSrvMip;
}
default:
// We only handle the cases corresponding to valid image indexes
UNIMPLEMENTED();
}
return false;
}
// Does *not* increment the resource ref count!!
ID3D11Resource *GetViewResource(ID3D11View *view)
{
ID3D11Resource *resource = NULL;
ASSERT(view);
view->GetResource(&resource);
resource->Release();
return resource;
}
} // anonymous namespace
void StateManager11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv)
{
ASSERT(resourceIndex < mCurrentSRVs.size());
SRVRecord *record = &mCurrentSRVs[resourceIndex];
record->srv = reinterpret_cast<uintptr_t>(srv);
if (srv)
{
record->resource = reinterpret_cast<uintptr_t>(GetViewResource(srv));
srv->GetDesc(&record->desc);
mHighestUsedSRV = std::max(resourceIndex + 1, mHighestUsedSRV);
}
else
{
record->resource = 0;
if (resourceIndex + 1 == mHighestUsedSRV)
{
do
{
--mHighestUsedSRV;
} while (mHighestUsedSRV > 0 && mCurrentSRVs[mHighestUsedSRV].srv == 0);
}
}
}
void StateManager11::SRVCache::clear()
{
if (mCurrentSRVs.empty())
{
return;
}
memset(&mCurrentSRVs[0], 0, sizeof(SRVRecord) * mCurrentSRVs.size());
mHighestUsedSRV = 0;
}
StateManager11::StateManager11(Renderer11 *renderer)
: mRenderer(renderer),
mBlendStateIsDirty(false),
mCurBlendColor(0, 0, 0, 0),
mCurSampleMask(0),
mDepthStencilStateIsDirty(false),
......@@ -31,9 +146,9 @@ StateManager11::StateManager11()
mCurNear(0.0f),
mCurFar(0.0f),
mViewportBounds(),
mRenderer11DeviceCaps(nullptr),
mDeviceContext(nullptr),
mStateCache(nullptr)
mCurPresentPathFastEnabled(false),
mCurPresentPathFastColorBufferHeight(0),
mAppliedDSV(angle::DirtyPointer)
{
mCurBlendState.blend = false;
mCurBlendState.sourceBlendRGB = GL_ONE;
......@@ -80,15 +195,6 @@ StateManager11::~StateManager11()
{
}
void StateManager11::initialize(ID3D11DeviceContext *deviceContext,
RenderStateCache *stateCache,
Renderer11DeviceCaps *renderer11DeviceCaps)
{
mDeviceContext = deviceContext;
mStateCache = stateCache;
mRenderer11DeviceCaps = renderer11DeviceCaps;
}
void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
unsigned int stencilSize)
{
......@@ -101,7 +207,7 @@ void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
void StateManager11::setViewportBounds(const int width, const int height)
{
if (mRenderer11DeviceCaps->featureLevel <= D3D_FEATURE_LEVEL_9_3 &&
if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 &&
(mViewportBounds.width != width || mViewportBounds.height != height))
{
mViewportBounds = gl::Extents(width, height, 1);
......@@ -349,7 +455,8 @@ gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer,
}
ID3D11BlendState *dxBlendState = nullptr;
gl::Error error = mStateCache->getBlendState(framebuffer, blendState, &dxBlendState);
gl::Error error =
mRenderer->getStateCache().getBlendState(framebuffer, blendState, &dxBlendState);
if (error.isError())
{
return error;
......@@ -376,7 +483,7 @@ gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer,
blendColors[3] = blendColor.alpha;
}
mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState, blendColors, sampleMask);
mCurBlendState = blendState;
mCurBlendColor = blendColor;
......@@ -424,8 +531,8 @@ gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
(depthStencilState.stencilBackMask & maxStencil));
ID3D11DepthStencilState *dxDepthStencilState = NULL;
gl::Error error = mStateCache->getDepthStencilState(depthStencilState, disableDepth,
disableStencil, &dxDepthStencilState);
gl::Error error = mRenderer->getStateCache().getDepthStencilState(
depthStencilState, disableDepth, disableStencil, &dxDepthStencilState);
if (error.isError())
{
return error;
......@@ -443,7 +550,7 @@ gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
"Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu);
mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
mRenderer->getDeviceContext()->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
mCurDepthStencilState = depthStencilState;
mCurStencilRef = stencilRef;
......@@ -464,14 +571,14 @@ gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterSt
}
ID3D11RasterizerState *dxRasterState = nullptr;
gl::Error error =
mStateCache->getRasterizerState(rasterState, mCurScissorEnabled, &dxRasterState);
gl::Error error = mRenderer->getStateCache().getRasterizerState(rasterState, mCurScissorEnabled,
&dxRasterState);
if (error.isError())
{
return error;
}
mDeviceContext->RSSetState(dxRasterState);
mRenderer->getDeviceContext()->RSSetState(dxRasterState);
mCurRasterState = rasterState;
mRasterizerStateIsDirty = false;
......@@ -492,7 +599,7 @@ void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enab
rect.right = scissor.x + std::max(0, scissor.width);
rect.bottom = scissor.y + std::max(0, scissor.height);
mDeviceContext->RSSetScissorRects(1, &rect);
mRenderer->getDeviceContext()->RSSetScissorRects(1, &rect);
}
mCurScissorRect = scissor;
......@@ -516,7 +623,7 @@ void StateManager11::setViewport(const gl::Caps *caps,
int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
if (mRenderer11DeviceCaps->featureLevel <= D3D_FEATURE_LEVEL_9_3)
if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
{
// Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width);
......@@ -538,7 +645,7 @@ void StateManager11::setViewport(const gl::Caps *caps,
dxViewport.MinDepth = actualZNear;
dxViewport.MaxDepth = actualZFar;
mDeviceContext->RSSetViewports(1, &dxViewport);
mRenderer->getDeviceContext()->RSSetViewports(1, &dxViewport);
mCurViewport = viewport;
mCurNear = actualZNear;
......@@ -546,7 +653,7 @@ void StateManager11::setViewport(const gl::Caps *caps,
// On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
// using viewAdjust (like the D3D9 renderer).
if (mRenderer11DeviceCaps->featureLevel <= D3D_FEATURE_LEVEL_9_3)
if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
{
mVertexConstants.viewAdjust[0] = static_cast<float>((viewport.width - dxViewportWidth) +
2 * (viewport.x - dxViewportTopLeftX)) /
......@@ -584,4 +691,276 @@ void StateManager11::setViewport(const gl::Caps *caps,
mViewportStateIsDirty = false;
}
void StateManager11::invalidateRenderTarget()
{
for (auto &appliedRTV : mAppliedRTVs)
{
appliedRTV = angle::DirtyPointer;
}
mAppliedDSV = angle::DirtyPointer;
}
void StateManager11::invalidateEverything()
{
mBlendStateIsDirty = true;
mDepthStencilStateIsDirty = true;
mRasterizerStateIsDirty = true;
mScissorStateIsDirty = true;
mViewportStateIsDirty = true;
// We reset the current SRV data because it might not be in sync with D3D's state
// anymore. For example when a currently used SRV is used as an RTV, D3D silently
// remove it from its state.
mCurVertexSRVs.clear();
mCurPixelSRVs.clear();
invalidateRenderTarget();
}
bool StateManager11::setRenderTargets(const RenderTargetArray &renderTargets,
ID3D11DepthStencilView *depthStencil)
{
// TODO(jmadill): Use context caps?
UINT drawBuffers = mRenderer->getRendererCaps().maxDrawBuffers;
// Apply the render target and depth stencil
size_t arraySize = sizeof(uintptr_t) * drawBuffers;
if (memcmp(renderTargets.data(), mAppliedRTVs.data(), arraySize) == 0 &&
reinterpret_cast<uintptr_t>(depthStencil) == mAppliedDSV)
{
return false;
}
// The D3D11 blend state is heavily dependent on the current render target.
mBlendStateIsDirty = true;
for (UINT rtIndex = 0; rtIndex < drawBuffers; rtIndex++)
{
mAppliedRTVs[rtIndex] = reinterpret_cast<uintptr_t>(renderTargets[rtIndex]);
}
mAppliedDSV = reinterpret_cast<uintptr_t>(depthStencil);
mRenderer->getDeviceContext()->OMSetRenderTargets(drawBuffers, renderTargets.data(),
depthStencil);
return true;
}
void StateManager11::setRenderTarget(ID3D11RenderTargetView *renderTarget,
ID3D11DepthStencilView *depthStencil)
{
mRenderer->getDeviceContext()->OMSetRenderTargets(1, &renderTarget, depthStencil);
}
void StateManager11::setShaderResource(gl::SamplerType shaderType,
UINT resourceSlot,
ID3D11ShaderResourceView *srv)
{
auto &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size());
const SRVRecord &record = currentSRVs[resourceSlot];
if (record.srv != reinterpret_cast<uintptr_t>(srv))
{
auto deviceContext = mRenderer->getDeviceContext();
if (shaderType == gl::SAMPLER_VERTEX)
{
deviceContext->VSSetShaderResources(resourceSlot, 1, &srv);
}
else
{
deviceContext->PSSetShaderResources(resourceSlot, 1, &srv);
}
currentSRVs.update(resourceSlot, srv);
}
}
gl::Error StateManager11::clearTextures(gl::SamplerType samplerType,
size_t rangeStart,
size_t rangeEnd)
{
if (rangeStart == rangeEnd)
{
return gl::Error(GL_NO_ERROR);
}
auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
gl::Range<size_t> clearRange(rangeStart, rangeStart);
clearRange.extend(std::min(rangeEnd, currentSRVs.highestUsed()));
if (clearRange.empty())
{
return gl::Error(GL_NO_ERROR);
}
auto deviceContext = mRenderer->getDeviceContext();
if (samplerType == gl::SAMPLER_VERTEX)
{
deviceContext->VSSetShaderResources(static_cast<unsigned int>(rangeStart),
static_cast<unsigned int>(rangeEnd - rangeStart),
&mNullSRVs[0]);
}
else
{
deviceContext->PSSetShaderResources(static_cast<unsigned int>(rangeStart),
static_cast<unsigned int>(rangeEnd - rangeStart),
&mNullSRVs[0]);
}
for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; ++samplerIndex)
{
currentSRVs.update(samplerIndex, nullptr);
}
return gl::Error(GL_NO_ERROR);
}
void StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType,
uintptr_t resource,
const gl::ImageIndex &index)
{
auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex)
{
auto &record = currentSRVs[resourceIndex];
if (record.srv && record.resource == resource &&
ImageIndexConflictsWithSRV(index, record.desc))
{
setShaderResource(samplerType, static_cast<UINT>(resourceIndex), NULL);
}
}
}
void StateManager11::initialize(const gl::Caps &caps)
{
mCurVertexSRVs.initialize(caps.maxVertexTextureImageUnits);
mCurPixelSRVs.initialize(caps.maxTextureImageUnits);
// Initialize cached NULL SRV block
mNullSRVs.resize(caps.maxTextureImageUnits, nullptr);
}
gl::Error StateManager11::syncFramebuffer(const gl::Framebuffer *framebuffer)
{
// Get the color render buffer and serial
// Also extract the render target dimensions and view
unsigned int renderTargetWidth = 0;
unsigned int renderTargetHeight = 0;
DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN;
RenderTargetArray framebufferRTVs;
bool missingColorRenderTarget = true;
framebufferRTVs.fill(nullptr);
const Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
const gl::AttachmentList &colorbuffers = framebuffer11->getColorAttachmentsForRender();
for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
{
const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
if (colorbuffer)
{
// the draw buffer must be either "none", "back" for the default buffer or the same
// index as this color (in order)
// check for zero-sized default framebuffer, which is a special case.
// in this case we do not wish to modify any state and just silently return false.
// this will not report any gl error but will cause the calling method to return.
const gl::Extents &size = colorbuffer->getSize();
if (size.width == 0 || size.height == 0)
{
return gl::Error(GL_NO_ERROR);
}
// Extract the render target dimensions and view
RenderTarget11 *renderTarget = NULL;
gl::Error error = colorbuffer->getRenderTarget(&renderTarget);
if (error.isError())
{
return error;
}
ASSERT(renderTarget);
framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
ASSERT(framebufferRTVs[colorAttachment]);
if (missingColorRenderTarget)
{
renderTargetWidth = renderTarget->getWidth();
renderTargetHeight = renderTarget->getHeight();
renderTargetFormat = renderTarget->getDXGIFormat();
missingColorRenderTarget = false;
}
// Unbind render target SRVs from the shader here to prevent D3D11 warnings.
if (colorbuffer->type() == GL_TEXTURE)
{
uintptr_t rtResource =
reinterpret_cast<uintptr_t>(GetViewResource(framebufferRTVs[colorAttachment]));
const gl::ImageIndex &index = colorbuffer->getTextureImageIndex();
// The index doesn't need to be corrected for the small compressed texture
// workaround
// because a rendertarget is never compressed.
unsetConflictingSRVs(gl::SAMPLER_VERTEX, rtResource, index);
unsetConflictingSRVs(gl::SAMPLER_PIXEL, rtResource, index);
}
}
}
// Get the depth stencil buffers
ID3D11DepthStencilView *framebufferDSV = NULL;
const gl::FramebufferAttachment *depthStencil = framebuffer->getDepthOrStencilbuffer();
if (depthStencil)
{
RenderTarget11 *depthStencilRenderTarget = NULL;
gl::Error error = depthStencil->getRenderTarget(&depthStencilRenderTarget);
if (error.isError())
{
return error;
}
ASSERT(depthStencilRenderTarget);
framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
ASSERT(framebufferDSV);
// If there is no render buffer, the width, height and format values come from
// the depth stencil
if (missingColorRenderTarget)
{
renderTargetWidth = depthStencilRenderTarget->getWidth();
renderTargetHeight = depthStencilRenderTarget->getHeight();
}
// Unbind render target SRVs from the shader here to prevent D3D11 warnings.
if (depthStencil->type() == GL_TEXTURE)
{
uintptr_t depthStencilResource =
reinterpret_cast<uintptr_t>(GetViewResource(framebufferDSV));
const gl::ImageIndex &index = depthStencil->getTextureImageIndex();
// The index doesn't need to be corrected for the small compressed texture workaround
// because a rendertarget is never compressed.
unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index);
unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index);
}
}
if (setRenderTargets(framebufferRTVs, framebufferDSV))
{
setViewportBounds(renderTargetWidth, renderTargetHeight);
}
gl::Error error = framebuffer11->invalidateSwizzles();
if (error.isError())
{
return error;
}
return gl::Error(GL_NO_ERROR);
}
} // namespace rx
......@@ -9,10 +9,13 @@
#ifndef LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
#define LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
#include <array>
#include "libANGLE/angletypes.h"
#include "libANGLE/Data.h"
#include "libANGLE/State.h"
#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
namespace rx
......@@ -24,13 +27,10 @@ struct Renderer11DeviceCaps;
class StateManager11 final : angle::NonCopyable
{
public:
StateManager11();
StateManager11(Renderer11 *renderer);
~StateManager11();
void initialize(ID3D11DeviceContext *deviceContext,
RenderStateCache *stateCache,
Renderer11DeviceCaps *renderer11DeviceCaps);
void initialize(const gl::Caps &caps);
void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
gl::Error setBlendState(const gl::Framebuffer *framebuffer,
......@@ -46,19 +46,33 @@ class StateManager11 final : angle::NonCopyable
void setViewport(const gl::Caps *caps, const gl::Rectangle &viewport, float zNear, float zFar);
void forceSetBlendState() { mBlendStateIsDirty = true; }
void forceSetDepthStencilState() { mDepthStencilStateIsDirty = true; }
void forceSetRasterState() { mRasterizerStateIsDirty = true; }
void forceSetScissorState() { mScissorStateIsDirty = true; }
void forceSetViewportState() { mViewportStateIsDirty = true; }
void setViewportBounds(const int width, const int height);
const dx_VertexConstants &getVertexConstants() const { return mVertexConstants; }
const dx_PixelConstants &getPixelConstants() const { return mPixelConstants; }
void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
void setShaderResource(gl::SamplerType shaderType,
UINT resourceSlot,
ID3D11ShaderResourceView *srv);
gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd);
gl::Error syncFramebuffer(const gl::Framebuffer *framebuffer);
void invalidateRenderTarget();
void invalidateEverything();
bool setRenderTargets(const RenderTargetArray &renderTargets,
ID3D11DepthStencilView *depthStencil);
void setRenderTarget(ID3D11RenderTargetView *renderTarget,
ID3D11DepthStencilView *depthStencil);
private:
void unsetConflictingSRVs(gl::SamplerType shaderType,
uintptr_t resource,
const gl::ImageIndex &index);
void setViewportBounds(const int width, const int height);
Renderer11 *mRenderer;
// Blend State
bool mBlendStateIsDirty;
// TODO(dianx) temporary representation of a dirty bit. once we move enough states in,
......@@ -98,9 +112,50 @@ class StateManager11 final : angle::NonCopyable
// Render target variables
gl::Extents mViewportBounds;
Renderer11DeviceCaps *mRenderer11DeviceCaps;
ID3D11DeviceContext *mDeviceContext;
RenderStateCache *mStateCache;
// EGL_ANGLE_experimental_present_path variables
bool mCurPresentPathFastEnabled;
int mCurPresentPathFastColorBufferHeight;
// Current RenderTarget state
std::array<uintptr_t, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS> mAppliedRTVs;
uintptr_t mAppliedDSV;
// Currently applied textures
struct SRVRecord
{
uintptr_t srv;
uintptr_t resource;
D3D11_SHADER_RESOURCE_VIEW_DESC desc;
};
// A cache of current SRVs that also tracks the highest 'used' (non-NULL) SRV
// We might want to investigate a more robust approach that is also fast when there's
// a large gap between used SRVs (e.g. if SRV 0 and 7 are non-NULL, this approach will
// waste time on SRVs 1-6.)
class SRVCache : angle::NonCopyable
{
public:
SRVCache() : mHighestUsedSRV(0) {}
void initialize(size_t size) { mCurrentSRVs.resize(size); }
size_t size() const { return mCurrentSRVs.size(); }
size_t highestUsed() const { return mHighestUsedSRV; }
const SRVRecord &operator[](size_t index) const { return mCurrentSRVs[index]; }
void clear();
void update(size_t resourceIndex, ID3D11ShaderResourceView *srv);
private:
std::vector<SRVRecord> mCurrentSRVs;
size_t mHighestUsedSRV;
};
SRVCache mCurVertexSRVs;
SRVCache mCurPixelSRVs;
// A block of NULL pointers, cached so we don't re-allocate every draw call
std::vector<ID3D11ShaderResourceView *> mNullSRVs;
};
} // namespace rx
......
......@@ -746,7 +746,8 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
deviceContext->RSSetViewports(1, &viewport);
// Apply textures
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView);
auto stateManager = mRenderer->getStateManager();
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView);
deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
// Draw
......@@ -755,7 +756,7 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
// Rendering to the swapchain is now complete. Now we can call Present().
// Before that, we perform any cleanup on the D3D device. We do this before Present() to make sure the
// cleanup is caught under the current eglSwapBuffers() PIX/Graphics Diagnostics call rather than the next one.
mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
mRenderer->unapplyRenderTargets();
mRenderer->markAllStateDirty();
......@@ -803,7 +804,7 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height)
// Some swapping mechanisms such as DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL unbind the current render
// target. Mark it dirty.
mRenderer->markRenderTargetStateDirty();
mRenderer->getStateManager()->invalidateRenderTarget();
if (result == DXGI_ERROR_DEVICE_REMOVED)
{
......
......@@ -10,13 +10,14 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
#include <array>
#include <vector>
#include "libANGLE/angletypes.h"
#include "libANGLE/Caps.h"
#include "libANGLE/Error.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include <vector>
namespace gl
{
class FramebufferAttachment;
......@@ -28,6 +29,8 @@ class RenderTarget11;
struct WorkaroundsD3D;
struct Renderer11DeviceCaps;
using RenderTargetArray = std::array<ID3D11RenderTargetView *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>;
namespace gl_d3d11
{
......
......@@ -2007,14 +2007,14 @@ void Renderer9::markAllStateDirty()
for (unsigned int i = 0; i < mCurVertexTextures.size(); i++)
{
mCurVertexSamplerStates[i].forceSet = true;
mCurVertexTextures[i] = DirtyPointer;
mCurVertexTextures[i] = angle::DirtyPointer;
}
ASSERT(mCurPixelSamplerStates.size() == mCurPixelTextures.size());
for (unsigned int i = 0; i < mCurPixelSamplerStates.size(); i++)
{
mCurPixelSamplerStates[i].forceSet = true;
mCurPixelTextures[i] = DirtyPointer;
mCurPixelTextures[i] = angle::DirtyPointer;
}
mAppliedIBSerial = 0;
......
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