/lib_angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
C++ | 3375 lines | 2674 code | 564 blank | 137 comment | 518 complexity | f4a36269050b3819983316f65a5f964b MD5 | raw file
Possible License(s): Zlib, BSD-3-Clause, CC0-1.0, GPL-3.0, GPL-2.0, CPL-1.0, MPL-2.0-no-copyleft-exception, LGPL-2.0, LGPL-2.1, LGPL-3.0, 0BSD, Cube
Large files files are truncated, but you can click here to view the full file
- //
- // Copyright (c) 2012-2014 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.
- //
- // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
- #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
- #include "common/utilities.h"
- #include "common/tls.h"
- #include "libANGLE/Buffer.h"
- #include "libANGLE/Display.h"
- #include "libANGLE/Framebuffer.h"
- #include "libANGLE/FramebufferAttachment.h"
- #include "libANGLE/Program.h"
- #include "libANGLE/State.h"
- #include "libANGLE/Surface.h"
- #include "libANGLE/formatutils.h"
- #include "libANGLE/renderer/d3d/CompilerD3D.h"
- #include "libANGLE/renderer/d3d/FramebufferD3D.h"
- #include "libANGLE/renderer/d3d/IndexDataManager.h"
- #include "libANGLE/renderer/d3d/ProgramD3D.h"
- #include "libANGLE/renderer/d3d/RenderbufferD3D.h"
- #include "libANGLE/renderer/d3d/ShaderD3D.h"
- #include "libANGLE/renderer/d3d/SurfaceD3D.h"
- #include "libANGLE/renderer/d3d/TextureD3D.h"
- #include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
- #include "libANGLE/renderer/d3d/VertexDataManager.h"
- #include "libANGLE/renderer/d3d/d3d11/Blit11.h"
- #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
- #include "libANGLE/renderer/d3d/d3d11/Clear11.h"
- #include "libANGLE/renderer/d3d/d3d11/Fence11.h"
- #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
- #include "libANGLE/renderer/d3d/d3d11/Image11.h"
- #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
- #include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
- #include "libANGLE/renderer/d3d/d3d11/Query11.h"
- #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
- #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
- #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
- #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
- #include "libANGLE/renderer/d3d/d3d11/Trim11.h"
- #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
- #include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
- #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
- #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
- #include <sstream>
- #include <EGL/eglext.h>
- // Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process
- // HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed.
- #ifndef ANGLE_SKIP_DXGI_1_2_CHECK
- #define ANGLE_SKIP_DXGI_1_2_CHECK 0
- #endif
- #ifdef _DEBUG
- // this flag enables suppressing some spurious warnings that pop up in certain WebGL samples
- // and conformance tests. to enable all warnings, remove this define.
- #define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1
- #endif
- namespace rx
- {
- namespace
- {
- static const DXGI_FORMAT RenderTargetFormats[] =
- {
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM
- };
- static const DXGI_FORMAT DepthStencilFormats[] =
- {
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D24_UNORM_S8_UINT,
- DXGI_FORMAT_D16_UNORM
- };
- enum
- {
- MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
- };
- static bool ImageIndexConflictsWithSRV(const gl::ImageIndex *index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
- {
- unsigned mipLevel = index->mipIndex;
- unsigned layerIndex = index->layerIndex;
- GLenum type = index->type;
- switch (desc.ViewDimension)
- {
- case D3D11_SRV_DIMENSION_TEXTURE2D:
- {
- unsigned maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
- maxSrvMip = (desc.Texture2D.MipLevels == -1) ? INT_MAX : maxSrvMip;
- unsigned mipMin = index->mipIndex;
- unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex;
- return type == GL_TEXTURE_2D && RangeUI(mipMin, mipMax).intersects(RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip));
- }
- case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
- {
- unsigned maxSrvMip = desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip;
- maxSrvMip = (desc.Texture2DArray.MipLevels == -1) ? INT_MAX : maxSrvMip;
- unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize;
- // Cube maps can be mapped to Texture2DArray SRVs
- return (type == GL_TEXTURE_2D_ARRAY || gl::IsCubeMapTextureTarget(type)) &&
- desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip &&
- desc.Texture2DArray.FirstArraySlice <= layerIndex && layerIndex < maxSlice;
- }
- case D3D11_SRV_DIMENSION_TEXTURECUBE:
- {
- unsigned maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip;
- maxSrvMip = (desc.TextureCube.MipLevels == -1) ? INT_MAX : maxSrvMip;
- return gl::IsCubeMapTextureTarget(type) &&
- desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
- }
- case D3D11_SRV_DIMENSION_TEXTURE3D:
- {
- unsigned maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip;
- maxSrvMip = (desc.Texture3D.MipLevels == -1) ? INT_MAX : maxSrvMip;
- return type == GL_TEXTURE_3D &&
- desc.Texture3D.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
- }
- default:
- // We only handle the cases corresponding to valid image indexes
- UNIMPLEMENTED();
- }
- return false;
- }
- // Does *not* increment the resource ref count!!
- ID3D11Resource *GetSRVResource(ID3D11ShaderResourceView *srv)
- {
- ID3D11Resource *resource = NULL;
- ASSERT(srv);
- srv->GetResource(&resource);
- resource->Release();
- return resource;
- }
- }
- Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes)
- : RendererD3D(display),
- mDc(hDc),
- mStateCache(this)
- {
- mVertexDataManager = NULL;
- mIndexDataManager = NULL;
- mLineLoopIB = NULL;
- mTriangleFanIB = NULL;
- mBlit = NULL;
- mPixelTransfer = NULL;
- mClear = NULL;
- mTrim = NULL;
- mSyncQuery = NULL;
- mD3d11Module = NULL;
- mDxgiModule = NULL;
- mDevice = NULL;
- mDeviceContext = NULL;
- mDeviceContext1 = NULL;
- mDxgiAdapter = NULL;
- mDxgiFactory = NULL;
- mDriverConstantBufferVS = NULL;
- mDriverConstantBufferPS = NULL;
- mAppliedVertexShader = NULL;
- mAppliedGeometryShader = NULL;
- mAppliedPixelShader = NULL;
- EGLint requestedMajorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
- EGLint requestedMinorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
- if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
- {
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
- }
- }
- if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10)
- {
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
- }
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
- }
- }
- if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
- }
- mDriverType = (attributes.get(EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_FALSE) == EGL_TRUE) ? D3D_DRIVER_TYPE_WARP
- : D3D_DRIVER_TYPE_HARDWARE;
- }
- Renderer11::~Renderer11()
- {
- release();
- }
- Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
- {
- ASSERT(HAS_DYNAMIC_TYPE(Renderer11*, renderer));
- return static_cast<Renderer11*>(renderer);
- }
- #ifndef __d3d11_1_h__
- #define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
- #endif
- EGLint Renderer11::initialize()
- {
- if (!mCompiler.initialize())
- {
- return EGL_NOT_INITIALIZED;
- }
- #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
- mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
- if (mD3d11Module == NULL || mDxgiModule == NULL)
- {
- ERR("Could not load D3D11 or DXGI library - aborting!\n");
- return EGL_NOT_INITIALIZED;
- }
- // create the D3D11 device
- ASSERT(mDevice == NULL);
- PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
- if (D3D11CreateDevice == NULL)
- {
- ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
- return EGL_NOT_INITIALIZED;
- }
- #endif
- HRESULT result = S_OK;
- #ifdef _DEBUG
- result = D3D11CreateDevice(NULL,
- mDriverType,
- NULL,
- D3D11_CREATE_DEVICE_DEBUG,
- mAvailableFeatureLevels.data(),
- mAvailableFeatureLevels.size(),
- D3D11_SDK_VERSION,
- &mDevice,
- &mFeatureLevel,
- &mDeviceContext);
- if (!mDevice || FAILED(result))
- {
- ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
- }
- if (!mDevice || FAILED(result))
- #endif
- {
- result = D3D11CreateDevice(NULL,
- mDriverType,
- NULL,
- 0,
- mAvailableFeatureLevels.data(),
- mAvailableFeatureLevels.size(),
- D3D11_SDK_VERSION,
- &mDevice,
- &mFeatureLevel,
- &mDeviceContext);
- if (!mDevice || FAILED(result))
- {
- ERR("Could not create D3D11 device - aborting!\n");
- return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer
- }
- }
- #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- #if !ANGLE_SKIP_DXGI_1_2_CHECK
- // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required.
- // The easiest way to check is to query for a IDXGIDevice2.
- bool requireDXGI1_2 = false;
- HWND hwnd = WindowFromDC(mDc);
- if (hwnd)
- {
- DWORD currentProcessId = GetCurrentProcessId();
- DWORD wndProcessId;
- GetWindowThreadProcessId(hwnd, &wndProcessId);
- requireDXGI1_2 = (currentProcessId != wndProcessId);
- }
- else
- {
- requireDXGI1_2 = true;
- }
- if (requireDXGI1_2)
- {
- IDXGIDevice2 *dxgiDevice2 = NULL;
- result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2);
- if (FAILED(result))
- {
- ERR("DXGI 1.2 required to present to HWNDs owned by another process.\n");
- return EGL_NOT_INITIALIZED;
- }
- SafeRelease(dxgiDevice2);
- }
- #endif
- #endif
- // Cast the DeviceContext to a DeviceContext1.
- // This could fail on Windows 7 without the Platform Update.
- // Don't error in this case- just don't use mDeviceContext1.
- mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext);
- IDXGIDevice *dxgiDevice = NULL;
- result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
- if (FAILED(result))
- {
- ERR("Could not query DXGI device - aborting!\n");
- return EGL_NOT_INITIALIZED;
- }
- result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter);
- if (FAILED(result))
- {
- ERR("Could not retrieve DXGI adapter - aborting!\n");
- return EGL_NOT_INITIALIZED;
- }
- SafeRelease(dxgiDevice);
- IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
- // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the description string.
- // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual hardware values.
- if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != NULL)
- {
- DXGI_ADAPTER_DESC2 adapterDesc2 = {0};
- dxgiAdapter2->GetDesc2(&adapterDesc2);
- // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a DXGI_ADAPTER_DESC).
- memcpy(mAdapterDescription.Description, adapterDesc2.Description, sizeof(mAdapterDescription.Description));
- mAdapterDescription.VendorId = adapterDesc2.VendorId;
- mAdapterDescription.DeviceId = adapterDesc2.DeviceId;
- mAdapterDescription.SubSysId = adapterDesc2.SubSysId;
- mAdapterDescription.Revision = adapterDesc2.Revision;
- mAdapterDescription.DedicatedVideoMemory = adapterDesc2.DedicatedVideoMemory;
- mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory;
- mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory;
- mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid;
- }
- else
- {
- mDxgiAdapter->GetDesc(&mAdapterDescription);
- }
- SafeRelease(dxgiAdapter2);
- memset(mDescription, 0, sizeof(mDescription));
- wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
- result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory);
- if (!mDxgiFactory || FAILED(result))
- {
- ERR("Could not create DXGI factory - aborting!\n");
- return EGL_NOT_INITIALIZED;
- }
- // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
- #if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
- ID3D11InfoQueue *infoQueue;
- result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);
- if (SUCCEEDED(result))
- {
- D3D11_MESSAGE_ID hideMessages[] =
- {
- D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET
- };
- D3D11_INFO_QUEUE_FILTER filter = {0};
- filter.DenyList.NumIDs = ArraySize(hideMessages);
- filter.DenyList.pIDList = hideMessages;
- infoQueue->AddStorageFilterEntries(&filter);
- SafeRelease(infoQueue);
- }
- #endif
- initializeDevice();
- return EGL_SUCCESS;
- }
- // do any one-time device initialization
- // NOTE: this is also needed after a device lost/reset
- // to reset the scene status and ensure the default states are reset.
- void Renderer11::initializeDevice()
- {
- mStateCache.initialize(mDevice);
- mInputLayoutCache.initialize(mDevice, mDeviceContext);
- ASSERT(!mVertexDataManager && !mIndexDataManager);
- mVertexDataManager = new VertexDataManager(this);
- mIndexDataManager = new IndexDataManager(this);
- ASSERT(!mBlit);
- mBlit = new Blit11(this);
- ASSERT(!mClear);
- mClear = new Clear11(this);
- ASSERT(!mTrim);
- mTrim = new Trim11(this);
- ASSERT(!mPixelTransfer);
- mPixelTransfer = new PixelTransfer11(this);
- const gl::Caps &rendererCaps = getRendererCaps();
- mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
- mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
- mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
- mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
- mCurVertexSRVs.resize(rendererCaps.maxVertexTextureImageUnits);
- mCurPixelSRVs.resize(rendererCaps.maxTextureImageUnits);
- markAllStateDirty();
- }
- std::vector<ConfigDesc> Renderer11::generateConfigs() const
- {
- std::vector<ConfigDesc> configs;
- unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
- unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
- for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
- {
- const d3d11::DXGIFormat &renderTargetFormatInfo = d3d11::GetDXGIFormatInfo(RenderTargetFormats[formatIndex]);
- const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat);
- if (renderTargetFormatCaps.renderable)
- {
- for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
- {
- const d3d11::DXGIFormat &depthStencilFormatInfo = d3d11::GetDXGIFormatInfo(DepthStencilFormats[depthStencilIndex]);
- const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat);
- if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == DXGI_FORMAT_UNKNOWN)
- {
- ConfigDesc newConfig;
- newConfig.renderTargetFormat = renderTargetFormatInfo.internalFormat;
- newConfig.depthStencilFormat = depthStencilFormatInfo.internalFormat;
- newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
- newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast
- // Before we check mFeatureLevel, we need to ensure that the D3D device has been created.
- ASSERT(mDevice != NULL);
- newConfig.es2Conformant = (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0);
- newConfig.es3Capable = isES3Capable();
- configs.push_back(newConfig);
- }
- }
- }
- }
- return configs;
- }
- gl::Error Renderer11::flush()
- {
- mDeviceContext->Flush();
- return gl::Error(GL_NO_ERROR);
- }
- gl::Error Renderer11::finish()
- {
- HRESULT result;
- if (!mSyncQuery)
- {
- D3D11_QUERY_DESC queryDesc;
- queryDesc.Query = D3D11_QUERY_EVENT;
- queryDesc.MiscFlags = 0;
- result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result);
- }
- }
- mDeviceContext->End(mSyncQuery);
- mDeviceContext->Flush();
- do
- {
- result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
- }
- // Keep polling, but allow other threads to do something useful first
- ScheduleYield();
- if (testDeviceLost())
- {
- mDisplay->notifyDeviceLost();
- return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync.");
- }
- }
- while (result == S_FALSE);
- return gl::Error(GL_NO_ERROR);
- }
- SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
- {
- return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
- }
- gl::Error Renderer11::generateSwizzle(gl::Texture *texture)
- {
- if (texture)
- {
- TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
- ASSERT(textureD3D);
- TextureStorage *texStorage = textureD3D->getNativeTexture();
- if (texStorage)
- {
- TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage);
- gl::Error error = storage11->generateSwizzles(texture->getSamplerState().swizzleRed,
- texture->getSamplerState().swizzleGreen,
- texture->getSamplerState().swizzleBlue,
- texture->getSamplerState().swizzleAlpha);
- if (error.isError())
- {
- return error;
- }
- }
- }
- return gl::Error(GL_NO_ERROR);
- }
- gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerStateParam)
- {
- // Make sure to add the level offset for our tiny compressed texture workaround
- TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
- gl::SamplerState samplerStateInternal = samplerStateParam;
- samplerStateInternal.baseLevel += textureD3D->getNativeTexture()->getTopLevel();
- if (type == gl::SAMPLER_PIXEL)
- {
- ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits);
- if (mForceSetPixelSamplerStates[index] || memcmp(&samplerStateInternal, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
- {
- ID3D11SamplerState *dxSamplerState = NULL;
- gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState);
- if (error.isError())
- {
- return error;
- }
- ASSERT(dxSamplerState != NULL);
- mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
- mCurPixelSamplerStates[index] = samplerStateInternal;
- }
- mForceSetPixelSamplerStates[index] = false;
- }
- else if (type == gl::SAMPLER_VERTEX)
- {
- ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits);
- if (mForceSetVertexSamplerStates[index] || memcmp(&samplerStateInternal, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
- {
- ID3D11SamplerState *dxSamplerState = NULL;
- gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState);
- if (error.isError())
- {
- return error;
- }
- ASSERT(dxSamplerState != NULL);
- mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
- mCurVertexSamplerStates[index] = samplerStateInternal;
- }
- mForceSetVertexSamplerStates[index] = false;
- }
- else UNREACHABLE();
- return gl::Error(GL_NO_ERROR);
- }
- gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
- {
- ID3D11ShaderResourceView *textureSRV = NULL;
- if (texture)
- {
- TextureD3D *textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation());
- TextureStorage *texStorage = textureImpl->getNativeTexture();
- ASSERT(texStorage != NULL);
- TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage);
- // Make sure to add the level offset for our tiny compressed texture workaround
- gl::SamplerState samplerState = texture->getSamplerState();
- samplerState.baseLevel += storage11->getTopLevel();
- gl::Error error = storage11->getSRV(samplerState, &textureSRV);
- if (error.isError())
- {
- return error;
- }
- // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly
- // missing the shader resource view
- ASSERT(textureSRV != NULL);
- textureImpl->resetDirty();
- }
- ASSERT((type == gl::SAMPLER_PIXEL && static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits) ||
- (type == gl::SAMPLER_VERTEX && static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits));
- setShaderResource(type, index, textureSRV);
- return gl::Error(GL_NO_ERROR);
- }
- gl::Error Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[])
- {
- for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++)
- {
- const gl::Buffer *uniformBuffer = vertexUniformBuffers[uniformBufferIndex];
- if (uniformBuffer)
- {
- Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation());
- ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM);
- if (!constantBuffer)
- {
- return gl::Error(GL_OUT_OF_MEMORY);
- }
- if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial())
- {
- mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex,
- 1, &constantBuffer);
- mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial();
- }
- }
- }
- for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++)
- {
- const gl::Buffer *uniformBuffer = fragmentUniformBuffers[uniformBufferIndex];
- if (uniformBuffer)
- {
- Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation());
- ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM);
- if (!constantBuffer)
- {
- return gl::Error(GL_OUT_OF_MEMORY);
- }
- if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial())
- {
- mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex,
- 1, &constantBuffer);
- mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial();
- }
- }
- }
- return gl::Error(GL_NO_ERROR);
- }
- gl::Error Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
- {
- if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
- {
- ID3D11RasterizerState *dxRasterState = NULL;
- gl::Error error = mStateCache.getRasterizerState(rasterState, mScissorEnabled, &dxRasterState);
- if (error.isError())
- {
- return error;
- }
- mDeviceContext->RSSetState(dxRasterState);
- mCurRasterState = rasterState;
- }
- mForceSetRasterState = false;
- return gl::Error(GL_NO_ERROR);
- }
- gl::Error Renderer11::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
- unsigned int sampleMask)
- {
- if (mForceSetBlendState ||
- memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 ||
- memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0 ||
- sampleMask != mCurSampleMask)
- {
- ID3D11BlendState *dxBlendState = NULL;
- gl::Error error = mStateCache.getBlendState(framebuffer, blendState, &dxBlendState);
- if (error.isError())
- {
- return error;
- }
- ASSERT(dxBlendState != NULL);
- 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;
- }
- mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
- mCurBlendState = blendState;
- mCurBlendColor = blendColor;
- mCurSampleMask = sampleMask;
- }
- mForceSetBlendState = false;
- return gl::Error(GL_NO_ERROR);
- }
- gl::Error Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
- int stencilBackRef, bool frontFaceCCW)
- {
- if (mForceSetDepthStencilState ||
- memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
- stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
- {
- ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask);
- ASSERT(stencilRef == stencilBackRef);
- ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask);
- ID3D11DepthStencilState *dxDepthStencilState = NULL;
- gl::Error error = mStateCache.getDepthStencilState(depthStencilState, &dxDepthStencilState);
- if (error.isError())
- {
- return error;
- }
- ASSERT(dxDepthStencilState);
- // 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
- META_ASSERT(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF);
- META_ASSERT(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF);
- UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu);
- mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
- mCurDepthStencilState = depthStencilState;
- mCurStencilRef = stencilRef;
- mCurStencilBackRef = stencilBackRef;
- }
- mForceSetDepthStencilState = false;
- return gl::Error(GL_NO_ERROR);
- }
- void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
- {
- if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
- enabled != mScissorEnabled)
- {
- if (enabled)
- {
- D3D11_RECT rect;
- rect.left = std::max(0, scissor.x);
- rect.top = std::max(0, scissor.y);
- rect.right = scissor.x + std::max(0, scissor.width);
- rect.bottom = scissor.y + std::max(0, scissor.height);
- mDeviceContext->RSSetScissorRects(1, &rect);
- }
- if (enabled != mScissorEnabled)
- {
- mForceSetRasterState = true;
- }
- mCurScissor = scissor;
- mScissorEnabled = enabled;
- }
- mForceSetScissor = false;
- }
- void Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
- bool ignoreViewport)
- {
- gl::Rectangle actualViewport = viewport;
- float actualZNear = gl::clamp01(zNear);
- float actualZFar = gl::clamp01(zFar);
- if (ignoreViewport)
- {
- actualViewport.x = 0;
- actualViewport.y = 0;
- actualViewport.width = mRenderTargetDesc.width;
- actualViewport.height = mRenderTargetDesc.height;
- actualZNear = 0.0f;
- actualZFar = 1.0f;
- }
- bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
- actualZNear != mCurNear || actualZFar != mCurFar;
- if (viewportChanged)
- {
- const gl::Caps& caps = getRendererCaps();
- int dxMaxViewportBoundsX = static_cast<int>(caps.maxViewportWidth);
- int dxMaxViewportBoundsY = static_cast<int>(caps.maxViewportHeight);
- int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
- int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
- if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3)
- {
- // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
- dxMaxViewportBoundsX = mRenderTargetDesc.width;
- dxMaxViewportBoundsY = mRenderTargetDesc.height;
- dxMinViewportBoundsX = 0;
- dxMinViewportBoundsY = 0;
- }
- int dxViewportTopLeftX = gl::clamp(actualViewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
- int dxViewportTopLeftY = gl::clamp(actualViewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
- int dxViewportWidth = gl::clamp(actualViewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
- int dxViewportHeight = gl::clamp(actualViewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
- D3D11_VIEWPORT dxViewport;
- dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
- dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
- dxViewport.Width = static_cast<float>(dxViewportWidth);
- dxViewport.Height = static_cast<float>(dxViewportHeight);
- dxViewport.MinDepth = actualZNear;
- dxViewport.MaxDepth = actualZFar;
- mDeviceContext->RSSetViewports(1, &dxViewport);
- mCurViewport = actualViewport;
- mCurNear = actualZNear;
- mCurFar = actualZFar;
- // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders using viewAdjust (like the D3D9 renderer).
- if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3)
- {
- mVertexConstants.viewAdjust[0] = static_cast<float>((actualViewport.width - dxViewportWidth) + 2 * (actualViewport.x - dxViewportTopLeftX)) / dxViewport.Width;
- mVertexConstants.viewAdjust[1] = static_cast<float>((actualViewport.height - dxViewportHeight) + 2 * (actualViewport.y - dxViewportTopLeftY)) / dxViewport.Height;
- mVertexConstants.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width;
- mVertexConstants.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height;
- }
- mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f;
- mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f;
- mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
- mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
- // Instanced pointsprite emulation requires ViewCoords to be defined in the
- // the vertex shader.
- mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0];
- mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1];
- mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2];
- mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3];
- mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
- mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
- mVertexConstants.depthRange[0] = actualZNear;
- mVertexConstants.depthRange[1] = actualZFar;
- mVertexConstants.depthRange[2] = actualZFar - actualZNear;
- mPixelConstants.depthRange[0] = actualZNear;
- mPixelConstants.depthRange[1] = actualZFar;
- mPixelConstants.depthRange[2] = actualZFar - actualZNear;
- }
- mForceSetViewport = false;
- }
- bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
- {
- D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
- GLsizei minCount = 0;
- switch (mode)
- {
- case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break;
- case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break;
- case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break;
- case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break;
- case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break;
- case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break;
- // emulate fans via rewriting index buffer
- case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break;
- default:
- UNREACHABLE();
- return false;
- }
- // If instanced pointsprite emulation is being used and If gl_PointSize is used in the shader,
- // GL_POINTS mode is expected to render pointsprites.
- // Instanced PointSprite emulation requires that the topology to be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
- if (mode == GL_POINTS && usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
- {
- primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
- }
- if (primitiveTopology != mCurrentPrimitiveTopology)
- {
- mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
- mCurrentPrimitiveTopology = primitiveTopology;
- }
- return count >= minCount;
- }
- void Renderer11::unsetConflictingSRVs(gl::SamplerType samplerType, const ID3D11Resource *resource, const gl::ImageIndex* index)
- {
- auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
- for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex)
- {
- auto &record = currentSRVs[resourceIndex];
- if (record.srv && record.resource == resource && ImageIndexConflictsWithSRV(index, record.desc))
- {
- setShaderResource(samplerType, static_cast<UINT>(resourceIndex), NULL);
- }
- }
- }
- gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
- {
- // Get the color render buffer and serial
- // Also extract the render target dimensions and view
- unsigned int renderTargetWidth = 0;
- unsigned int renderTargetHeight = 0;
- DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN;
- unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0};
- ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
- bool missingColorRenderTarget = true;
- const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(getWorkarounds());
- for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
- {
- gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
- if (colorbuffer)
- {
- // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order)
- // check for zero-sized default framebuffer, which is a special case.
- // in this case we do not wish to modify any state and just silently return false.
- // this will not report any gl error but will cause the calling method to return.
- if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
- {
- return gl::Error(GL_NO_ERROR);
- }
- renderTargetSerials[colorAttachment] = GetAttachmentSerial(colorbuffer);
- // Extract the render target dimensions and view
- RenderTarget11 *renderTarget = NULL;
- gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(renderTarget);
- framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
- ASSERT(framebufferRTVs[colorAttachment]);
- if (missingColorRenderTarget)
- {
- renderTargetWidth = renderTarget->getWidth();
- renderTargetHeight = renderTarget->getHeight();
- renderTargetFormat = renderTarget->getDXGIFormat();
- missingColorRenderTarget = false;
- }
- // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
- if (colorbuffer->type() == GL_TEXTURE)
- {
- ID3D11Resource *renderTargetResource = renderTarget->getTexture();
- const gl::ImageIndex *index = colorbuffer->getTextureImageIndex();
- ASSERT(index);
- // The index doesn't need to be corrected for the small compressed texture workaround
- // because a rendertarget is never compressed.
- unsetConflictingSRVs(gl::SAMPLER_VERTEX, renderTargetResource, index);
- unsetConflictingSRVs(gl::SAMPLER_PIXEL, renderTargetResource, index);
- }
- }
- }
- // Get the depth stencil render buffter and serials
- gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer();
- unsigned int depthbufferSerial = 0;
- unsigned int stencilbufferSerial = 0;
- if (depthStencil)
- {
- depthbufferSerial = GetAttachmentSerial(depthStencil);
- }
- else if (framebuffer->getStencilbuffer())
- {
- depthStencil = framebuffer->getStencilbuffer();
- stencilbufferSerial = GetAttachmentSerial(depthStencil);
- }
- ID3D11DepthStencilView* framebufferDSV = NULL;
- if (depthStencil)
- {
- RenderTarget11 *depthStencilRenderTarget = NULL;
- gl::Error error = d3d11::GetAttachmentRenderTarget(depthStencil, &depthStencilRenderTarget);
- if (error.isError())
- {
- SafeRelease(framebufferRTVs);
- return error;
- }
- ASSERT(depthStencilRenderTarget);
- framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
- ASSERT(framebufferDSV);
- // If there is no render buffer, the width, height and format values come from
- // the depth stencil
- if (missingColorRenderTarget)
- {
- renderTargetWidth = depthStencilRenderTarget->getWidth();
- renderTargetHeight = depthStencilRenderTarget->getHeight();
- renderTargetFormat = depthStencilRenderTarget->getDXGIFormat();
- }
- }
- // Apply the render target and depth stencil
- if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
- memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 ||
- depthbufferSerial != mAppliedDepthbufferSerial ||
- stencilbufferSerial != mAppliedStencilbufferSerial)
- {
- mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV);
- mRenderTargetDesc.width = renderTargetWidth;
- mRenderTargetDesc.height = renderTargetHeight;
- mRenderTargetDesc.format = renderTargetFormat;
- mForceSetViewport = true;
- mForceSetScissor = true;
- mForceSetBlendState = true;
- if (!mDepthStencilInitialized)
- {
- mForceSetRasterState = true;
- }
- for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
- {
- mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex];
- }
- mAppliedDepthbufferSerial = depthbufferSerial;
- mAppliedStencilbufferSerial = stencilbufferSerial;
- mRenderTargetDescInitialized = true;
- mDepthStencilInitialized = true;
- }
- invalidateFramebufferSwizzles(framebuffer);
- return gl::Error(GL_NO_ERROR);
- }
- gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances)
- {
- TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
- gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances);
- if (error.isError())
- {
- return error;
- }
- return mInputLayoutCache.applyVertexBuffers(attributes, state.getProgram());
- }
- gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
- {
- gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
- if (error.isError())
- {
- return error;
- }
- ID3D11Buffer *buffer = NULL;
- DXGI_FORMAT bufferFormat = (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;
- if (indexInfo->storage)
- {
- Buffer11 *storage = Buffer11::makeBuffer11(indexInfo->storage);
- buffer = storage->getBuffer(BUFFER_USAGE_INDEX);
- }
- else
- {
- IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
- buffer = indexBuffer->getBuffer();
- }
- if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat || indexInfo->startOffset != mAppliedIBOffset)
- {
- mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset);
- mAppliedIB = buffer;
- mAppliedIBFormat = bufferFormat;
- mAppliedIBOffset = indexInfo->startOffset;
- }
- return gl::Error(GL_NO_ERROR);
- }
- void Renderer11::applyTransformFeedbackBuffers(const gl::State& state)
- {
- size_t numXFBBindings = state.getTransformFeedbackBufferIndexRange();
- ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
- bool requiresUpdate = false;
- for (size_t i = 0; i < numXFBBindings; i++)
- {
- gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i);
- GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i);
- ID3D11Buffer *d3dBuffer = NULL;
- if (curXFBBuffer)
- {
- Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation());
- d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
- }
- // TODO: mAppliedTFBuffers and friends should also be kept in a vector.
- if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i])
- {
- requiresUpdate = true;
- }
- }
- if (requiresUpdate)
- {
- for (size_t i = 0; i < numXFBBindings; ++i)
- {
- gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i);
- GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i);
- if (curXFBBuffer)
- {
- Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation());
- ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
- mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != curXFBOffset) ?
- static_cast<UINT>(curXFBOffset) : -1;
- mAppliedTFBuffers[i] = d3dBuffer;
- }
- else
- {
- mAppliedTFBuffers[i] = NULL;
- mCurrentD3DOffsets[i] = 0;
- }
- mAppliedTFOffsets[i] = curXFBOffset;
- }
- mDeviceContext->SOSetTargets(numXFBBindings, mAppliedTFBuffers, mCurrentD3DOffsets);
- }
- }
- gl::Error Renderer11::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive, bool usesPointSize)
- {
- bool useInstancedPointSpriteEmulation = usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation;
- if (mode == GL_POINTS && transformFeedbackActive)
- {
- // Since point sprites are generated with a geometry shader, too many vertices will
- // be written if transform feedback is active. To work around this, draw only the points
- // with the stream out shader and no pixel shader to feed the stream out buffers and then
- // draw again with the point sprite geometry shader to rasterize the point sprites.
- mDeviceContext->PSSetShader(NULL, NULL, 0);
- if (instances > 0)
- {
- mDeviceContext->DrawInstanced(count, instances, 0, 0);
- }
- else
- {
- mDeviceContext->Draw(count, 0);
- }
- ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(data.state->getProgram()->getImplementation());
- rx::ShaderExecutableD3D *pixelExe = NULL;
- gl::Error error = programD3D->getPixelExecutableForFramebuffer(data.state->getDrawFramebuffer(), &pixelExe);
- if (error.isError())
- {
- return error;
- }
- // Skip this step if we're doing rasterizer discard.
- if (pixelExe && !data.state->getRasterizerState().rasterizerDiscard)
- {
- ID3D11PixelShader *pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader();
- ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader);
- mDeviceContext->PSSetShader(pixelShader, NULL, 0);
- // Retrieve the point sprite geometry shader
- rx::ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable();
- ID3D11GeometryShader *geometryShader = (geometryExe ? ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader() : NULL);
- mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
- ASSERT(geometryShader);
- mDeviceContext->GSSetShader(geometryShader, NULL, 0);
- if (instances > 0)
- {
- mDeviceContext->DrawInstanced(count, instances, 0, 0);
- }
- else
- {
- mDeviceContext->Draw(count, 0);
- }
- }
- return gl::Error(GL_NO_ERROR);
- }
- else if (mode == GL_LINE_LOOP)
- {
- return drawLineLoop(count, GL_NONE, NULL, 0, NULL);
- }
- else if (mode == GL_TRIANGLE_FAN)
- {
- return drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances);
- }
- else if (instances > 0)
- {
- mDeviceContext->DrawInstanced(count, instances, 0, 0);
- return gl::Error(GL_NO_ERROR);
- }
- else
- {
- // If gl_PointSize is used and GL_POINTS is specified, then it is expected to render pointsprites.
- // If instanced pointsprite emulation is being used the topology is expexted to be
- // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced must be used.
- if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
- {
- mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
- }
- else
- {
- mDeviceContext->Draw(count, 0);
- }
- r…
Large files files are truncated, but you can click here to view the full file