diff options
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp | 3075 |
1 files changed, 0 insertions, 3075 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp deleted file mode 100644 index e9902d3f14..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp +++ /dev/null @@ -1,3075 +0,0 @@ -// -// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// StateManager11.cpp: Defines a class for caching D3D11 state - -#include "libANGLE/renderer/d3d/d3d11/StateManager11.h" - -#include "common/bitset_utils.h" -#include "common/utilities.h" -#include "libANGLE/Context.h" -#include "libANGLE/Query.h" -#include "libANGLE/VertexArray.h" -#include "libANGLE/renderer/d3d/TextureD3D.h" -#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" -#include "libANGLE/renderer/d3d/d3d11/Context11.h" -#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" -#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" -#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" -#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" -#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" -#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" -#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h" -#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" - -namespace rx -{ - -namespace -{ -bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc) -{ - unsigned mipLevel = index.mipIndex; - GLint layerIndex = index.layerIndex; - GLenum type = index.type; - - switch (desc.ViewDimension) - { - case D3D11_SRV_DIMENSION_TEXTURE2D: - { - bool allLevels = (desc.Texture2D.MipLevels == std::numeric_limits<UINT>::max()); - unsigned int maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip; - maxSrvMip = allLevels ? 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: - { - bool allLevels = (desc.Texture2DArray.MipLevels == std::numeric_limits<UINT>::max()); - unsigned int maxSrvMip = - desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip; - maxSrvMip = allLevels ? 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 <= static_cast<UINT>(layerIndex) && - static_cast<UINT>(layerIndex) < maxSlice; - } - - case D3D11_SRV_DIMENSION_TEXTURECUBE: - { - bool allLevels = (desc.TextureCube.MipLevels == std::numeric_limits<UINT>::max()); - unsigned int maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip; - maxSrvMip = allLevels ? INT_MAX : maxSrvMip; - - return gl::IsCubeMapTextureTarget(type) && - desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip; - } - - case D3D11_SRV_DIMENSION_TEXTURE3D: - { - bool allLevels = (desc.Texture3D.MipLevels == std::numeric_limits<UINT>::max()); - unsigned int maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip; - maxSrvMip = allLevels ? 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 = nullptr; - ASSERT(view); - view->GetResource(&resource); - resource->Release(); - return resource; -} - -int GetWrapBits(GLenum wrap) -{ - switch (wrap) - { - case GL_CLAMP_TO_EDGE: - return 0x1; - case GL_REPEAT: - return 0x2; - case GL_MIRRORED_REPEAT: - return 0x3; - default: - UNREACHABLE(); - return 0; - } -} - -Optional<size_t> FindFirstNonInstanced( - const std::vector<const TranslatedAttribute *> ¤tAttributes) -{ - for (size_t index = 0; index < currentAttributes.size(); ++index) - { - if (currentAttributes[index]->divisor == 0) - { - return Optional<size_t>(index); - } - } - - return Optional<size_t>::Invalid(); -} - -void SortAttributesByLayout(const gl::Program *program, - const std::vector<TranslatedAttribute> &vertexArrayAttribs, - const std::vector<TranslatedAttribute> ¤tValueAttribs, - AttribIndexArray *sortedD3DSemanticsOut, - std::vector<const TranslatedAttribute *> *sortedAttributesOut) -{ - sortedAttributesOut->clear(); - - const auto &locationToSemantic = - GetImplAs<ProgramD3D>(program)->getAttribLocationToD3DSemantics(); - - for (auto locationIndex : program->getActiveAttribLocationsMask()) - { - int d3dSemantic = locationToSemantic[locationIndex]; - if (sortedAttributesOut->size() <= static_cast<size_t>(d3dSemantic)) - { - sortedAttributesOut->resize(d3dSemantic + 1); - } - - (*sortedD3DSemanticsOut)[d3dSemantic] = d3dSemantic; - - const auto *arrayAttrib = &vertexArrayAttribs[locationIndex]; - if (arrayAttrib->attribute && arrayAttrib->attribute->enabled) - { - (*sortedAttributesOut)[d3dSemantic] = arrayAttrib; - } - else - { - ASSERT(currentValueAttribs[locationIndex].attribute); - (*sortedAttributesOut)[d3dSemantic] = ¤tValueAttribs[locationIndex]; - } - } -} - -void UpdateUniformBuffer(ID3D11DeviceContext *deviceContext, - UniformStorage11 *storage, - const d3d11::Buffer *buffer) -{ - deviceContext->UpdateSubresource(buffer->get(), 0, nullptr, storage->getDataPointer(0, 0), 0, - 0); -} - -} // anonymous namespace - -// StateManager11::SRVCache Implementation. - -StateManager11::SRVCache::SRVCache() : mHighestUsedSRV(0) -{ -} - -StateManager11::SRVCache::~SRVCache() -{ -} - -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; -} - -// ShaderConstants11 implementation - -ShaderConstants11::ShaderConstants11() - : mVertexDirty(true), - mPixelDirty(true), - mComputeDirty(true), - mSamplerMetadataVSDirty(true), - mSamplerMetadataPSDirty(true), - mSamplerMetadataCSDirty(true) -{ -} - -ShaderConstants11::~ShaderConstants11() -{ -} - -void ShaderConstants11::init(const gl::Caps &caps) -{ - mSamplerMetadataVS.resize(caps.maxVertexTextureImageUnits); - mSamplerMetadataPS.resize(caps.maxTextureImageUnits); - mSamplerMetadataCS.resize(caps.maxComputeTextureImageUnits); -} - -size_t ShaderConstants11::getRequiredBufferSize(gl::SamplerType samplerType) const -{ - switch (samplerType) - { - case gl::SAMPLER_VERTEX: - return sizeof(Vertex) + mSamplerMetadataVS.size() * sizeof(SamplerMetadata); - case gl::SAMPLER_PIXEL: - return sizeof(Pixel) + mSamplerMetadataPS.size() * sizeof(SamplerMetadata); - case gl::SAMPLER_COMPUTE: - return sizeof(Compute) + mSamplerMetadataCS.size() * sizeof(SamplerMetadata); - default: - UNREACHABLE(); - return 0; - } -} - -void ShaderConstants11::markDirty() -{ - mVertexDirty = true; - mPixelDirty = true; - mComputeDirty = true; - mSamplerMetadataVSDirty = true; - mSamplerMetadataPSDirty = true; - mSamplerMetadataCSDirty = true; -} - -bool ShaderConstants11::updateSamplerMetadata(SamplerMetadata *data, const gl::Texture &texture) -{ - bool dirty = false; - unsigned int baseLevel = texture.getTextureState().getEffectiveBaseLevel(); - GLenum sizedFormat = - texture.getFormat(texture.getTarget(), baseLevel).info->sizedInternalFormat; - if (data->baseLevel != static_cast<int>(baseLevel)) - { - data->baseLevel = static_cast<int>(baseLevel); - dirty = true; - } - - // Some metadata is needed only for integer textures. We avoid updating the constant buffer - // unnecessarily by changing the data only in case the texture is an integer texture and - // the values have changed. - bool needIntegerTextureMetadata = false; - // internalFormatBits == 0 means a 32-bit texture in the case of integer textures. - int internalFormatBits = 0; - switch (sizedFormat) - { - case GL_RGBA32I: - case GL_RGBA32UI: - case GL_RGB32I: - case GL_RGB32UI: - case GL_RG32I: - case GL_RG32UI: - case GL_R32I: - case GL_R32UI: - needIntegerTextureMetadata = true; - break; - case GL_RGBA16I: - case GL_RGBA16UI: - case GL_RGB16I: - case GL_RGB16UI: - case GL_RG16I: - case GL_RG16UI: - case GL_R16I: - case GL_R16UI: - needIntegerTextureMetadata = true; - internalFormatBits = 16; - break; - case GL_RGBA8I: - case GL_RGBA8UI: - case GL_RGB8I: - case GL_RGB8UI: - case GL_RG8I: - case GL_RG8UI: - case GL_R8I: - case GL_R8UI: - needIntegerTextureMetadata = true; - internalFormatBits = 8; - break; - case GL_RGB10_A2UI: - needIntegerTextureMetadata = true; - internalFormatBits = 10; - break; - default: - break; - } - if (needIntegerTextureMetadata) - { - if (data->internalFormatBits != internalFormatBits) - { - data->internalFormatBits = internalFormatBits; - dirty = true; - } - // Pack the wrap values into one integer so we can fit all the metadata in one 4-integer - // vector. - GLenum wrapS = texture.getWrapS(); - GLenum wrapT = texture.getWrapT(); - GLenum wrapR = texture.getWrapR(); - int wrapModes = GetWrapBits(wrapS) | (GetWrapBits(wrapT) << 2) | (GetWrapBits(wrapR) << 4); - if (data->wrapModes != wrapModes) - { - data->wrapModes = wrapModes; - dirty = true; - } - } - - return dirty; -} - -void ShaderConstants11::setComputeWorkGroups(GLuint numGroupsX, - GLuint numGroupsY, - GLuint numGroupsZ) -{ - mCompute.numWorkGroups[0] = numGroupsX; - mCompute.numWorkGroups[1] = numGroupsY; - mCompute.numWorkGroups[2] = numGroupsZ; - mComputeDirty = true; -} - -void ShaderConstants11::setMultiviewWriteToViewportIndex(GLfloat index) -{ - mVertex.multiviewWriteToViewportIndex = index; - mVertexDirty = true; - mPixel.multiviewWriteToViewportIndex = index; - mPixelDirty = true; -} - -void ShaderConstants11::onViewportChange(const gl::Rectangle &glViewport, - const D3D11_VIEWPORT &dxViewport, - bool is9_3, - bool presentPathFast) -{ - mVertexDirty = true; - mPixelDirty = true; - - // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders - // using viewAdjust (like the D3D9 renderer). - if (is9_3) - { - mVertex.viewAdjust[0] = static_cast<float>((glViewport.width - dxViewport.Width) + - 2 * (glViewport.x - dxViewport.TopLeftX)) / - dxViewport.Width; - mVertex.viewAdjust[1] = static_cast<float>((glViewport.height - dxViewport.Height) + - 2 * (glViewport.y - dxViewport.TopLeftY)) / - dxViewport.Height; - mVertex.viewAdjust[2] = static_cast<float>(glViewport.width) / dxViewport.Width; - mVertex.viewAdjust[3] = static_cast<float>(glViewport.height) / dxViewport.Height; - } - - mPixel.viewCoords[0] = glViewport.width * 0.5f; - mPixel.viewCoords[1] = glViewport.height * 0.5f; - mPixel.viewCoords[2] = glViewport.x + (glViewport.width * 0.5f); - mPixel.viewCoords[3] = glViewport.y + (glViewport.height * 0.5f); - - // Instanced pointsprite emulation requires ViewCoords to be defined in the - // the vertex shader. - mVertex.viewCoords[0] = mPixel.viewCoords[0]; - mVertex.viewCoords[1] = mPixel.viewCoords[1]; - mVertex.viewCoords[2] = mPixel.viewCoords[2]; - mVertex.viewCoords[3] = mPixel.viewCoords[3]; - - const float zNear = dxViewport.MinDepth; - const float zFar = dxViewport.MaxDepth; - - mPixel.depthFront[0] = (zFar - zNear) * 0.5f; - mPixel.depthFront[1] = (zNear + zFar) * 0.5f; - - mVertex.depthRange[0] = zNear; - mVertex.depthRange[1] = zFar; - mVertex.depthRange[2] = zFar - zNear; - - mPixel.depthRange[0] = zNear; - mPixel.depthRange[1] = zFar; - mPixel.depthRange[2] = zFar - zNear; - - mPixel.viewScale[0] = 1.0f; - mPixel.viewScale[1] = presentPathFast ? 1.0f : -1.0f; - // Updates to the multiviewWriteToViewportIndex member are to be handled whenever the draw - // framebuffer's layout is changed. - - mVertex.viewScale[0] = mPixel.viewScale[0]; - mVertex.viewScale[1] = mPixel.viewScale[1]; -} - -void ShaderConstants11::onSamplerChange(gl::SamplerType samplerType, - unsigned int samplerIndex, - const gl::Texture &texture) -{ - switch (samplerType) - { - case gl::SAMPLER_VERTEX: - if (updateSamplerMetadata(&mSamplerMetadataVS[samplerIndex], texture)) - { - mSamplerMetadataVSDirty = true; - } - break; - case gl::SAMPLER_PIXEL: - if (updateSamplerMetadata(&mSamplerMetadataPS[samplerIndex], texture)) - { - mSamplerMetadataPSDirty = true; - } - break; - case gl::SAMPLER_COMPUTE: - if (updateSamplerMetadata(&mSamplerMetadataCS[samplerIndex], texture)) - { - mSamplerMetadataCSDirty = true; - } - break; - default: - UNREACHABLE(); - break; - } -} - -gl::Error ShaderConstants11::updateBuffer(ID3D11DeviceContext *deviceContext, - gl::SamplerType samplerType, - const ProgramD3D &programD3D, - const d3d11::Buffer &driverConstantBuffer) -{ - bool dirty = false; - size_t dataSize = 0; - const uint8_t *data = nullptr; - const uint8_t *samplerData = nullptr; - - switch (samplerType) - { - case gl::SAMPLER_VERTEX: - dirty = mVertexDirty || mSamplerMetadataVSDirty; - dataSize = sizeof(Vertex); - data = reinterpret_cast<const uint8_t *>(&mVertex); - samplerData = reinterpret_cast<const uint8_t *>(mSamplerMetadataVS.data()); - mVertexDirty = false; - mSamplerMetadataVSDirty = false; - break; - case gl::SAMPLER_PIXEL: - dirty = mPixelDirty || mSamplerMetadataPSDirty; - dataSize = sizeof(Pixel); - data = reinterpret_cast<const uint8_t *>(&mPixel); - samplerData = reinterpret_cast<const uint8_t *>(mSamplerMetadataPS.data()); - mPixelDirty = false; - mSamplerMetadataPSDirty = false; - break; - case gl::SAMPLER_COMPUTE: - dirty = mComputeDirty || mSamplerMetadataCSDirty; - dataSize = sizeof(Compute); - data = reinterpret_cast<const uint8_t *>(&mCompute); - samplerData = reinterpret_cast<const uint8_t *>(mSamplerMetadataCS.data()); - mComputeDirty = false; - mSamplerMetadataCSDirty = false; - break; - default: - UNREACHABLE(); - break; - } - - ASSERT(driverConstantBuffer.valid()); - - if (!dirty) - { - return gl::NoError(); - } - - // Previous buffer contents are discarded, so we need to refresh the whole buffer. - D3D11_MAPPED_SUBRESOURCE mapping = {0}; - HRESULT result = - deviceContext->Map(driverConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapping); - - if (FAILED(result)) - { - return gl::OutOfMemory() << "Internal error mapping constant buffer: " << gl::FmtHR(result); - } - - size_t samplerDataBytes = sizeof(SamplerMetadata) * programD3D.getUsedSamplerRange(samplerType); - - memcpy(mapping.pData, data, dataSize); - memcpy(reinterpret_cast<uint8_t *>(mapping.pData) + dataSize, samplerData, samplerDataBytes); - - deviceContext->Unmap(driverConstantBuffer.get(), 0); - - return gl::NoError(); -} - -static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE, - GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED_EXT, - GL_COMMANDS_COMPLETED_CHROMIUM}; - -StateManager11::StateManager11(Renderer11 *renderer) - : mRenderer(renderer), - mInternalDirtyBits(), - mCurBlendColor(0, 0, 0, 0), - mCurSampleMask(0), - mCurStencilRef(0), - mCurStencilBackRef(0), - mCurStencilSize(0), - mCurScissorEnabled(false), - mCurScissorRect(), - mCurViewport(), - mCurNear(0.0f), - mCurFar(0.0f), - mViewportBounds(), - mRenderTargetIsDirty(true), - mCurPresentPathFastEnabled(false), - mCurPresentPathFastColorBufferHeight(0), - mDirtyCurrentValueAttribs(), - mCurrentValueAttribs(), - mCurrentInputLayout(), - mInputLayoutIsDirty(false), - mVertexAttribsNeedTranslation(false), - mDirtyVertexBufferRange(gl::MAX_VERTEX_ATTRIBS, 0), - mCurrentPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED), - mDirtySwizzles(false), - mAppliedIB(nullptr), - mAppliedIBFormat(DXGI_FORMAT_UNKNOWN), - mAppliedIBOffset(0), - mIndexBufferIsDirty(false), - mVertexDataManager(renderer), - mIndexDataManager(renderer), - mIsMultiviewEnabled(false), - mEmptySerial(mRenderer->generateSerial()), - mIsTransformFeedbackCurrentlyActiveUnpaused(false) -{ - mCurBlendState.blend = false; - mCurBlendState.sourceBlendRGB = GL_ONE; - mCurBlendState.destBlendRGB = GL_ZERO; - mCurBlendState.sourceBlendAlpha = GL_ONE; - mCurBlendState.destBlendAlpha = GL_ZERO; - mCurBlendState.blendEquationRGB = GL_FUNC_ADD; - mCurBlendState.blendEquationAlpha = GL_FUNC_ADD; - mCurBlendState.colorMaskRed = true; - mCurBlendState.colorMaskBlue = true; - mCurBlendState.colorMaskGreen = true; - mCurBlendState.colorMaskAlpha = true; - mCurBlendState.sampleAlphaToCoverage = false; - mCurBlendState.dither = false; - - mCurDepthStencilState.depthTest = false; - mCurDepthStencilState.depthFunc = GL_LESS; - mCurDepthStencilState.depthMask = true; - mCurDepthStencilState.stencilTest = false; - mCurDepthStencilState.stencilMask = true; - mCurDepthStencilState.stencilFail = GL_KEEP; - mCurDepthStencilState.stencilPassDepthFail = GL_KEEP; - mCurDepthStencilState.stencilPassDepthPass = GL_KEEP; - mCurDepthStencilState.stencilWritemask = static_cast<GLuint>(-1); - mCurDepthStencilState.stencilBackFunc = GL_ALWAYS; - mCurDepthStencilState.stencilBackMask = static_cast<GLuint>(-1); - mCurDepthStencilState.stencilBackFail = GL_KEEP; - mCurDepthStencilState.stencilBackPassDepthFail = GL_KEEP; - mCurDepthStencilState.stencilBackPassDepthPass = GL_KEEP; - mCurDepthStencilState.stencilBackWritemask = static_cast<GLuint>(-1); - - mCurRasterState.rasterizerDiscard = false; - mCurRasterState.cullFace = false; - mCurRasterState.cullMode = gl::CullFaceMode::Back; - mCurRasterState.frontFace = GL_CCW; - mCurRasterState.polygonOffsetFill = false; - mCurRasterState.polygonOffsetFactor = 0.0f; - mCurRasterState.polygonOffsetUnits = 0.0f; - mCurRasterState.pointDrawMode = false; - mCurRasterState.multiSample = false; - - // Start with all internal dirty bits set. - mInternalDirtyBits.set(); - - // Initially all current value attributes must be updated on first use. - mDirtyCurrentValueAttribs.set(); - - mCurrentVertexBuffers.fill(nullptr); - mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max()); - mCurrentVertexOffsets.fill(std::numeric_limits<UINT>::max()); -} - -StateManager11::~StateManager11() -{ -} - -template <typename SRVType> -void StateManager11::setShaderResourceInternal(gl::SamplerType shaderType, - UINT resourceSlot, - const SRVType *srv) -{ - auto ¤tSRVs = (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)) - { - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - ID3D11ShaderResourceView *srvPtr = srv ? srv->get() : nullptr; - if (shaderType == gl::SAMPLER_VERTEX) - { - deviceContext->VSSetShaderResources(resourceSlot, 1, &srvPtr); - } - else - { - deviceContext->PSSetShaderResources(resourceSlot, 1, &srvPtr); - } - - currentSRVs.update(resourceSlot, srvPtr); - } -} - -void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized, - unsigned int stencilSize) -{ - if (!depthStencilInitialized || stencilSize != mCurStencilSize) - { - mCurStencilSize = stencilSize; - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); - } -} - -void StateManager11::checkPresentPath(const gl::Context *context) -{ - if (!mRenderer->presentPathFastEnabled()) - return; - - const auto *framebuffer = context->getGLState().getDrawFramebuffer(); - const auto *firstColorAttachment = framebuffer->getFirstColorbuffer(); - const bool presentPathFastActive = UsePresentPathFast(mRenderer, firstColorAttachment); - - const int colorBufferHeight = firstColorAttachment ? firstColorAttachment->getSize().height : 0; - - if ((mCurPresentPathFastEnabled != presentPathFastActive) || - (presentPathFastActive && (colorBufferHeight != mCurPresentPathFastColorBufferHeight))) - { - mCurPresentPathFastEnabled = presentPathFastActive; - mCurPresentPathFastColorBufferHeight = colorBufferHeight; - - // Scissor rect may need to be vertically inverted - mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); - - // Cull Mode may need to be inverted - mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); - - // Viewport may need to be vertically inverted - invalidateViewport(context); - } -} - -gl::Error StateManager11::updateStateForCompute(const gl::Context *context, - GLuint numGroupsX, - GLuint numGroupsY, - GLuint numGroupsZ) -{ - mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ); - - // TODO(jmadill): Use dirty bits. - const auto &glState = context->getGLState(); - auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); - programD3D->updateSamplerMapping(); - - // TODO(jmadill): Use dirty bits. - ANGLE_TRY(generateSwizzlesForShader(context, gl::SAMPLER_COMPUTE)); - - // TODO(jmadill): More complete implementation. - ANGLE_TRY(syncTextures(context)); - - // TODO(Xinghua): applyUniformBuffers for compute shader. - - return gl::NoError(); -} - -void StateManager11::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) -{ - if (!dirtyBits.any()) - { - return; - } - - const auto &state = context->getGLState(); - - for (auto dirtyBit : dirtyBits) - { - switch (dirtyBit) - { - case gl::State::DIRTY_BIT_BLEND_EQUATIONS: - { - const gl::BlendState &blendState = state.getBlendState(); - if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB || - blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha) - { - mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); - } - break; - } - case gl::State::DIRTY_BIT_BLEND_FUNCS: - { - const gl::BlendState &blendState = state.getBlendState(); - if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB || - blendState.destBlendRGB != mCurBlendState.destBlendRGB || - blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha || - blendState.destBlendAlpha != mCurBlendState.destBlendAlpha) - { - mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); - } - break; - } - case gl::State::DIRTY_BIT_BLEND_ENABLED: - if (state.getBlendState().blend != mCurBlendState.blend) - { - mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); - } - break; - case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: - if (state.getBlendState().sampleAlphaToCoverage != - mCurBlendState.sampleAlphaToCoverage) - { - mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); - } - break; - case gl::State::DIRTY_BIT_DITHER_ENABLED: - if (state.getBlendState().dither != mCurBlendState.dither) - { - mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); - } - break; - case gl::State::DIRTY_BIT_COLOR_MASK: - { - const gl::BlendState &blendState = state.getBlendState(); - if (blendState.colorMaskRed != mCurBlendState.colorMaskRed || - blendState.colorMaskGreen != mCurBlendState.colorMaskGreen || - blendState.colorMaskBlue != mCurBlendState.colorMaskBlue || - blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha) - { - mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); - } - break; - } - case gl::State::DIRTY_BIT_BLEND_COLOR: - if (state.getBlendColor() != mCurBlendColor) - { - mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); - } - break; - case gl::State::DIRTY_BIT_DEPTH_MASK: - if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask) - { - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); - } - break; - case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: - if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest) - { - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); - } - break; - case gl::State::DIRTY_BIT_DEPTH_FUNC: - if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc) - { - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); - } - break; - case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: - if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest) - { - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); - } - break; - case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: - { - const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); - if (depthStencil.stencilFunc != mCurDepthStencilState.stencilFunc || - depthStencil.stencilMask != mCurDepthStencilState.stencilMask || - state.getStencilRef() != mCurStencilRef) - { - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); - } - break; - } - case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: - { - const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); - if (depthStencil.stencilBackFunc != mCurDepthStencilState.stencilBackFunc || - depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask || - state.getStencilBackRef() != mCurStencilBackRef) - { - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); - } - break; - } - case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: - if (state.getDepthStencilState().stencilWritemask != - mCurDepthStencilState.stencilWritemask) - { - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); - } - break; - case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: - if (state.getDepthStencilState().stencilBackWritemask != - mCurDepthStencilState.stencilBackWritemask) - { - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); - } - break; - case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: - { - const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); - if (depthStencil.stencilFail != mCurDepthStencilState.stencilFail || - depthStencil.stencilPassDepthFail != - mCurDepthStencilState.stencilPassDepthFail || - depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass) - { - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); - } - break; - } - case gl::State::DIRTY_BIT_STENCIL_OPS_BACK: - { - const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); - if (depthStencil.stencilBackFail != mCurDepthStencilState.stencilBackFail || - depthStencil.stencilBackPassDepthFail != - mCurDepthStencilState.stencilBackPassDepthFail || - depthStencil.stencilBackPassDepthPass != - mCurDepthStencilState.stencilBackPassDepthPass) - { - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); - } - break; - } - case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: - if (state.getRasterizerState().cullFace != mCurRasterState.cullFace) - { - mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); - } - break; - case gl::State::DIRTY_BIT_CULL_FACE: - if (state.getRasterizerState().cullMode != mCurRasterState.cullMode) - { - mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); - } - break; - case gl::State::DIRTY_BIT_FRONT_FACE: - if (state.getRasterizerState().frontFace != mCurRasterState.frontFace) - { - mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); - } - break; - case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: - if (state.getRasterizerState().polygonOffsetFill != - mCurRasterState.polygonOffsetFill) - { - mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); - } - break; - case gl::State::DIRTY_BIT_POLYGON_OFFSET: - { - const gl::RasterizerState &rasterState = state.getRasterizerState(); - if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor || - rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits) - { - mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); - } - break; - } - case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED: - if (state.getRasterizerState().rasterizerDiscard != - mCurRasterState.rasterizerDiscard) - { - mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); - - // Enabling/disabling rasterizer discard affects the pixel shader. - invalidateShaders(); - } - break; - case gl::State::DIRTY_BIT_SCISSOR: - if (state.getScissor() != mCurScissorRect) - { - mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); - } - break; - case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: - if (state.isScissorTestEnabled() != mCurScissorEnabled) - { - mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); - // Rasterizer state update needs mCurScissorsEnabled and updates when it changes - mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); - } - break; - case gl::State::DIRTY_BIT_DEPTH_RANGE: - if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar) - { - invalidateViewport(context); - } - break; - case gl::State::DIRTY_BIT_VIEWPORT: - if (state.getViewport() != mCurViewport) - { - invalidateViewport(context); - } - break; - case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: - invalidateRenderTarget(); - if (mIsMultiviewEnabled) - { - handleMultiviewDrawFramebufferChange(context); - } - break; - case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING: - invalidateVertexBuffer(); - // Force invalidate the current value attributes, since the VertexArray11 keeps an - // internal cache of TranslatedAttributes, and they CurrentValue attributes are - // owned by the StateManager11/Context. - mDirtyCurrentValueAttribs.set(); - // Invalidate the cached index buffer. - mIndexBufferIsDirty = true; - break; - case gl::State::DIRTY_BIT_TEXTURE_BINDINGS: - invalidateTexturesAndSamplers(); - break; - case gl::State::DIRTY_BIT_SAMPLER_BINDINGS: - invalidateTexturesAndSamplers(); - break; - case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE: - { - mInternalDirtyBits.set(DIRTY_BIT_SHADERS); - invalidateVertexBuffer(); - invalidateRenderTarget(); - invalidateTexturesAndSamplers(); - invalidateProgramUniforms(); - invalidateProgramUniformBuffers(); - gl::VertexArray *vao = state.getVertexArray(); - if (mIsMultiviewEnabled && vao != nullptr) - { - // If ANGLE_multiview is enabled, the attribute divisor has to be updated for - // each binding. - VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao); - const gl::Program *program = state.getProgram(); - int numViews = 1; - if (program != nullptr && program->usesMultiview()) - { - numViews = program->getNumViews(); - } - vao11->markAllAttributeDivisorsForAdjustment(numViews); - } - break; - } - case gl::State::DIRTY_BIT_CURRENT_VALUES: - { - for (auto attribIndex : state.getAndResetDirtyCurrentValues()) - { - invalidateCurrentValueAttrib(attribIndex); - } - } - default: - break; - } - } - - // TODO(jmadill): Input layout and vertex buffer state. -} - -void StateManager11::handleMultiviewDrawFramebufferChange(const gl::Context *context) -{ - const auto &glState = context->getGLState(); - const gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer(); - ASSERT(drawFramebuffer != nullptr); - - // Update viewport offsets. - const std::vector<gl::Offset> *attachmentViewportOffsets = - drawFramebuffer->getViewportOffsets(); - const std::vector<gl::Offset> &viewportOffsets = - attachmentViewportOffsets != nullptr - ? *attachmentViewportOffsets - : gl::FramebufferAttachment::GetDefaultViewportOffsetVector(); - if (mViewportOffsets != viewportOffsets) - { - mViewportOffsets = viewportOffsets; - - // Because new viewport offsets are to be applied, we have to mark the internal viewport and - // scissor state as dirty. - invalidateViewport(context); - mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); - } - switch (drawFramebuffer->getMultiviewLayout()) - { - case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE: - mShaderConstants.setMultiviewWriteToViewportIndex(1.0f); - break; - case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE: - // Because the base view index is applied as an offset to the 2D texture array when the - // RTV is created, we just have to pass a boolean to select which code path is to be - // used. - mShaderConstants.setMultiviewWriteToViewportIndex(0.0f); - break; - default: - // There is no need to update the value in the constant buffer if the active framebuffer - // object does not have a multiview layout. - break; - } -} - -gl::Error StateManager11::syncBlendState(const gl::Context *context, - const gl::Framebuffer *framebuffer, - const gl::BlendState &blendState, - const gl::ColorF &blendColor, - unsigned int sampleMask) -{ - const d3d11::BlendState *dxBlendState = nullptr; - const d3d11::BlendStateKey &key = - RenderStateCache::GetBlendStateKey(context, framebuffer, blendState); - - ANGLE_TRY(mRenderer->getBlendState(key, &dxBlendState)); - - ASSERT(dxBlendState != nullptr); - - float blendColors[4] = {0.0f}; - if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && - blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && - blendState.destBlendRGB != GL_CONSTANT_ALPHA && - blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) - { - blendColors[0] = blendColor.red; - blendColors[1] = blendColor.green; - blendColors[2] = blendColor.blue; - blendColors[3] = blendColor.alpha; - } - else - { - blendColors[0] = blendColor.alpha; - blendColors[1] = blendColor.alpha; - blendColors[2] = blendColor.alpha; - blendColors[3] = blendColor.alpha; - } - - mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState->get(), blendColors, sampleMask); - - mCurBlendState = blendState; - mCurBlendColor = blendColor; - mCurSampleMask = sampleMask; - - return gl::NoError(); -} - -gl::Error StateManager11::syncDepthStencilState(const gl::State &glState) -{ - mCurDepthStencilState = glState.getDepthStencilState(); - mCurStencilRef = glState.getStencilRef(); - mCurStencilBackRef = glState.getStencilBackRef(); - - // get the maximum size of the stencil ref - unsigned int maxStencil = 0; - if (mCurDepthStencilState.stencilTest && mCurStencilSize > 0) - { - maxStencil = (1 << mCurStencilSize) - 1; - } - ASSERT((mCurDepthStencilState.stencilWritemask & maxStencil) == - (mCurDepthStencilState.stencilBackWritemask & maxStencil)); - ASSERT(mCurStencilRef == mCurStencilBackRef); - ASSERT((mCurDepthStencilState.stencilMask & maxStencil) == - (mCurDepthStencilState.stencilBackMask & maxStencil)); - - gl::DepthStencilState modifiedGLState = glState.getDepthStencilState(); - - ASSERT(mCurDisableDepth.valid() && mCurDisableStencil.valid()); - - if (mCurDisableDepth.value()) - { - modifiedGLState.depthTest = false; - modifiedGLState.depthMask = false; - } - - if (mCurDisableStencil.value()) - { - modifiedGLState.stencilWritemask = 0; - modifiedGLState.stencilBackWritemask = 0; - modifiedGLState.stencilTest = false; - } - - const d3d11::DepthStencilState *d3dState = nullptr; - ANGLE_TRY(mRenderer->getDepthStencilState(modifiedGLState, &d3dState)); - ASSERT(d3dState); - - // Max D3D11 stencil reference value is 0xFF, - // corresponding to the max 8 bits in a stencil buffer - // GL specifies we should clamp the ref value to the - // nearest bit depth when doing stencil ops - static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF, - "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>(mCurStencilRef, 0xFFu); - - mRenderer->getDeviceContext()->OMSetDepthStencilState(d3dState->get(), dxStencilRef); - - return gl::NoError(); -} - -gl::Error StateManager11::syncRasterizerState(const gl::Context *context, bool pointDrawMode) -{ - // TODO: Remove pointDrawMode and multiSample from gl::RasterizerState. - gl::RasterizerState rasterState = context->getGLState().getRasterizerState(); - rasterState.pointDrawMode = pointDrawMode; - rasterState.multiSample = mCurRasterState.multiSample; - - ID3D11RasterizerState *dxRasterState = nullptr; - - if (mCurPresentPathFastEnabled) - { - gl::RasterizerState modifiedRasterState = rasterState; - - // If prseent path fast is active then we need invert the front face state. - // This ensures that both gl_FrontFacing is correct, and front/back culling - // is performed correctly. - if (modifiedRasterState.frontFace == GL_CCW) - { - modifiedRasterState.frontFace = GL_CW; - } - else - { - ASSERT(modifiedRasterState.frontFace == GL_CW); - modifiedRasterState.frontFace = GL_CCW; - } - - ANGLE_TRY( - mRenderer->getRasterizerState(modifiedRasterState, mCurScissorEnabled, &dxRasterState)); - } - else - { - ANGLE_TRY(mRenderer->getRasterizerState(rasterState, mCurScissorEnabled, &dxRasterState)); - } - - mRenderer->getDeviceContext()->RSSetState(dxRasterState); - - mCurRasterState = rasterState; - - return gl::NoError(); -} - -void StateManager11::syncScissorRectangle(const gl::Rectangle &scissor, bool enabled) -{ - int modifiedScissorY = scissor.y; - if (mCurPresentPathFastEnabled) - { - modifiedScissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y; - } - - if (enabled) - { - std::array<D3D11_RECT, gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS> rectangles; - const UINT numRectangles = static_cast<UINT>(mViewportOffsets.size()); - for (UINT i = 0u; i < numRectangles; ++i) - { - D3D11_RECT &rect = rectangles[i]; - int x = scissor.x + mViewportOffsets[i].x; - int y = modifiedScissorY + mViewportOffsets[i].y; - rect.left = std::max(0, x); - rect.top = std::max(0, y); - rect.right = x + std::max(0, scissor.width); - rect.bottom = y + std::max(0, scissor.height); - } - mRenderer->getDeviceContext()->RSSetScissorRects(numRectangles, rectangles.data()); - } - - mCurScissorRect = scissor; - mCurScissorEnabled = enabled; -} - -void StateManager11::syncViewport(const gl::Context *context) -{ - const auto &glState = context->getGLState(); - gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); - float actualZNear = gl::clamp01(glState.getNearPlane()); - float actualZFar = gl::clamp01(glState.getFarPlane()); - - const auto &caps = context->getCaps(); - int dxMaxViewportBoundsX = static_cast<int>(caps.maxViewportWidth); - int dxMaxViewportBoundsY = static_cast<int>(caps.maxViewportHeight); - int dxMinViewportBoundsX = -dxMaxViewportBoundsX; - int dxMinViewportBoundsY = -dxMaxViewportBoundsY; - - bool is9_3 = mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3; - - if (is9_3) - { - // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget. - dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width); - dxMaxViewportBoundsY = static_cast<int>(mViewportBounds.height); - dxMinViewportBoundsX = 0; - dxMinViewportBoundsY = 0; - } - - const auto &viewport = glState.getViewport(); - std::array<D3D11_VIEWPORT, gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS> dxViewports; - const UINT numRectangles = static_cast<UINT>(mViewportOffsets.size()); - - int dxViewportTopLeftX = 0; - int dxViewportTopLeftY = 0; - int dxViewportWidth = 0; - int dxViewportHeight = 0; - - for (UINT i = 0u; i < numRectangles; ++i) - { - dxViewportTopLeftX = gl::clamp(viewport.x + mViewportOffsets[i].x, dxMinViewportBoundsX, - dxMaxViewportBoundsX); - dxViewportTopLeftY = gl::clamp(viewport.y + mViewportOffsets[i].y, dxMinViewportBoundsY, - dxMaxViewportBoundsY); - dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX); - dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY); - - D3D11_VIEWPORT &dxViewport = dxViewports[i]; - dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX); - if (mCurPresentPathFastEnabled) - { - // When present path fast is active and we're rendering to framebuffer 0, we must invert - // the viewport in Y-axis. - // NOTE: We delay the inversion until right before the call to RSSetViewports, and leave - // dxViewportTopLeftY unchanged. This allows us to calculate viewAdjust below using the - // unaltered dxViewportTopLeftY value. - dxViewport.TopLeftY = static_cast<float>(mCurPresentPathFastColorBufferHeight - - dxViewportTopLeftY - dxViewportHeight); - } - else - { - dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY); - } - - // The es 3.1 spec section 9.2 states that, "If there are no attachments, rendering - // will be limited to a rectangle having a lower left of (0, 0) and an upper right of - // (width, height), where width and height are the framebuffer object's default width - // and height." See http://anglebug.com/1594 - // If the Framebuffer has no color attachment and the default width or height is smaller - // than the current viewport, use the smaller of the two sizes. - // If framebuffer default width or height is 0, the params should not set. - if (!framebuffer->getFirstNonNullAttachment() && - (framebuffer->getDefaultWidth() || framebuffer->getDefaultHeight())) - { - dxViewport.Width = - static_cast<GLfloat>(std::min(viewport.width, framebuffer->getDefaultWidth())); - dxViewport.Height = - static_cast<GLfloat>(std::min(viewport.height, framebuffer->getDefaultHeight())); - } - else - { - dxViewport.Width = static_cast<float>(dxViewportWidth); - dxViewport.Height = static_cast<float>(dxViewportHeight); - } - dxViewport.MinDepth = actualZNear; - dxViewport.MaxDepth = actualZFar; - } - - mRenderer->getDeviceContext()->RSSetViewports(numRectangles, dxViewports.data()); - - mCurViewport = viewport; - mCurNear = actualZNear; - mCurFar = actualZFar; - - const D3D11_VIEWPORT adjustViewport = {static_cast<FLOAT>(dxViewportTopLeftX), - static_cast<FLOAT>(dxViewportTopLeftY), - static_cast<FLOAT>(dxViewportWidth), - static_cast<FLOAT>(dxViewportHeight), - actualZNear, - actualZFar}; - mShaderConstants.onViewportChange(viewport, adjustViewport, is9_3, mCurPresentPathFastEnabled); -} - -void StateManager11::invalidateRenderTarget() -{ - mRenderTargetIsDirty = true; -} - -void StateManager11::processFramebufferInvalidation(const gl::Context *context) -{ - if (!mRenderTargetIsDirty) - { - return; - } - - ASSERT(context); - - mRenderTargetIsDirty = false; - mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET); - - // The pixel shader is dependent on the output layout. - invalidateShaders(); - - // The D3D11 blend state is heavily dependent on the current render target. - mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); - - gl::Framebuffer *fbo = context->getGLState().getDrawFramebuffer(); - ASSERT(fbo); - - // Disable the depth test/depth write if we are using a stencil-only attachment. - // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read - // nor write to the unused depth part of this emulated texture. - bool disableDepth = (!fbo->hasDepth() && fbo->hasStencil()); - - // Similarly we disable the stencil portion of the DS attachment if the app only binds depth. - bool disableStencil = (fbo->hasDepth() && !fbo->hasStencil()); - - if (!mCurDisableDepth.valid() || disableDepth != mCurDisableDepth.value() || - !mCurDisableStencil.valid() || disableStencil != mCurDisableStencil.value()) - { - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); - mCurDisableDepth = disableDepth; - mCurDisableStencil = disableStencil; - } - - bool multiSample = (fbo->getCachedSamples(context) != 0); - if (multiSample != mCurRasterState.multiSample) - { - mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); - mCurRasterState.multiSample = multiSample; - } - - checkPresentPath(context); - - if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) - { - const auto *firstAttachment = fbo->getFirstNonNullAttachment(); - if (firstAttachment) - { - const auto &size = firstAttachment->getSize(); - if (mViewportBounds.width != size.width || mViewportBounds.height != size.height) - { - mViewportBounds = gl::Extents(size.width, size.height, 1); - invalidateViewport(context); - } - } - } -} - -void StateManager11::invalidateBoundViews() -{ - mCurVertexSRVs.clear(); - mCurPixelSRVs.clear(); - - invalidateRenderTarget(); -} - -void StateManager11::invalidateVertexBuffer() -{ - unsigned int limit = std::min<unsigned int>(mRenderer->getNativeCaps().maxVertexAttributes, - gl::MAX_VERTEX_ATTRIBS); - mDirtyVertexBufferRange = gl::RangeUI(0, limit); - mInputLayoutIsDirty = true; - mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS); - invalidateVertexAttributeTranslation(); -} - -void StateManager11::invalidateViewport(const gl::Context *context) -{ - mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE); - - // Viewport affects the driver constants. - invalidateDriverUniforms(); -} - -void StateManager11::invalidateTexturesAndSamplers() -{ - mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); - invalidateSwizzles(); - - // Texture state affects the driver uniforms (base level, etc). - invalidateDriverUniforms(); -} - -void StateManager11::invalidateSwizzles() -{ - mDirtySwizzles = true; -} - -void StateManager11::invalidateProgramUniforms() -{ - mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS); -} - -void StateManager11::invalidateDriverUniforms() -{ - mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS); -} - -void StateManager11::invalidateProgramUniformBuffers() -{ - mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS); -} - -void StateManager11::invalidateConstantBuffer(unsigned int slot) -{ - if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER) - { - invalidateDriverUniforms(); - } - else if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK) - { - invalidateProgramUniforms(); - } - else - { - invalidateProgramUniformBuffers(); - } -} - -void StateManager11::invalidateShaders() -{ - mInternalDirtyBits.set(DIRTY_BIT_SHADERS); -} - -void StateManager11::setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv) -{ - if ((rtv && unsetConflictingView(rtv)) || (dsv && unsetConflictingView(dsv))) - { - mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); - } - - mRenderer->getDeviceContext()->OMSetRenderTargets(1, &rtv, dsv); - mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET); -} - -void StateManager11::setRenderTargets(ID3D11RenderTargetView **rtvs, - UINT numRTVs, - ID3D11DepthStencilView *dsv) -{ - bool anyDirty = false; - - for (UINT rtvIndex = 0; rtvIndex < numRTVs; ++rtvIndex) - { - anyDirty = anyDirty || unsetConflictingView(rtvs[rtvIndex]); - } - - if (dsv) - { - anyDirty = anyDirty || unsetConflictingView(dsv); - } - - if (anyDirty) - { - mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); - } - - mRenderer->getDeviceContext()->OMSetRenderTargets(numRTVs, (numRTVs > 0) ? rtvs : nullptr, dsv); - mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET); -} - -void StateManager11::invalidateVertexAttributeTranslation() -{ - mVertexAttribsNeedTranslation = true; -} - -void StateManager11::onBeginQuery(Query11 *query) -{ - mCurrentQueries.insert(query); -} - -void StateManager11::onDeleteQueryObject(Query11 *query) -{ - mCurrentQueries.erase(query); -} - -gl::Error StateManager11::onMakeCurrent(const gl::Context *context) -{ - const gl::State &state = context->getGLState(); - - for (Query11 *query : mCurrentQueries) - { - ANGLE_TRY(query->pause()); - } - mCurrentQueries.clear(); - - for (GLenum queryType : QueryTypes) - { - gl::Query *query = state.getActiveQuery(queryType); - if (query != nullptr) - { - Query11 *query11 = GetImplAs<Query11>(query); - ANGLE_TRY(query11->resume()); - mCurrentQueries.insert(query11); - } - } - - return gl::NoError(); -} - -gl::Error StateManager11::clearTextures(gl::SamplerType samplerType, - size_t rangeStart, - size_t rangeEnd) -{ - if (rangeStart == rangeEnd) - { - return gl::NoError(); - } - - auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); - - gl::Range<size_t> clearRange(rangeStart, std::min(rangeEnd, currentSRVs.highestUsed())); - if (clearRange.empty()) - { - return gl::NoError(); - } - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - if (samplerType == gl::SAMPLER_VERTEX) - { - deviceContext->VSSetShaderResources(static_cast<unsigned int>(clearRange.low()), - static_cast<unsigned int>(clearRange.length()), - &mNullSRVs[0]); - } - else - { - deviceContext->PSSetShaderResources(static_cast<unsigned int>(clearRange.low()), - static_cast<unsigned int>(clearRange.length()), - &mNullSRVs[0]); - } - - for (size_t samplerIndex : clearRange) - { - currentSRVs.update(samplerIndex, nullptr); - } - - return gl::NoError(); -} - -bool StateManager11::unsetConflictingView(ID3D11View *view) -{ - uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(view)); - return unsetConflictingSRVs(gl::SAMPLER_VERTEX, resource, nullptr) || - unsetConflictingSRVs(gl::SAMPLER_PIXEL, resource, nullptr); -} - -bool StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType, - uintptr_t resource, - const gl::ImageIndex *index) -{ - auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); - - bool foundOne = false; - - for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex) - { - auto &record = currentSRVs[resourceIndex]; - - if (record.srv && record.resource == resource && - (!index || ImageIndexConflictsWithSRV(*index, record.desc))) - { - setShaderResourceInternal<d3d11::ShaderResourceView>( - samplerType, static_cast<UINT>(resourceIndex), nullptr); - foundOne = true; - } - } - - return foundOne; -} - -void StateManager11::unsetConflictingAttachmentResources( - const gl::FramebufferAttachment *attachment, - ID3D11Resource *resource) -{ - // Unbind render target SRVs from the shader here to prevent D3D11 warnings. - if (attachment->type() == GL_TEXTURE) - { - uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource); - const gl::ImageIndex &index = attachment->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, resourcePtr, &index); - unsetConflictingSRVs(gl::SAMPLER_PIXEL, resourcePtr, &index); - } - else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT) - { - uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource); - unsetConflictingSRVs(gl::SAMPLER_VERTEX, resourcePtr, nullptr); - unsetConflictingSRVs(gl::SAMPLER_PIXEL, resourcePtr, nullptr); - } -} - -gl::Error StateManager11::initialize(const gl::Caps &caps, const gl::Extensions &extensions) -{ - mCurVertexSRVs.initialize(caps.maxVertexTextureImageUnits); - mCurPixelSRVs.initialize(caps.maxTextureImageUnits); - - // Initialize cached NULL SRV block - mNullSRVs.resize(caps.maxTextureImageUnits, nullptr); - - mCurrentValueAttribs.resize(caps.maxVertexAttributes); - - mForceSetVertexSamplerStates.resize(caps.maxVertexTextureImageUnits, true); - mForceSetPixelSamplerStates.resize(caps.maxTextureImageUnits, true); - mForceSetComputeSamplerStates.resize(caps.maxComputeTextureImageUnits, true); - - mCurVertexSamplerStates.resize(caps.maxVertexTextureImageUnits); - mCurPixelSamplerStates.resize(caps.maxTextureImageUnits); - mCurComputeSamplerStates.resize(caps.maxComputeTextureImageUnits); - - mShaderConstants.init(caps); - - mIsMultiviewEnabled = extensions.multiview; - mViewportOffsets.resize(1u); - - ANGLE_TRY(mVertexDataManager.initialize()); - - mCurrentAttributes.reserve(gl::MAX_VERTEX_ATTRIBS); - - return gl::NoError(); -} - -void StateManager11::deinitialize() -{ - mCurrentValueAttribs.clear(); - mInputLayoutCache.clear(); - mVertexDataManager.deinitialize(); - mIndexDataManager.deinitialize(); - - mDriverConstantBufferVS.reset(); - mDriverConstantBufferPS.reset(); - mDriverConstantBufferCS.reset(); -} - -gl::Error StateManager11::syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer) -{ - Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer); - - // Applies the render target surface, depth stencil surface, viewport rectangle and - // scissor rectangle to the renderer - ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->cachedComplete()); - - // 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. - if (framebuffer->id() == 0) - { - ASSERT(!framebuffer11->hasAnyInternalDirtyBit()); - const gl::Extents &size = framebuffer->getFirstColorbuffer()->getSize(); - if (size.width == 0 || size.height == 0) - { - return gl::NoError(); - } - } - - RTVArray framebufferRTVs = {{}}; - - const auto &colorRTs = framebuffer11->getCachedColorRenderTargets(); - - size_t appliedRTIndex = 0; - bool skipInactiveRTs = mRenderer->getWorkarounds().mrtPerfWorkaround; - const auto &drawStates = framebuffer->getDrawBufferStates(); - gl::DrawBufferMask activeProgramOutputs = - context->getContextState().getState().getProgram()->getActiveOutputVariables(); - UINT maxExistingRT = 0; - - for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex) - { - const RenderTarget11 *renderTarget = colorRTs[rtIndex]; - - // Skip inactive rendertargets if the workaround is enabled. - if (skipInactiveRTs && - (!renderTarget || drawStates[rtIndex] == GL_NONE || !activeProgramOutputs[rtIndex])) - { - continue; - } - - if (renderTarget) - { - framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView().get(); - ASSERT(framebufferRTVs[appliedRTIndex]); - maxExistingRT = static_cast<UINT>(appliedRTIndex) + 1; - - // Unset conflicting texture SRVs - const auto *attachment = framebuffer->getColorbuffer(rtIndex); - ASSERT(attachment); - unsetConflictingAttachmentResources(attachment, renderTarget->getTexture().get()); - } - - appliedRTIndex++; - } - - // Get the depth stencil buffers - ID3D11DepthStencilView *framebufferDSV = nullptr; - const auto *depthStencilRenderTarget = framebuffer11->getCachedDepthStencilRenderTarget(); - if (depthStencilRenderTarget) - { - framebufferDSV = depthStencilRenderTarget->getDepthStencilView().get(); - ASSERT(framebufferDSV); - - // Unset conflicting texture SRVs - const auto *attachment = framebuffer->getDepthOrStencilbuffer(); - ASSERT(attachment); - unsetConflictingAttachmentResources(attachment, - depthStencilRenderTarget->getTexture().get()); - } - - // TODO(jmadill): Use context caps? - ASSERT(maxExistingRT <= static_cast<UINT>(mRenderer->getNativeCaps().maxDrawBuffers)); - - // Apply the render target and depth stencil - mRenderer->getDeviceContext()->OMSetRenderTargets(maxExistingRT, framebufferRTVs.data(), - framebufferDSV); - - return gl::NoError(); -} - -void StateManager11::invalidateCurrentValueAttrib(size_t attribIndex) -{ - mDirtyCurrentValueAttribs.set(attribIndex); - mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS); -} - -gl::Error StateManager11::syncCurrentValueAttribs(const gl::State &glState) -{ - const auto &activeAttribsMask = glState.getProgram()->getActiveAttribLocationsMask(); - const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs); - - if (!dirtyActiveAttribs.any()) - { - return gl::NoError(); - } - - const auto &vertexAttributes = glState.getVertexArray()->getVertexAttributes(); - const auto &vertexBindings = glState.getVertexArray()->getVertexBindings(); - mDirtyCurrentValueAttribs = (mDirtyCurrentValueAttribs & ~dirtyActiveAttribs); - - for (auto attribIndex : dirtyActiveAttribs) - { - if (vertexAttributes[attribIndex].enabled) - continue; - - const auto *attrib = &vertexAttributes[attribIndex]; - const auto ¤tValue = glState.getVertexAttribCurrentValue(attribIndex); - TranslatedAttribute *currentValueAttrib = &mCurrentValueAttribs[attribIndex]; - currentValueAttrib->currentValueType = currentValue.Type; - currentValueAttrib->attribute = attrib; - currentValueAttrib->binding = &vertexBindings[attrib->bindingIndex]; - - mDirtyVertexBufferRange.extend(static_cast<unsigned int>(attribIndex)); - mInputLayoutIsDirty = true; - - ANGLE_TRY(mVertexDataManager.storeCurrentValue(currentValue, currentValueAttrib, - static_cast<size_t>(attribIndex))); - } - - return gl::NoError(); -} - -void StateManager11::setInputLayout(const d3d11::InputLayout *inputLayout) -{ - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - if (inputLayout == nullptr) - { - if (!mCurrentInputLayout.empty()) - { - deviceContext->IASetInputLayout(nullptr); - mCurrentInputLayout.clear(); - mInputLayoutIsDirty = true; - } - } - else if (inputLayout->getSerial() != mCurrentInputLayout) - { - deviceContext->IASetInputLayout(inputLayout->get()); - mCurrentInputLayout = inputLayout->getSerial(); - mInputLayoutIsDirty = true; - } -} - -bool StateManager11::queueVertexBufferChange(size_t bufferIndex, - ID3D11Buffer *buffer, - UINT stride, - UINT offset) -{ - if (buffer != mCurrentVertexBuffers[bufferIndex] || - stride != mCurrentVertexStrides[bufferIndex] || - offset != mCurrentVertexOffsets[bufferIndex]) - { - mInputLayoutIsDirty = true; - mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex)); - - mCurrentVertexBuffers[bufferIndex] = buffer; - mCurrentVertexStrides[bufferIndex] = stride; - mCurrentVertexOffsets[bufferIndex] = offset; - return true; - } - - return false; -} - -bool StateManager11::queueVertexOffsetChange(size_t bufferIndex, UINT offsetOnly) -{ - if (offsetOnly != mCurrentVertexOffsets[bufferIndex]) - { - mInputLayoutIsDirty = true; - mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex)); - mCurrentVertexOffsets[bufferIndex] = offsetOnly; - return true; - } - return false; -} - -void StateManager11::applyVertexBufferChanges() -{ - if (mDirtyVertexBufferRange.empty()) - { - return; - } - - ASSERT(mDirtyVertexBufferRange.high() <= gl::MAX_VERTEX_ATTRIBS); - - UINT start = static_cast<UINT>(mDirtyVertexBufferRange.low()); - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - deviceContext->IASetVertexBuffers(start, static_cast<UINT>(mDirtyVertexBufferRange.length()), - &mCurrentVertexBuffers[start], &mCurrentVertexStrides[start], - &mCurrentVertexOffsets[start]); - - mDirtyVertexBufferRange = gl::RangeUI(gl::MAX_VERTEX_ATTRIBS, 0); -} - -void StateManager11::setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset) -{ - ID3D11Buffer *native = buffer ? buffer->get() : nullptr; - if (queueVertexBufferChange(0, native, stride, offset)) - { - applyVertexBufferChanges(); - } -} - -gl::Error StateManager11::updateState(const gl::Context *context, GLenum drawMode) -{ - const auto &glState = context->getGLState(); - auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); - - // TODO(jmadill): Use dirty bits. - processFramebufferInvalidation(context); - - // TODO(jmadill): Use dirty bits. - if (programD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty) - { - invalidateTexturesAndSamplers(); - } - - // TODO(jmadill): Use dirty bits. - if (programD3D->areVertexUniformsDirty() || programD3D->areFragmentUniformsDirty()) - { - mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS); - } - - // Transform feedback affects the stream-out geometry shader. - // TODO(jmadill): Use dirty bits. - if (glState.isTransformFeedbackActiveUnpaused() != mIsTransformFeedbackCurrentlyActiveUnpaused) - { - mIsTransformFeedbackCurrentlyActiveUnpaused = glState.isTransformFeedbackActiveUnpaused(); - invalidateShaders(); - } - - // Swizzling can cause internal state changes with blit shaders. - if (mDirtySwizzles) - { - ANGLE_TRY(generateSwizzles(context)); - mDirtySwizzles = false; - } - - gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); - Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer); - ANGLE_TRY(framebuffer11->markAttachmentsDirty(context)); - - if (framebuffer11->hasAnyInternalDirtyBit()) - { - ASSERT(framebuffer->id() != 0); - framebuffer11->syncInternalState(context); - } - - bool pointDrawMode = (drawMode == GL_POINTS); - if (pointDrawMode != mCurRasterState.pointDrawMode) - { - mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); - - // Changing from points to not points (or vice-versa) affects the geometry shader. - invalidateShaders(); - } - - // TODO(jiawei.shao@intel.com): This can be recomputed only on framebuffer or multisample mask - // state changes. - RenderTarget11 *firstRT = framebuffer11->getFirstRenderTarget(); - int samples = (firstRT ? firstRT->getSamples() : 0); - unsigned int sampleMask = GetBlendSampleMask(glState, samples); - if (sampleMask != mCurSampleMask) - { - mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); - } - - // Changing the vertex attribute state can affect the vertex shader. - gl::VertexArray *vao = glState.getVertexArray(); - VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao); - if (vao11->flushAttribUpdates(context)) - { - mInternalDirtyBits.set(DIRTY_BIT_SHADERS); - } - - auto dirtyBitsCopy = mInternalDirtyBits; - mInternalDirtyBits.reset(); - - for (auto dirtyBit : dirtyBitsCopy) - { - switch (dirtyBit) - { - case DIRTY_BIT_RENDER_TARGET: - ANGLE_TRY(syncFramebuffer(context, framebuffer)); - break; - case DIRTY_BIT_VIEWPORT_STATE: - syncViewport(context); - break; - case DIRTY_BIT_SCISSOR_STATE: - syncScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled()); - break; - case DIRTY_BIT_RASTERIZER_STATE: - ANGLE_TRY(syncRasterizerState(context, pointDrawMode)); - break; - case DIRTY_BIT_BLEND_STATE: - ANGLE_TRY(syncBlendState(context, framebuffer, glState.getBlendState(), - glState.getBlendColor(), sampleMask)); - break; - case DIRTY_BIT_DEPTH_STENCIL_STATE: - ANGLE_TRY(syncDepthStencilState(glState)); - break; - case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE: - // TODO(jmadill): More fine-grained update. - ANGLE_TRY(syncTextures(context)); - break; - case DIRTY_BIT_PROGRAM_UNIFORMS: - ANGLE_TRY(applyUniforms(programD3D)); - break; - case DIRTY_BIT_DRIVER_UNIFORMS: - // This must happen after viewport sync; the viewport affects builtin uniforms. - ANGLE_TRY(applyDriverUniforms(*programD3D)); - break; - case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS: - ANGLE_TRY(syncUniformBuffers(context, programD3D)); - break; - case DIRTY_BIT_SHADERS: - ANGLE_TRY(syncProgram(context, drawMode)); - break; - case DIRTY_BIT_CURRENT_VALUE_ATTRIBS: - ANGLE_TRY(syncCurrentValueAttribs(glState)); - break; - default: - UNREACHABLE(); - break; - } - } - - ANGLE_TRY(syncTransformFeedbackBuffers(context)); - - // Check that we haven't set any dirty bits in the flushing of the dirty bits loop. - ASSERT(mInternalDirtyBits.none()); - - return gl::NoError(); -} - -void StateManager11::setShaderResourceShared(gl::SamplerType shaderType, - UINT resourceSlot, - const d3d11::SharedSRV *srv) -{ - setShaderResourceInternal(shaderType, resourceSlot, srv); - - // TODO(jmadill): Narrower dirty region. - mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); -} - -void StateManager11::setShaderResource(gl::SamplerType shaderType, - UINT resourceSlot, - const d3d11::ShaderResourceView *srv) -{ - setShaderResourceInternal(shaderType, resourceSlot, srv); - - // TODO(jmadill): Narrower dirty region. - mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); -} - -void StateManager11::setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology) -{ - if (primitiveTopology != mCurrentPrimitiveTopology) - { - mRenderer->getDeviceContext()->IASetPrimitiveTopology(primitiveTopology); - mCurrentPrimitiveTopology = primitiveTopology; - } -} - -void StateManager11::setDrawShaders(const d3d11::VertexShader *vertexShader, - const d3d11::GeometryShader *geometryShader, - const d3d11::PixelShader *pixelShader) -{ - setVertexShader(vertexShader); - setGeometryShader(geometryShader); - setPixelShader(pixelShader); -} - -void StateManager11::setVertexShader(const d3d11::VertexShader *shader) -{ - ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); - - if (serial != mAppliedVertexShader) - { - ID3D11VertexShader *appliedShader = shader ? shader->get() : nullptr; - mRenderer->getDeviceContext()->VSSetShader(appliedShader, nullptr, 0); - mAppliedVertexShader = serial; - invalidateShaders(); - } -} - -void StateManager11::setGeometryShader(const d3d11::GeometryShader *shader) -{ - ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); - - if (serial != mAppliedGeometryShader) - { - ID3D11GeometryShader *appliedShader = shader ? shader->get() : nullptr; - mRenderer->getDeviceContext()->GSSetShader(appliedShader, nullptr, 0); - mAppliedGeometryShader = serial; - invalidateShaders(); - } -} - -void StateManager11::setPixelShader(const d3d11::PixelShader *shader) -{ - ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); - - if (serial != mAppliedPixelShader) - { - ID3D11PixelShader *appliedShader = shader ? shader->get() : nullptr; - mRenderer->getDeviceContext()->PSSetShader(appliedShader, nullptr, 0); - mAppliedPixelShader = serial; - invalidateShaders(); - } -} - -void StateManager11::setComputeShader(const d3d11::ComputeShader *shader) -{ - ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); - - if (serial != mAppliedComputeShader) - { - ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr; - mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0); - mAppliedComputeShader = serial; - // TODO(jmadill): Dirty bits for compute. - } -} - -void StateManager11::setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer) -{ - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - auto ¤tSerial = mCurrentConstantBufferVS[slot]; - - mCurrentConstantBufferVSOffset[slot] = 0; - mCurrentConstantBufferVSSize[slot] = 0; - - if (buffer) - { - if (currentSerial != buffer->getSerial()) - { - deviceContext->VSSetConstantBuffers(slot, 1, buffer->getPointer()); - currentSerial = buffer->getSerial(); - invalidateConstantBuffer(slot); - } - } - else - { - if (!currentSerial.empty()) - { - ID3D11Buffer *nullBuffer = nullptr; - deviceContext->VSSetConstantBuffers(slot, 1, &nullBuffer); - currentSerial.clear(); - invalidateConstantBuffer(slot); - } - } -} - -void StateManager11::setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer) -{ - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - auto ¤tSerial = mCurrentConstantBufferPS[slot]; - - mCurrentConstantBufferPSOffset[slot] = 0; - mCurrentConstantBufferPSSize[slot] = 0; - - if (buffer) - { - if (currentSerial != buffer->getSerial()) - { - deviceContext->PSSetConstantBuffers(slot, 1, buffer->getPointer()); - currentSerial = buffer->getSerial(); - invalidateConstantBuffer(slot); - } - } - else - { - if (!currentSerial.empty()) - { - ID3D11Buffer *nullBuffer = nullptr; - deviceContext->PSSetConstantBuffers(slot, 1, &nullBuffer); - currentSerial.clear(); - invalidateConstantBuffer(slot); - } - } -} - -void StateManager11::setDepthStencilState(const d3d11::DepthStencilState *depthStencilState, - UINT stencilRef) -{ - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - if (depthStencilState) - { - deviceContext->OMSetDepthStencilState(depthStencilState->get(), stencilRef); - } - else - { - deviceContext->OMSetDepthStencilState(nullptr, stencilRef); - } - - mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); -} - -void StateManager11::setSimpleBlendState(const d3d11::BlendState *blendState) -{ - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - if (blendState) - { - deviceContext->OMSetBlendState(blendState->get(), nullptr, 0xFFFFFFFF); - } - else - { - deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF); - } - - mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); -} - -void StateManager11::setRasterizerState(const d3d11::RasterizerState *rasterizerState) -{ - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - if (rasterizerState) - { - deviceContext->RSSetState(rasterizerState->get()); - } - else - { - deviceContext->RSSetState(nullptr); - } - - mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); -} - -void StateManager11::setSimpleViewport(const gl::Extents &extents) -{ - setSimpleViewport(extents.width, extents.height); -} - -void StateManager11::setSimpleViewport(int width, int height) -{ - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = static_cast<FLOAT>(width); - viewport.Height = static_cast<FLOAT>(height); - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - - mRenderer->getDeviceContext()->RSSetViewports(1, &viewport); - mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE); -} - -void StateManager11::setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv, - const d3d11::SamplerState &samplerState) -{ - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - setShaderResourceInternal(gl::SAMPLER_PIXEL, 0, &srv); - deviceContext->PSSetSamplers(0, 1, samplerState.getPointer()); - - mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); - mForceSetPixelSamplerStates[0] = true; -} - -void StateManager11::setSimpleScissorRect(const gl::Rectangle &glRect) -{ - D3D11_RECT scissorRect; - scissorRect.left = glRect.x; - scissorRect.right = glRect.x + glRect.width; - scissorRect.top = glRect.y; - scissorRect.bottom = glRect.y + glRect.height; - setScissorRectD3D(scissorRect); -} - -void StateManager11::setScissorRectD3D(const D3D11_RECT &d3dRect) -{ - mRenderer->getDeviceContext()->RSSetScissorRects(1, &d3dRect); - mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); -} - -// For each Direct3D sampler of either the pixel or vertex stage, -// looks up the corresponding OpenGL texture image unit and texture type, -// and sets the texture and its addressing/filtering state (or NULL when inactive). -// Sampler mapping needs to be up-to-date on the program object before this is called. -gl::Error StateManager11::applyTextures(const gl::Context *context, gl::SamplerType shaderType) -{ - const auto &glState = context->getGLState(); - const auto &caps = context->getCaps(); - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); - - ASSERT(!programD3D->isSamplerMappingDirty()); - - // TODO(jmadill): Use the Program's sampler bindings. - const auto &completeTextures = glState.getCompleteTextureCache(); - - unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType); - for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) - { - GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps); - ASSERT(textureUnit != -1); - gl::Texture *texture = completeTextures[textureUnit]; - - // A nullptr texture indicates incomplete. - if (texture) - { - gl::Sampler *samplerObject = glState.getSampler(textureUnit); - - const gl::SamplerState &samplerState = - samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState(); - - ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState)); - ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture)); - } - else - { - GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex); - - // Texture is not sampler complete or it is in use by the framebuffer. Bind the - // incomplete texture. - gl::Texture *incompleteTexture = nullptr; - ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture)); - ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture, - incompleteTexture->getSamplerState())); - ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture)); - } - } - - // Set all the remaining textures to NULL - size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? caps.maxTextureImageUnits - : caps.maxVertexTextureImageUnits; - ANGLE_TRY(clearTextures(shaderType, samplerRange, samplerCount)); - - return gl::NoError(); -} - -gl::Error StateManager11::syncTextures(const gl::Context *context) -{ - ANGLE_TRY(applyTextures(context, gl::SAMPLER_VERTEX)); - ANGLE_TRY(applyTextures(context, gl::SAMPLER_PIXEL)); - return gl::NoError(); -} - -gl::Error StateManager11::setSamplerState(const gl::Context *context, - gl::SamplerType type, - int index, - gl::Texture *texture, - const gl::SamplerState &samplerState) -{ -#if !defined(NDEBUG) - // Storage should exist, texture should be complete. Only verified in Debug. - TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); - TextureStorage *storage = nullptr; - ANGLE_TRY(textureD3D->getNativeTexture(context, &storage)); - ASSERT(storage); -#endif // !defined(NDEBUG) - - auto *deviceContext = mRenderer->getDeviceContext(); - - if (type == gl::SAMPLER_PIXEL) - { - ASSERT(static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxTextureImageUnits); - - if (mForceSetPixelSamplerStates[index] || - memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = nullptr; - ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState)); - - ASSERT(dxSamplerState != nullptr); - deviceContext->PSSetSamplers(index, 1, &dxSamplerState); - - mCurPixelSamplerStates[index] = samplerState; - } - - mForceSetPixelSamplerStates[index] = false; - } - else if (type == gl::SAMPLER_VERTEX) - { - ASSERT(static_cast<unsigned int>(index) < - mRenderer->getNativeCaps().maxVertexTextureImageUnits); - - if (mForceSetVertexSamplerStates[index] || - memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = nullptr; - ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState)); - - ASSERT(dxSamplerState != nullptr); - deviceContext->VSSetSamplers(index, 1, &dxSamplerState); - - mCurVertexSamplerStates[index] = samplerState; - } - - mForceSetVertexSamplerStates[index] = false; - } - else if (type == gl::SAMPLER_COMPUTE) - { - ASSERT(static_cast<unsigned int>(index) < - mRenderer->getNativeCaps().maxComputeTextureImageUnits); - - if (mForceSetComputeSamplerStates[index] || - memcmp(&samplerState, &mCurComputeSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = nullptr; - ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState)); - - ASSERT(dxSamplerState != nullptr); - deviceContext->CSSetSamplers(index, 1, &dxSamplerState); - - mCurComputeSamplerStates[index] = samplerState; - } - - mForceSetComputeSamplerStates[index] = false; - } - else - UNREACHABLE(); - - // Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the - // sampler state since having it in contiguous memory makes it possible to memcpy to a constant - // buffer, and it doesn't affect the state set by PSSetSamplers/VSSetSamplers. - mShaderConstants.onSamplerChange(type, index, *texture); - - return gl::NoError(); -} - -gl::Error StateManager11::setTexture(const gl::Context *context, - gl::SamplerType type, - int index, - gl::Texture *texture) -{ - const d3d11::SharedSRV *textureSRV = nullptr; - - if (texture) - { - TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture); - - TextureStorage *texStorage = nullptr; - ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage)); - - // Texture should be complete and have a storage - ASSERT(texStorage); - - TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage); - - ANGLE_TRY(storage11->getSRV(context, texture->getTextureState(), &textureSRV)); - - // If we get an invalid SRV here, something went wrong in the texture class and we're - // unexpectedly missing the shader resource view. - ASSERT(textureSRV->valid()); - - textureImpl->resetDirty(); - } - - ASSERT( - (type == gl::SAMPLER_PIXEL && - static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxTextureImageUnits) || - (type == gl::SAMPLER_VERTEX && - static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxVertexTextureImageUnits)); - - setShaderResourceInternal(type, index, textureSRV); - return gl::NoError(); -} - -// Things that affect a program's dirtyness: -// 1. Directly changing the program executable -> triggered in StateManager11::syncState. -// 2. The vertex attribute layout -> triggered in VertexArray11::syncState/signal. -// 3. The fragment shader's rendertargets -> triggered in Framebuffer11::syncState/signal. -// 4. Enabling/disabling rasterizer discard. -> triggered in StateManager11::syncState. -// 5. Enabling/disabling transform feedback. -> checked in StateManager11::updateState. -// 6. An internal shader was used. -> triggered in StateManager11::set*Shader. -// 7. Drawing with/without point sprites. -> checked in StateManager11::updateState. -// TODO(jmadill): Use dirty bits for transform feedback. -gl::Error StateManager11::syncProgram(const gl::Context *context, GLenum drawMode) -{ - Context11 *context11 = GetImplAs<Context11>(context); - ANGLE_TRY(context11->triggerDrawCallProgramRecompilation(context, drawMode)); - - const auto &glState = context->getGLState(); - const auto *va11 = GetImplAs<VertexArray11>(glState.getVertexArray()); - auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); - - programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState); - - // Binaries must be compiled before the sync. - ASSERT(programD3D->hasVertexExecutableForCachedInputLayout()); - ASSERT(programD3D->hasGeometryExecutableForPrimitiveType(drawMode)); - ASSERT(programD3D->hasPixelExecutableForCachedOutputLayout()); - - ShaderExecutableD3D *vertexExe = nullptr; - ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&vertexExe, nullptr)); - - ShaderExecutableD3D *pixelExe = nullptr; - ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr)); - - ShaderExecutableD3D *geometryExe = nullptr; - ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, drawMode, &geometryExe, - nullptr)); - - const d3d11::VertexShader *vertexShader = - (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr); - - // Skip pixel shader if we're doing rasterizer discard. - const d3d11::PixelShader *pixelShader = nullptr; - if (!glState.getRasterizerState().rasterizerDiscard) - { - pixelShader = (pixelExe ? &GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : nullptr); - } - - const d3d11::GeometryShader *geometryShader = nullptr; - if (glState.isTransformFeedbackActiveUnpaused()) - { - geometryShader = - (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr); - } - else - { - geometryShader = - (geometryExe ? &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr); - } - - setDrawShaders(vertexShader, geometryShader, pixelShader); - - // Explicitly clear the shaders dirty bit. - mInternalDirtyBits.reset(DIRTY_BIT_SHADERS); - - return gl::NoError(); -} - -gl::Error StateManager11::applyVertexBuffer(const gl::Context *context, - GLenum mode, - const DrawCallVertexParams &vertexParams, - bool isIndexedRendering) -{ - const auto &state = context->getGLState(); - const gl::VertexArray *vertexArray = state.getVertexArray(); - VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(vertexArray); - - if (mVertexAttribsNeedTranslation) - { - ANGLE_TRY(vertexArray11->updateDirtyAndDynamicAttribs(context, &mVertexDataManager, - vertexParams)); - mInputLayoutIsDirty = true; - - // Determine if we need to update attribs on the next draw. - mVertexAttribsNeedTranslation = (vertexArray11->hasActiveDynamicAttrib(context)); - } - - if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != vertexParams.firstVertex()) - { - mLastFirstVertex = vertexParams.firstVertex(); - mInputLayoutIsDirty = true; - } - - if (!mInputLayoutIsDirty) - { - return gl::NoError(); - } - - const auto &vertexArrayAttribs = vertexArray11->getTranslatedAttribs(); - gl::Program *program = state.getProgram(); - - // Sort the attributes according to ensure we re-use similar input layouts. - AttribIndexArray sortedSemanticIndices; - SortAttributesByLayout(program, vertexArrayAttribs, mCurrentValueAttribs, - &sortedSemanticIndices, &mCurrentAttributes); - - auto featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel; - - // If we are using FL 9_3, make sure the first attribute is not instanced - if (featureLevel <= D3D_FEATURE_LEVEL_9_3 && !mCurrentAttributes.empty()) - { - if (mCurrentAttributes[0]->divisor > 0) - { - Optional<size_t> firstNonInstancedIndex = FindFirstNonInstanced(mCurrentAttributes); - if (firstNonInstancedIndex.valid()) - { - size_t index = firstNonInstancedIndex.value(); - std::swap(mCurrentAttributes[0], mCurrentAttributes[index]); - std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]); - } - } - } - - // Update the applied input layout by querying the cache. - ANGLE_TRY(mInputLayoutCache.updateInputLayout(mRenderer, state, mCurrentAttributes, mode, - sortedSemanticIndices, vertexParams)); - - // Update the applied vertex buffers. - ANGLE_TRY(mInputLayoutCache.applyVertexBuffers(context, mCurrentAttributes, mode, - vertexParams.firstVertex(), isIndexedRendering)); - - // InputLayoutCache::applyVertexBuffers calls through to the Bufer11 to get the native vertex - // buffer (ID3D11Buffer *). Because we allocate these buffers lazily, this will trigger - // allocation. This in turn will signal that the buffer is dirty. Since we just resolved the - // dirty-ness in VertexArray11::updateDirtyAndDynamicAttribs, this can make us do a needless - // update on the second draw call. - // Hence we clear the flags here, after we've applied vertex data, since we know everything - // is clean. This is a bit of a hack. - vertexArray11->clearDirtyAndPromoteDynamicAttribs(context, vertexParams); - - mInputLayoutIsDirty = false; - return gl::NoError(); -} - -gl::Error StateManager11::applyIndexBuffer(const gl::Context *context, - const void *indices, - GLsizei count, - GLenum type, - const gl::HasIndexRange &lazyIndexRange, - bool usePrimitiveRestartWorkaround) -{ - const auto &glState = context->getGLState(); - gl::VertexArray *vao = glState.getVertexArray(); - VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao); - - GLenum destElementType = - GetIndexTranslationDestType(type, lazyIndexRange, usePrimitiveRestartWorkaround); - - if (!vao11->updateElementArrayStorage(context, type, destElementType, indices) && - !mIndexBufferIsDirty) - { - // No streaming or index buffer application necessary. - return gl::NoError(); - } - - gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); - - TranslatedIndexData *indexInfo = vao11->getCachedIndexInfo(); - ANGLE_TRY(mIndexDataManager.prepareIndexData(context, type, destElementType, count, - elementArrayBuffer, indices, indexInfo)); - - ID3D11Buffer *buffer = nullptr; - DXGI_FORMAT bufferFormat = - (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; - - if (indexInfo->storage) - { - Buffer11 *storage = GetAs<Buffer11>(indexInfo->storage); - ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDEX), buffer); - } - else - { - IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo->indexBuffer); - buffer = indexBuffer->getBuffer().get(); - } - - // Track dirty indices in the index range cache. - indexInfo->srcIndexData.srcIndicesChanged = - syncIndexBuffer(buffer, bufferFormat, indexInfo->startOffset); - - mIndexBufferIsDirty = false; - - vao11->setCachedIndexInfoValid(); - return gl::NoError(); -} - -void StateManager11::setIndexBuffer(ID3D11Buffer *buffer, - DXGI_FORMAT indexFormat, - unsigned int offset) -{ - if (syncIndexBuffer(buffer, indexFormat, offset)) - { - mIndexBufferIsDirty = true; - } -} - -bool StateManager11::syncIndexBuffer(ID3D11Buffer *buffer, - DXGI_FORMAT indexFormat, - unsigned int offset) -{ - if (buffer != mAppliedIB || indexFormat != mAppliedIBFormat || offset != mAppliedIBOffset) - { - mRenderer->getDeviceContext()->IASetIndexBuffer(buffer, indexFormat, offset); - - mAppliedIB = buffer; - mAppliedIBFormat = indexFormat; - mAppliedIBOffset = offset; - return true; - } - - return false; -} - -// Vertex buffer is invalidated outside this function. -gl::Error StateManager11::updateVertexOffsetsForPointSpritesEmulation(GLint startVertex, - GLsizei emulatedInstanceId) -{ - return mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation( - mRenderer, mCurrentAttributes, startVertex, emulatedInstanceId); -} - -gl::Error StateManager11::generateSwizzle(const gl::Context *context, gl::Texture *texture) -{ - if (!texture) - { - return gl::NoError(); - } - - TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); - ASSERT(textureD3D); - - TextureStorage *texStorage = nullptr; - ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage)); - - if (texStorage) - { - TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage); - const gl::TextureState &textureState = texture->getTextureState(); - ANGLE_TRY(storage11->generateSwizzles(context, textureState.getSwizzleState())); - } - - return gl::NoError(); -} - -gl::Error StateManager11::generateSwizzlesForShader(const gl::Context *context, - gl::SamplerType type) -{ - const auto &glState = context->getGLState(); - ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram()); - - unsigned int samplerRange = programD3D->getUsedSamplerRange(type); - - for (unsigned int i = 0; i < samplerRange; i++) - { - GLenum textureType = programD3D->getSamplerTextureType(type, i); - GLint textureUnit = programD3D->getSamplerMapping(type, i, context->getCaps()); - if (textureUnit != -1) - { - gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType); - ASSERT(texture); - if (texture->getTextureState().swizzleRequired()) - { - ANGLE_TRY(generateSwizzle(context, texture)); - } - } - } - - return gl::NoError(); -} - -gl::Error StateManager11::generateSwizzles(const gl::Context *context) -{ - ANGLE_TRY(generateSwizzlesForShader(context, gl::SAMPLER_VERTEX)); - ANGLE_TRY(generateSwizzlesForShader(context, gl::SAMPLER_PIXEL)); - return gl::NoError(); -} - -gl::Error StateManager11::applyUniforms(ProgramD3D *programD3D) -{ - UniformStorage11 *vertexUniformStorage = - GetAs<UniformStorage11>(&programD3D->getVertexUniformStorage()); - UniformStorage11 *fragmentUniformStorage = - GetAs<UniformStorage11>(&programD3D->getFragmentUniformStorage()); - ASSERT(vertexUniformStorage); - ASSERT(fragmentUniformStorage); - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - const d3d11::Buffer *vertexConstantBuffer = nullptr; - ANGLE_TRY(vertexUniformStorage->getConstantBuffer(mRenderer, &vertexConstantBuffer)); - const d3d11::Buffer *pixelConstantBuffer = nullptr; - ANGLE_TRY(fragmentUniformStorage->getConstantBuffer(mRenderer, &pixelConstantBuffer)); - - if (vertexUniformStorage->size() > 0 && programD3D->areVertexUniformsDirty()) - { - UpdateUniformBuffer(deviceContext, vertexUniformStorage, vertexConstantBuffer); - } - - if (fragmentUniformStorage->size() > 0 && programD3D->areFragmentUniformsDirty()) - { - UpdateUniformBuffer(deviceContext, fragmentUniformStorage, pixelConstantBuffer); - } - - unsigned int slot = d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK; - - if (mCurrentConstantBufferVS[slot] != vertexConstantBuffer->getSerial()) - { - deviceContext->VSSetConstantBuffers(slot, 1, vertexConstantBuffer->getPointer()); - mCurrentConstantBufferVS[slot] = vertexConstantBuffer->getSerial(); - mCurrentConstantBufferVSOffset[slot] = 0; - mCurrentConstantBufferVSSize[slot] = 0; - } - - if (mCurrentConstantBufferPS[slot] != pixelConstantBuffer->getSerial()) - { - deviceContext->PSSetConstantBuffers(slot, 1, pixelConstantBuffer->getPointer()); - mCurrentConstantBufferPS[slot] = pixelConstantBuffer->getSerial(); - mCurrentConstantBufferPSOffset[slot] = 0; - mCurrentConstantBufferPSSize[slot] = 0; - } - - programD3D->markUniformsClean(); - - return gl::NoError(); -} - -gl::Error StateManager11::applyDriverUniforms(const ProgramD3D &programD3D) -{ - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - if (!mDriverConstantBufferVS.valid()) - { - size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SAMPLER_VERTEX); - - D3D11_BUFFER_DESC constantBufferDescription = {0}; - d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize); - ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferVS)); - - ID3D11Buffer *driverVSConstants = mDriverConstantBufferVS.get(); - deviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1, - &driverVSConstants); - } - - if (!mDriverConstantBufferPS.valid()) - { - size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SAMPLER_PIXEL); - - D3D11_BUFFER_DESC constantBufferDescription = {0}; - d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize); - ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferPS)); - - ID3D11Buffer *driverVSConstants = mDriverConstantBufferPS.get(); - deviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1, - &driverVSConstants); - } - - // Sampler metadata and driver constants need to coexist in the same constant buffer to conserve - // constant buffer slots. We update both in the constant buffer if needed. - ANGLE_TRY(mShaderConstants.updateBuffer(deviceContext, gl::SAMPLER_VERTEX, programD3D, - mDriverConstantBufferVS)); - ANGLE_TRY(mShaderConstants.updateBuffer(deviceContext, gl::SAMPLER_PIXEL, programD3D, - mDriverConstantBufferPS)); - - // needed for the point sprite geometry shader - // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it for ES3. - if (mRenderer->isES3Capable()) - { - if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS.getSerial()) - { - ASSERT(mDriverConstantBufferPS.valid()); - deviceContext->GSSetConstantBuffers(0, 1, mDriverConstantBufferPS.getPointer()); - mCurrentGeometryConstantBuffer = mDriverConstantBufferPS.getSerial(); - } - } - - return gl::NoError(); -} - -gl::Error StateManager11::applyComputeUniforms(ProgramD3D *programD3D) -{ - UniformStorage11 *computeUniformStorage = - GetAs<UniformStorage11>(&programD3D->getComputeUniformStorage()); - ASSERT(computeUniformStorage); - - const d3d11::Buffer *constantBuffer = nullptr; - ANGLE_TRY(computeUniformStorage->getConstantBuffer(mRenderer, &constantBuffer)); - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - if (computeUniformStorage->size() > 0 && programD3D->areComputeUniformsDirty()) - { - UpdateUniformBuffer(deviceContext, computeUniformStorage, constantBuffer); - programD3D->markUniformsClean(); - } - - if (mCurrentComputeConstantBuffer != constantBuffer->getSerial()) - { - deviceContext->CSSetConstantBuffers( - d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, - constantBuffer->getPointer()); - mCurrentComputeConstantBuffer = constantBuffer->getSerial(); - } - - if (!mDriverConstantBufferCS.valid()) - { - size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SAMPLER_COMPUTE); - - D3D11_BUFFER_DESC constantBufferDescription = {0}; - d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize); - ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferCS)); - ID3D11Buffer *buffer = mDriverConstantBufferCS.get(); - deviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1, - &buffer); - } - - ANGLE_TRY(mShaderConstants.updateBuffer(deviceContext, gl::SAMPLER_COMPUTE, *programD3D, - mDriverConstantBufferCS)); - - return gl::NoError(); -} - -gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, ProgramD3D *programD3D) -{ - unsigned int reservedVertex = mRenderer->getReservedVertexUniformBuffers(); - unsigned int reservedFragment = mRenderer->getReservedFragmentUniformBuffers(); - - programD3D->updateUniformBufferCache(context->getCaps(), reservedVertex, reservedFragment); - - const auto &vertexUniformBuffers = programD3D->getVertexUniformBufferCache(); - const auto &fragmentUniformBuffers = programD3D->getFragmentUniformBufferCache(); - const auto &glState = context->getGLState(); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); - - for (size_t bufferIndex = 0; bufferIndex < vertexUniformBuffers.size(); bufferIndex++) - { - GLint binding = vertexUniformBuffers[bufferIndex]; - - if (binding == -1) - { - continue; - } - - const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding); - GLintptr uniformBufferOffset = uniformBuffer.getOffset(); - GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); - - if (uniformBuffer.get() == nullptr) - { - continue; - } - - Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get()); - const d3d11::Buffer *constantBuffer = nullptr; - UINT firstConstant = 0; - UINT numConstants = 0; - - ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset, - uniformBufferSize, &constantBuffer, - &firstConstant, &numConstants)); - - ASSERT(constantBuffer); - - if (mCurrentConstantBufferVS[bufferIndex] == constantBuffer->getSerial() && - mCurrentConstantBufferVSOffset[bufferIndex] == uniformBufferOffset && - mCurrentConstantBufferVSSize[bufferIndex] == uniformBufferSize) - { - continue; - } - - unsigned int appliedIndex = reservedVertex + static_cast<unsigned int>(bufferIndex); - - if (firstConstant != 0 && uniformBufferSize != 0) - { - ASSERT(numConstants != 0); - deviceContext1->VSSetConstantBuffers1(appliedIndex, 1, constantBuffer->getPointer(), - &firstConstant, &numConstants); - } - else - { - deviceContext->VSSetConstantBuffers(appliedIndex, 1, constantBuffer->getPointer()); - } - - mCurrentConstantBufferVS[appliedIndex] = constantBuffer->getSerial(); - mCurrentConstantBufferVSOffset[appliedIndex] = uniformBufferOffset; - mCurrentConstantBufferVSSize[appliedIndex] = uniformBufferSize; - } - - for (size_t bufferIndex = 0; bufferIndex < fragmentUniformBuffers.size(); bufferIndex++) - { - GLint binding = fragmentUniformBuffers[bufferIndex]; - - if (binding == -1) - { - continue; - } - - const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding); - GLintptr uniformBufferOffset = uniformBuffer.getOffset(); - GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); - - if (uniformBuffer.get() == nullptr) - { - continue; - } - - Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get()); - const d3d11::Buffer *constantBuffer = nullptr; - UINT firstConstant = 0; - UINT numConstants = 0; - - ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset, - uniformBufferSize, &constantBuffer, - &firstConstant, &numConstants)); - - ASSERT(constantBuffer); - - if (mCurrentConstantBufferPS[bufferIndex] == constantBuffer->getSerial() && - mCurrentConstantBufferPSOffset[bufferIndex] == uniformBufferOffset && - mCurrentConstantBufferPSSize[bufferIndex] == uniformBufferSize) - { - continue; - } - - unsigned int appliedIndex = reservedFragment + static_cast<unsigned int>(bufferIndex); - - if (firstConstant != 0 && uniformBufferSize != 0) - { - deviceContext1->PSSetConstantBuffers1(appliedIndex, 1, constantBuffer->getPointer(), - &firstConstant, &numConstants); - } - else - { - deviceContext->PSSetConstantBuffers(appliedIndex, 1, constantBuffer->getPointer()); - } - - mCurrentConstantBufferPS[appliedIndex] = constantBuffer->getSerial(); - mCurrentConstantBufferPSOffset[appliedIndex] = uniformBufferOffset; - mCurrentConstantBufferPSSize[appliedIndex] = uniformBufferSize; - } - - return gl::NoError(); -} - -gl::Error StateManager11::syncTransformFeedbackBuffers(const gl::Context *context) -{ - const auto &glState = context->getGLState(); - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - // If transform feedback is not active, unbind all buffers - if (!glState.isTransformFeedbackActiveUnpaused()) - { - if (mAppliedTFSerial != mEmptySerial) - { - deviceContext->SOSetTargets(0, nullptr, nullptr); - mAppliedTFSerial = mEmptySerial; - } - return gl::NoError(); - } - - gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback(); - TransformFeedback11 *tf11 = GetImplAs<TransformFeedback11>(transformFeedback); - if (mAppliedTFSerial == tf11->getSerial() && !tf11->isDirty()) - { - return gl::NoError(); - } - - const std::vector<ID3D11Buffer *> *soBuffers = nullptr; - ANGLE_TRY_RESULT(tf11->getSOBuffers(context), soBuffers); - const std::vector<UINT> &soOffsets = tf11->getSOBufferOffsets(); - - deviceContext->SOSetTargets(tf11->getNumSOBuffers(), soBuffers->data(), soOffsets.data()); - - mAppliedTFSerial = tf11->getSerial(); - tf11->onApply(); - - return gl::NoError(); -} - -// DrawCallVertexParams implementation. -DrawCallVertexParams::DrawCallVertexParams(GLint firstVertex, - GLsizei vertexCount, - GLsizei instances) - : mHasIndexRange(nullptr), - mFirstVertex(firstVertex), - mVertexCount(vertexCount), - mInstances(instances), - mBaseVertex(0) -{ -} - -// Use when in a drawElements call. -DrawCallVertexParams::DrawCallVertexParams(bool firstVertexDefinitelyZero, - const gl::HasIndexRange &hasIndexRange, - GLint baseVertex, - GLsizei instances) - : mHasIndexRange(&hasIndexRange), - mFirstVertex(), - mVertexCount(0), - mInstances(instances), - mBaseVertex(baseVertex) -{ - if (firstVertexDefinitelyZero) - { - mFirstVertex = baseVertex; - } -} - -GLint DrawCallVertexParams::firstVertex() const -{ - if (!mFirstVertex.valid()) - { - ensureResolved(); - ASSERT(mFirstVertex.valid()); - } - return mFirstVertex.value(); -} - -GLsizei DrawCallVertexParams::vertexCount() const -{ - ensureResolved(); - return mVertexCount; -} - -GLsizei DrawCallVertexParams::instances() const -{ - return mInstances; -} - -void DrawCallVertexParams::ensureResolved() const -{ - if (mHasIndexRange) - { - ASSERT(!mFirstVertex.valid() || mFirstVertex == mBaseVertex); - - // Resolve the index range now if we need to. - const auto &indexRange = mHasIndexRange->getIndexRange().value(); - mFirstVertex = mBaseVertex + static_cast<GLint>(indexRange.start); - mVertexCount = static_cast<GLsizei>(indexRange.vertexCount()); - mHasIndexRange = nullptr; - } -} - -} // namespace rx |